savinmax c226bdab7f feat(hub): update graceful shutdown to iterate rooms for multi-room cleanup
Refactor the stop case in Hub.Run() to iterate h.rooms directly
instead of h.connRoom. For each room, iterate all connections and
send CloseGoingAway frame before closing. After the loop, reset both
maps (h.rooms, h.connRoom) in one shot rather than deleting entries
incrementally. This is cleaner and avoids modifying a map during
iteration.

Add TestIntegration_GracefulShutdownMultiRoom to verify clients in
separate rooms all receive close frames during shutdown.

🤖 Assisted by the code-assist SOP
2026-06-13 13:26:03 +02:00
2025-08-02 21:00:28 +02:00
2025-08-02 18:33:50 +02:00
2025-08-02 18:33:50 +02:00
2025-08-02 18:33:50 +02:00
2025-08-02 18:33:50 +02:00

WebSocket Relay Server

A minimal Go WebSocket relay server that broadcasts every incoming message to all connected clients. Supports TLS, Prometheus metrics, configurable logging, and graceful shutdown.

Features

  • Fan-out broadcasting — every message is relayed to all connected clients
  • TLS support — optional wss:// via cert/key PEM files
  • Prometheus metrics — connection counts, message totals, disconnections
  • Configurable logging — output to stdout, stderr, or file with level filtering
  • Graceful shutdown — clean exit on SIGINT/SIGTERM with client notification
  • Zero dependencies at runtime — single static binary

Quick Start

# Install dependencies
go mod tidy

# Run the server (defaults to ws://localhost:8443)
make run

# Or with a custom config
go run . --config-file=./config.yaml

Open example/index.html in multiple browser tabs to test the P2P chat demo.

Configuration

Edit config.yaml:

server:
  port: 8443
  tls:
    enabled: false       # Set true for wss://
    cert_file: cert.pem
    key_file: key.pem

metrics:
  enabled: true
  port: 9090            # Prometheus metrics at :9090/metrics

logging:
  output: stderr        # stdout, stderr, or a file path
  level: info           # debug, info, warn, error

Override the config file path with --config-file:

./websocket-relay --config-file=/etc/relay/config.yaml

Logging

The logging section controls where and what the server logs:

Field Values Default Description
output stdout, stderr, or a file path stderr Log output destination
level debug, info, warn, error info Minimum log level to output

Examples:

# Log everything to a file
logging:
  output: /var/log/websocket-relay.log
  level: debug

# Quiet mode — only warnings and errors to stderr
logging:
  output: stderr
  level: warn

Log messages are prefixed with the level: [DEBUG], [INFO], [WARN], [ERROR].

File output uses append mode (O_APPEND) so logs are preserved across restarts and safe for external log rotation tools.

Usage

Connect any WebSocket client to the server:

const ws = new WebSocket('ws://localhost:8443/');

ws.onmessage = (event) => console.log('Received:', event.data);
ws.onopen = () => ws.send('Hello from client!');

With TLS enabled:

const ws = new WebSocket('wss://localhost:8443/');

All messages sent by any client are broadcast to every connected client (including the sender).

Build

make build      # Build binary → build/websocket-relay
make release    # Cross-compile linux/amd64 + darwin/arm64
make clean      # Remove build artifacts

Testing

make test       # Run all tests (unit + integration)

Metrics

When metrics.enabled is true, Prometheus metrics are exposed at http://localhost:9090/metrics:

Metric Type Description
websocket_connected_clients Gauge Currently connected clients
websocket_messages_total Counter Total messages relayed
websocket_connections_total Counter Total connections established
websocket_disconnections_total Counter Total disconnections

Graceful Shutdown

The server handles SIGINT and SIGTERM signals:

  1. Stops accepting new connections
  2. Sends WebSocket CloseGoingAway frame to all connected clients
  3. Closes all connections and exits cleanly

Shutdown timeout is 10 seconds.

Project Structure

websocket-relay/
├── main.go                  # Entry point, signal handling, graceful shutdown
├── internal/
│   ├── config/config.go     # YAML config loader
│   ├── hub/hub.go           # WebSocket hub, connection management, broadcast
│   ├── logging/logging.go   # Log output setup and leveled logger
│   └── metrics/metrics.go   # Prometheus metric definitions
├── example/index.html       # Browser P2P chat demo
├── config.yaml              # Runtime configuration
├── config.example.yaml      # Example config with TLS and logging
└── Makefile                 # Build, test, release commands

License

See repository for license details.

Description
A minimal Go WebSocket relay server with SSL support for P2P connections.
Readme 122 KiB
2025-08-02 21:31:35 +02:00
Languages
Go 86.2%
HTML 13.1%
Makefile 0.7%