ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
Client Handler

📡 Client-side packet processing and data reception thread More...

Files

file  protocol.c
 ðŸ“¡ Client protocol handler: packet reception, parsing, and dispatch with data thread coordination
 
file  protocol.h
 ascii-chat Client Protocol Handler Interface
 

Functions

 __attribute__ ((unused))
 Data reception thread handle.
 
int protocol_start_connection ()
 Start protocol connection handling.
 
void protocol_stop_connection ()
 Stop protocol connection handling.
 
bool protocol_connection_lost ()
 Check if connection has been lost.
 
const acip_client_callbacks_tprotocol_get_acip_callbacks ()
 Get ACIP client callbacks for packet dispatch.
 

Detailed Description

📡 Client-side packet processing and data reception thread

Client Protocol README

Overview

The protocol handler manages the data reception thread, processes incoming packets from the server, and dispatches them to appropriate handlers based on packet type.

Implementation: src/client/protocol.c, src/client/protocol.h

Data Reception Thread

static void *data_reception_thread(void *arg)
{
(void)arg;
void *payload = NULL;
size_t payload_len = 0;
// Receive and decrypt packet
int result = receive_packet(sockfd, crypto_ctx, &header, &payload, &payload_len);
if (result < 0) {
log_debug("receive_packet failed - connection lost");
break;
}
// Dispatch based on packet type
handle_packet(&header, payload, payload_len);
if (payload) {
free(payload);
payload = NULL;
}
}
atomic_store(&g_data_thread_exited, true);
return NULL;
}
bool should_exit()
Check if client should exit.
bool server_connection_is_active()
Check if server connection is currently active.
socket_t server_connection_get_socket()
Get current socket file descriptor.
void server_connection_lost()
Signal that connection has been lost.
const crypto_context_t * crypto_client_get_context(void)
Get crypto context for encryption/decryption.
#define log_debug(...)
Log a DEBUG message.
int receive_packet(socket_t sockfd, packet_type_t *type, void **data, size_t *len)
Receive a basic packet without encryption.
Definition packet.c:767
int socket_t
Socket handle type (POSIX: int)
Definition socket.h:50
Cryptographic context structure.
Network packet header structure.
Definition packet.h:490

Packet Handlers

ASCII Frame Handler

static void handle_ascii_frame(const void *payload, size_t payload_len)
{
// Render ASCII frame to terminal
display_render_frame((const char *)payload, opt_snapshot);
// Snapshot mode: exit after displaying frame
if (opt_snapshot) {
}
}
void signal_exit()
Signal client to exit.
void display_render_frame(const char *frame_data, bool is_snapshot_frame)
Render ASCII frame to display.
Definition display.c:353

Audio Batch Handler

static void handle_audio_batch(const void *payload, size_t payload_len)
{
const float *samples = (const float *)payload;
int num_samples = payload_len / sizeof(float);
// Process received audio samples
audio_process_received_samples(samples, num_samples);
}
void audio_process_received_samples(const float *samples, int num_samples)
Process received audio samples from server.

Pong Handler

static void handle_pong(void)
{
// Update last pong time for keepalive timeout tracking
keepalive_record_pong();
}

Clear Console Handler

static void handle_clear_console(void)
{
// Server requests terminal clear
}
void display_full_reset()
Perform full display reset.
Definition display.c:301

Server State Handler

static void handle_server_state(const void *payload, size_t payload_len)
{
// Log server state information
log_debug("Received server state update");
}

Connection Loss Detection

Loss triggers in protocol thread:

  • receive_packet() returns error
  • Socket read error (connection closed by server)
  • Decryption failure (corrupted stream)
  • Invalid packet magic number
if (receive_packet(...) < 0) {
server_connection_lost(); // Signal connection loss
break; // Exit thread
}
See also
src/client/protocol.c
src/client/protocol.h
Client Overview

Function Documentation

◆ __attribute__()

__attribute__ ( (unused)  )

#include <protocol.c>

Data reception thread handle.

Handle incoming audio batch packet from server.

Thread handle for the background thread that receives and processes packets from the server. Created during connection establishment, joined during shutdown.

Remote client information structure for multi-user client tracking

Tracks information about other clients connected to the server. Used by the client to maintain awareness of other participants in the chat session.

CORE FIELDS:

  • client_id: Unique identifier for this remote client
  • display_name: User-friendly display name for the client
  • is_active: Whether this client is currently active (sending video/audio)
  • last_seen: Timestamp when this client was last seen (for timeout detection)

USAGE:

The client maintains an array of remote_client_info_t structures to track all other clients. This information is used for:

  • Multi-user display coordination
  • Client list display
  • Connection state awareness
  • Timeout detection
Note
The client_id matches the server's assigned client identifier.
display_name is received from server in CLIENT_JOIN packets.
is_active indicates whether client is sending media (video/audio).
last_seen is updated when receiving packets from this client.

Processes batched audio packets more efficiently than individual packets. Parses the audio batch header, converts quantized samples to float, and processes them through the audio subsystem.

Parameters
dataPacket payload containing audio batch header + quantized samples
lenTotal packet length in bytes

Unique client identifier assigned by server

User-friendly display name (null-terminated)

Whether client is currently active (sending video/audio)

Timestamp when client was last seen (for timeout detection)

Definition at line 143 of file client/protocol.c.

198 {
200 uint32_t client_id;
202 char display_name[MAX_DISPLAY_NAME_LEN];
204 bool is_active;
206 time_t last_seen;
remote_client_info_t
unsigned int uint32_t
Definition common.h:58
#define MAX_DISPLAY_NAME_LEN
Maximum display name length in characters.
Definition limits.h:20

References MAX_DISPLAY_NAME_LEN.

◆ protocol_connection_lost()

bool protocol_connection_lost ( )

#include <protocol.c>

Check if connection has been lost.

Check if connection has been lost

Returns
true if protocol detected connection loss, false otherwise
true if connection lost, false otherwise

Definition at line 1192 of file client/protocol.c.

1192 {
1193 return atomic_load(&g_data_thread_exited) || server_connection_is_lost();
1194}
bool server_connection_is_lost()
Check if connection loss has been detected.

References server_connection_is_lost().

Referenced by client_main().

◆ protocol_get_acip_callbacks()

const acip_client_callbacks_t * protocol_get_acip_callbacks ( )

#include <protocol.h>

Get ACIP client callbacks for packet dispatch.

Returns
Pointer to client callbacks structure

Used by WebRTC sessions to receive and dispatch ACDS signaling packets.

Returns pointer to the global callback structure for use by WebRTC sessions that need to receive ACDS signaling packets.

Returns
Pointer to client callbacks (never NULL)

Definition at line 950 of file client/protocol.c.

950 {
951 return &g_acip_client_callbacks;
952}

◆ protocol_start_connection()

int protocol_start_connection ( )

#include <protocol.c>

Start protocol connection handling.

Start protocol connection handling

Initializes protocol state and starts the data reception thread. Must be called after successful server connection establishment.

Returns
0 on success, negative on error
0 on success, negative on error

Definition at line 1061 of file client/protocol.c.

1061 {
1062 // Reset protocol state for new connection
1063 g_server_state_initialized = false;
1064 g_last_active_count = 0;
1065 g_should_clear_before_next_frame = false;
1066
1067 // Reset display state for new connection
1069
1070 // Send CLIENT_CAPABILITIES packet FIRST before starting any threads
1071 // Server expects this as the first packet after crypto handshake
1072 log_info("Sending client capabilities to server...");
1074 log_error("Failed to send client capabilities to server");
1075 return -1;
1076 }
1077 log_info("Client capabilities sent successfully");
1078
1079 // Send STREAM_START packet with combined stream types BEFORE starting worker threads
1080 // This tells the server what streams to expect before any data arrives
1081 uint32_t stream_types = STREAM_TYPE_VIDEO; // Always have video
1082 if (GET_OPTION(audio_enabled)) {
1083 stream_types |= STREAM_TYPE_AUDIO; // Add audio if enabled
1084 }
1085 log_info("Sending STREAM_START packet (types=0x%x: %s%s)...", stream_types, "video",
1086 (stream_types & STREAM_TYPE_AUDIO) ? "+audio" : "");
1087 if (threaded_send_stream_start_packet(stream_types) < 0) {
1088 log_error("Failed to send STREAM_START packet");
1089 return -1;
1090 }
1091 log_info("STREAM_START packet sent successfully");
1092
1093 // Start data reception thread
1094 atomic_store(&g_data_thread_exited, false);
1095 if (thread_pool_spawn(g_client_worker_pool, data_reception_thread_func, NULL, 1, "data_reception") != ASCIICHAT_OK) {
1096 log_error("Failed to spawn data reception thread in worker pool");
1097 LOG_ERRNO_IF_SET("Data reception thread creation failed");
1098 return -1;
1099 }
1100
1101 // Start webcam capture thread
1102 log_info("Starting webcam capture thread...");
1103 if (capture_start_thread() != 0) {
1104 log_error("Failed to start webcam capture thread");
1105 return -1;
1106 }
1107 log_info("Webcam capture thread started successfully");
1108
1109 // Start audio capture thread if audio is enabled
1110 log_info("Starting audio capture thread...");
1111 if (audio_start_thread() != 0) {
1112 log_error("Failed to start audio capture thread");
1113 return -1;
1114 }
1115 log_info("Audio capture thread started successfully (or skipped if audio disabled)");
1116
1117 // Start keepalive/ping thread to prevent server timeout
1118 log_info("Starting keepalive/ping thread...");
1119 if (keepalive_start_thread() != 0) {
1120 log_error("Failed to start keepalive/ping thread");
1121 return -1;
1122 }
1123 log_info("Keepalive/ping thread started successfully");
1124
1125 g_data_thread_created = true;
1126 return 0;
1127}
#define LOG_ERRNO_IF_SET(message)
Check if any error occurred and log it if so.
thread_pool_t * g_client_worker_pool
Global client worker thread pool.
int audio_start_thread()
Start audio capture thread.
int capture_start_thread()
Start capture thread.
Definition capture.c:449
int threaded_send_terminal_size_with_auto_detect(unsigned short width, unsigned short height)
Thread-safe terminal size packet transmission with auto-detection.
int threaded_send_stream_start_packet(uint32_t stream_type)
Thread-safe stream start packet transmission.
void display_reset_for_new_connection()
Reset display state for new connection.
Definition display.c:315
int keepalive_start_thread()
Start keepalive/ping thread.
Definition keepalive.c:234
@ ASCIICHAT_OK
Definition error_codes.h:48
#define log_error(...)
Log an ERROR message.
#define log_info(...)
Log an INFO message.
#define STREAM_TYPE_VIDEO
Video stream.
Definition packet.h:829
#define STREAM_TYPE_AUDIO
Audio stream.
Definition packet.h:830
#define GET_OPTION(field)
Safely get a specific option field (lock-free read)
Definition options.h:644
asciichat_error_t thread_pool_spawn(thread_pool_t *pool, void *(*thread_func)(void *), void *thread_arg, int stop_id, const char *thread_name)
Spawn a worker thread in the pool.
Definition thread_pool.c:65

References ASCIICHAT_OK, audio_start_thread(), capture_start_thread(), display_reset_for_new_connection(), g_client_worker_pool, GET_OPTION, keepalive_start_thread(), LOG_ERRNO_IF_SET, log_error, log_info, STREAM_TYPE_AUDIO, STREAM_TYPE_VIDEO, thread_pool_spawn(), threaded_send_stream_start_packet(), and threaded_send_terminal_size_with_auto_detect().

Referenced by client_main().

◆ protocol_stop_connection()

void protocol_stop_connection ( )

#include <protocol.c>

Stop protocol connection handling.

Stop protocol connection handling

Gracefully shuts down the data reception thread and cleans up protocol state. Safe to call multiple times.

Definition at line 1137 of file client/protocol.c.

1137 {
1138 if (!g_data_thread_created) {
1139 return;
1140 }
1141
1142 // Don't call signal_exit() here - that's for global shutdown only!
1143 // We just want to stop threads for this connection, not exit the entire client
1144
1145 // Shutdown the socket to interrupt any blocking recv() in data thread
1147
1148 // Stop keepalive/ping thread - it checks connection status and will exit
1150
1151 // Stop webcam capture thread
1153
1154 // Stop audio threads if running
1156
1157 // Wait for data reception thread to exit gracefully
1158 int wait_count = 0;
1159 while (wait_count < 20 && !atomic_load(&g_data_thread_exited)) {
1160 platform_sleep_usec(100000); // 100ms
1161 wait_count++;
1162 }
1163
1164 if (!atomic_load(&g_data_thread_exited)) {
1165 log_warn("Data thread not responding after 2 seconds - will be joined by thread pool");
1166 }
1167
1168 // Join all threads in the client worker pool (in stop_id order)
1169 // This handles the data reception thread and (eventually) all other worker threads
1172 if (result != ASCIICHAT_OK) {
1173 log_error("Failed to stop client worker threads");
1174 LOG_ERRNO_IF_SET("Thread pool stop failed");
1175 }
1176 }
1177
1178 g_data_thread_created = false;
1179
1180#ifdef DEBUG_THREADS
1181 log_info("Data reception thread stopped and joined by thread pool");
1182#endif
1183}
void audio_stop_thread()
Stop audio capture thread.
void capture_stop_thread()
Stop capture thread.
Definition capture.c:481
void server_connection_shutdown()
Emergency connection shutdown for signal handlers.
void keepalive_stop_thread()
Stop keepalive/ping thread.
Definition keepalive.c:260
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:46
#define log_warn(...)
Log a WARN message.
void platform_sleep_usec(unsigned int usec)
High-precision sleep function with microsecond precision.
asciichat_error_t thread_pool_stop_all(thread_pool_t *pool)
Stop all threads in the pool in stop_id order.

References ASCIICHAT_OK, audio_stop_thread(), capture_stop_thread(), g_client_worker_pool, keepalive_stop_thread(), LOG_ERRNO_IF_SET, log_error, log_info, log_warn, platform_sleep_usec(), server_connection_shutdown(), and thread_pool_stop_all().

Referenced by client_main().