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;
int result =
receive_packet(sockfd, crypto_ctx, &header, &payload, &payload_len);
if (result < 0) {
log_debug(
"receive_packet failed - connection lost");
break;
}
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.
Cryptographic context structure.
Packet Handlers
ASCII Frame Handler
static void handle_ascii_frame(const void *payload, size_t payload_len)
{
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.
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);
}
void audio_process_received_samples(const float *samples, int num_samples)
Process received audio samples from server.
Pong Handler
static void handle_pong(void)
{
keepalive_record_pong();
}
Clear Console Handler
static void handle_clear_console(void)
{
}
void display_full_reset()
Perform full display reset.
Server State Handler
static void handle_server_state(const void *payload, size_t payload_len)
{
}
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
- See also
- src/client/protocol.c
-
src/client/protocol.h
-
Client Overview
#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
-
| data | Packet payload containing audio batch header + quantized samples |
| len | Total 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 {
204 bool is_active;
206 time_t last_seen;
#define MAX_DISPLAY_NAME_LEN
Maximum display name length in characters.
References MAX_DISPLAY_NAME_LEN.
| 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
1063 g_server_state_initialized = false;
1064 g_last_active_count = 0;
1065 g_should_clear_before_next_frame = false;
1066
1067
1069
1070
1071
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
1080
1084 }
1085 log_info(
"Sending STREAM_START packet (types=0x%x: %s%s)...", stream_types,
"video",
1088 log_error(
"Failed to send STREAM_START packet");
1089 return -1;
1090 }
1091 log_info(
"STREAM_START packet sent successfully");
1092
1093
1094 atomic_store(&g_data_thread_exited, false);
1096 log_error(
"Failed to spawn data reception thread in worker pool");
1098 return -1;
1099 }
1100
1101
1102 log_info(
"Starting webcam capture thread...");
1104 log_error(
"Failed to start webcam capture thread");
1105 return -1;
1106 }
1107 log_info(
"Webcam capture thread started successfully");
1108
1109
1110 log_info(
"Starting audio capture thread...");
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
1118 log_info(
"Starting keepalive/ping thread...");
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.
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.
int keepalive_start_thread()
Start keepalive/ping thread.
#define log_error(...)
Log an ERROR message.
#define log_info(...)
Log an INFO message.
#define STREAM_TYPE_VIDEO
Video stream.
#define STREAM_TYPE_AUDIO
Audio stream.
#define GET_OPTION(field)
Safely get a specific option field (lock-free read)
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.
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().
| 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
1143
1144
1145
1147
1148
1150
1151
1153
1154
1156
1157
1158 int wait_count = 0;
1159 while (wait_count < 20 && !atomic_load(&g_data_thread_exited)) {
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
1169
1173 log_error(
"Failed to stop client worker threads");
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.
void server_connection_shutdown()
Emergency connection shutdown for signal handlers.
void keepalive_stop_thread()
Stop keepalive/ping thread.
asciichat_error_t
Error and exit codes - unified status values (0-255)
#define log_warn(...)
Log a WARN message.
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().