Files
enit/src/esvm/socket.go
T

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
}