ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
Acds

Enumerations

enum  acds_session_type_t { SESSION_TYPE_DIRECT_TCP = 0 , SESSION_TYPE_WEBRTC = 1 }
 Session connection type. More...
 

ACDS Discovery Mode Messages (Host Negotiation & Migration)

enum  acip_nat_type_t {
  ACIP_NAT_TYPE_OPEN = 0 , ACIP_NAT_TYPE_FULL_CONE = 1 , ACIP_NAT_TYPE_RESTRICTED = 2 , ACIP_NAT_TYPE_PORT_RESTRICTED = 3 ,
  ACIP_NAT_TYPE_SYMMETRIC = 4
}
 NAT type classification for host selection. More...
 
enum  acip_connection_type_t { ACIP_CONNECTION_TYPE_DIRECT_PUBLIC = 0 , ACIP_CONNECTION_TYPE_UPNP = 1 , ACIP_CONNECTION_TYPE_STUN = 2 , ACIP_CONNECTION_TYPE_TURN = 3 }
 Connection type for host announcement. More...
 
 acip_nat_quality_t
 
 acip_host_announcement_t
 
 acip_host_designated_t
 
 acip_host_lost_t
 
 acip_future_host_elected_t
 

ACDS Error Handling

enum  acip_error_code_t {
  ACIP_ERROR_NONE = 0 , ACIP_ERROR_SESSION_NOT_FOUND = 1 , ACIP_ERROR_SESSION_FULL = 2 , ACIP_ERROR_INVALID_PASSWORD = 3 ,
  ACIP_ERROR_INVALID_SIGNATURE = 4 , ACIP_ERROR_RATE_LIMITED = 5 , ACIP_ERROR_STRING_TAKEN = 6 , ACIP_ERROR_STRING_INVALID = 7 ,
  ACIP_ERROR_INTERNAL = 255
}
 ACIP error codes. More...
 
 acip_error_t
 
 acip_bandwidth_test_t
 
 acip_bandwidth_result_t
 
 acip_broadcast_ack_t
 

ACDS Session Management Messages

 acip_session_create_t
 
 acip_session_created_t
 
 acip_session_lookup_t
 
 acip_session_info_t
 
 acip_session_join_t
 
 acip_session_joined_t
 
 acip_participant_joined_t
 
 acip_participant_left_t
 
 acip_session_leave_t
 
 acip_session_end_t
 
 acip_session_reconnect_t
 
struct __attribute__ ((packed))
 SESSION_CREATE (PACKET_TYPE_ACIP_SESSION_CREATE) - Create new session.
 

ACDS WebRTC Signaling Messages

 acip_webrtc_sdp_t
 
 acip_webrtc_ice_t
 

ACDS String Reservation Messages (Future)

 acip_string_reserve_t
 
 acip_string_reserved_t
 
 acip_string_renew_t
 
 acip_string_release_t
 

ACDS Ring Consensus Protocol (New P2P Design)

NEW ARCHITECTURE: Proactive future host election every 5 minutes. Participants form a virtual ring and rotate who collects NAT data. Every 5 minutes, a new "quorum leader" emerges with complete knowledge and elects the future host. This pre-elected host is announced to all participants so they know who will take over if current host dies.

Benefits:

  • No election delay when host dies (future host already known)
  • Fresh NAT data every 5 minutes (not stale)
  • Automatic rotation ensures fair load (each participant gets a turn)
  • Ring topology enables P2P coordination without central ACDS
 acip_participant_list_t
 
 acip_participant_entry_t
 
 acip_ring_collect_t
 

ACDS Protocol Constants

#define ACIP_MAX_SESSION_STRING_LEN   48
 Maximum session string length (e.g., "swift-river-mountain" = 20 chars)
 
#define ACIP_SESSION_EXPIRATION_MS   (24ULL * 60 * 60 * 1000)
 Session maximum lifetime (24 hours in milliseconds) Note: Sessions are actually cleaned up after 3 hours of inactivity (last_activity_at), but expires_at serves as an absolute maximum lifetime.
 
#define ACIP_DISCOVERY_DEFAULT_PORT   OPT_ACDS_PORT_INT_DEFAULT
 Discovery server default port (use OPT_ACDS_PORT_INT_DEFAULT from options.h)
 
#define ACIP_HOST_DEFAULT_PORT   OPT_PORT_INT_DEFAULT
 Default port for discovery mode hosts (use OPT_PORT_INT_DEFAULT from options.h)
 
#define ACDS_OFFICIAL_SERVER_HOSTNAME   "discovery-service.ascii-chat.com"
 Official ACDS server hostname (automatic HTTPS key trust)
 

Detailed Description

This module defines the binary message formats for the ACIP discovery protocol. All messages use packed structs sent over TCP using the existing ACIP packet infrastructure (packet_header_t + payload).

ACDS Protocol Specification

Protocol Overview

Packet Header Format (22 bytes)

Offset Size Field Value/Description
------ ---- ----- -----------------
0 8 magic 0xA5C11C4A1 ("ASCIICHAT" in hex)
8 2 type 6000-6199 (ACIP packet type enum)
10 4 length Payload length (0-2097152 bytes)
14 4 crc32 CRC32 of payload bytes only
18 4 client_id Client identifier (0 if not assigned)
------
Total: 22 bytes + payload_length bytes

Version Information

Session Lifecycle

Creation Phase:

  1. Client sends SESSION_CREATE (host public key + signature)
  2. Server generates session_id, expires_at (now + 24hrs)
  3. Server returns SESSION_CREATED (session_id, session_string, STUN/TURN servers)

Discovery Phase:

  1. Client sends SESSION_LOOKUP (session_string)
  2. Server returns SESSION_INFO (metadata, but NOT server IP/port)

Join Phase:

  1. Client sends SESSION_JOIN (credentials: password or Ed25519 signature)
  2. Server verifies credentials in database
  3. Server returns SESSION_JOINED (server IP/port, TURN credentials)
  4. Server broadcasts PARTICIPANT_JOINED to all session members

P2P Negotiation (Discovery mode only):

  1. Participants exchange WEBRTC_SDP (offers/answers)
  2. Participants exchange WEBRTC_ICE (candidates)
  3. Peers discover NAT quality, elect host, establish P2P connection

Disconnect Phase:

  1. Client sends SESSION_LEAVE
  2. Server removes participant from roster
  3. Server broadcasts PARTICIPANT_LEFT to remaining members
  4. Server sends SESSION_END when last participant leaves

Authentication Methods

Field Meanings

PROTOCOL DESIGN:

MESSAGE STRUCTURE:

All ACDS messages follow the standard ACIP packet structure:

INTEGRATION WITH OTHER MODULES:

Note
All structures are packed with attribute((packed)) for wire format.
Payload sizes include both fixed and variable-length portions.
String fields are null-terminated UTF-8 (not length-prefixed)
UUID fields are 16 bytes of raw binary data (not ASCII strings)
All numeric fields are little-endian
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026
Version
1.0 (ACIP/ACDS Protocol Specification)

Macro Definition Documentation

◆ ACDS_OFFICIAL_SERVER_HOSTNAME

#define ACDS_OFFICIAL_SERVER_HOSTNAME   "discovery-service.ascii-chat.com"

#include <acds.h>

Official ACDS server hostname (automatic HTTPS key trust)

Used by:

Single source of truth to avoid duplication across headers.

Definition at line 1107 of file acds.h.

◆ ACIP_DISCOVERY_DEFAULT_PORT

#define ACIP_DISCOVERY_DEFAULT_PORT   OPT_ACDS_PORT_INT_DEFAULT

#include <acds.h>

Discovery server default port (use OPT_ACDS_PORT_INT_DEFAULT from options.h)

Definition at line 1094 of file acds.h.

◆ ACIP_HOST_DEFAULT_PORT

#define ACIP_HOST_DEFAULT_PORT   OPT_PORT_INT_DEFAULT

#include <acds.h>

Default port for discovery mode hosts (use OPT_PORT_INT_DEFAULT from options.h)

Definition at line 1097 of file acds.h.

◆ ACIP_MAX_SESSION_STRING_LEN

#define ACIP_MAX_SESSION_STRING_LEN   48

#include <acds.h>

Maximum session string length (e.g., "swift-river-mountain" = 20 chars)

Definition at line 1085 of file acds.h.

◆ ACIP_SESSION_EXPIRATION_MS

#define ACIP_SESSION_EXPIRATION_MS   (24ULL * 60 * 60 * 1000)

#include <acds.h>

Session maximum lifetime (24 hours in milliseconds) Note: Sessions are actually cleaned up after 3 hours of inactivity (last_activity_at), but expires_at serves as an absolute maximum lifetime.

Definition at line 1091 of file acds.h.

Enumeration Type Documentation

◆ acds_session_type_t

#include <acds.h>

Session connection type.

Determines how clients connect to the session host:

  • DIRECT_TCP: Clients connect directly to server IP:port (default, requires public IP)
  • WEBRTC: Clients use WebRTC P2P mesh with STUN/TURN (works behind NAT)
Enumerator
SESSION_TYPE_DIRECT_TCP 

Direct TCP connection to server IP:port (default)

SESSION_TYPE_WEBRTC 

WebRTC P2P mesh with STUN/TURN relay.

Definition at line 144 of file acds.h.

144 {
acds_session_type_t
Session connection type.
Definition acds.h:144
@ SESSION_TYPE_WEBRTC
WebRTC P2P mesh with STUN/TURN relay.
Definition acds.h:146
@ SESSION_TYPE_DIRECT_TCP
Direct TCP connection to server IP:port (default)
Definition acds.h:145

◆ acip_connection_type_t

#include <acds.h>

Connection type for host announcement.

Enumerator
ACIP_CONNECTION_TYPE_DIRECT_PUBLIC 

Direct public IP connection.

ACIP_CONNECTION_TYPE_UPNP 

UPnP/NAT-PMP port mapping.

ACIP_CONNECTION_TYPE_STUN 

STUN hole-punching.

ACIP_CONNECTION_TYPE_TURN 

TURN relay (fallback)

Definition at line 837 of file acds.h.

837 {
acip_connection_type_t
Connection type for host announcement.
Definition acds.h:837
@ ACIP_CONNECTION_TYPE_TURN
TURN relay (fallback)
Definition acds.h:841
@ ACIP_CONNECTION_TYPE_UPNP
UPnP/NAT-PMP port mapping.
Definition acds.h:839
@ ACIP_CONNECTION_TYPE_DIRECT_PUBLIC
Direct public IP connection.
Definition acds.h:838
@ ACIP_CONNECTION_TYPE_STUN
STUN hole-punching.
Definition acds.h:840

◆ acip_error_code_t

#include <acds.h>

ACIP error codes.

Standard error codes returned in ACIP error responses.

Enumerator
ACIP_ERROR_NONE 

No error (success)

ACIP_ERROR_SESSION_NOT_FOUND 

Session does not exist.

ACIP_ERROR_SESSION_FULL 

Session has reached max participants.

ACIP_ERROR_INVALID_PASSWORD 

Password verification failed.

ACIP_ERROR_INVALID_SIGNATURE 

Identity signature invalid.

ACIP_ERROR_RATE_LIMITED 

Too many requests from this IP.

ACIP_ERROR_STRING_TAKEN 

Requested string already reserved.

ACIP_ERROR_STRING_INVALID 

String format invalid.

ACIP_ERROR_INTERNAL 

Internal server error.

Definition at line 1064 of file acds.h.

1064 {
1065 ACIP_ERROR_NONE = 0,
1073 ACIP_ERROR_INTERNAL = 255
acip_error_code_t
ACIP error codes.
Definition acds.h:1064
@ ACIP_ERROR_RATE_LIMITED
Too many requests from this IP.
Definition acds.h:1070
@ ACIP_ERROR_STRING_TAKEN
Requested string already reserved.
Definition acds.h:1071
@ ACIP_ERROR_STRING_INVALID
String format invalid.
Definition acds.h:1072
@ ACIP_ERROR_INTERNAL
Internal server error.
Definition acds.h:1073
@ ACIP_ERROR_INVALID_PASSWORD
Password verification failed.
Definition acds.h:1068
@ ACIP_ERROR_SESSION_NOT_FOUND
Session does not exist.
Definition acds.h:1066
@ ACIP_ERROR_SESSION_FULL
Session has reached max participants.
Definition acds.h:1067
@ ACIP_ERROR_INVALID_SIGNATURE
Identity signature invalid.
Definition acds.h:1069
@ ACIP_ERROR_NONE
No error (success)
Definition acds.h:1065

◆ acip_nat_type_t

#include <acds.h>

NAT type classification for host selection.

Enumerator
ACIP_NAT_TYPE_OPEN 

No NAT (public IP)

ACIP_NAT_TYPE_FULL_CONE 

Full cone NAT (easiest to traverse)

ACIP_NAT_TYPE_RESTRICTED 

Address-restricted cone NAT.

ACIP_NAT_TYPE_PORT_RESTRICTED 

Port-restricted cone NAT.

ACIP_NAT_TYPE_SYMMETRIC 

Symmetric NAT (hardest, requires TURN)

Definition at line 825 of file acds.h.

825 {
acip_nat_type_t
NAT type classification for host selection.
Definition acds.h:825
@ ACIP_NAT_TYPE_RESTRICTED
Address-restricted cone NAT.
Definition acds.h:828
@ ACIP_NAT_TYPE_SYMMETRIC
Symmetric NAT (hardest, requires TURN)
Definition acds.h:830
@ ACIP_NAT_TYPE_FULL_CONE
Full cone NAT (easiest to traverse)
Definition acds.h:827
@ ACIP_NAT_TYPE_OPEN
No NAT (public IP)
Definition acds.h:826
@ ACIP_NAT_TYPE_PORT_RESTRICTED
Port-restricted cone NAT.
Definition acds.h:829

Function Documentation

◆ __attribute__()

struct __attribute__ ( (packed)  )

#include <acds.h>

SESSION_CREATE (PACKET_TYPE_ACIP_SESSION_CREATE) - Create new session.

BROADCAST_ACK (PACKET_TYPE_ACIP_BROADCAST_ACK) - Acknowledge broadcast receipt.

Bandwidth test result packet.

Bandwidth test request packet.

ERROR (PACKET_TYPE_ACIP_ERROR) - Generic error response.

FUTURE_HOST_ELECTED (PACKET_TYPE_ACIP_FUTURE_HOST_ELECTED) - Future host announcement.

HOST_LOST (PACKET_TYPE_ACIP_HOST_LOST) - Host disconnect notification.

HOST_DESIGNATED (PACKET_TYPE_ACIP_HOST_DESIGNATED) - Host assignment.

HOST_ANNOUNCEMENT (PACKET_TYPE_ACIP_HOST_ANNOUNCEMENT) - Host declaration.

NETWORK_QUALITY (PACKET_TYPE_ACIP_NETWORK_QUALITY) - Unified quality metrics.

RING_COLLECT (PACKET_TYPE_ACIP_RING_COLLECT) - NAT quality request.

Participant entry in ring (variable-length data following PARTICIPANT_LIST)

PARTICIPANT_LIST (PACKET_TYPE_ACIP_PARTICIPANT_LIST) - Ordered ring list.

STRING_RELEASE (PACKET_TYPE_ACIP_STRING_RELEASE) - Release string reservation.

STRING_RENEW (PACKET_TYPE_ACIP_STRING_RENEW) - Renew string reservation.

STRING_RESERVED (PACKET_TYPE_ACIP_STRING_RESERVED) - String reservation response.

STRING_RESERVE (PACKET_TYPE_ACIP_STRING_RESERVE) - Reserve a session string.

WEBRTC_ICE (PACKET_TYPE_ACIP_WEBRTC_ICE) - ICE candidate relay.

WEBRTC_SDP (PACKET_TYPE_ACIP_WEBRTC_SDP) - SDP offer/answer relay.

SESSION_RECONNECT (PACKET_TYPE_ACIP_SESSION_RECONNECT) - Reconnect to session.

SESSION_END (PACKET_TYPE_ACIP_SESSION_END) - End session (host only)

SESSION_LEAVE (PACKET_TYPE_ACIP_SESSION_LEAVE) - Leave session.

PARTICIPANT_LEFT (PACKET_TYPE_ACIP_PARTICIPANT_LEFT) - Participant left notification.

PARTICIPANT_JOINED (PACKET_TYPE_ACIP_PARTICIPANT_JOINED) - New participant notification.

SESSION_JOINED (PACKET_TYPE_ACIP_SESSION_JOINED) - Session join response.

SESSION_JOIN (PACKET_TYPE_ACIP_SESSION_JOIN) - Join existing session.

SESSION_INFO (PACKET_TYPE_ACIP_SESSION_INFO) - Session info response.

SESSION_LOOKUP (PACKET_TYPE_ACIP_SESSION_LOOKUP) - Lookup session by string.

SESSION_CREATED (PACKET_TYPE_ACIP_SESSION_CREATED) - Session created response.

Direction: Client -> Discovery Server

Payload structure (fixed + variable):

  • Fixed part: acip_session_create_t (295 bytes minimum)
  • Variable part: reserved_string (if reserved_string_len > 0, max 47 bytes)

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 32 identity_pubkey Ed25519 public key (host identity)
32 64 signature Ed25519(type || timestamp || capabilities)
96 8 timestamp Unix milliseconds (replay protection)
104 1 capabilities Bit 0=video, Bit 1=audio
105 1 max_participants 1-8 allowed concurrent participants
106 1 session_type 0=DIRECT_TCP, 1=WEBRTC
107 1 has_password 0=no password, 1=password protected
108 128 password_hash Argon2id hash (if has_password=1)
236 1 expose_ip_publicly 0=require verify, 1=allow public IP
237 1 reserved_string_len 0=auto-generate, >0=use provided
238 1 total_keys Total number of keys in multi-key sequence (0=single key mode)
239 1 key_index Index of this key in sequence (0-based, only valid if total_keys > 0)
240 64 server_address IPv4/IPv6/hostname (null-terminated)
304 2 server_port TCP port for client connection
------
Total: 306 bytes + reserved_string (if len > 0, max 47 bytes)
bool valid

The client requests creation of a new session with specific capabilities, optionally providing a pre-reserved session string. The server responds with SESSION_CREATED containing the session identifier.

Host Responsibility: The creator becomes the session host (participant_id) and controls session settings in discovery mode.

Direction: Discovery Server -> Client

Payload structure (fixed + variable):

  • Fixed part: acip_session_created_t (90 bytes)
  • Variable part: stun_server_t[stun_count] + turn_server_t[turn_count]

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 1 session_string_len Length of generated/provided string
1 48 session_string Session ID string (null-padded)
49 16 session_id UUID bytes (generated by server)
65 16 participant_id Creator's participant UUID
81 8 expires_at Unix ms (session creation + 24 hours)
89 1 stun_count Number of STUN servers (0-N)
90 1 turn_count Number of TURN servers (0-N)
------
Total: 91 bytes + STUN/TURN server data
uint8_t session_id[16]
uint8_t participant_id[16]

STUN/TURN Servers: Followed by packed stun_server_t and turn_server_t structs for WebRTC P2P connectivity behind NAT.

The server responds to SESSION_CREATE with the generated session identifier, session string (either auto-generated or the provided reserved string), and optional STUN/TURN server information for WebRTC connectivity.

The creator is assigned a participant_id and is considered the session initiator (controls session settings in discovery mode).

Note
STUN server configuration (stun_server_t) is defined in networking/webrtc/stun.h
TURN server configuration (turn_server_t) is defined in networking/webrtc/turn.h

Direction: Client -> Discovery Server

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 1 session_string_len Length of query string
1 48 session_string Session ID string to lookup
------
Total: 49 bytes

The client queries for session information using the session string. Server responds with SESSION_INFO containing basic session metadata (but NOT the server connection information, which is only revealed after successful authentication via SESSION_JOIN).

Security Note: Server does NOT reveal host IP in SESSION_INFO response, preventing information leakage to non-members.

Direction: Discovery Server -> Client

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 1 found 0=not found, 1=found
1 16 session_id UUID (valid if found=1)
17 32 host_pubkey Ed25519 public key of host
49 1 capabilities Bit 0=video, Bit 1=audio
50 1 max_participants Maximum allowed participants
51 1 current_participants Current count (may increase during lookup)
52 1 session_type 0=DIRECT_TCP, 1=WEBRTC
53 1 has_password 0=open, 1=password required
54 8 created_at Unix ms (session creation time)
62 8 expires_at Unix ms (24 hours after creation)
70 1 require_server_verify ACDS policy flag (host verifies guest)
71 1 require_client_verify ACDS policy flag (guest verifies host)
------
Total: 72 bytes

SECURITY NOTE: Does NOT include server connection information (IP/port). Server address is only revealed after authentication via SESSION_JOIN. This prevents IP address leakage to unauthenticated clients.

Server Verification: If require_server_verify=1, host must verify client identity using Ed25519 signatures.

Direction: Client -> Discovery Server

Payload structure: acip_session_join_t (241 bytes fixed)

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 1 session_string_len Length of session string
1 48 session_string Session ID to join
49 32 identity_pubkey Client's Ed25519 public key
81 64 signature Ed25519(type || timestamp || session_string)
145 8 timestamp Unix ms (replay protection, ±5min window)
153 1 has_password 0=no password, 1=password provided
154 128 password Cleartext password (TLS protects wire)
------
Total: 282 bytes

Authentication Methods:

  • Identity Signature: Client signs (type || timestamp || session_string) with Ed25519
  • Password: Optional additional requirement, stored as Argon2id hash on server
  • Replay Protection: Timestamp must be within ±5 minute window of server time

Response: Server verifies credentials and responds with SESSION_JOINED containing server IP:port and TURN credentials.

The client requests to join an existing session, providing identity proof via Ed25519 signature and optionally a password. Server responds with SESSION_JOINED containing server connection information upon successful authentication.

Direction: Discovery Server -> Client

Packet Format (Variable Length)

Offset Size Field Value/Description
------ ---- ----- -----------------
0 1 success 0=failed, 1=joined
1 1 error_code Error code if success=0
2 128 error_message Human-readable error (null-terminated)
130 16 participant_id Client's new UUID (if success=1)
146 16 session_id Session UUID
162 16 initiator_id Session creator's UUID
178 1 host_established 0=negotiate, 1=host exists
179 16 host_id Host's UUID (if host_established=1)
195 1 peer_count Number of peers (if host_established=0)
196 N*16 peer_ids[] Variable: peer UUIDs (N*16 bytes)
(196+N*16) 1 session_type 0=DIRECT_TCP, 1=WEBRTC (if success=1)
(197+N*16) 64 server_address Host IP/hostname (if success=1)
(261+N*16) 2 server_port Host TCP port (if success=1)
(263+N*16) 128 turn_username TURN auth user (if session_type=WEBRTC)
(391+N*16) 128 turn_password TURN auth pass (if session_type=WEBRTC)
------
Total: 519+ bytes (variable based on peer_count)
asciichat_error_t error_code

CRITICAL SECURITY: Server connection information (IP/port) is ONLY revealed after successful authentication (password verification or identity verification). This prevents IP address leakage to unauthenticated clients who only know the session string.

HOST NEGOTIATION: When host_established == 0, the joiner must negotiate with existing peers to determine who becomes the host. When host_established == 1, the joiner can connect directly to the established host.

TURN Credentials: RFC 5766 time-limited credentials for NAT traversal. Format: "timestamp:session_id" and HMAC-SHA1(secret, username).

Direction: Discovery Server -> Existing Participants

Sent to all existing participants when a new participant joins the session. In discovery mode, this triggers NAT quality exchange and host negotiation between the new joiner and existing participants.

Direction: Discovery Server -> Remaining Participants

Sent to remaining participants when someone leaves the session (gracefully or timeout). If the leaving participant was the host, this triggers host migration.

Direction: Client -> Discovery Server

The client gracefully leaves a session, allowing the server to update participant count and potentially notify other participants.

Direction: Host -> Discovery Server

The session host terminates the session, preventing new joins and notifying all participants. Requires signature proof of host identity.

Direction: Client -> Discovery Server

The client reconnects to a session after disconnection, using stored participant ID and identity proof to resume participation.

Direction: Bidirectional (relayed through discovery server)

Payload structure (fixed + variable):

  • Fixed: acip_webrtc_sdp_t (50 bytes minimum)
  • Variable: sdp_data (SDP string, null-terminated)

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 16 session_id Session UUID
16 16 from_id Sender's participant UUID
32 16 to_id Recipient's participant UUID (or all if broadcast)
48 2 sdp_len Length of SDP data (0-2MB)
50 N sdp_data UTF-8 SDP string (null-terminated)
------
Total: 50 + sdp_len bytes

SDP Format: RFC 4566 Session Description Protocol

  • Offer: Media offer with local capabilities
  • Answer: Media answer matching peer capabilities
  • Both include ICE ufrag/pwd for candidate exchange

WebRTC session description protocol messages are relayed through the discovery server to facilitate peer-to-peer connection establishment.

Direction: Bidirectional (relayed through discovery server)

Payload structure (fixed + variable):

  • Fixed: acip_webrtc_ice_t (50 bytes minimum)
  • Variable: candidate (ICE candidate string, null-terminated)

Packet Format

Offset Size Field Value/Description
------ ---- ----- -----------------
0 16 session_id Session UUID
16 16 sender_id Sender's participant UUID
32 16 recipient_id Recipient's participant UUID
48 2 candidate_len Length of ICE candidate (0-512)
50 N candidate UTF-8 ICE candidate (null-terminated)
------
Total: 50 + candidate_len bytes

ICE Candidate Format: RFC 5245 Interactive Connectivity Establishment

  • Example: "candidate:1 1 udp 2122260223 192.168.1.100 54321 typ host"
  • Contains: foundation, component, transport, priority, address, port, type
  • Relayed candidate: includes related-address/port for NAT-mapped endpoints

Candidate Types:

  • host: Local machine (non-NATted)
  • srflx: Server reflexive (STUN-discovered)
  • prflx: Peer reflexive (discovered via STUN from peer)
  • relay: TURN-relayed candidate

WebRTC ICE candidates are relayed through the discovery server to facilitate NAT traversal during peer-to-peer connection establishment.

Direction: Client -> Discovery Server

FUTURE FEATURE: Reserve a memorable session string for future use, preventing others from using it for a specified duration.

Direction: Discovery Server -> Client

FUTURE FEATURE: Confirms successful string reservation or reports error.

Direction: Client -> Discovery Server

FUTURE FEATURE: Extends an existing string reservation before expiration.

Direction: Client -> Discovery Server

FUTURE FEATURE: Voluntarily releases a reserved string before expiration.

Direction: ACDS -> All Participants

Broadcast by ACDS after session join or when participant joins/leaves. Lists all participants in deterministic ring order (by join time or participant ID). Participants use this to determine:

  • My position in the ring
  • Who is next in ring (for NAT collection)
  • Who is quorum leader this round (last in rotation)

Follows acip_participant_list_t in packet payload. Array of num_participants entries.

Direction: Previous Participant -> Next Participant (via direct connection)

Sent during ring rotation to request NAT quality from next participant. Forms the "spoke" of the ring, where one participant collects from all others.

During each 5-minute round:

  • Participant[0] connects to Participant[1], gets NAT data
  • Participant[1] connects to Participant[2], gets NAT data
  • ... (continues around ring)
  • Participant[N-1] has all NAT data, runs election, announces future host

Direction: Participant -> Others (via ring collection, WebRTC signaling, or direct P2P)

NEW DESIGN: Unified packet for all network quality metrics, replacing separate NAT_QUALITY, HOST_LOST NAT fields, etc. Used in three contexts:

  1. Initial Negotiation (during host selection before session established)
    • Exchanged between first two participants to determine initial host
  2. Ring Collection (proactive, every 5 minutes)
    • Quorum leader collects from all participants for future host election
    • Fresh NAT data ensures optimal host selection
    • Participants know future host before current host dies
  3. Migration Recovery (if current host dies unexpectedly)
    • Participants exchange fresh NETWORK_QUALITY if pre-elected future host unavailable
    • Enables fallback re-election

Direction: Participant -> ACDS

Sent by the participant who won host negotiation to announce they are starting the server. ACDS stores this and includes it in future SESSION_JOINED responses.

Direction: ACDS -> All Participants

Sent by ACDS after receiving HOST_ANNOUNCEMENT to notify all participants who the host is and where to connect.

Direction: Participant -> ACDS

Lightweight notification that a participant detected the host disconnected. NAT quality data is NOT included - migration participants use pre-elected future host instead of re-electing. If future host unavailable, participants can request fresh NETWORK_QUALITY exchange for re-election if needed.

NEW P2P DESIGN: This is now just a notification for ACDS bookkeeping. Actual migration happens peer-to-peer without ACDS involvement - participants connect to pre-elected future host immediately upon detection.

Direction: Quorum Leader -> ACDS -> All Participants

NEW P2P DESIGN: Sent proactively by quorum leader after completing ring consensus (every 5 minutes or when new participant joins). Announces to all participants who will become host if current host dies.

Key Insight: Future host is PRE-ELECTED and stored by everyone. When current host dies, participants don't need to elect - they immediately:

  • Future host: starts hosting (already know they will)
  • Others: connect to future host (address already stored)
  • Total failover time: <500ms (no election!)

This packet is broadcast by ACDS after receiving it from quorum leader, ensuring all participants know the migration plan before host dies.

Direction: Discovery Server -> Client

Generic error response used when no specific response packet type exists. Contains error code and human-readable message.

Sent by client to ACDS to request bandwidth measurement. Client sends this packet followed by test payload data. ACDS measures receive time and calculates upload speed.

Sent by ACDS to client with measured bandwidth results. Includes upload speed (measured by ACDS), download speed (echo test), RTT, jitter, and packet loss metrics.

Direction: Client -> ACDS

Sent by clients to acknowledge receipt of critical broadcast messages (e.g., HOST_DESIGNATED, FUTURE_HOST_ELECTED). ACDS tracks ACKs and retries broadcasts to clients that haven't acknowledged.

< Ed25519 public key of session host

< Signs: type || timestamp || capabilities

< Unix ms (replay protection)

< Bit 0: video, Bit 1: audio

< 1-8 participants allowed

< acds_session_type_t: 0=DIRECT_TCP (default), 1=WEBRTC

< 0 = no password, 1 = password protected

< Argon2id hash (only if has_password == 1)

< 0 = require verification, 1 = allow public IP disclosure (explicit –acds-expose-ip opt-in)

< 0 = auto-generate, >0 = use provided string

< Total number of keys to transmit (0 = single key mode, legacy)

< Index of this key in the sequence (0-based), only valid if total_keys > 0

< IPv4/IPv6 address or hostname (null-terminated)

< Port number for client connection

< Length of session string (e.g., 20 for "swift-river-mountain")

< Null-padded session string

< UUID as bytes (not string)

< Creator's participant ID (they are a participant too)

< Unix ms (created_at + 24 hours)

< Number of STUN servers

< Number of TURN servers

< 0 = not found, 1 = found

< Valid only if found == 1

< Host's Ed25519 public key

< Session capabilities

< acds_session_type_t: 0=DIRECT_TCP, 1=WEBRTC

< 1 = password required to join

< Unix ms

< Unix ms

< ACDS policy: server must verify client identity

< ACDS policy: client must verify server identity

< Joiner's Ed25519 public key

< Signs: type || timestamp || session_string

< Unix ms

< Cleartext password (TLS protects transport)

< 0 = failed, 1 = joined

< Error code if success == 0

< Human-readable error

< UUID for this participant (valid if success == 1)

< Session UUID

< Who created the session (controls settings)

< 0 = no host yet (negotiate), 1 = host exists (connect directly)

< Host's participant ID (valid if host_established == 1)

< Number of other participants to negotiate with

< acds_session_type_t: 0=DIRECT_TCP, 1=WEBRTC

< IPv4/IPv6 address or hostname (null-terminated)

< Port number for client connection

< Format: "{timestamp}:{session_id}"

< Base64-encoded HMAC-SHA1(secret, username)

< Session UUID

< UUID of the new participant

< Ed25519 public key of new participant

< Total participants including new one

< Session UUID

< UUID of participant who left

< 1 if the leaving participant was the host

< Participants remaining in session

< Host proves ownership

< Prove identity

< Session UUID

< Participant UUID

< All zeros = broadcast to all

< 0 = offer, 1 = answer

< Length of SDP data

< How long to reserve (1-365)

< Unix ms

< Number of participants in session

< Participant's address (for direct connection)

< Participant's listening port

< acip_connection_type_t

< Who is requesting

< Who is requested

< Which 5-minute round (for detection of stale requests)

< STUN reflexive == local IP

< UPnP/NAT-PMP port mapping works

< Port we mapped (network byte order)

< acip_nat_type_t classification

< Same subnet as peer (mDNS/ARP)

< RTT to STUN server in nanoseconds

< Upload bandwidth in Kbps (from ACDS test)

< Download bandwidth in Kbps (informational)

< Latency to ACDS server in nanoseconds

< Packet timing variance in nanoseconds

< Packet loss percentage (0-100)

< Our public IP (if has_public_ip or upnp)

< Our public port

< Bitmask: 1=host, 2=srflx, 4=relay

< My participant ID

< Where clients should connect

< Port

< acip_connection_type_t

< acip_connection_type_t

< Who is reporting

< The host that disconnected

< 0=unknown, 1=timeout, 2=tcp_reset, 3=graceful

< When disconnect was detected (Unix ms)

< Who will host if current host dies

< Where to connect when needed

< Port number

< acip_connection_type_t (DIRECT, UPNP, STUN, TURN)

< Which 5-minute round this was elected in

< Error code (see acip_error_code_t)

< Human-readable error

< Session identifier

< Participant identifier

< Size of test payload (typically 64KB)

< Timestamp when client sent packet

< Upload bandwidth in kilobits/sec

< Download bandwidth in kilobits/sec

< Round-trip time in nanoseconds

< Packet timing variance in nanoseconds

< Packet loss percentage (0-100)

< Session UUID

< Participant acknowledging

< ID of broadcast being acknowledged

< Type of packet being acknowledged

Definition at line 1 of file acds.h.

195 {
196 uint8_t identity_pubkey[32];
197 uint8_t signature[64];
198 uint64_t timestamp;
199
200 uint8_t capabilities;
201 uint8_t max_participants;
202 uint8_t session_type;
203
204 uint8_t has_password;
205 uint8_t password_hash[128];
206 uint8_t expose_ip_publicly;
208
209 uint8_t reserved_string_len;
210 // char reserved_string[]; ///< Variable length, follows if len > 0
211
212 // Multi-key protocol: tracks which key in sequence this is
213 uint8_t total_keys;
214 uint8_t key_index;
215
216 // Server connection information (where clients should connect)
217 // For DIRECT_TCP: server_address and server_port specify where to connect
218 // For WEBRTC: these fields are ignored, signaling happens through ACDS
219 char server_address[64];
220 uint16_t server_port;
acip_session_create_t
Definition acds.h:221
unsigned short uint16_t
Definition common.h:57
unsigned long long uint64_t
Definition common.h:59
unsigned char uint8_t
Definition common.h:56

Variable Documentation

◆ acip_bandwidth_result_t

acip_bandwidth_result_t

#include <acds.h>

Definition at line 1037 of file acds.h.

Referenced by nat_measure_bandwidth().

◆ acip_bandwidth_test_t

acip_bandwidth_test_t

#include <acds.h>

Definition at line 1020 of file acds.h.

Referenced by nat_measure_bandwidth().

◆ acip_broadcast_ack_t

acip_broadcast_ack_t

#include <acds.h>

Definition at line 1055 of file acds.h.

◆ acip_error_t

acip_error_t

#include <acds.h>

Definition at line 1004 of file acds.h.

Referenced by acip_server_send_error(), and send_error_packet_message().

◆ acip_future_host_elected_t

acip_future_host_elected_t

#include <acds.h>

Definition at line 981 of file acds.h.

◆ acip_host_announcement_t

acip_host_announcement_t

#include <acds.h>

Definition at line 910 of file acds.h.

Referenced by discovery_session_become_host(), and discovery_session_process().

◆ acip_host_designated_t

acip_host_designated_t

#include <acds.h>

Definition at line 928 of file acds.h.

◆ acip_host_lost_t

acip_host_lost_t

#include <acds.h>

Definition at line 952 of file acds.h.

Referenced by discovery_session_handle_host_disconnect().

◆ acip_nat_quality_t

acip_nat_quality_t

#include <acds.h>

Definition at line 891 of file acds.h.

Referenced by __attribute__(), nat_quality_to_acip(), and signaling_relay_network_quality().

◆ acip_participant_entry_t

acip_participant_entry_t

#include <acds.h>

Definition at line 788 of file acds.h.

◆ acip_participant_joined_t

acip_participant_joined_t

#include <acds.h>

Definition at line 492 of file acds.h.

◆ acip_participant_left_t

acip_participant_left_t

#include <acds.h>

Definition at line 509 of file acds.h.

◆ acip_participant_list_t

acip_participant_list_t

#include <acds.h>

Definition at line 774 of file acds.h.

◆ acip_ring_collect_t

acip_ring_collect_t

#include <acds.h>

Definition at line 811 of file acds.h.

◆ acip_session_create_t

acip_session_create_t

#include <acds.h>

Definition at line 221 of file acds.h.

Referenced by acds_session_create().

◆ acip_session_created_t

acip_session_created_t

#include <acds.h>

Definition at line 269 of file acds.h.

Referenced by acds_session_create().

◆ acip_session_end_t

acip_session_end_t

#include <acds.h>

Definition at line 539 of file acds.h.

◆ acip_session_info_t

acip_session_info_t

#include <acds.h>

Definition at line 355 of file acds.h.

Referenced by acds_session_lookup().

◆ acip_session_join_t

acip_session_join_t

#include <acds.h>

Definition at line 403 of file acds.h.

Referenced by acds_session_join().

◆ acip_session_joined_t

acip_session_joined_t

#include <acds.h>

Definition at line 474 of file acds.h.

Referenced by acds_session_join().

◆ acip_session_leave_t

acip_session_leave_t

#include <acds.h>

Definition at line 524 of file acds.h.

Referenced by discovery_session_stop().

◆ acip_session_lookup_t

acip_session_lookup_t

#include <acds.h>

Definition at line 304 of file acds.h.

Referenced by acds_session_lookup().

◆ acip_session_reconnect_t

acip_session_reconnect_t

#include <acds.h>

Definition at line 555 of file acds.h.

◆ acip_string_release_t

acip_string_release_t

#include <acds.h>

Definition at line 728 of file acds.h.

◆ acip_string_renew_t

acip_string_renew_t

#include <acds.h>

Definition at line 711 of file acds.h.

◆ acip_string_reserve_t

acip_string_reserve_t

#include <acds.h>

Definition at line 677 of file acds.h.

◆ acip_string_reserved_t

acip_string_reserved_t

#include <acds.h>

Definition at line 693 of file acds.h.

◆ acip_webrtc_ice_t

acip_webrtc_ice_t

#include <acds.h>

Definition at line 650 of file acds.h.

◆ acip_webrtc_sdp_t

acip_webrtc_sdp_t

#include <acds.h>

Definition at line 604 of file acds.h.