Features¶
Complete overview of Signal Fish Server capabilities.
Room Management¶
Automatic Room Codes¶
Rooms are identified by auto-generated 6-character codes (configurable length).
Create a room by joining without a room code:
{
"type": "JoinRoom",
"data": {
"game_name": "my-game",
"player_name": "Player1",
"max_players": 8
}
}
Response:
{
"type": "RoomJoined",
"data": {
"room_code": "ABC123",
"room_id": "uuid-string",
"player_id": "your-player-id",
"game_name": "my-game",
"max_players": 8,
"supports_authority": true,
"current_players": [
{
"id": "your-player-id",
"name": "Player1",
"is_authority": false,
"is_ready": false,
"connected_at": "2025-01-15T10:30:00Z"
}
],
"is_authority": false,
"lobby_state": "waiting",
"ready_players": [],
"relay_type": "WebRTC",
"current_spectators": []
}
}
Players join using the room code:
{
"type": "JoinRoom",
"data": {
"game_name": "my-game",
"room_code": "ABC123",
"player_name": "Player2"
}
}
Room Limits¶
Configure per-game room limits:
When auth is enabled, per-app limits apply:
{
"security": {
"authorized_apps": [
{
"app_id": "my-game",
"max_rooms": 100,
"max_players_per_room": 16
}
]
}
}
Lobby State Machine¶
Rooms transition through three states based on player ready status:
Waiting¶
Initial state. Waiting for players to join until the room reaches
max_players. No ready-state toggles happen in this state.
Lobby¶
Room is full and players are coordinating readiness.
Finalized¶
All players are ready and the game is starting.
State Transitions¶
Waiting --> Lobby (room full)
Lobby --> Waiting (player leaves)
Lobby --> Finalized (all players ready)
Finalized --> [*] (game started, room cleanup)
Clients are notified of state changes:
{
"type": "LobbyStateChanged",
"data": {
"lobby_state": "finalized",
"ready_players": ["player-id-1", "player-id-2"],
"all_ready": true
}
}
Player Ready State¶
Players toggle their own ready state by sending PlayerReady:
Each PlayerReady send flips that player's ready/unready status and broadcasts
LobbyStateChanged. When all players are ready, the server sends
GameStarting.
Authority Management¶
Players can request game authority (e.g., for server-authoritative gameplay):
When granted, all players are notified:
{
"type": "AuthorityChanged",
"data": {
"authority_player": "player-id",
"you_are_authority": false
}
}
Only one player can hold authority at a time.
Spectator Mode¶
Join rooms as a spectator without participating in gameplay:
{
"type": "JoinAsSpectator",
"data": {
"game_name": "my-game",
"room_code": "ABC123",
"spectator_name": "Observer1"
}
}
Spectators:
- Don't count toward max_players
- Can't send
PlayerReady(cannot toggle readiness) - Receive all game data
- Don't participate in authority decisions
Reconnection¶
Token-based reconnection with event replay.
Disconnect and Token Generation¶
When a player disconnects, the server generates a reconnection token bound to their player ID and room ID. The server buffers room events during the disconnection window so they can be replayed on reconnect.
Reconnecting¶
If the connection is lost, reconnect using stored credentials:
{
"type": "Reconnect",
"data": {
"player_id": "your-player-id",
"room_id": "your-room-id",
"auth_token": "stored-token"
}
}
Event Replay¶
On successful reconnection, the server sends a Reconnected message with the current room state and replays any
events that occurred during the disconnection window.
Configuration¶
{
"server": {
"enable_reconnection": true,
"reconnection_window": 300,
"event_buffer_size": 100
}
}
Message Batching¶
Batch outbound messages for improved throughput.
batch_size- Max messages per batchbatch_interval_ms- Max time to wait before flushing
Batching is transparent to clients.
Rate Limiting¶
In-memory rate limiting for room creation and join attempts.
max_room_creations- Max rooms per IP per time windowtime_window- Window duration in secondsmax_join_attempts- Max join attempts per IP per window
When auth is enabled, per-app rate limits apply:
Metrics¶
JSON Metrics¶
Returns:
{
"active_rooms": 42,
"active_players": 156,
"total_rooms_created": 1024,
"total_messages_sent": 50000,
"uptime_seconds": 3600
}
Prometheus Metrics¶
Returns Prometheus text format for scraping.
Metrics Authentication¶
Protect metrics endpoints:
Access with:
Authentication¶
Optional app-based authentication with per-app limits.
{
"security": {
"require_websocket_auth": true,
"authorized_apps": [
{
"app_id": "my-game",
"app_secret": "secret-key",
"max_rooms": 100,
"max_players_per_room": 16,
"rate_limit_per_minute": 60
}
]
}
}
See Authentication for full details.
MessagePack Support¶
Enable MessagePack encoding for game data:
Game data messages can be sent in MessagePack format for reduced bandwidth.
CORS Support¶
Configure allowed origins:
Multiple origins (comma-separated):
Allow all (development only):
Connection Limits¶
Limit concurrent connections per IP:
Message Size Limits¶
Limit maximum WebSocket message size:
Messages exceeding this size are rejected.
Room Cleanup¶
Automatic cleanup of empty and inactive rooms:
{
"server": {
"room_cleanup_interval": 60,
"empty_room_timeout": 300,
"inactive_room_timeout": 3600
}
}
room_cleanup_interval- Seconds between cleanup sweepsempty_room_timeout- Seconds before empty room removalinactive_room_timeout- Seconds before inactive room removal
Ping/Pong¶
Keep-alive mechanism to detect dead connections:
Clients should send periodic Ping messages. Server disconnects clients that are silent for longer than ping_timeout.
Structured Logging¶
JSON-formatted structured logs for production observability:
{
"logging": {
"enable_file_logging": true,
"dir": "logs",
"filename": "server.log",
"rotation": "daily",
"format": "Json"
}
}
Zero External Dependencies¶
Everything runs in-memory:
- No database required
- No message broker
- No cloud services
- No external runtime dependencies
Perfect for:
- Local development
- LAN games
- Self-hosted deployments
- Embedded systems
Next Steps¶
- Getting Started - Quick start guide
- Protocol Reference - Complete message documentation
- Configuration - Full configuration options