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

ascii-chat Discovery Mode Entry Point More...

Go to the source code of this file.

Data Structures

struct  discovery_video_receiver_t
 

Functions

int discovery_main (void)
 Run discovery mode main loop.
 

Detailed Description

ascii-chat Discovery Mode Entry Point

Discovery mode enables zero-configuration video chat where participants can dynamically become hosts based on NAT quality. This implements the "one command to start, one command to join" philosophy.

Discovery Flow

  1. Parse session string (word-word-word format)
  2. Query ACDS for session information
  3. Assess NAT quality (STUN test)
  4. Either: a. Connect to existing host as participant b. Become host if no host exists or better NAT quality
  5. Handle dynamic role changes during session

Implementation Architecture

Discovery mode uses lib/session APIs for media handling:

  • session_host_t: For rendering and broadcasting when elected host
  • session_participant_t: For capture and display when not host
  • discovery_session_t: For ACDS connection and host negotiation

No network protocol code duplication - all media handling via lib/session.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026
Version
1.0

Definition in file discovery/main.c.

Function Documentation

◆ discovery_main()

int discovery_main ( void  )

Run discovery mode main loop.

Discovery mode entry point for unified binary.

Handles session discovery, host negotiation, and media flow.

Returns
0 on success, non-zero error code on failure

Definition at line 661 of file discovery/main.c.

661 {
662 log_debug("discovery_main() starting");
663
664 // Discovery-specific setup: initialize ACDS connection and session negotiation
665 // Note: Shared setup (keepawake, splash, terminal, capture, display, audio)
666 // is handled by session_client_like_run()
667
668 // Get session string from options (command-line argument)
669 const char *session_string = GET_OPTION(session_string);
670 bool is_initiator = (session_string == NULL || session_string[0] == '\0');
671
672 int port_int = GET_OPTION(port);
673
674 log_debug("Discovery: is_initiator=%d, port=%d", is_initiator, port_int);
675
676 // Validate mutually exclusive options: discovery_service_url vs discovery_port
677 const char *service_url = GET_OPTION(discovery_service_url);
678 if (service_url && service_url[0] != '\0') {
679 int discovery_port = GET_OPTION(discovery_port);
680 if (discovery_port != ACIP_DISCOVERY_DEFAULT_PORT) {
681 log_fatal("--discovery-service-url and --discovery-service-port are mutually exclusive");
682 return ERROR_USAGE;
683 }
684 }
685
686 // Create discovery session configuration
687 discovery_config_t discovery_config = {
688 .acds_address = GET_OPTION(discovery_server),
689 .acds_port = (uint16_t)GET_OPTION(discovery_port),
690 .acds_url = service_url,
691 .session_string = is_initiator ? NULL : session_string,
692 .password = GET_OPTION(password),
693 .local_port = (uint16_t)port_int,
694 .on_state_change = on_discovery_state_change,
695 .on_session_ready = on_session_ready,
696 .on_error = on_discovery_error,
697 .callback_user_data = NULL,
698 .should_exit_callback = discovery_capture_should_exit_adapter,
699 .exit_callback_data = NULL,
700 };
701
702 // Create discovery session (stored in global for discovery_run() to access)
703 g_discovery = discovery_session_create(&discovery_config);
704 if (!g_discovery) {
705 log_fatal("Failed to create discovery session");
706 return ERROR_MEMORY;
707 }
708
709 // Start discovery session (connects to ACDS, creates/joins, initiates NAT negotiation)
710 log_debug("Discovery: starting discovery session");
711 asciichat_error_t result = discovery_session_start(g_discovery);
712 if (result != ASCIICHAT_OK) {
713 log_fatal("Failed to start discovery session: %d", result);
714 discovery_session_destroy(g_discovery);
715 g_discovery = NULL;
716 return result;
717 }
718
719 // No network interrupt callback needed - discovery session handles its own shutdown
721
722 /* ========================================================================
723 * Configure and Run Shared Client-Like Session Framework
724 * ========================================================================
725 * session_client_like_run() handles all shared initialization:
726 * - Terminal output management
727 * - Keepawake system
728 * - Splash screen lifecycle
729 * - Media source selection
730 * - FPS probing
731 * - Audio initialization
732 * - Display context creation
733 * - Proper cleanup ordering
734 *
735 * Discovery mode provides:
736 * - discovery_run() callback: NAT negotiation, role determination, media handling
737 * - discovery_keyboard_handler: interactive controls for participant role
738 */
739
741 .run_fn = discovery_run,
742 .run_user_data = NULL,
744 .discovery = (void *)g_discovery, // Opaque pointer to discovery session
745 .custom_should_exit = NULL,
746 .exit_user_data = NULL,
747 .keyboard_handler = discovery_keyboard_handler,
748 .max_reconnect_attempts = 0, // Discovery doesn't retry - role is determined once
749 .should_reconnect_callback = NULL,
750 .reconnect_user_data = NULL,
751 .reconnect_delay_ms = 0,
752 .print_newline_on_tty_exit = false, // Server/participant manages cursor
753 };
754
755 log_debug("Discovery: calling session_client_like_run()");
756 asciichat_error_t session_result = session_client_like_run(&config);
757 log_debug("Discovery: session_client_like_run() returned %d", session_result);
758
759 // Cleanup discovery session
760 log_debug("Discovery: cleaning up");
761
762 if (g_discovery) {
763 discovery_session_stop(g_discovery);
764 discovery_session_destroy(g_discovery);
765 g_discovery = NULL;
766 }
767
768 return (session_result == ASCIICHAT_OK) ? 0 : (int)session_result;
769}
asciichat_error_t session_client_like_run(const session_client_like_config_t *config)
@ SESSION_CLIENT_LIKE_KIND_DISCOVERY
Definition client_like.h:66
#define ACIP_DISCOVERY_DEFAULT_PORT
Discovery server default port (use OPT_ACDS_PORT_INT_DEFAULT from options.h)
Definition acds.h:1094
unsigned short uint16_t
Definition common.h:57
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_USAGE
Definition error_codes.h:53
#define log_fatal(...)
Log a FATAL message.
Definition log/log.h:599
#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)
void set_interrupt_callback(void(*callback)(void))
Definition misc.c:125
void discovery_session_stop(discovery_session_t *session)
Stop the discovery session.
discovery_session_t * discovery_session_create(const discovery_config_t *config)
Create a new discovery session.
asciichat_error_t discovery_session_start(discovery_session_t *session)
Start the discovery session.
void discovery_session_destroy(discovery_session_t *session)
Destroy discovery session and free resources.
Configuration for discovery session.
const char * acds_address
ACDS address (default: "127.0.0.1")
session_client_like_run_fn run_fn

References discovery_config_t::acds_address, ACIP_DISCOVERY_DEFAULT_PORT, ASCIICHAT_OK, discovery_session_create(), discovery_session_destroy(), discovery_session_start(), discovery_session_stop(), ERROR_MEMORY, ERROR_USAGE, GET_OPTION, log_debug, log_fatal, SESSION_CLIENT_LIKE_KIND_DISCOVERY, session_client_like_run(), and set_interrupt_callback().