Files
statusServer/handlers/clientHandler.go
Adrian Zuercher e36d393749 first commit
2025-08-23 22:22:22 +02:00

126 lines
3.4 KiB
Go

package handlers
import (
"encoding/json"
"fmt"
"statusServer/models"
"sync"
json_dataModels "gitea.tecamino.com/paadi/tecamino-json_data/models"
"github.com/gin-gonic/gin"
)
// ClientHandler manages active websocket clients.
// - Keeps a map of connected clients (thread-safe).
// - Provides helper methods to connect, lookup, and send responses.
type ClientHandler struct {
sync.RWMutex // protects access to Clients map
clients models.Clients // map[string]*Client (id → client)
}
// SendBroadcast sends a raw message to all clients in the global Broadcast list.
// Note: uses `models.Broadcast` (separate global client slice).
func SendBroadcast(data []byte) {
for _, c := range models.Broadcast {
c.SendData(data)
}
}
// NewConnectionHandler creates and initializes a new ClientHandler
// with an empty client map.
func NewConnectionHandler() *ClientHandler {
return &ClientHandler{
clients: models.NewClients(),
}
}
// ConnectNewClient registers a new websocket client by ID.
// - If client with same ID already exists, returns the existing client.
// - Otherwise, creates a new connection and stores it in the handler map.
func (cH *ClientHandler) ConnectNewClient(id string, c *gin.Context) (client *models.Client, err error) {
// Check if client already exists (reuse connection).
if _, exists := cH.clients[id]; exists {
return cH.clients[id], nil
}
// Create a new websocket client instance.
client, err = models.ConnectNewClient(id, c)
if err != nil {
return nil, err
}
// Ensure cleanup: when client disconnects, remove from map.
client.OnClose = func(code int, reason string) {
delete(cH.clients, id)
}
// Add client to handler map.
cH.Lock()
cH.clients[id] = client
cH.Unlock()
return client, nil
}
// GetClient retrieves a client by ID.
// Returns nil if client does not exist.
func (c *ClientHandler) GetClient(id string) *models.Client {
if client, ok := c.clients[id]; ok {
return client
}
return nil
}
func (cH *ClientHandler) RemoveClient(id string) {
delete(cH.clients, id)
}
// SendResponse sends a structured JSON response to a given client by ID.
// - If client is not found, returns error.
// - Otherwise marshals the Response and sends via websocket.
func (c *ClientHandler) SendResponse(id string, r *json_dataModels.Response) error {
client, ok := c.clients[id]
if !ok {
return fmt.Errorf("client not found for id %s", id)
}
// Encode response to JSON.
b, err := json.Marshal(*r)
if err != nil {
return err
}
// Send JSON payload over websocket.
client.SendData(b)
return nil
}
// --- Sending helpers (proxy to server messaging system) ---
// SendInfo sends an "info" log message to the server.
func (c *ClientHandler) SendInfo(id string, data any) error {
return c.clients[id].SendInfo(data)
}
// SendInfo sends an "info" log message to the server.
func (c *ClientHandler) SendStatus(id string, data any) error {
return c.clients[id].SendStatus(data)
}
// SendDebug sends a "debug" log message to the server.
func (c *ClientHandler) SendDebug(id string, data any) error {
return c.clients[id].SendDebug(data)
}
// SendWarning sends a "warning" log message to the server.
func (c *ClientHandler) SendWarning(id string, data any) error {
return c.clients[id].SendWarning(data)
}
// SendError sends an "error" log message to the server.
func (c *ClientHandler) SendError(id string, data any) error {
return c.clients[id].SendError(data)
}