adding to git.i0t.app
This commit is contained in:
75
internal/ipc/ipc.go
Normal file
75
internal/ipc/ipc.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Package ipc defines the tiny control protocol shared by the daemon (server)
|
||||
// and the CLI/TUI (clients). Messages are newline-delimited JSON over a unix
|
||||
// socket, so switching layouts or reading status never requires restarting
|
||||
// the video wall.
|
||||
package ipc
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Request is a command sent to the daemon.
|
||||
type Request struct {
|
||||
Cmd string `json:"cmd"` // "status" | "reload" | "set-layout"
|
||||
Name string `json:"name,omitempty"` // layout name for set-layout
|
||||
}
|
||||
|
||||
// SlotStatus reports one grid cell's state.
|
||||
type SlotStatus struct {
|
||||
Slot int `json:"slot"`
|
||||
Camera string `json:"camera"`
|
||||
PID int `json:"pid"`
|
||||
Running bool `json:"running"`
|
||||
Healthy bool `json:"healthy"`
|
||||
}
|
||||
|
||||
// Response is the daemon's reply.
|
||||
type Response struct {
|
||||
OK bool `json:"ok"`
|
||||
Error string `json:"error,omitempty"`
|
||||
ActiveLayout string `json:"active_layout,omitempty"`
|
||||
Slots []SlotStatus `json:"slots,omitempty"`
|
||||
}
|
||||
|
||||
// SocketPath returns the control socket path inside the runtime dir.
|
||||
func SocketPath() string {
|
||||
return filepath.Join(RunDir(), "control.sock")
|
||||
}
|
||||
|
||||
// RunDir is the per-user runtime directory for sockets, created on demand.
|
||||
func RunDir() string {
|
||||
base := os.Getenv("XDG_RUNTIME_DIR")
|
||||
if base == "" {
|
||||
base = filepath.Join(os.TempDir(), "rtsp-streamer-"+strconv.Itoa(os.Getuid()))
|
||||
} else {
|
||||
base = filepath.Join(base, "rtsp-streamer")
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
// Send dials the daemon, sends one request, and returns the reply.
|
||||
func Send(req Request) (*Response, error) {
|
||||
conn, err := net.DialTimeout("unix", SocketPath(), 3*time.Second)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot reach daemon (is it running?): %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
_ = conn.SetDeadline(time.Now().Add(5 * time.Second))
|
||||
|
||||
enc := json.NewEncoder(conn)
|
||||
if err := enc.Encode(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp Response
|
||||
if err := json.NewDecoder(bufio.NewReader(conn)).Decode(&resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
Reference in New Issue
Block a user