ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
Discovery Service (ACDS)

🔍 ascii-chat Discovery Service for session management and NAT traversal More...

Modules

 ACDS Server
 đŸŒ Discovery server TCP connection manager
 
 ACDS Database
 đŸ’ž SQLite-based session management
 
 ACDS Signaling
 đŸŽŹ WebRTC SDP/ICE signaling relay
 
 ACDS Identity
 đŸ”‘ Ed25519 identity key management
 
 ACDS Session Strings
 đŸˇď¸ Human-friendly session string generation
 

Detailed Description

🔍 ascii-chat Discovery Service for session management and NAT traversal

ACDS enables clients to discover servers using memorable session strings, provides WebRTC signaling for P2P connections, and handles NAT traversal.

ascii-chat Discovery Service (ACDS)

Overview

Welcome to ACDS—the magic that makes ascii-chat "just work" without dealing with networking headaches!

The Problem: Running a video chat server should be as easy as starting a Zoom call. But networking is complicated:

  • Port forwarding: Most home routers block incoming connections, requiring manual router configuration
  • IP addresses: You need to know your public IP and communicate it to friends—tedious and error-prone
  • NAT traversal: Symmetric NAT makes peer-to-peer connections nearly impossible without help
  • Firewalls: Corporate and university networks often block non-standard ports

The ACDS Solution: Instead of dealing with IP addresses and ports, you get:

Three-word session strings like purple-mountain-lake that uniquely identify your session. Share those three words and people can join—no IP addresses, no port forwarding, no network configuration.

ACDS transforms ascii-chat from a LAN-only toy into a production-ready video conferencing system that works anywhere, for anyone.

Implementation: src/acds/*.c, lib/acds/*.c

What makes ACDS powerful?

  • Human-friendly: Share "happy-sunset-ocean" instead of "73.251.42.118:27224"
  • Automatic NAT traversal: Works behind firewalls without manual configuration
  • Fallback strategy: Tries best connection first (direct TCP), falls back gracefully (WebRTC/TURN)
  • mDNS for local: Zero-config on LANs—no internet/server required
  • Privacy-first: ACDS never sees your media—only exchanges connection metadata
  • Open protocol: Run your own ACDS server for complete privacy

Architecture

Core Components

ACDS consists of several tightly integrated components:

Discovery Server

File: src/acds/main.c, src/acds/server.c

The main ACDS server that:

  • Listens for TCP connections on port 27225 (default)
  • Handles session creation, lookup, and join requests
  • Relays WebRTC signaling (SDP offers/answers, ICE candidates)
  • Manages rate limiting to prevent abuse
  • Runs cleanup threads for expired sessions

Threading Model:

  • Main Thread: Accept loop using select() for responsive shutdown
  • Per-Client Handler Threads: One thread per connected client
  • Cleanup Thread: Background thread for rate limit and session expiration cleanup
  • Worker Pool: Thread pool for background tasks

Key Functions:

// Initialize ACDS server
// Run server (blocking until shutdown)
asciichat_error_t acds_server_run(acds_server_t *server);
// Graceful shutdown
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
void acds_server_shutdown(acds_server_t *server)
Shutdown discovery server.
asciichat_error_t acds_server_init(acds_server_t *server, const acds_config_t *config)
Initialize discovery server.
Discovery server configuration.
Discovery server state.

Session Database

File: lib/acds/database.c, lib/acds/database.h

SQLite-based session storage:

  • Sessions table: session_id, session_string, host_pubkey, password_hash, participants, capabilities
  • Participants table: participant_id, session_id, identity_pubkey, joined_at
  • Rate events table: IP address, event type, timestamp for rate limiting
  • WAL mode: Write-Ahead Logging for concurrent read performance

Database Schema:

CREATE TABLE sessions (
session_id BLOB PRIMARY KEY,
session_string TEXT UNIQUE NOT NULL,
host_pubkey BLOB NOT NULL,
password_hash TEXT,
max_participants INTEGER DEFAULT 4,
current_participants INTEGER DEFAULT 0,
capabilities INTEGER DEFAULT 3, -- video + audio
has_password INTEGER DEFAULT 0,
expose_ip_publicly INTEGER DEFAULT 0,
session_type INTEGER DEFAULT 0, -- DirectTCP or WebRTC
server_address TEXT,
server_port INTEGER DEFAULT 0,
created_at INTEGER NOT NULL,
expires_at INTEGER NOT NULL
);
CREATE TABLE participants (
participant_id BLOB PRIMARY KEY,
session_id BLOB NOT NULL,
identity_pubkey BLOB NOT NULL,
joined_at INTEGER NOT NULL,
FOREIGN KEY (session_id) REFERENCES sessions(session_id) ON DELETE CASCADE
);

Key Functions:

// Database lifecycle
asciichat_error_t database_init(const char *db_path, sqlite3 **db);
void database_close(sqlite3 *db);
// Session operations
const acds_config_t *config, acip_session_created_t *resp);
asciichat_error_t database_session_lookup(sqlite3 *db, const char *session_string,
const acds_config_t *config, acip_session_info_t *resp);
const acds_config_t *config, acip_session_joined_t *resp);
const uint8_t participant_id[16]);
// Maintenance
asciichat_error_t database_session_lookup(sqlite3 *db, const char *session_string, const acds_config_t *config, acip_session_info_t *resp)
Lookup session by string.
asciichat_error_t database_session_join(sqlite3 *db, const acip_session_join_t *req, const acds_config_t *config, acip_session_joined_t *resp)
Join existing session.
asciichat_error_t database_session_leave(sqlite3 *db, const uint8_t session_id[16], const uint8_t participant_id[16])
Leave session.
void database_close(sqlite3 *db)
Close database.
asciichat_error_t database_session_create(sqlite3 *db, const acip_session_create_t *req, const acds_config_t *config, acip_session_created_t *resp)
Create new session.
asciichat_error_t database_init(const char *db_path, sqlite3 **db)
Initialize database and create schema.
void database_session_cleanup_expired(sqlite3 *db)
Clean up inactive sessions.
acip_session_join_t
Definition acds.h:403
acip_session_joined_t
Definition acds.h:474
acip_session_created_t
Definition acds.h:269
acip_session_create_t
Definition acds.h:221
acip_session_info_t
Definition acds.h:355
unsigned char uint8_t
Definition common.h:56
uint8_t session_id[16]
uint8_t participant_id[16]

WebRTC Signaling

File: src/acds/signaling.c, src/acds/signaling.h

Pure relay server for WebRTC signaling—no media processing:

  • Relays SDP offers/answers between participants
  • Relays ICE candidates for P2P connection establishment
  • Supports unicast (to specific participant) and broadcast (to all in session)
  • Uses participant_id → socket mapping from TCP server registry

Key Functions:

// Relay SDP offer/answer
const acip_webrtc_sdp_t *sdp, size_t total_packet_len);
// Relay ICE candidate
const acip_webrtc_ice_t *ice, size_t total_packet_len);
// Broadcast to all participants in session
const uint8_t session_id[16], packet_type_t packet_type,
const void *packet, size_t packet_len);
acip_webrtc_ice_t
Definition acds.h:650
acip_webrtc_sdp_t
Definition acds.h:604
packet_type_t
Network protocol packet type enumeration.
Definition packet.h:286
asciichat_error_t signaling_broadcast(sqlite3 *db, tcp_server_t *tcp_server, const uint8_t session_id[16], packet_type_t packet_type, const void *packet, size_t packet_len, const uint8_t *exclude_participant_id)
Broadcast packet to all session participants.
Definition signaling.c:230
asciichat_error_t signaling_relay_ice(sqlite3 *db, tcp_server_t *tcp_server, const acip_webrtc_ice_t *ice, size_t total_packet_len)
Relay ICE candidate to recipient.
Definition signaling.c:187
asciichat_error_t signaling_relay_sdp(sqlite3 *db, tcp_server_t *tcp_server, const acip_webrtc_sdp_t *sdp, size_t total_packet_len)
Relay SDP offer/answer to recipient.
Definition signaling.c:139

Identity Management

File: lib/acds/identity.c, lib/acds/identity.h

Ed25519 identity key management for ACDS server:

  • Auto-generates identity key on first run
  • Loads existing key from ~/.config/ascii-chat/acds_identity
  • Computes SHA256 fingerprint for display
  • Cross-platform key storage (Unix and Windows paths)

Key Functions:

// Key lifecycle
asciichat_error_t acds_identity_generate(uint8_t public_key[32], uint8_t secret_key[64]);
asciichat_error_t acds_identity_load(const char *path, uint8_t public_key[32], uint8_t secret_key[64]);
asciichat_error_t acds_identity_save(const char *path, const uint8_t public_key[32],
const uint8_t secret_key[64]);
// Display
void acds_identity_fingerprint(const uint8_t public_key[32], char fingerprint[65]);
asciichat_error_t acds_identity_default_path(char *path_out, size_t path_size);
asciichat_error_t acds_identity_load(const char *path, uint8_t public_key[32], uint8_t secret_key[64])
Load identity from file.
Definition identity.c:31
asciichat_error_t acds_identity_default_path(char *path_out, size_t path_size)
Get default identity file path for current platform.
Definition identity.c:120
asciichat_error_t acds_identity_save(const char *path, const uint8_t public_key[32], const uint8_t secret_key[64])
Save identity to file.
Definition identity.c:60
void acds_identity_fingerprint(const uint8_t public_key[32], char fingerprint[65])
Compute SHA256 fingerprint of public key.
Definition identity.c:103
asciichat_error_t acds_identity_generate(uint8_t public_key[32], uint8_t secret_key[64])
Generate new Ed25519 keypair.
Definition identity.c:17

Session Strings

File: lib/acds/strings.c, lib/acds/strings.h

Human-friendly session identifier generation:

  • Format: adjective-noun-noun (e.g., bright-forest-river)
  • ~100 adjectives, ~100 nouns = 1,000,000+ unique combinations
  • Cryptographically random selection via libsodium
  • Easy to speak, remember, and type without errors

Key Functions:

// Initialize generator (requires sodium_init())
// Generate random session string
asciichat_error_t acds_string_generate(char *output, size_t output_size);
// Validate session string (format + dictionary)
bool is_session_string(const char *str);
asciichat_error_t acds_string_init(void)
Initialize session string system with cached word validation.
bool is_session_string(const char *str)
Check if a string is a valid session string.
asciichat_error_t acds_string_generate(char *output, size_t output_size)
Generate random session string.

Validation Rules (enforced by is_session_string()):

  • Only lowercase ASCII letters and hyphens allowed
  • Exactly 2 hyphens separating 3 words (adjective-noun-noun format)
  • First word must be a valid adjective from wordlist (2500 adjectives)
  • Second and third words must be valid nouns from wordlist (5000 nouns)
  • Each word is 2-12 characters
  • No consecutive hyphens
  • Cannot start or end with hyphen
  • Length 5-47 characters

Protocol

Packet Flow

ACDS uses the ACIP (ascii-chat Internet Protocol) packet format over TCP.

Session Creation Flow:

Server ACDS
| |
|--- ACIP_SESSION_CREATE --------------->| (identity, capabilities, max_participants)
| | [Rate limit check]
| | [Signature verification (optional)]
| | [IP reachability check (Direct TCP)]
| | [Generate session_string]
|<-- ACIP_SESSION_CREATED ---------------| (session_string, STUN/TURN servers)
| |

Session Join Flow:

Client ACDS
| |
|--- ACIP_SESSION_LOOKUP --------------->| (session_string)
| | [Rate limit check]
|<-- ACIP_SESSION_INFO ------------------| (found, capabilities, has_password)
| |
|--- ACIP_SESSION_JOIN ----------------->| (session_string, identity, password)
| | [Rate limit check]
| | [Signature verification (optional)]
| | [Password verification (if required)]
|<-- ACIP_SESSION_JOINED ----------------| (participant_id, server_address, TURN creds)
| |

WebRTC Signaling Flow:

Client A ACDS Client B
| | |
|--- WEBRTC_SDP ------>| | (SDP offer)
| |--- WEBRTC_SDP ---->| (relay to recipient)
| | |
| |<-- WEBRTC_SDP ----| (SDP answer)
|<-- WEBRTC_SDP -------| | (relay to sender)
| | |
|--- WEBRTC_ICE ------>| | (ICE candidates)
| |--- WEBRTC_ICE --->| (relay)
| | |

Packet Types

ACDS handles these ACIP packet types:

Packet Type Direction Description
ACIP_SESSION_CREATE Client→ACDS Create new session
ACIP_SESSION_CREATED ACDS→Client Session created response
ACIP_SESSION_LOOKUP Client→ACDS Query session info
ACIP_SESSION_INFO ACDS→Client Session info response
ACIP_SESSION_JOIN Client→ACDS Join existing session
ACIP_SESSION_JOINED ACDS→Client Join response with connection info
ACIP_SESSION_LEAVE Client→ACDS Leave session
ACIP_WEBRTC_SDP Client↔ACDS SDP offer/answer relay
ACIP_WEBRTC_ICE Client↔ACDS ICE candidate relay
ACIP_ERROR ACDS→Client Error response

NAT Traversal Technologies

ACDS leverages multiple NAT traversal techniques to maximize connectivity:

UPnP (Universal Plug and Play)

  • Works on ~70% of home routers
  • Automatic port forwarding via miniupnpc library
  • Enables direct TCP connections (lowest latency)
  • Server registers with --upnp flag

NAT-PMP (NAT Port Mapping Protocol)

  • Apple's alternative to UPnP
  • Common on Apple routers and some enterprise equipment
  • Also enables direct TCP connections
  • Supported via libnatpmp integration

WebRTC (ICE/STUN/TURN)

  • STUN: Discovers public IP/port mapping through NAT
  • ICE: Negotiates P2P connection through NAT using candidate gathering
  • TURN: Provides relay fallback when P2P fails (always succeeds, higher latency)
  • WebRTC DataChannels provide reliable data transfer

Connection Priority:

  1. Direct TCP (if UPnP/NAT-PMP succeeded) — Best latency
  2. WebRTC P2P (via ICE/STUN) — Good latency, works behind most NATs
  3. TURN relay (fallback) — Higher latency, always works

mDNS Support (Local Network Discovery)

ACDS also supports mDNS (multicast DNS) for local network discovery:

# Server announces on local network
ascii-chat server --mdns
# Client discovers servers automatically
ascii-chat client --mdns

How it works:

  • ACDS server advertises as _ascii-chat-discovery-service._tcp.local
  • Clients can discover ACDS servers on the LAN without knowing their IP
  • Zero-configuration for local sessions
  • No internet connectivity required

Security

Identity Verification

ACDS supports optional Ed25519 identity verification:

Server Identity (--require-server-identity):

  • Servers must sign their SESSION_CREATE request with Ed25519
  • Prevents impersonation attacks
  • Signature covers: timestamp, capabilities, max_participants

Client Identity (--require-client-identity):

  • Clients must sign their SESSION_JOIN request with Ed25519
  • Enables client whitelisting
  • Signature covers: timestamp, session_string

Timestamp Validation:

  • All signed requests include Unix timestamp
  • 5-minute window for replay attack protection
  • Prevents captured requests from being replayed later

Privacy Protection

IP Address Protection:

  • By default, server IP is NOT revealed to clients
  • IP revealed only when:
    • Password authentication succeeds, OR
    • Server explicitly opts in with expose_ip_publicly flag
  • Prevents IP harvesting attacks

ACDS Never Sees Media:

  • Only exchanges connection metadata (IPs, ports, session strings)
  • All media flows directly between peers using ACIP encryption
  • ACDS doesn't decrypt, proxy, or store media content

Rate Limiting

ACDS implements rate limiting to prevent abuse:

  • SESSION_CREATE: Max 10 per hour per IP
  • SESSION_LOOKUP: Max 60 per minute per IP
  • SESSION_JOIN: Max 30 per minute per IP
  • Events stored in SQLite with automatic cleanup (1 hour retention)
  • Rate limit exceeded returns ACIP_ERROR packet

Configuration

Command-Line Options

Run ascii-chat discovery-server --help for complete options:

Network Options:

  • -p --port PORT: TCP listen port (default: 27225)
  • [address] [address]: IPv4 and/or IPv6 bind addresses (default: 127.0.0.1 ::1)

Database & Identity:

  • -d --database PATH: SQLite database file path (default: ~/.config/ascii-chat/acds.db)
  • -k --key PATH: Ed25519 identity key file path (default: ~/.config/ascii-chat/acds_identity)

Security Policies:

  • -S --require-server-identity: Require servers to provide signed identity
  • -C --require-client-identity: Require clients to provide signed identity
  • -V --require-server-verify: Require servers to verify client identity during handshake
  • -c --require-client-verify: Require clients to verify server identity during handshake

WebRTC Configuration:

  • --stun-servers LIST: Comma-separated STUN server URLs
  • --turn-servers LIST: Comma-separated TURN server URLs
  • --turn-username USER: Username for TURN server authentication
  • --turn-credential PASS: Credential/password for TURN server authentication
  • --turn-secret SECRET: Shared secret for dynamic TURN credential generation (HMAC-SHA1)
  • --upnp: Enable UPnP/NAT-PMP for automatic router port mapping

Usage Examples

# Run discovery server on all interfaces
ascii-chat discovery-server 0.0.0.0 :: --port 27225
# Run with custom database and identity key
ascii-chat discovery-server --database /var/lib/acds/sessions.db --key /etc/acds/identity.key
# Run with strict identity requirements
ascii-chat discovery-server --require-server-identity --require-client-identity
# Run with debug logging
ascii-chat -V --log-level debug discovery-server --port 27225
# Run with custom STUN/TURN servers
ascii-chat discovery-server \
--stun-servers "stun:stun.example.com:3478,stun:stun.l.google.com:19302" \
--turn-servers "turn:turn.example.com:3478" \
--turn-username myuser --turn-credential mypassword

Integration with Client and Server

Server Integration

When starting an ascii-chat server with ACDS registration:

# Server registers with ACDS and gets a session string
ascii-chat server --acds --acds-server acds.example.com --acds-port 27225
# Server displays session string for users to share
# "Session: happy-sunset-ocean"

Server Registration Process:

  1. Server sends ACIP_SESSION_CREATE to ACDS
  2. ACDS generates unique session_string and stores session info
  3. ACDS returns session_string and STUN/TURN servers
  4. Server displays session_string to user
  5. Server maintains keepalive with ACDS

Client Integration

When connecting to an ascii-chat server via ACDS:

# Client looks up session and connects
ascii-chat client happy-sunset-ocean
# Or with explicit ACDS server
ascii-chat client happy-sunset-ocean --acds-server acds.example.com

Client Connection Process:

  1. Client sends ACIP_SESSION_LOOKUP to ACDS
  2. If session found, client sends ACIP_SESSION_JOIN
  3. ACDS returns server address/port (if allowed) or TURN credentials
  4. Client attempts connection:
    • Direct TCP to server_address:server_port (if available)
    • WebRTC P2P via ICE/STUN (if direct fails)
    • TURN relay (fallback)

Error Handling

ACDS returns standardized error codes via ACIP_ERROR packets:

Error Code Meaning
ERROR_SESSION_NOT_FOUND Invalid session string
ERROR_SESSION_FULL Session at max capacity
ERROR_INVALID_PASSWORD Password verification failed
ERROR_CRYPTO_VERIFICATION Signature verification failed
ERROR_RATE_LIMITED Too many requests from IP
ERROR_INVALID_PARAM Malformed request

ACDS Deployment & Operation

Official ACDS Infrastructure

The official ACDS infrastructure consists of two components:

  1. discovery.ascii-chat.com - Public key distribution website (HTTPS)
  2. discovery-service.ascii-chat.com:27225 - ACDS server (TCP)

Public Key Distribution via HTTPS (discovery.ascii-chat.com):

  • SSH Ed25519 public key: https://discovery.ascii-chat.com/key.pub (OpenSSH format)
  • GPG public key: https://discovery.ascii-chat.com/key.gpg (GPG export format)
  • Both key types are provided as a convenience - clients can use either
  • Keys served over HTTPS for integrity and authenticity
  • HTML landing page displays key fingerprints and usage instructions
  • Plaintext rendering allows users to verify keys manually before downloading

ACDS Server (discovery-service.ascii-chat.com:27225):

  • Default ACDS server address built into ascii-chat client
  • Handles session creation, lookup, join, and WebRTC signaling
  • Operates transparently - no manual configuration needed
  • Uses the Ed25519 keys published at discovery.ascii-chat.com

Client Trust Model:

  • ascii-chat client automatically trusts keys downloaded from discovery.ascii-chat.com over HTTPS
  • Connects to discovery-service.ascii-chat.com:27225 by default for ACDS operations
  • Keys are cached locally and trusted for subsequent connections
  • User verification required if ACDS keys ever change (prevents MITM attacks)
  • Alternative: Users can manually specify ACDS server and keys via command-line flags

Default Behavior (no flags needed):

# Client automatically uses discovery-service.ascii-chat.com:27225
# and trusts keys from discovery.ascii-chat.com
ascii-chat client happy-sunset-ocean
# Or explicitly specify ACDS server and key
ascii-chat client happy-sunset-ocean \
--acds-server discovery-service.ascii-chat.com \
--acds-key https://discovery.ascii-chat.com/key.pub

Manual Key Specification (optional):

# Download and verify SSH key
curl -O https://discovery.ascii-chat.com/key.pub
ssh-keygen -lf key.pub # Verify fingerprint
# Use local key file
ascii-chat client happy-sunset-ocean \
--acds-key ~/.config/ascii-chat/acds_known_keys/discovery.ascii-chat.com.pub

Running Your Own ACDS Server

If you want to run your own ACDS instance for privacy or custom deployments, you should follow the same pattern as the official server:

Public Key Hosting via HTTPS (Required for public ACDS servers):

To make your ACDS server usable by clients, you must host at least one public key over HTTPS at a URL of your choice:

  • Host your ACDS key (SSH Ed25519 or GPG) at any HTTPS URL
  • Examples: https://your-domain.com/acds-key.pub (SSH) or https://your-domain.com/acds.gpg (GPG)
  • You can provide both SSH and GPG keys (like the official server) or just one type
  • HTTPS is required - HTTP is not acceptable for key distribution
  • Serve keys as plaintext so users can verify them in their browser
  • Provide an HTML landing page with key fingerprints and usage instructions

Why HTTPS Key Hosting is Critical:

For third-party ACDS servers, ascii-chat clients will not work unless they can:

  1. Download your public key from your HTTPS URL, OR
  2. Be manually configured with your public key file via --acds-key flag

Note: The official discovery.ascii-chat.com server is special-cased in the client - it automatically trusts keys downloaded from that domain over HTTPS. Your ACDS server will require explicit client configuration.

Client Configuration for Custom ACDS:

Clients connecting to your ACDS server must explicitly trust your key:

# Method 1: Download SSH key from your HTTPS endpoint (recommended)
ascii-chat client session-name \
--acds-server acds.example.com \
--acds-key https://acds.example.com/acds-key.pub
# Or download GPG key from your HTTPS endpoint
ascii-chat client session-name \
--acds-server acds.example.com \
--acds-key https://acds.example.com/acds.gpg
# Method 2: Distribute key file to users manually
ascii-chat client session-name \
--acds-server acds.example.com \
--acds-key /path/to/acds-example-com.pub

IMPORTANT: Without the --acds-key flag, ascii-chat will not connect to third-party ACDS servers. Only the official discovery.ascii-chat.com server has automatic HTTPS key trust built into the client.

Best Practices

For Public ACDS Operators:

  • Host at least one public key (SSH or GPG) over HTTPS - this is mandatory for clients to use your server
  • You can provide both SSH and GPG keys (like discovery.ascii-chat.com) or just one type
  • Serve keys as plaintext for easy browser verification
  • Display key fingerprints on your HTML landing page
  • Document the --acds-key https://your-domain.com/path/to/key flag usage for your server
  • Clients must explicitly configure your key - only discovery.ascii-chat.com has automatic trust
  • Enable identity requirements for production (--require-server-identity, --require-client-identity)
  • Monitor rate limit events for abuse detection
  • Configure appropriate STUN/TURN servers for your region
  • Regular database backups (SQLite file)
  • Consider key rotation policies (with advance user notification)

For Private ACDS Operators (Corporate/Organizational):

  • Distribute ACDS public key via internal documentation or HTTPS
  • Require client/server identity verification (--require-*-identity flags)
  • Run ACDS on internal network (no public internet exposure)
  • Use mDNS for local network discovery where appropriate
  • Implement monitoring and alerting for session activity

For Server Hosts:

  • Enable --upnp for automatic port forwarding
  • Use identity keys for server authentication
  • Consider password-protecting sensitive sessions
  • Don't expose IP publicly unless necessary

For Clients:

  • Verify server identity when possible (--server-key)
  • Use identity keys for authenticated sessions
  • Prefer local mDNS discovery on trusted networks

Service Lifecycle

The ACDS server follows a well-defined lifecycle with distinct phases:

Initialization Phase

Entry Point: acds_main() in src/discovery-service/main.c

Initialization sequence:

  1. Signal Handling: Register SIGINT/SIGTERM handlers for graceful shutdown
  2. Global Context: Initialize global server instance and UPnP/mDNS contexts
  3. Server Initialization: Call acds_server_init()
    • Load or generate Ed25519 identity keys (stored in ~/.config/ascii-chat/acds_identity)
    • Open SQLite database (~/.config/ascii-chat/acds.db by default)
    • Create database schema if missing
    • Initialize rate limiter
    • Bind TCP socket(s) to configured addresses
    • Enable UPnP/NAT-PMP port mapping if requested
    • Register mDNS service if enabled
  4. Thread Pool: Create worker thread pool for background tasks
  5. Cleanup Thread: Spawn background cleanup thread
  6. Status Screen: Initialize optional discovery status UI

Running Phase

Main Loop: acds_server_run() in src/discovery-service/server.c

Server runs in an accept loop that:

  1. Accept Loop: Use select()-based multiplexing to accept client connections
  2. Per-Client Handler: Spawn a handler thread for each connected client
  3. Client Processing:
    • Perform crypto handshake (using shared lib/crypto/ infrastructure)
    • Enter packet dispatch loop
    • Process incoming ACIP packets:
      • SESSION_CREATE/LOOKUP/JOIN - routed to lib/discovery/database.c
      • WEBRTC_SDP/ICE - routed to signaling relay
      • Invalid packets rejected with error response
  4. Connection Cleanup: Remove from client registry on disconnect
  5. Background Tasks:
    • Cleanup thread runs every 5 minutes
    • Removes old rate limit events from database
    • Cleans up expired sessions
    • Monitors host migrations with timeout detection

Shutdown Phase

Graceful Shutdown: Triggered by SIGINT/SIGTERM or application request

Shutdown sequence in acds_server_shutdown():

  1. Signal Main Loop: Set server->tcp_server.running = false
  2. Stop Accepting: Close listen socket (pending accepts fail)
  3. Wait for Handlers: All per-client handler threads exit
  4. Stop Workers: Signal worker thread pool to shutdown
  5. Database Cleanup: Checkpoint and close SQLite database
  6. Resource Cleanup:
    • Release UPnP/NAT-PMP port mappings
    • Deregister mDNS service
    • Free thread pool and memory
  7. Status Display: Shutdown status screen UI

Persistence and Data Management

SQLite as Single Source of Truth

ACDS uses SQLite as the authoritative storage for all persistent data:

Sessions Table (sessions):

  • Indexed by 16-byte session_id (UUID)
  • Stores session metadata: string, host pubkey, capabilities, participant count, max participants
  • Tracks expiration time for automatic cleanup
  • Records whether IP is publicly exposed
  • Stores server address/port for Direct TCP connections

Participants Table (participants):

  • Indexed by 16-byte participant_id (UUID)
  • Foreign key reference to session_id
  • Cascade delete when session expires
  • Stores participant's Ed25519 identity pubkey
  • Records join timestamp

Rate Limit Events Table (rate_events):

  • Tracks request events for rate limiting (IP address, event type, timestamp)
  • Automatic cleanup removes events older than 1 hour
  • Prevents abuse through per-IP rate limiting:
    • SESSION_CREATE: 10 per hour
    • SESSION_LOOKUP: 60 per minute
    • SESSION_JOIN: 30 per minute

Database Features:

  • WAL (Write-Ahead Logging) mode for concurrent read performance
  • Synchronous writes for data integrity
  • Automatic schema migration on first run
  • Efficient queries with proper indexing

Multi-Key Session Creation

ACDS supports multi-key session creation - servers can register with multiple identity keys (e.g., SSH + GPG) in a single session.

Protocol (defined in server.h):

  1. Client sends SESSION_CREATE with first key
    • ACDS generates session_id and stores in pending_session
    • Client enters multi-key creation state: in_multikey_session_create = true
  2. Client sends SESSION_CREATE with second key
    • Key added to pending_session_keys[] array
    • Duplicate detection prevents adding same key twice
  3. Client sends SESSION_CREATE with zero key (empty key field)
    • Finalizes session creation
    • All keys in pending_session_keys[] written to database
    • Session exits multi-key state

Implementation (acds_client_data_t in server.h):

  • in_multikey_session_create: State flag
  • pending_session: Session data from first CREATE request
  • pending_session_keys[]: Array of Ed25519 public keys (up to MAX_IDENTITY_KEYS)
  • num_pending_keys: Count of keys received so far

Restrictions During Multi-Key Creation:

  • Only PING/PONG packets allowed (other commands rejected)
  • Prevents interleaving with other session operations
  • Timeout after 5 minutes automatically clears pending state

Host Migration Management

ACDS tracks host migration events when a session changes its host server.

Migration Tracking (migration_context_t in server.h):

  • session_id: Session undergoing migration
  • migration_start_ns: When migration started (nanoseconds)
  • Array of up to 32 concurrent migrations

Migration Process:

  1. Host picks a future host (every 5 minutes proactively)
  2. Host notifies ACDS of pending migration
  3. New host connects to ACDS and takes over session
  4. ACDS updates database with new host
  5. Migration context tracked until completion
  6. Timeout (configurable, typically 30 seconds) marks migration as failed
  7. database_session_clear_host() clears host on timeout

Cleanup Thread Monitoring (monitor_host_migrations()):

Peer Discovery Integration

ACDS provides both server-side discovery service and integrates with client-side peer discovery:

Server-Side Discovery Service

The ACDS server (src/discovery-service/) enables:

  1. Session Registration: Servers register via SESSION_CREATE
  2. Session Lookup: Clients find servers via SESSION_LOOKUP/SESSION_INFO
  3. Session Join: Clients join via SESSION_JOIN
  4. Fallback Coordination: ACDS provides STUN/TURN servers for WebRTC fallback
  5. Metadata Relay: Participants can relay SDP/ICE through ACDS

Client-Side Discovery Integration

ascii-chat clients use ACDS for:

  1. Session String Resolution: Convert "happy-sunset-ocean" → session metadata
  2. NAT Traversal: Obtain STUN/TURN servers from ACDS
  3. Signaling Relay: Optional relay of WebRTC signaling through ACDS
  4. Address Resolution: Get server address (if allowed) for Direct TCP

Client Connection Sequence:

Client ACDS Server
| | |
|--- SESSION_LOOKUP->| |
|<-- SESSION_INFO ---| |
|--- SESSION_JOIN --->| |
| |-- [identity check]-|
|<-- SESSION_JOINED -| |
|<-- STUN/TURN list -| |
| | |
|-- Try Direct TCP ------->| (if addr provided)
|-- Try WebRTC P2P ------->| (via ICE/STUN)
|-- Try TURN relay ------->| (fallback)

mDNS Local Discovery

ACDS also integrates with mDNS for local network discovery:

  • Server registers as _ascii-chat-discovery-service._tcp.local
  • Clients can discover servers without knowing their IP
  • Useful for LANs where no internet connectivity is available
  • Zero-configuration for local sessions

Implementation Files

Source Files (src/discovery-service/):

  • main.c - ACDS entry point, signal handling, initialization, main loop
  • main.h - Configuration structures and entry point declaration
  • server.c - TCP server implementation, client handlers, migration tracking, cleanup
  • server.h - Server structures, per-client state, migration context
  • signaling.c - WebRTC SDP/ICE relay implementation
  • signaling.h - Signaling relay function declarations

Library Files (lib/discovery/):

  • database.c/h - SQLite operations, session lifecycle, rate limiting
  • session.c - Session data structure helpers
  • identity.c/h - Ed25519 key generation, loading, saving, fingerprinting
  • strings.c/h - Session string generation (adjective-noun-noun)
  • adjectives.c/nouns.c - Word lists for session string generation

Network Protocol (lib/network/acip/):

  • acds.c - ACDS packet parsing and type definitions
  • acds_handlers.c - Packet type handlers (SESSION_*, WEBRTC_*)
  • acds_client.c - Client-side ACDS protocol helpers
  • send.c - ACDS packet sending helpers
  • Transport abstraction uses lib/network/tcp/ for connection handling

Rate Limiting (lib/network/rate_limit/):

See also
Network Protocol
Cryptographic Handshake
Server Architecture
Client Architecture