diff --git a/client.go b/client.go index fb6b923..c215554 100644 --- a/client.go +++ b/client.go @@ -1,5 +1,11 @@ package main +// WebSocket client read/write pumps. +// +// ReadPump pulls messages from the client's WebSocket connection and routes +// them into the Hub. WritePump pushes outbound messages from the Hub to the +// client's connection. Both functions are expected to run as goroutines per +// client. import ( "encoding/json" "fmt" @@ -9,6 +15,7 @@ import ( "github.com/gorilla/websocket" ) +// ReadPump reads from the websocket connection and handles client pings/pongs. func ReadPump(c *server.Client) { defer func() { c.Hub.Unregister <- c @@ -187,6 +194,7 @@ func ReadPump(c *server.Client) { } } +// WritePump writes queued messages to the websocket connection and sends periodic pings. func WritePump(c *server.Client) { defer func(conn *websocket.Conn) { _ = conn.Close() diff --git a/main.go b/main.go index 89dcce4..1d901a4 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,8 @@ package main +// main is the entrypoint for RadChat. It parses flags, prepares storage, +// configures middleware and routes, and starts the HTTP server. See README for +// the flag reference and architecture overview. import ( "flag" "fmt" diff --git a/message.go b/message.go index 6791fa0..8f97596 100644 --- a/message.go +++ b/message.go @@ -1,5 +1,112 @@ package main +// Message is a generic envelope exchanged over the WebSocket signaling channel. +// +// Type is the message kind (e.g., "join", "leave", "chat", "offer", +// "answer", "ice", etc.). Other fields are used depending on Type; unused +// fields are omitted in JSON. +// +// The flexibility helps keep the client and server loosely coupled; consider +// introducing stricter typed payloads if this grows. +// +// Note: This struct is intentionally broad to carry both chat and WebRTC +// signaling payloads. +// +// Timestamp is set by the sender (usually server) for ordering. +// Target is a peer client ID for directed messages. +// Data/DataExt/DataList support heterogeneous payloads where necessary. +// Offer/Answer/ICE carry WebRTC SDP/ICE candidate info. +// DataType can be used by clients to dispatch UI behavior. +// DataTime is optional timing metadata. +// +// Username/UserID are the sender identity. +// Error holds error information if Type indicates a failure. +// +// All fields are optional in JSON except Type. +// Keep in sync with frontend parsing in static/app.js +// to avoid breaking changes. +// +// Consider versioning if wire format evolves. +// +//nolint:lll // wide field tags +// +// +// Message struct definition: +// +// - Type: message category +// - Username, UserID: identity +// - Data/DataExt/DataList: generic payloads +// - Offer/Answer/ICE: WebRTC signaling +// - Target: directed recipient id +// - Error: error description if any +// - Timestamp: unix ms or ns +// +// The JSON tags omit empty fields to minimize bandwidth. +// +// End of doc. +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// Actual type follows. +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// + type Message struct { Type string `json:"type"` Username string `json:"username,omitempty"` diff --git a/server/client.go b/server/client.go index 69276ce..88df255 100644 --- a/server/client.go +++ b/server/client.go @@ -1,5 +1,7 @@ package server +// Client represents a single WebSocket connection and associated user state. +// It includes a send channel for outbound messages and LastPong for liveness. import ( "sync" "time" @@ -7,6 +9,7 @@ import ( "github.com/gorilla/websocket" ) +// Client holds the websocket connection and linkage back to the Hub. type Client struct { Conn *websocket.Conn Username string diff --git a/server/hub.go b/server/hub.go index 464c8b8..d774195 100644 --- a/server/hub.go +++ b/server/hub.go @@ -1,11 +1,16 @@ package server +// Hub is the central registry/bus for all connected clients. +// +// It exposes channels for broadcast, register, and unregister events +// and protects the Clients map with a RWMutex for safe concurrent access. import ( "sync" "github.com/gorilla/websocket" ) +// Hub groups clients and channels used by the server runtime. type Hub struct { Clients map[*Client]bool Broadcast chan []byte @@ -15,6 +20,7 @@ type Hub struct { Upgrader websocket.Upgrader } +// NewHub constructs a Hub with buffered channels sized by bufferSize. func NewHub(bufferSize int, upgrader websocket.Upgrader) *Hub { return &Hub{ Clients: make(map[*Client]bool), diff --git a/server/middleware.go b/server/middleware.go index 9824eeb..0ba49b6 100644 --- a/server/middleware.go +++ b/server/middleware.go @@ -1,5 +1,6 @@ package server +// HTTP middleware for gzip compression and cache control. import ( "compress/gzip" "io" @@ -7,6 +8,7 @@ import ( "strings" ) +// MiddlewareChain composes multiple middleware into a single http.Handler wrapper. func MiddlewareChain(middlewares ...func(http.Handler) http.Handler) func(http.Handler) http.Handler { return func(final http.Handler) http.Handler { for _, middleware := range middlewares { @@ -16,6 +18,7 @@ func MiddlewareChain(middlewares ...func(http.Handler) http.Handler) func(http.H } } +// gzipResponseWriter wraps http.ResponseWriter to write gzipped data. type gzipResponseWriter struct { http.ResponseWriter io.Writer diff --git a/server/utils.go b/server/utils.go index b42f3f4..7e653dd 100644 --- a/server/utils.go +++ b/server/utils.go @@ -1,5 +1,6 @@ package server +// Utilities for server package: WebSocket upgrader with Origin checks. import ( "net/http" "strings" @@ -7,6 +8,9 @@ import ( "github.com/gorilla/websocket" ) +// Upgrader creates a Gorilla websocket.Upgrader that enforces Origin checks. +// If bypass is true, any Origin is accepted. Otherwise, the Origin must match +// the provided originAddress (host[:port]). func Upgrader(originAddress string, bypass bool) websocket.Upgrader { if strings.HasPrefix(originAddress, "http://") || strings.HasPrefix(originAddress, "https://") { originAddress = strings.TrimPrefix(originAddress, "http://")