32 const acip_server_callbacks_t *callbacks) {
34 log_dev_every(4500 * US_PER_MS_INT,
35 "ACIP_SERVER_DISPATCH: Entry, transport=%p, client_ctx=%p, callbacks=%p, timestamp=%llu",
36 (
void *)transport, client_ctx, (
const void *)callbacks, (
unsigned long long)dispatch_start_ns);
39 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid transport (NULL)");
42 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid callbacks (NULL)");
46 if (!transport->methods->is_connected(transport)) {
47 return SET_ERRNO(ERROR_NETWORK,
"Transport not connected");
50 packet_envelope_t envelope;
51 bool enforce_encryption = (transport->crypto_ctx != NULL);
54 socket_t sock = transport->methods->get_socket(transport);
55 log_dev_every(4500 * US_PER_MS_INT,
"ACIP_SERVER_DISPATCH: Socket=%d (INVALID=%d)", sock, INVALID_SOCKET_VALUE);
57 if (sock != INVALID_SOCKET_VALUE) {
59 packet_recv_result_t result =
receive_packet_secure(sock, transport->crypto_ctx, enforce_encryption, &envelope);
62 if (result != PACKET_RECV_SUCCESS) {
63 if (result == PACKET_RECV_EOF) {
64 return SET_ERRNO(ERROR_NETWORK,
"Connection closed (EOF)");
65 }
else if (result == PACKET_RECV_SECURITY_VIOLATION) {
66 return SET_ERRNO(ERROR_CRYPTO,
"Security violation: unencrypted packet when encryption required");
68 return SET_ERRNO(ERROR_NETWORK,
"Failed to receive packet");
73 void *packet_data = NULL;
74 void *allocated_buffer = NULL;
75 size_t packet_len = 0;
78 asciichat_error_t recv_result = transport->methods->recv(transport, &packet_data, &packet_len, &allocated_buffer);
81 if (recv_result != ASCIICHAT_OK) {
82 char recv_duration_str[32];
83 format_duration_ns((
double)(recv_end_ns - recv_start_ns), recv_duration_str,
sizeof(recv_duration_str));
84 log_warn(
"[ACIP_RECV_ERROR] recv() failed after %s (result=%d)", recv_duration_str, recv_result);
85 return SET_ERRNO(ERROR_NETWORK,
"Transport recv() failed");
88 char recv_duration_str[32];
89 format_duration_ns((
double)(recv_end_ns - recv_start_ns), recv_duration_str,
sizeof(recv_duration_str));
90 log_info(
"[ACIP_RECV_SUCCESS] Received %zu bytes in %s", packet_len, recv_duration_str);
93 if (packet_len <
sizeof(packet_header_t)) {
95 return SET_ERRNO(ERROR_NETWORK,
"Packet too small: %zu < %zu", packet_len,
sizeof(packet_header_t));
98 const packet_header_t *header = (
const packet_header_t *)packet_data;
99 envelope.type = NET_TO_HOST_U16(header->type);
100 envelope.len = NET_TO_HOST_U32(header->length);
101 envelope.data = (uint8_t *)packet_data +
sizeof(packet_header_t);
102 envelope.allocated_buffer = allocated_buffer;
103 envelope.allocated_size = packet_len;
105 log_dev_every(4500 * US_PER_MS_INT,
"ACIP_SERVER_DISPATCH: WebRTC packet parsed: type=%d, len=%u", envelope.type,
109 if (envelope.type == PACKET_TYPE_ENCRYPTED && transport->crypto_ctx) {
111 uint8_t *ciphertext = (uint8_t *)envelope.data;
112 size_t ciphertext_len = envelope.len;
115 size_t plaintext_size = ciphertext_len + 1024;
119 return SET_ERRNO(ERROR_MEMORY,
"Failed to allocate plaintext buffer for decryption");
122 size_t plaintext_len;
123 crypto_result_t crypto_result =
124 crypto_decrypt(transport->crypto_ctx, ciphertext, ciphertext_len, plaintext, plaintext_size, &plaintext_len);
129 if (crypto_result != CRYPTO_OK) {
131 return SET_ERRNO(ERROR_CRYPTO,
"Failed to decrypt WebSocket packet: %s",
135 if (plaintext_len <
sizeof(packet_header_t)) {
137 return SET_ERRNO(ERROR_CRYPTO,
"Decrypted packet too small: %zu < %zu", plaintext_len,
sizeof(packet_header_t));
141 const packet_header_t *inner_header = (
const packet_header_t *)plaintext;
142 envelope.type = NET_TO_HOST_U16(inner_header->type);
143 envelope.len = NET_TO_HOST_U32(inner_header->length);
144 envelope.data = plaintext +
sizeof(packet_header_t);
145 envelope.allocated_buffer = plaintext;
146 envelope.allocated_size = plaintext_size;
149 char decrypt_duration_str[32];
151 sizeof(decrypt_duration_str));
152 log_info(
"[WS_TIMING] Decrypt %zu bytes → %zu bytes in %s (inner_type=%d)", ciphertext_len, plaintext_len,
153 decrypt_duration_str, envelope.type);
159 log_info(
"ACIP_DISPATCH_PKT: type=%d, len=%zu, client_ctx=%p", envelope.type, envelope.len, client_ctx);
160 uint64_t dispatch_handler_start_ns =
time_get_ns();
161 asciichat_error_t dispatch_result =
164 char handler_duration_str[32];
165 format_duration_ns((
double)(dispatch_handler_end_ns - dispatch_handler_start_ns), handler_duration_str,
166 sizeof(handler_duration_str));
167 log_info(
"[WS_TIMING] Handler for type=%d took %s (result=%d)", envelope.type, handler_duration_str, dispatch_result);
170 if (envelope.allocated_buffer) {
175 return dispatch_result;
183 uint32_t width, uint32_t height, uint32_t client_id) {
184 if (!transport || !frame_data) {
185 return SET_ERRNO(ERROR_INVALID_PARAM,
"Invalid transport or frame_data");
188 if (frame_size == 0) {
189 return SET_ERRNO(ERROR_INVALID_PARAM,
"Empty frame data");
193 uint32_t checksum_value = asciichat_crc32(frame_data, frame_size);
196 ascii_frame_packet_t header;
197 header.width = HOST_TO_NET_U32(width);
198 header.height = HOST_TO_NET_U32(height);
199 header.original_size = HOST_TO_NET_U32((uint32_t)frame_size);
200 header.compressed_size = 0;
201 header.checksum = HOST_TO_NET_U32(checksum_value);
206 if (checked_size_add(
sizeof(header), frame_size, &total_size) != ASCIICHAT_OK) {
207 return SET_ERRNO(ERROR_INVALID_PARAM,
"Packet size overflow");
213 return SET_ERRNO(ERROR_MEMORY,
"Failed to allocate buffer: %zu bytes", total_size);
217 memcpy(buffer, &header,
sizeof(header));
218 memcpy(buffer +
sizeof(header), frame_data, frame_size);
221 asciichat_error_t result =