diff options
Diffstat (limited to 'internal/api/websocket.go')
| -rw-r--r-- | internal/api/websocket.go | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/internal/api/websocket.go b/internal/api/websocket.go new file mode 100644 index 0000000..6bd8c88 --- /dev/null +++ b/internal/api/websocket.go @@ -0,0 +1,72 @@ +package api + +import ( + "log/slog" + "net/http" + "sync" + + "golang.org/x/net/websocket" +) + +// Hub manages WebSocket connections and broadcasts messages. +type Hub struct { + mu sync.RWMutex + clients map[*websocket.Conn]bool + logger *slog.Logger +} + +func NewHub() *Hub { + return &Hub{ + clients: make(map[*websocket.Conn]bool), + logger: slog.Default(), + } +} + +// Run is a no-op loop kept for future cleanup/heartbeat logic. +func (h *Hub) Run() {} + +func (h *Hub) Register(ws *websocket.Conn) { + h.mu.Lock() + h.clients[ws] = true + h.mu.Unlock() +} + +func (h *Hub) Unregister(ws *websocket.Conn) { + h.mu.Lock() + delete(h.clients, ws) + h.mu.Unlock() +} + +// Broadcast sends a message to all connected WebSocket clients. +func (h *Hub) Broadcast(msg []byte) { + h.mu.RLock() + defer h.mu.RUnlock() + for conn := range h.clients { + if _, err := conn.Write(msg); err != nil { + h.logger.Error("websocket write error", "error", err) + } + } +} + +// ClientCount returns the number of connected clients. +func (h *Hub) ClientCount() int { + h.mu.RLock() + defer h.mu.RUnlock() + return len(h.clients) +} + +func (s *Server) handleWebSocket(w http.ResponseWriter, r *http.Request) { + handler := websocket.Handler(func(ws *websocket.Conn) { + s.hub.Register(ws) + defer s.hub.Unregister(ws) + + // Keep connection alive until client disconnects. + buf := make([]byte, 1024) + for { + if _, err := ws.Read(buf); err != nil { + break + } + } + }) + handler.ServeHTTP(w, r) +} |
