mirror of
https://github.com/EnumeratedDev/enit.git
synced 2026-09-16 02:26:11 +00:00
262 lines
6.5 KiB
Go
262 lines
6.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net"
|
|
"path"
|
|
)
|
|
|
|
var commandHandlers = make(map[string]func(conn net.Conn, jsonData map[string]any))
|
|
|
|
func initSocket() (socket net.Listener, err error) {
|
|
socket, err = net.Listen("unix", path.Join(runtimeServiceDir, "esvm.sock"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Register command handlers
|
|
commandHandlers["reload"] = handleReloadServicesCommand
|
|
commandHandlers["start"] = handleStartServiceCommand
|
|
commandHandlers["stop"] = handleStopServiceCommand
|
|
commandHandlers["restart"] = handleRestartServiceCommand
|
|
commandHandlers["status"] = handleStatusServiceCommand
|
|
commandHandlers["list"] = handleListServicesCommand
|
|
|
|
return socket, nil
|
|
}
|
|
|
|
func listenToSocket() {
|
|
conn, err := socket.Accept()
|
|
if err != nil {
|
|
logger.Println("Could not accept socket connection!")
|
|
return
|
|
}
|
|
|
|
// Handle the connection in a separate goroutine.
|
|
go func(conn net.Conn) {
|
|
defer conn.Close()
|
|
|
|
// Read data from the connection.
|
|
data, err := readAllConn(conn)
|
|
if err != nil {
|
|
logger.Fatalf("Could not read data from socket! Error: %s\n", err)
|
|
return
|
|
}
|
|
|
|
// Decoode JSON data
|
|
var jsonData map[string]any
|
|
err = json.Unmarshal(data, &jsonData)
|
|
if err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Invalid JSON")))
|
|
return
|
|
}
|
|
|
|
// Get command to execute
|
|
command, ok := jsonData["command"]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("'command' field missing")))
|
|
return
|
|
}
|
|
|
|
// Get command handler
|
|
commandHandler, ok := commandHandlers[command.(string)]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("command (%s) has not been implemented", command.(string))))
|
|
return
|
|
}
|
|
commandHandler(conn, jsonData)
|
|
}(conn)
|
|
}
|
|
|
|
func handleReloadServicesCommand(conn net.Conn, jsonData map[string]any) {
|
|
// Reload services
|
|
Reload()
|
|
|
|
conn.Write(wrapSuccessMsgInJson("Services reloaded successfully"))
|
|
}
|
|
|
|
func handleStartServiceCommand(conn net.Conn, jsonData map[string]any) {
|
|
// Get service name from json data
|
|
serviceName, ok := jsonData["service"]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
|
|
return
|
|
}
|
|
|
|
// Ensure service exists
|
|
service := GetServiceByName(serviceName.(string))
|
|
if service == nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
// Start the service
|
|
if err := service.StartService(); err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be started", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has started sucessfully", serviceName.(string))))
|
|
}
|
|
|
|
func handleStopServiceCommand(conn net.Conn, jsonData map[string]any) {
|
|
// Get service name from json data
|
|
serviceName, ok := jsonData["service"]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
|
|
return
|
|
}
|
|
|
|
// Ensure service exists
|
|
service := GetServiceByName(serviceName.(string))
|
|
if service == nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
// Stop the service
|
|
if err := service.StopService(); err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be stopped", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has stopped sucessfully", serviceName.(string))))
|
|
}
|
|
|
|
func handleRestartServiceCommand(conn net.Conn, jsonData map[string]any) {
|
|
// Get service name from json data
|
|
serviceName, ok := jsonData["service"]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
|
|
return
|
|
}
|
|
|
|
// Ensure service exists
|
|
service := GetServiceByName(serviceName.(string))
|
|
if service == nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
// Restart the service
|
|
if err := service.RestartService(); err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) could not be restarted", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
conn.Write(wrapSuccessMsgInJson(fmt.Sprintf("Service (%s) has restarted sucessfully", serviceName.(string))))
|
|
}
|
|
|
|
func handleStatusServiceCommand(conn net.Conn, jsonData map[string]any) {
|
|
// Get service name from json data
|
|
serviceName, ok := jsonData["service"]
|
|
if !ok {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("'service' field missing")))
|
|
return
|
|
}
|
|
|
|
// Ensure service exists
|
|
service := GetServiceByName(serviceName.(string))
|
|
if service == nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Service (%s) not found", serviceName.(string))))
|
|
return
|
|
}
|
|
|
|
statusMap := make(map[string]any)
|
|
statusMap["name"] = service.Name
|
|
statusMap["description"] = service.Description
|
|
statusMap["state"] = EnitServiceStateNames[service.state]
|
|
statusMap["process_id"] = service.processID
|
|
|
|
// Encode map to json string
|
|
newJsonData, err := json.Marshal(statusMap)
|
|
if err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Could not encode JSON data")))
|
|
return
|
|
}
|
|
|
|
conn.Write(newJsonData)
|
|
}
|
|
|
|
func handleListServicesCommand(conn net.Conn, _ map[string]any) {
|
|
servicesMap := make(map[string]any)
|
|
servicesMap["services"] = make([]map[string]any, 0)
|
|
|
|
// Loop through each service
|
|
for _, service := range Services {
|
|
statusMap := make(map[string]any)
|
|
statusMap["name"] = service.Name
|
|
statusMap["description"] = service.Description
|
|
statusMap["state"] = EnitServiceStateNames[service.state]
|
|
statusMap["process_id"] = service.processID
|
|
servicesMap["services"] = append(servicesMap["services"].([]map[string]any), statusMap)
|
|
}
|
|
|
|
// Encode map to json string
|
|
newJsonData, err := json.Marshal(servicesMap)
|
|
if err != nil {
|
|
conn.Write(wrapErrorInJson(fmt.Errorf("Could not encode JSON data")))
|
|
return
|
|
}
|
|
|
|
conn.Write(newJsonData)
|
|
}
|
|
|
|
func wrapErrorInJson(err error) []byte {
|
|
// Wrap error in struct
|
|
type jsonErrorStruct struct {
|
|
Error string `json:"error"`
|
|
}
|
|
jsonError := jsonErrorStruct{
|
|
Error: err.Error(),
|
|
}
|
|
|
|
// Encode struct to json string
|
|
jsonData, _err := json.Marshal(jsonError)
|
|
if _err != nil {
|
|
return nil
|
|
}
|
|
return jsonData
|
|
}
|
|
|
|
func wrapSuccessMsgInJson(msg string) []byte {
|
|
// Wrap message in struct
|
|
type jsonSuccessStruct struct {
|
|
Success string `json:"success"`
|
|
}
|
|
jsonSuccess := jsonSuccessStruct{
|
|
Success: msg,
|
|
}
|
|
|
|
// Encode struct to json string
|
|
jsonData, _err := json.Marshal(jsonSuccess)
|
|
if _err != nil {
|
|
return nil
|
|
}
|
|
return jsonData
|
|
}
|
|
|
|
func readAllConn(conn net.Conn) ([]byte, error) {
|
|
var buf bytes.Buffer
|
|
|
|
for {
|
|
dataChunk := make([]byte, 1024)
|
|
|
|
n, err := conn.Read(dataChunk)
|
|
if err != nil && err != io.EOF {
|
|
return nil, err
|
|
}
|
|
|
|
buf.Write(dataChunk[:n])
|
|
|
|
if n < 1024 {
|
|
break
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|