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

ascii-chat Server Mode Entry Point Header More...

Go to the source code of this file.

Data Structures

struct  server_context_t
 Server context - encapsulates all server state. More...
 

Typedefs

typedef struct server_context_t server_context_t
 Server context - encapsulates all server state.
 

Functions

int server_main (void)
 Server mode entry point for unified binary.
 

Variables

atomic_t g_should_exit
 Global application exit flag (shared across all modes)
 
rate_limiter_t * g_rate_limiter
 Global connection rate limiter.
 
client_manager_t g_client_manager
 Global client manager.
 
rwlock_t g_client_manager_rwlock
 Read-write lock protecting client manager.
 
mixer_t *volatile g_audio_mixer
 Global audio mixer.
 
h265_server_context_t *volatile g_h265_server
 Global H.265 codec server context.
 
bool g_server_encryption_enabled
 Server encryption enabled flag.
 
private_key_t g_server_private_key
 Server's private key.
 
private_key_t g_server_identity_keys [MAX_IDENTITY_KEYS]
 Array of server identity keys.
 
size_t g_num_server_identity_keys
 Number of server identity keys in use.
 
public_key_t g_client_whitelist [MAX_CLIENTS]
 Whitelist of allowed client public keys.
 
size_t g_num_whitelisted_clients
 Number of whitelisted clients.
 

Detailed Description

ascii-chat Server Mode Entry Point Header

This header exposes the server mode entry point for the unified binary architecture. The unified binary dispatches to server_main() when invoked as ascii-chat server.

Unified Binary Architecture

The ascii-chat application uses a single binary with multiple operating modes:

  • ascii-chat server - Run as server (multi-client connection manager)
  • ascii-chat client - Run as client (connects to server, streams video/audio)

This design provides several benefits:

  • Simplified distribution (single binary to install)
  • Reduced disk space (shared library code)
  • Easier testing (one binary to build and deploy)
  • Consistent versioning across modes

Mode Entry Point Contract

Each mode entry point (server_main, client_main) must:

  • Accept no arguments: int mode_main(void)
  • Options are already parsed by main dispatcher (available via global opt_* variables)
  • Return 0 on success, non-zero error code on failure
  • Perform mode-specific initialization and main loop
  • Perform complete cleanup before returning

Implementation Notes

The server_main() function is the original main() from src/server/main.c, adapted to the new dispatcher pattern. Common initialization (options parsing, logging setup, lock debugging) now happens in src/main.c before dispatch.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
2025
Version
2.0

Definition in file server/main.h.

Function Documentation

◆ server_main()

int server_main ( void  )

Server mode entry point for unified binary.

This function implements the complete server lifecycle including:

  • Server-specific initialization (crypto, shutdown callback)
  • Network socket setup and binding
  • Main connection accept loop
  • Client lifecycle management
  • Graceful shutdown and cleanup

Options are already parsed by the main dispatcher before this function is called, so they are available via global opt_* variables.

Returns
0 on success, non-zero error code on failure
Example
# Invoked by dispatcher after options are parsed:
ascii-chat server --port 8080
# Options parsed in main.c, then server_main() called

Definition at line 2204 of file server/main.c.

2204 {
2205 // Common initialization (options, logging, lock debugging) now happens in main.c before dispatch
2206
2207 // Register atomic for debug tracking
2209
2210 // Register shutdown check callback for library code
2211 shutdown_register_callback(check_shutdown);
2212
2213 // Initialize crypto after logging is ready
2214 log_debug("Initializing crypto...");
2215 if (init_server_crypto() != 0) {
2216 LOG_ERRNO_IF_SET("Crypto initialization failed");
2217 FATAL(ERROR_CRYPTO, "Crypto initialization failed");
2218 }
2219 log_debug("Crypto initialized successfully");
2220
2221 log_info("ascii-chat server starting...");
2222
2223 int port = GET_OPTION(port);
2224 if (port < 1 || port > 65535) {
2225 log_error("Invalid port configuration: %d", port);
2226 FATAL(ERROR_CONFIG, "Invalid port configuration: %d", port);
2227 }
2228
2231
2232#ifndef NDEBUG
2233 if (stats_init() != 0) {
2234 FATAL(ERROR_THREAD, "Statistics system initialization failed");
2235 }
2236#endif
2237
2238 // Create background worker thread pool for server operations
2239 g_server_worker_pool = thread_pool_create("server_workers");
2240 if (!g_server_worker_pool) {
2241 LOG_ERRNO_IF_SET("Failed to create server worker thread pool");
2242 FATAL(ERROR_MEMORY, "Failed to create server worker thread pool");
2243 }
2244
2245 // Spawn statistics logging thread in worker pool
2246 if (thread_pool_spawn(g_server_worker_pool, stats_logger_thread, NULL, 0, "stats_logger") != ASCIICHAT_OK) {
2247 LOG_ERRNO_IF_SET("Statistics logger thread creation failed");
2248 } else {
2249 log_debug("Statistics logger thread started");
2250 }
2251
2252 // Initialize static server context (populated further in server_init_fn)
2253 // H.265 context is initialized in server_init_fn, not here
2254 g_server_ctx = (server_context_t){
2255 .tcp_server = NULL, // Set in server_init_fn after TCP server is ready
2256 .rate_limiter = g_rate_limiter,
2257 .client_manager = &g_client_manager,
2258 .client_manager_rwlock = &g_client_manager_rwlock,
2259 .server_should_exit = &g_should_exit,
2260 .audio_mixer = g_audio_mixer,
2261 .stats = &g_stats,
2262 .stats_mutex = &g_stats_mutex,
2263 .encryption_enabled = g_server_encryption_enabled,
2264 .server_private_key = &g_server_private_key,
2265 .client_whitelist = g_client_whitelist,
2266 .num_whitelisted_clients = g_num_whitelisted_clients,
2267 .session_host = NULL,
2268 .h265_server = NULL, // Initialized in server_init_fn
2269 };
2270
2272 .init_fn = server_init_fn,
2273 .init_user_data = NULL,
2274 .interrupt_fn = server_handle_sigint,
2275 .cleanup_fn = server_cleanup_fn,
2276 .cleanup_user_data = NULL,
2277 .status_fn = server_status_fn,
2278 .status_user_data = NULL,
2279 .tcp_handler = ascii_chat_client_handler,
2280 .tcp_user_data = &g_server_ctx,
2281 .websocket =
2282 {
2283 .enabled = true,
2284 .handler = websocket_client_handler,
2285 .user_data = &g_server_ctx,
2286 },
2287 .mdns =
2288 {
2289 .enabled = !GET_OPTION(no_mdns_advertise),
2290 .service_name = NULL, // Deferred: advertised after ACDS or mDNS session string is ready
2291 .service_type = "_ascii-chat._tcp",
2292 },
2293 .upnp =
2294 {
2295 .enabled = GET_OPTION(enable_upnp),
2296 .description = "ascii-chat Server",
2297 },
2298 // Raise FD limit for high-client-count scenarios (matches discovery-service policy)
2299 // Server accepts MAX_CLIENTS connections plus WebSocket, TCP, UPnP, mDNS, etc.
2300 // Each client may use multiple FDs (socket, media buffers, file handles)
2301 // Raising to 65536 ensures we don't hit system limits under load
2302 .raise_fd_limit = true,
2303 .fd_limit_target = 65536,
2304 };
2305
2307 return (result == ASCIICHAT_OK) ? 0 : 1;
2308}
#define LOG_ERRNO_IF_SET(message)
Check if any error occurred and log it if so.
#define ATOMIC_REGISTER_AUTO(name, parent_ptr)
Register an atomic variable for debug tracking with automatic name generation.
Definition atomic.h:472
asciichat_error_t thread_pool_spawn(void *pool, void *(*thread_func)(void *), void *thread_arg, int stop_id, const char *name)
Spawn a worker thread in the pool.
atomic_t g_should_exit
Global application exit flag (shared across all modes)
Definition globals.c:34
#define FATAL(code,...)
Exit with error code and custom message, with stack trace in debug builds.
Definition common.h:158
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ERROR_MEMORY
Definition error_codes.h:56
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_CONFIG
Definition error_codes.h:57
@ ERROR_CRYPTO
Definition error_codes.h:96
@ ERROR_THREAD
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define GET_OPTION(field)
Safely get a specific option field (lock-free read)
const float weight_blue
Blue weight for luminance calculation.
const float weight_red
Red weight for luminance calculation.
const float weight_green
Green weight for luminance calculation.
size_t g_num_whitelisted_clients
Number of whitelisted clients.
bool g_server_encryption_enabled
Global flag indicating if server encryption is enabled.
public_key_t g_client_whitelist[MAX_CLIENTS]
Global client public key whitelist.
private_key_t g_server_private_key
Global server private key (first identity key, for backward compatibility)
void shutdown_register_callback(shutdown_check_fn callback)
Register application's shutdown check function.
Definition common.c:69
void precalc_rgb_palettes(const float red, const float green, const float blue)
Precalculate RGB palettes with color adjustment.
void ascii_simd_init(void)
Initialize SIMD subsystem.
rate_limiter_t * g_rate_limiter
Global rate limiter for connection attempts and packet processing.
mixer_t *volatile g_audio_mixer
Global audio mixer instance for multi-client audio processing.
asciichat_error_t session_server_like_run(const session_server_like_config_t *config)
rwlock_t g_client_manager_rwlock
Reader-writer lock protecting the global client manager.
client_manager_t g_client_manager
Global client manager singleton - central coordination point.
server_stats_t g_stats
Global server statistics structure.
Definition stats.c:163
void * stats_logger_thread(void *arg)
Main statistics collection and reporting thread function.
Definition stats.c:327
int stats_init(void)
Initialize the stats mutex.
Definition stats.c:188
mutex_t g_stats_mutex
Mutex protecting global server statistics.
Definition stats.c:172
Server context - encapsulates all server state.
tcp_server_t * tcp_server
TCP server managing connections.
session_server_like_init_fn init_fn
thread_pool_t * thread_pool_create(int num_threads)

References ascii_simd_init(), ASCIICHAT_OK, ATOMIC_REGISTER_AUTO, ERROR_CONFIG, ERROR_CRYPTO, ERROR_MEMORY, ERROR_THREAD, FATAL, g_audio_mixer, g_client_manager, g_client_manager_rwlock, g_client_whitelist, g_num_whitelisted_clients, g_rate_limiter, g_server_encryption_enabled, g_server_private_key, g_should_exit, g_stats, g_stats_mutex, GET_OPTION, session_server_like_config::init_fn, log_debug, LOG_ERRNO_IF_SET, log_error, log_info, precalc_rgb_palettes(), session_server_like_run(), shutdown_register_callback(), stats_init(), stats_logger_thread(), server_context_t::tcp_server, thread_pool_create(), thread_pool_spawn(), weight_blue, weight_green, and weight_red.

Variable Documentation

◆ g_audio_mixer

mixer_t* volatile g_audio_mixer
extern

Global audio mixer.

Volatile pointer to the multi-client audio mixer instance. Used to mix audio from multiple clients for playback.

Global audio mixer.

The mixer combines audio streams from multiple clients, excluding each client's own audio from their outbound stream (preventing echo). Created once during server initialization and shared by all audio render threads.

THREAD SAFETY: The mixer itself is thread-safe and can be used concurrently by multiple render.c audio threads without external synchronization. During shutdown, set to NULL before destroying to prevent use-after-free.

Definition at line 175 of file server/main.c.

Referenced by add_client(), add_webrtc_client(), client_audio_render_thread(), remove_client(), and server_main().

◆ g_client_manager

client_manager_t g_client_manager
extern

Global client manager.

Registry for all connected clients. Used to track client state, routing, and lifecycle management across server threads.

Global client manager.

This is the primary data structure for managing all connected clients. It serves as the bridge between main.c's connection accept loop and the per-client threading architecture.

STRUCTURE COMPONENTS:

  • clients[]: Array backing storage for client_info_t structs
  • client_hashtable: O(1) lookup table for client_id -> client_info_t*
  • client_count: Current number of active clients
  • mutex: Legacy mutex (mostly replaced by rwlock)
  • next_client_id: Monotonic counter for unique client identification

THREAD SAFETY: Protected by g_client_manager_rwlock for concurrent access

Definition at line 347 of file src/server/client.c.

Referenced by add_client(), add_webrtc_client(), any_clients_sending_video(), broadcast_server_state_to_all_clients(), find_client_by_id(), find_client_by_socket(), remove_client(), send_server_state_to_client(), server_main(), stats_logger_thread(), and update_server_stats().

◆ g_client_manager_rwlock

rwlock_t g_client_manager_rwlock
extern

Read-write lock protecting client manager.

Protects concurrent access to g_client_manager from server threads. Use rwlock_rdlock() for reads, rwlock_wrlock() for writes.

Read-write lock protecting client manager.

This lock enables high-performance concurrent access patterns:

  • Multiple threads can read client data simultaneously (stats, rendering)
  • Only one thread can modify client data at a time (add/remove operations)
  • Eliminates contention between read-heavy operations

USAGE PATTERN:

Definition at line 362 of file src/server/client.c.

362{0};

Referenced by add_client(), add_webrtc_client(), broadcast_server_state_to_all_clients(), find_client_by_id(), find_client_by_socket(), remove_client(), server_main(), stats_logger_thread(), and update_server_stats().

◆ g_h265_server

h265_server_context_t* volatile g_h265_server
extern

Global H.265 codec server context.

Shared H.265 decoding context used by all packet handlers to decode client H.265 frames. Each client gets its own decoder instance.

Shared H.265 decoding context used by all packet handlers to decode client H.265 frames. Each client gets its own decoder instance.

THREAD SAFETY: The h265_server context is thread-safe and can be used concurrently by multiple client handlers. Decoders are per-client. During shutdown, set to NULL before destroying to prevent use-after-free.

Definition at line 187 of file server/main.c.

Referenced by handle_image_frame_h265_packet().

◆ g_rate_limiter

rate_limiter_t* g_rate_limiter
extern

Global connection rate limiter.

Shared rate limiter instance used by packet handlers to prevent DoS attacks. Tracks connection attempts and packet rates per IP address.

Global connection rate limiter.

In-memory rate limiter to prevent connection flooding and DoS attacks. Tracks connection attempts and packet rates per IP address with configurable limits.

Default limits (from rate_limit.c):

  • RATE_EVENT_CONNECTION: 50 connections per 60 seconds
  • RATE_EVENT_IMAGE_FRAME: 144 FPS (8640 frames/min)
  • RATE_EVENT_AUDIO: 172 FPS (10320 packets/min)
  • RATE_EVENT_PING: 2 Hz (120 pings/min)
  • RATE_EVENT_CLIENT_JOIN: 10 joins per 60 seconds
  • RATE_EVENT_CONTROL: 100 control packets per 60 seconds

THREAD SAFETY: The rate limiter is thread-safe and can be used concurrently from the main accept loop and packet handlers without external synchronization.

See also
main.h for extern declaration

Definition at line 217 of file server/main.c.

Referenced by process_decrypted_packet(), and server_main().

◆ g_should_exit

atomic_t g_should_exit
extern

Global application exit flag (shared across all modes)

Set by signal handlers to request graceful shutdown. Used by all server threads to check if they should exit their loops.

Global shutdown flag referenced by lib/logging.c and lib/debug/lock.c In production builds, this is defined in main.c and set during shutdown. For tests, we stub it out as false (tests don't perform shutdown).

Definition at line 34 of file globals.c.

34{0};