ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
server_like.c File Reference

Unified lifecycle for server-like modes (server, discovery-service) More...

Go to the source code of this file.

Macros

#define KEYBOARD_QUEUE_SIZE   256
 

Functions

tcp_server_t * session_server_like_get_tcp_server (void)
 
asciichat_mdns_t * session_server_like_get_mdns_ctx (void)
 
nat_upnp_context_t * session_server_like_get_upnp_ctx (void)
 
websocket_server_t * session_server_like_get_websocket_server (void)
 
asciichat_error_t session_server_like_mdns_advertise (const char *name, const char *type, uint16_t port, const char **txt, size_t txt_count)
 
bool session_server_like_shutdown_requested (void)
 
asciichat_error_t session_server_like_handshake (crypto_handshake_context_t *ctx, acip_transport_t *transport)
 
asciichat_error_t session_server_like_run (const session_server_like_config_t *config)
 

Detailed Description

Unified lifecycle for server-like modes (server, discovery-service)

Owns TCP server, WebSocket server, mDNS, UPnP, status screen, keyboard, and signal handling. Modes plug in via callbacks.

Definition in file server_like.c.

Macro Definition Documentation

◆ KEYBOARD_QUEUE_SIZE

#define KEYBOARD_QUEUE_SIZE   256

Definition at line 73 of file server_like.c.

Function Documentation

◆ session_server_like_get_mdns_ctx()

asciichat_mdns_t * session_server_like_get_mdns_ctx ( void  )

Get the mDNS context owned by server_like.

READINESS GUARANTEE: Available from step 6 onward (during init_fn and after). Use for deferred advertisement when service_name is not known at config time. NULL if mDNS is disabled or initialization failed (non-fatal).

Returns
Pointer to mDNS context, or NULL if not initialized or disabled

Definition at line 266 of file server_like.c.

266 {
267 return g_mdns_ctx;
268}

◆ session_server_like_get_tcp_server()

tcp_server_t * session_server_like_get_tcp_server ( void  )

Get the TCP server instance owned by server_like.

READINESS GUARANTEE: Available from step 4 onward (during init_fn, interrupt_fn, cleanup_fn). Modes use this for client registry operations and to close listen sockets in interrupt_fn. The TCP server is guaranteed to be valid during init_fn and in interrupt_fn (async-signal context).

Returns
Pointer to TCP server (never NULL after step 4), or NULL if called before TCP init

Definition at line 262 of file server_like.c.

262 {
263 return g_tcp_server_initialized ? &g_tcp_server : NULL;
264}

Referenced by acds_server_init().

◆ session_server_like_get_upnp_ctx()

nat_upnp_context_t * session_server_like_get_upnp_ctx ( void  )

Get the UPnP context owned by server_like.

READINESS GUARANTEE: Available from step 5 onward (during init_fn and after). Use for querying the public address. NULL if port mapping failed or was disabled. Failure to map UPnP is non-fatal; WebRTC fallback will be used.

Returns
Pointer to UPnP context, or NULL if not initialized or disabled

Definition at line 270 of file server_like.c.

270 {
271 return g_upnp_ctx;
272}

◆ session_server_like_get_websocket_server()

websocket_server_t * session_server_like_get_websocket_server ( void  )

Get the WebSocket server instance owned by server_like.

READINESS GUARANTEE: WebSocket object is constructed at step 7, but the event loop thread does NOT start until after mode init succeeds (step 9). Callbacks will not run until after init_fn returns successfully. This prevents client connections before mode state is ready.

Available for configuration during init_fn, and for state queries after init_fn succeeds. The WebSocket object is valid for the lifetime of the session_server_like_run() call.

Returns
Pointer to WebSocket server, or NULL if not initialized or disabled

Definition at line 274 of file server_like.c.

274 {
275 return g_websocket_thread_started ? &g_websocket_server : NULL;
276}

◆ session_server_like_handshake()

asciichat_error_t session_server_like_handshake ( crypto_handshake_context_t *  ctx,
acip_transport_t *  transport 
)

Perform the server-side crypto handshake on a transport.

Runs the full handshake sequence: receive PROTOCOL_VERSION, send parameters, key exchange, auth challenge, and completion. Both server and discovery-service modes use this single implementation.

The caller must initialize the handshake context (crypto_handshake_init or crypto_handshake_init_with_password) and configure keys/whitelist on it before calling this function.

Parameters
ctxInitialized handshake context with keys/auth configured
transportACIP transport for the client connection
Returns
ASCIICHAT_OK on success, error code on handshake failure

Definition at line 416 of file server_like.c.

416 {
417 if (!ctx || !transport) {
418 return SET_ERRNO(ERROR_INVALID_PARAM, "handshake context or transport is NULL");
419 }
420
421 // Crypto key generation and signing can exceed the normal one-second packet
422 // polling interval on slower or busy peers. Keep the longer deadline scoped
423 // to the handshake so idle-session polling remains responsive.
424 const uint64_t previous_receive_timeout_ns = transport->receive_timeout_ns;
425 transport->receive_timeout_ns = 30ULL * NS_PER_SEC_INT;
426 asciichat_error_t result = session_server_like_handshake_impl(ctx, transport);
427 transport->receive_timeout_ns = previous_receive_timeout_ns;
428 return result;
429}
unsigned long long uint64_t
Definition common.h:59
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ERROR_INVALID_PARAM
#define NS_PER_SEC_INT
Definition time.h:157
uint64_t receive_timeout_ns
Optional TCP receive timeout override; zero uses the normal polling timeout.
Definition transport.h:217

References ERROR_INVALID_PARAM, NS_PER_SEC_INT, acip_transport::receive_timeout_ns, and SET_ERRNO.

Referenced by acds_client_handler(), and acds_websocket_client_handler().

◆ session_server_like_mdns_advertise()

asciichat_error_t session_server_like_mdns_advertise ( const char *  name,
const char *  type,
uint16_t  port,
const char **  txt,
size_t  txt_count 
)

Advertise or re-advertise an mDNS service.

Convenience wrapper for modes that need deferred or updated advertisement (e.g., server mode advertises after ACDS registration provides session string).

Parameters
nameService instance name
typeService type (e.g., "_ascii-chat._tcp")
portService port
txtOptional TXT records (NULL-terminated array), or NULL
txt_countNumber of TXT records
Returns
ASCIICHAT_OK on success, error if mDNS is not initialized

Definition at line 282 of file server_like.c.

283 {
284 if (!g_mdns_ctx) {
285 return SET_ERRNO(ERROR_INVALID_STATE, "mDNS context not initialized");
286 }
287
288 char hostname[256] = {0};
289 gethostname(hostname, sizeof(hostname) - 1);
290
291 asciichat_mdns_service_t service = {
292 .name = name,
293 .type = type,
294 .host = hostname,
295 .port = port,
296 .txt_records = txt,
297 .txt_count = txt_count,
298 };
299
300 asciichat_error_t result = asciichat_mdns_advertise(g_mdns_ctx, &service);
301 if (result != ASCIICHAT_OK) {
302 LOG_ERRNO_IF_SET("Failed to advertise mDNS service");
303 log_warn("mDNS advertising failed - LAN discovery disabled");
304 } else {
305 log_info("mDNS: Service advertised as '%s' type '%s' (port=%d)", name, type, port);
306 }
307
308 return result;
309}
#define LOG_ERRNO_IF_SET(message)
Check if any error occurred and log it if so.
@ ERROR_INVALID_STATE
@ ASCIICHAT_OK
Definition error_codes.h:51
#define log_warn(...)
Log a WARN message.
Definition log/log.h:574
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
asciichat_error_t asciichat_mdns_advertise(asciichat_mdns_t *mdns, const asciichat_mdns_service_t *service)
Advertise a service on the local network.
Service information for advertisement.

References asciichat_mdns_advertise(), ASCIICHAT_OK, ERROR_INVALID_STATE, LOG_ERRNO_IF_SET, log_info, log_warn, asciichat_mdns_service_t::name, and SET_ERRNO.

Referenced by session_server_like_run().

◆ session_server_like_run()

asciichat_error_t session_server_like_run ( const session_server_like_config_t *  config)

Run a server-like mode with unified lifecycle management.

Orchestrates the complete lifecycle with proper initialization ordering to ensure mode-specific state is ready before external clients can connect.

Initialization Sequence

  1. Keepawake validation and setup
  2. File descriptor limit raising (if configured)
  3. Signal handler registration (SIGINT, SIGTERM, SIGPIPE) with shutdown persistence
  4. TCP server init (binds to GET_OPTION port/address)
  5. UPnP port mapping (if enabled)
  6. mDNS context init and optional immediate advertisement
  7. WebSocket server construction (object created, event loop thread deferred)
  8. Mode-specific init_fn() - mode initializes its state (crypto keys, rate limiter, DB, etc.)
  9. WebSocket event loop thread start (only if mode init succeeds)
  10. Status screen and keyboard threads (if status_fn provided)
  11. TCP accept loop (blocks until shutdown)

CRITICAL ORDERING NOTES:

  • WebSocket event loop thread ONLY starts after mode init succeeds (step 9, not step 7)
  • This prevents clients from arriving before mode state is ready
  • If SIGINT/SIGTERM arrives during init, subsequent steps are skipped
  • Mode-specific init can check session_server_like_shutdown_requested() for early shutdowns

Cleanup (always runs, in order, guarded against partial init)

  1. Join status screen and keyboard threads
  2. Stop WebSocket server (only if thread was started, atomic stop, cancel, join with 500ms timeout)
  3. Mode-specific cleanup_fn() (TCP registry still available, guarded by mode state flags)
  4. Destroy WebSocket server (only if successfully initialized)
  5. Destroy TCP server
  6. Close UPnP port mapping
  7. Destroy mDNS context
  8. Disable keepawake

SAFETY GUARANTEES:

  • Cleanup operations only touch resources that were successfully initialized
  • Signal handler safely sets shutdown flag during early initialization
  • Modes can detect early shutdown via session_server_like_shutdown_requested()
  • Partial initialization failures do not trigger undefined behavior in cleanup
Parameters
configMode configuration (must not be NULL)
Returns
ASCIICHAT_OK on success, or first error from init or accept loop

Definition at line 435 of file server_like.c.

435 {
436 if (!config) {
437 return SET_ERRNO(ERROR_INVALID_PARAM, "config is NULL");
438 }
439 if (!config->init_fn) {
440 return SET_ERRNO(ERROR_INVALID_PARAM, "init_fn is NULL");
441 }
442 if (!config->interrupt_fn) {
443 return SET_ERRNO(ERROR_INVALID_PARAM, "interrupt_fn is NULL");
444 }
445 if (!config->tcp_handler) {
446 return SET_ERRNO(ERROR_INVALID_PARAM, "tcp_handler is NULL");
447 }
448
449 g_config = config;
451
452 /* === 1. Keepawake === */
453
454 bool keepawake_enabled = GET_OPTION(enable_keepawake);
455 bool keepawake_disabled = GET_OPTION(disable_keepawake);
456 if (keepawake_enabled && keepawake_disabled) {
457 return SET_ERRNO(ERROR_INVALID_PARAM, "Cannot specify both --keepawake and --no-keepawake");
458 }
459 if (keepawake_enabled) {
461 }
462
463 /* === 2. File descriptor limit === */
464
465 if (config->raise_fd_limit) {
467 }
468
469 /* === 3. Signal handlers === */
470
471 atomic_store_u64(&g_shutdown_requested, 0);
472 g_interrupt_fn = config->interrupt_fn;
473 platform_signal(SIGINT, server_like_signal_handler);
474 platform_signal(SIGTERM, server_like_signal_handler);
475#ifndef _WIN32
476 platform_signal(SIGPIPE, SIG_IGN);
477#endif
478
479 /* === 4. TCP server init === */
480
481 int port = GET_OPTION(port);
482 const char *address = GET_OPTION(address);
483 const char *address6 = GET_OPTION(address6);
484
485 bool ipv4_has_value = (address && strlen(address) > 0);
486 bool ipv6_has_value = (address6 && strlen(address6) > 0);
487
488 tcp_server_config_t tcp_config = {
489 .port = port,
490 .ipv4_address = ipv4_has_value ? address : NULL,
491 .ipv6_address = ipv6_has_value ? address6 : NULL,
492 .bind_ipv4 = ipv4_has_value || !ipv6_has_value,
493 .bind_ipv6 = ipv6_has_value || !ipv4_has_value,
494 .accept_timeout_sec = 1,
495 .client_handler = config->tcp_handler,
496 .user_data = config->tcp_user_data,
497 .status_update_fn = NULL,
498 .status_update_data = NULL,
499 };
500
501 result = tcp_server_init(&g_tcp_server, &tcp_config);
502 if (result != ASCIICHAT_OK) {
503 log_error("Failed to initialize TCP server on port %d", port);
504 goto cleanup;
505 }
506 g_tcp_server_initialized = true;
507 log_info("TCP server initialized on port %d", port);
508
509 /* === 5. UPnP port mapping === */
510
511 if (config->upnp.enabled && GET_OPTION(enable_upnp)) {
512 asciichat_error_t upnp_result = nat_upnp_open(port, config->upnp.description, &g_upnp_ctx);
513
514 if (upnp_result == ASCIICHAT_OK && g_upnp_ctx) {
515 char public_addr[22];
516 if (nat_upnp_get_address(g_upnp_ctx, public_addr, sizeof(public_addr)) == ASCIICHAT_OK) {
517 char msg[256];
518 safe_snprintf(msg, sizeof(msg), "Public endpoint: %s (direct TCP)", public_addr);
519 log_console(LOG_INFO, msg);
520 log_info("UPnP: Port mapping successful, public endpoint: %s", public_addr);
521 }
522 } else {
523 log_info("UPnP: Port mapping unavailable or failed - will use WebRTC fallback");
524 }
525 }
526
527 /* === 6. mDNS === */
528
529 if (config->mdns.enabled) {
530 g_mdns_ctx = asciichat_mdns_init();
531 if (!g_mdns_ctx) {
532 LOG_ERRNO_IF_SET("Failed to initialize mDNS (non-fatal, LAN discovery disabled)");
533 log_warn("mDNS disabled - LAN discovery will not be available");
534 } else if (config->mdns.service_name) {
535 // Immediate advertisement if service_name is provided
537 }
538 }
539
540 /* === 7. WebSocket server construction (thread deferred until after mode init) === */
541
542 if (config->websocket.enabled) {
543 websocket_server_config_t ws_config = {
544 .port = GET_OPTION(websocket_port),
545 .client_handler = config->websocket.handler,
546 .user_data = config->websocket.user_data,
547 .tls_cert_path = GET_OPTION(websocket_tls_cert),
548 .tls_key_path = GET_OPTION(websocket_tls_key),
549 };
550
551 memset(&g_websocket_server, 0, sizeof(g_websocket_server));
552 asciichat_error_t ws_result = websocket_server_init(&g_websocket_server, &ws_config);
553 if (ws_result != ASCIICHAT_OK) {
554 log_warn("Failed to initialize WebSocket server - browser clients will not be supported");
555 } else {
556 g_websocket_initialized = true;
557 log_info("WebSocket server initialized on port %d (event loop deferred until after mode init)",
558 GET_OPTION(websocket_port));
559 }
560 }
561
562 /* === 8. Mode-specific init === */
563
564 result = config->init_fn(config->init_user_data);
565 if (result != ASCIICHAT_OK) {
566 log_error("Mode initialization failed");
567 goto cleanup;
568 }
569
570 /* === 8b. WebSocket event loop thread start (after mode init succeeds) === */
571
572 if (g_websocket_initialized && !atomic_load_u64(&g_shutdown_requested)) {
573 if (asciichat_thread_create(&g_websocket_thread, "websocket_event_loop", websocket_server_thread_wrapper,
574 &g_websocket_server) == 0) {
575 g_websocket_thread_started = true;
576 log_info("WebSocket event loop thread started");
577 } else {
578 log_error("Failed to start WebSocket event loop thread");
579 }
580 }
581
582 /* === 9. Status screen === */
583
584 if (config->status_fn) {
585 bool status_opt = GET_OPTION(status_screen);
586 bool status_explicit = GET_OPTION(status_screen_explicitly_set);
587 if ((status_opt && terminal_is_interactive()) || (status_explicit && status_opt)) {
588 atomic_store_bool(&g_status_should_exit, false);
590
591 // Store callback and user data for status thread (avoids reliance on g_config lifetime)
592 g_status_fn = config->status_fn;
593 g_status_user_data = config->status_user_data;
594
595 if (asciichat_thread_create(&g_status_screen_thread, "status_screen", status_screen_thread_func, NULL) == 0) {
596 g_status_screen_thread_started = true;
597 log_info("Status screen thread started");
598 } else {
599 log_error("Failed to start status screen thread");
601 g_status_fn = NULL;
602 g_status_user_data = NULL;
603 }
604 }
605 }
606
607 /* === 10. TCP accept loop (blocks) === */
608
609 log_info("Server accepting connections on port %d", port);
610 result = tcp_server_run(&g_tcp_server);
611 if (result != ASCIICHAT_OK) {
612 log_error("TCP server exited with error");
613 }
614
615 /* === CLEANUP === */
616
617cleanup:
618 g_config = NULL;
619
620 /* 11. Stop status screen */
621 if (g_status_screen_thread_started) {
622 atomic_store_bool(&g_status_should_exit, true);
623 int join_result = asciichat_thread_join_timeout(&g_status_screen_thread, NULL, 2000 * NS_PER_MS_INT);
624 if (join_result != 0) {
625 log_warn("Status screen thread did not exit within 2s");
626 }
627 g_status_screen_thread_started = false;
628 g_status_fn = NULL;
629 g_status_user_data = NULL;
631 }
632
633 /* 12. Stop WebSocket server (only if thread was started, i.e., init succeeded) */
634 if (g_websocket_thread_started) {
635 atomic_store_bool(&g_websocket_server.running, false);
636 websocket_server_cancel_service(&g_websocket_server);
637 int ws_join = asciichat_thread_join_timeout(&g_websocket_thread, NULL, 500 * NS_PER_MS_INT);
638 if (ws_join != 0) {
639 log_warn("WebSocket event loop thread did not exit within 500ms");
640 }
641 g_websocket_thread_started = false;
642 }
643
644 /* 13. Mode-specific cleanup (only call if config provided) */
645 if (config && config->cleanup_fn) {
646 config->cleanup_fn(config->cleanup_user_data);
647 }
648
649 /* 14. Destroy WebSocket server (only if successfully initialized) */
650 if (g_websocket_initialized) {
651 websocket_server_destroy(&g_websocket_server);
652 g_websocket_initialized = false;
653 log_debug("WebSocket server destroyed");
654 }
655
656 /* 15. Destroy TCP server */
657 if (g_tcp_server_initialized) {
658 tcp_server_destroy(&g_tcp_server);
659 g_tcp_server_initialized = false;
660 log_debug("TCP server destroyed");
661 }
662
663 /* 16. UPnP cleanup */
664 if (g_upnp_ctx) {
665 nat_upnp_close(&g_upnp_ctx);
666 log_debug("UPnP port mapping closed");
667 }
668
669 /* 17. mDNS cleanup */
670 if (g_mdns_ctx) {
671 asciichat_mdns_destroy(g_mdns_ctx);
672 g_mdns_ctx = NULL;
673 log_debug("mDNS context destroyed");
674 }
675
676 /* 18. Keepawake */
677 if (keepawake_enabled) {
679 }
680
681 return result;
682}
void atomic_store_bool(atomic_t *a, bool value)
Atomically store a boolean value.
Definition atomic.c:177
void atomic_store_u64(atomic_t *a, uint64_t value)
Atomically store a uint64_t value.
Definition atomic.c:241
uint64_t atomic_load_u64(atomic_t *a)
Atomically load a uint64_t value.
Definition atomic.c:233
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define NS_PER_MS_INT
Definition time.h:156
#define GET_OPTION(field)
Safely get a specific option field (lock-free read)
signal_handler_t platform_signal(int sig, signal_handler_t handler)
Set a signal handler.
Definition misc.c:115
int asciichat_thread_join_timeout(asciichat_thread_t *thread, void **retval, uint64_t timeout_ns)
Wait for a thread to complete with timeout.
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:148
void platform_disable_keepawake(void)
Disable system sleep prevention (allow OS to sleep)
void platform_raise_fd_limit(unsigned int limit)
Raise the file descriptor limit for the current process.
asciichat_error_t platform_enable_keepawake(void)
Enable system sleep prevention (keepawake mode)
void tcp_server_destroy(tcp_server_t *server)
Shutdown TCP server.
asciichat_error_t tcp_server_init(tcp_server_t *server, const tcp_server_config_t *config)
Initialize TCP server.
asciichat_error_t tcp_server_run(tcp_server_t *server)
Run TCP server accept loop.
asciichat_error_t websocket_server_init(websocket_server_t *server, const websocket_server_config_t *config)
Initialize WebSocket server.
void websocket_server_destroy(websocket_server_t *server)
Destroy WebSocket server and free resources.
void websocket_server_cancel_service(websocket_server_t *server)
Wake the WebSocket server event loop immediately.
#define asciichat_thread_create(thread_ptr, attr, start_routine, arg)
#define log_console(level, message)
Definition log/log.h:1003
void asciichat_mdns_destroy(asciichat_mdns_t *mdns)
Shutdown mDNS context and cleanup.
asciichat_mdns_t * asciichat_mdns_init(void)
Initialize mDNS context.
bool terminal_is_interactive(void)
Check if the session is fully interactive.
asciichat_error_t session_server_like_mdns_advertise(const char *name, const char *type, uint16_t port, const char **txt, size_t txt_count)
void ui_status_log_destroy(void)
Cleanup status screen log capture system.
Definition status.c:36
void ui_status_log_init(void)
Initialize status screen log capture system.
Definition status.c:28
struct session_server_like_config::@12 upnp
session_server_like_interrupt_fn interrupt_fn
struct session_server_like_config::@10 websocket
struct session_server_like_config::@11 mdns
tcp_client_handler_fn tcp_handler
session_server_like_init_fn init_fn
session_server_like_cleanup_fn cleanup_fn
session_server_like_status_fn status_fn
websocket_client_handler_fn handler
#define LOG_INFO
Definition types.h:40
void nat_upnp_close(nat_upnp_context_t **ctx)
Close port mapping and clean up.
Definition upnp.c:276
asciichat_error_t nat_upnp_open(uint16_t internal_port, const char *description, nat_upnp_context_t **ctx)
Discover and open port via UPnP.
Definition upnp.c:236
asciichat_error_t nat_upnp_get_address(const nat_upnp_context_t *ctx, char *addr, size_t addr_len)
Get the public address (IP:port) for advertising to clients.
Definition upnp.c:310

References asciichat_mdns_destroy(), asciichat_mdns_init(), ASCIICHAT_OK, asciichat_thread_create, asciichat_thread_join_timeout(), atomic_load_u64(), atomic_store_bool(), atomic_store_u64(), session_server_like_config::cleanup_fn, session_server_like_config::cleanup_user_data, session_server_like_config::description, session_server_like_config::enabled, ERROR_INVALID_PARAM, session_server_like_config::fd_limit_target, GET_OPTION, session_server_like_config::handler, session_server_like_config::init_fn, session_server_like_config::init_user_data, session_server_like_config::interrupt_fn, log_console, log_debug, LOG_ERRNO_IF_SET, log_error, log_info, LOG_INFO, log_warn, session_server_like_config::mdns, nat_upnp_close(), nat_upnp_get_address(), nat_upnp_open(), NS_PER_MS_INT, platform_disable_keepawake(), platform_enable_keepawake(), platform_raise_fd_limit(), platform_signal(), tcp_server_config_t::port, websocket_server_config_t::port, session_server_like_config::raise_fd_limit, websocket_server::running, safe_snprintf(), session_server_like_config::service_name, session_server_like_config::service_type, session_server_like_mdns_advertise(), SET_ERRNO, session_server_like_config::status_fn, session_server_like_config::status_user_data, session_server_like_config::tcp_handler, tcp_server_destroy(), tcp_server_init(), tcp_server_run(), session_server_like_config::tcp_user_data, terminal_is_interactive(), ui_status_log_destroy(), ui_status_log_init(), session_server_like_config::upnp, session_server_like_config::user_data, session_server_like_config::websocket, websocket_server_cancel_service(), websocket_server_destroy(), and websocket_server_init().

Referenced by acds_main(), and server_main().

◆ session_server_like_shutdown_requested()

bool session_server_like_shutdown_requested ( void  )

Check if a shutdown request was received during initialization.

Modes can use this during init_fn to detect early SIGINT/SIGTERM signals and exit gracefully instead of proceeding with partial initialization.

Returns
true if SIGINT or SIGTERM was received, false otherwise

Definition at line 315 of file server_like.c.

315 {
316 return (bool)atomic_load_u64(&g_shutdown_requested);
317}

References atomic_load_u64().