ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
server.c File Reference

ACIP server-side protocol implementation. More...

Go to the source code of this file.

Functions

asciichat_error_t acip_server_receive_and_dispatch (acip_transport_t *transport, void *client_ctx, const acip_server_callbacks_t *callbacks)
 Receive packet from client and dispatch to callbacks.
 
asciichat_error_t acip_send_ascii_frame (acip_transport_t *transport, const char *frame_data, uint32_t width, uint32_t height)
 Send ASCII frame to client (server → client)
 
asciichat_error_t acip_send_clear_console (acip_transport_t *transport)
 Send clear console command to client (server → client)
 
asciichat_error_t acip_send_server_state (acip_transport_t *transport, const server_state_packet_t *state)
 Send server state update to client (server → client)
 

Detailed Description

ACIP server-side protocol implementation.

Provides server-side ACIP protocol utilities for:

  • Packet validation
  • Error response generation
  • Protocol compliance checking

ACIP (ASCII-Chat IP Protocol) is the wire protocol for session discovery and WebRTC signaling. This module provides reusable server-side utilities for any ACIP server implementation.

Server-side packet sending and receiving for ascii-chat protocol. Handles server→client communication (ASCII frames, state updates, console control).

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

Definition in file lib/network/acip/server.c.

Function Documentation

◆ acip_send_ascii_frame()

asciichat_error_t acip_send_ascii_frame ( acip_transport_t transport,
const char *  frame_data,
uint32_t  width,
uint32_t  height 
)

Send ASCII frame to client (server → client)

Sends rendered ASCII art frame to client for display.

Parameters
transportTransport instance
frame_dataASCII frame data (null-terminated string)
widthFrame width in characters
heightFrame height in characters
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 79 of file lib/network/acip/server.c.

80 {
81 if (!transport || !frame_data) {
82 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or frame_data");
83 }
84
85 size_t frame_size = strlen(frame_data);
86 if (frame_size == 0) {
87 return SET_ERRNO(ERROR_INVALID_PARAM, "Empty frame data");
88 }
89
90 // Calculate CRC32 checksum of frame data for integrity verification
91 uint32_t checksum_value = asciichat_crc32(frame_data, frame_size);
92
93 // Create ASCII frame packet header
95 header.width = HOST_TO_NET_U32(width);
96 header.height = HOST_TO_NET_U32(height);
97 header.original_size = HOST_TO_NET_U32((uint32_t)frame_size);
98 header.compressed_size = 0;
99 header.checksum = HOST_TO_NET_U32(checksum_value);
100 header.flags = 0;
101
102 // Calculate total packet size
103 size_t total_size;
104 if (checked_size_add(sizeof(header), frame_size, &total_size) != ASCIICHAT_OK) {
105 return SET_ERRNO(ERROR_INVALID_PARAM, "Packet size overflow");
106 }
107
108 // Allocate buffer
109 uint8_t *buffer = buffer_pool_alloc(NULL, total_size);
110 if (!buffer) {
111 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate buffer: %zu bytes", total_size);
112 }
113
114 // Build packet: header + data
115 memcpy(buffer, &header, sizeof(header));
116 memcpy(buffer + sizeof(header), frame_data, frame_size);
117
118 // Send via transport
119 asciichat_error_t result = packet_send_via_transport(transport, PACKET_TYPE_ASCII_FRAME, buffer, total_size);
120
121 buffer_pool_free(NULL, buffer, total_size);
122 return result;
123}
#define HOST_TO_NET_U32(val)
Definition endian.h:71
void buffer_pool_free(buffer_pool_t *pool, void *data, size_t size)
Free a buffer back to the pool (lock-free)
void * buffer_pool_alloc(buffer_pool_t *pool, size_t size)
Allocate a buffer from the pool (lock-free fast path)
unsigned int uint32_t
Definition common.h:58
unsigned char uint8_t
Definition common.h:56
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:46
@ ERROR_MEMORY
Definition error_codes.h:53
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_INVALID_PARAM
uint32_t width
Terminal width in characters.
Definition packet.h:742
uint32_t checksum
CRC32 checksum of original ASCII data.
Definition packet.h:750
uint32_t original_size
Size of original uncompressed ASCII data in bytes.
Definition packet.h:746
uint32_t height
Terminal height in characters.
Definition packet.h:744
uint32_t compressed_size
Size of compressed data (0 = not compressed)
Definition packet.h:748
uint32_t flags
Frame flags bitmask (HAS_COLOR, IS_COMPRESSED, etc.)
Definition packet.h:752
@ PACKET_TYPE_ASCII_FRAME
Complete ASCII frame with all metadata.
Definition packet.h:286
#define asciichat_crc32(data, len)
Main CRC32 dispatcher macro - use this in application code.
Definition crc32.h:144
asciichat_error_t packet_send_via_transport(acip_transport_t *transport, packet_type_t type, const void *payload, size_t payload_len)
Send packet via transport with proper header (exported for generic wrappers)
Definition send.c:40
ASCII frame packet structure (Packet Type 2)
Definition packet.h:740

References asciichat_crc32, ASCIICHAT_OK, buffer_pool_alloc(), buffer_pool_free(), ascii_frame_packet_t::checksum, ascii_frame_packet_t::compressed_size, ERROR_INVALID_PARAM, ERROR_MEMORY, ascii_frame_packet_t::flags, ascii_frame_packet_t::height, HOST_TO_NET_U32, ascii_frame_packet_t::original_size, packet_send_via_transport(), PACKET_TYPE_ASCII_FRAME, SET_ERRNO, and ascii_frame_packet_t::width.

Referenced by client_send_thread_func().

◆ acip_send_clear_console()

asciichat_error_t acip_send_clear_console ( acip_transport_t transport)

Send clear console command to client (server → client)

Instructs client to clear the terminal/console.

Parameters
transportTransport instance
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 125 of file lib/network/acip/server.c.

125 {
126 if (!transport) {
127 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
128 }
129
130 return packet_send_via_transport(transport, PACKET_TYPE_CLEAR_CONSOLE, NULL, 0);
131}
@ PACKET_TYPE_CLEAR_CONSOLE
Server tells client to clear console.
Definition packet.h:308

References ERROR_INVALID_PARAM, packet_send_via_transport(), PACKET_TYPE_CLEAR_CONSOLE, and SET_ERRNO.

Referenced by client_send_thread_func().

◆ acip_send_server_state()

asciichat_error_t acip_send_server_state ( acip_transport_t transport,
const server_state_packet_t state 
)

Send server state update to client (server → client)

Notifies client of server state changes (client count, grid layout, etc.)

Parameters
transportTransport instance
stateServer state structure
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 133 of file lib/network/acip/server.c.

133 {
134 if (!transport || !state) {
135 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or state");
136 }
137
138 return packet_send_via_transport(transport, PACKET_TYPE_SERVER_STATE, state, sizeof(*state));
139}
@ PACKET_TYPE_SERVER_STATE
Server sends current state to clients.
Definition packet.h:310

References ERROR_INVALID_PARAM, packet_send_via_transport(), PACKET_TYPE_SERVER_STATE, and SET_ERRNO.

Referenced by broadcast_server_state_to_all_clients(), and send_server_state_to_client().

◆ acip_server_receive_and_dispatch()

asciichat_error_t acip_server_receive_and_dispatch ( acip_transport_t transport,
void *  client_ctx,
const acip_server_callbacks_t callbacks 
)

Receive packet from client and dispatch to callbacks.

High-level receive function for server side. Receives a single packet from the transport, handles decryption, and dispatches to appropriate callback handler.

Parameters
transportTransport instance
client_ctxClient context pointer (passed to callbacks)
callbacksCallback structure for handling received packets
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 29 of file lib/network/acip/server.c.

30 {
31 if (!transport || !callbacks) {
32 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or callbacks");
33 }
34
35 // Get socket from transport for low-level packet reception
36 socket_t sock = transport->methods->get_socket(transport);
37 if (sock == INVALID_SOCKET_VALUE) {
38 return SET_ERRNO(ERROR_NETWORK, "Transport has no valid socket");
39 }
40
41 // Check if transport is connected
42 if (!transport->methods->is_connected(transport)) {
43 return SET_ERRNO(ERROR_NETWORK, "Transport not connected");
44 }
45
46 // Receive packet with automatic decryption
47 packet_envelope_t envelope;
48 bool enforce_encryption = (transport->crypto_ctx != NULL);
49 packet_recv_result_t result = receive_packet_secure(sock, transport->crypto_ctx, enforce_encryption, &envelope);
50
51 // Handle receive errors
52 if (result != PACKET_RECV_SUCCESS) {
53 if (result == PACKET_RECV_EOF) {
54 return SET_ERRNO(ERROR_NETWORK, "Connection closed (EOF)");
55 } else if (result == PACKET_RECV_SECURITY_VIOLATION) {
56 return SET_ERRNO(ERROR_CRYPTO, "Security violation: unencrypted packet when encryption required");
57 } else {
58 return SET_ERRNO(ERROR_NETWORK, "Failed to receive packet");
59 }
60 }
61
62 // Dispatch packet to appropriate ACIP handler
63 asciichat_error_t dispatch_result =
64 acip_handle_server_packet(transport, envelope.type, envelope.data, envelope.len, client_ctx, callbacks);
65
66 // Always free the allocated buffer (even if handler failed)
67 if (envelope.allocated_buffer) {
68 buffer_pool_free(NULL, envelope.allocated_buffer, envelope.allocated_size);
69 }
70
71 // Return handler result
72 return dispatch_result;
73}
@ ERROR_NETWORK
Definition error_codes.h:69
@ ERROR_CRYPTO
Definition error_codes.h:88
void * allocated_buffer
Buffer that needs to be freed by caller (may be NULL if not allocated)
Definition packet.h:990
size_t allocated_size
Size of allocated buffer in bytes.
Definition packet.h:992
size_t len
Length of payload data in bytes.
Definition packet.h:986
void * data
Packet payload data (decrypted and decompressed if applicable)
Definition packet.h:984
packet_recv_result_t receive_packet_secure(socket_t sockfd, void *crypto_ctx, bool enforce_encryption, packet_envelope_t *envelope)
Receive a packet with decryption and decompression support.
Definition packet.c:568
packet_type_t type
Packet type (from packet_types.h)
Definition packet.h:982
packet_recv_result_t
Packet reception result codes.
Definition packet.h:1003
@ PACKET_RECV_EOF
Connection closed (EOF)
Definition packet.h:1007
@ PACKET_RECV_SECURITY_VIOLATION
Encryption policy violation (e.g., unencrypted packet when encryption required)
Definition packet.h:1011
@ PACKET_RECV_SUCCESS
Packet received successfully.
Definition packet.h:1005
int socket_t
Socket handle type (POSIX: int)
Definition socket.h:50
#define INVALID_SOCKET_VALUE
Invalid socket value (POSIX: -1)
Definition socket.h:52
asciichat_error_t acip_handle_server_packet(acip_transport_t *transport, packet_type_t type, const void *payload, size_t payload_len, void *client_ctx, const acip_server_callbacks_t *callbacks)
Handle incoming packet on server side.
Definition handlers.c:534
bool(* is_connected)(acip_transport_t *transport)
Check if transport is connected.
Definition transport.h:149
socket_t(* get_socket)(acip_transport_t *transport)
Get underlying socket (if applicable)
Definition transport.h:141
const acip_transport_methods_t * methods
Method table (virtual functions)
Definition transport.h:170
crypto_context_t * crypto_ctx
Optional encryption context.
Definition transport.h:171
Packet envelope containing received packet data.
Definition packet.h:980

References acip_handle_server_packet(), packet_envelope_t::allocated_buffer, packet_envelope_t::allocated_size, buffer_pool_free(), acip_transport::crypto_ctx, packet_envelope_t::data, ERROR_CRYPTO, ERROR_INVALID_PARAM, ERROR_NETWORK, acip_transport_methods_t::get_socket, INVALID_SOCKET_VALUE, acip_transport_methods_t::is_connected, packet_envelope_t::len, acip_transport::methods, PACKET_RECV_EOF, PACKET_RECV_SECURITY_VIOLATION, PACKET_RECV_SUCCESS, receive_packet_secure(), SET_ERRNO, and packet_envelope_t::type.

Referenced by client_receive_thread().