Download websocket.go from Harp404/Space: direct link, hf CLI and curl.
- Browser
- Download file 3.5 kB
-
https://huggingface.co/spaces/Harp404/Space/resolve/main/websocket.go
- Command line
-
hf download hf://spaces/Harp404/Space/websocket.go
-
curl -L -o websocket.go https://huggingface.co/spaces/Harp404/Space/resolve/main/websocket.go
3.5 kB
| package main | |
| import ( | |
| "encoding/json" | |
| "log" | |
| "net/http" | |
| "sync" | |
| "time" | |
| "github.com/gorilla/websocket" | |
| ) | |
| // wsMessage is the envelope sent over WebSocket. | |
| type wsMessage struct { | |
| Type string `json:"type"` | |
| Payload interface{} `json:"payload"` | |
| } | |
| // wsClient represents a connected WebSocket client. | |
| type wsClient struct { | |
| conn *websocket.Conn | |
| send chan []byte | |
| } | |
| // Hub manages all connected WebSocket clients. | |
| type Hub struct { | |
| mu sync.RWMutex | |
| clients map[*wsClient]struct{} | |
| register chan *wsClient | |
| unregister chan *wsClient | |
| broadcast chan []byte | |
| } | |
| var hub = &Hub{ | |
| clients: make(map[*wsClient]struct{}), | |
| register: make(chan *wsClient, 32), | |
| unregister: make(chan *wsClient, 32), | |
| broadcast: make(chan []byte, 256), | |
| } | |
| var upgrader = websocket.Upgrader{ | |
| CheckOrigin: func(r *http.Request) bool { return true }, | |
| ReadBufferSize: 1024, | |
| WriteBufferSize: 4096, | |
| } | |
| // startHub runs the hub event loop. | |
| func startHub() { | |
| for { | |
| select { | |
| case c := <-hub.register: | |
| hub.mu.Lock() | |
| hub.clients[c] = struct{}{} | |
| hub.mu.Unlock() | |
| log.Printf("[WS] client connected (total=%d)", len(hub.clients)) | |
| // Send full state immediately on connect | |
| go func() { | |
| state := getNetworkState() | |
| msg := wsMessage{Type: "NETWORK_UPDATE", Payload: state} | |
| data, _ := json.Marshal(msg) | |
| c.send <- data | |
| }() | |
| case c := <-hub.unregister: | |
| hub.mu.Lock() | |
| if _, ok := hub.clients[c]; ok { | |
| delete(hub.clients, c) | |
| close(c.send) | |
| } | |
| hub.mu.Unlock() | |
| log.Printf("[WS] client disconnected (total=%d)", len(hub.clients)) | |
| case data := <-hub.broadcast: | |
| hub.mu.RLock() | |
| for c := range hub.clients { | |
| select { | |
| case c.send <- data: | |
| default: | |
| // Client too slow – drop message | |
| } | |
| } | |
| hub.mu.RUnlock() | |
| } | |
| } | |
| } | |
| // handleWebSocket upgrades an HTTP connection to WebSocket. | |
| func handleWebSocket(w http.ResponseWriter, r *http.Request) { | |
| conn, err := upgrader.Upgrade(w, r, nil) | |
| if err != nil { | |
| log.Printf("[WS] upgrade error: %v", err) | |
| return | |
| } | |
| client := &wsClient{ | |
| conn: conn, | |
| send: make(chan []byte, 64), | |
| } | |
| hub.register <- client | |
| // Writer goroutine | |
| go func() { | |
| defer func() { | |
| conn.Close() | |
| }() | |
| for data := range client.send { | |
| conn.SetWriteDeadline(time.Now().Add(5 * time.Second)) | |
| if err := conn.WriteMessage(websocket.TextMessage, data); err != nil { | |
| return | |
| } | |
| } | |
| }() | |
| // Reader goroutine (keep connection alive; ignore client messages) | |
| defer func() { | |
| hub.unregister <- client | |
| }() | |
| conn.SetReadLimit(512) | |
| conn.SetReadDeadline(time.Now().Add(120 * time.Second)) | |
| conn.SetPongHandler(func(string) error { | |
| conn.SetReadDeadline(time.Now().Add(120 * time.Second)) | |
| return nil | |
| }) | |
| for { | |
| _, _, err := conn.ReadMessage() | |
| if err != nil { | |
| break | |
| } | |
| // Reset deadline on any message | |
| conn.SetReadDeadline(time.Now().Add(120 * time.Second)) | |
| } | |
| } | |
| // broadcastNetworkUpdate sends a full NETWORK_UPDATE event to all clients. | |
| func broadcastNetworkUpdate() { | |
| state := getNetworkState() | |
| msg := wsMessage{Type: "NETWORK_UPDATE", Payload: state} | |
| data, err := json.Marshal(msg) | |
| if err != nil { | |
| return | |
| } | |
| select { | |
| case hub.broadcast <- data: | |
| default: | |
| } | |
| } | |
| // broadcastEvent sends a typed event to all connected WebSocket clients. | |
| func broadcastEvent(eventType string, payload interface{}) { | |
| msg := wsMessage{Type: eventType, Payload: payload} | |
| data, err := json.Marshal(msg) | |
| if err != nil { | |
| return | |
| } | |
| select { | |
| case hub.broadcast <- data: | |
| default: | |
| } | |
| } | |