ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
client.h File Reference

ACIP client-side protocol API. More...

Go to the source code of this file.

Functions

asciichat_error_t acip_client_receive_packet (acip_transport_t *transport, packet_envelope_t *envelope)
asciichat_error_t acip_client_receive_and_dispatch (acip_transport_t *transport, const acip_client_callbacks_t *callbacks)
 Receive packet from server and dispatch to callbacks.
asciichat_error_t acip_send_image_frame (acip_transport_t *transport, const void *pixel_data, uint32_t width, uint32_t height, uint32_t pixel_format)
 Send image frame to server (client → server).
asciichat_error_t acip_send_image_frame_h265 (acip_transport_t *transport, h265_encoder_t *encoder, const void *pixel_data, uint32_t width, uint32_t height)
 Send H.265-encoded video frame to server (client → server).
asciichat_error_t acip_send_stream_start (acip_transport_t *transport, uint8_t stream_types)
 Request to start media streaming (client → server).
asciichat_error_t acip_send_stream_stop (acip_transport_t *transport, uint8_t stream_types)
 Request to stop media streaming (client → server).
asciichat_error_t acip_send_capabilities (acip_transport_t *transport, const void *cap_data, size_t cap_len)
 Send terminal capabilities to server (client → server).
asciichat_error_t acip_send_protocol_version (acip_transport_t *transport, const protocol_version_packet_t *version)
 Send protocol version to server (client → server).

Detailed Description

ACIP client-side protocol API.

Client-side API for ascii-chat protocol. Provides functions for:

  • Receiving and dispatching packets from server
  • Sending image frames to server
  • Sending client control messages (join, leave, stream control)
  • Sending capabilities and protocol version
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Definition in file include/ascii-chat/network/acip/client.h.

Function Documentation

◆ acip_client_receive_and_dispatch()

asciichat_error_t acip_client_receive_and_dispatch ( acip_transport_t * transport,
const acip_client_callbacks_t * callbacks )

Receive packet from server and dispatch to callbacks.

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

Parameters
transportTransport instance
callbacksCallback structure for handling received packets
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 45 of file lib/network/acip/client.c.

46 {
47 ASCII_OTEL_SCOPE(ACIP_CLIENT_RECEIVE_AND_DISPATCH);
48 if (!callbacks)
49 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing client packet callbacks");
50 packet_envelope_t envelope = {0};
51 asciichat_error_t result = acip_client_receive_packet(transport, &envelope);
52 if (result == ASCIICHAT_OK)
53 result = acip_handle_client_packet(transport, envelope.type, envelope.data, envelope.len, callbacks);
54 if (envelope.allocated_buffer)
55 buffer_release(envelope.allocated_buffer);
56 return result;
57}
#define SET_ERRNO(code,...)
#define buffer_release(data)
Definition buffer.h:91
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
asciichat_error_t acip_handle_client_packet(acip_transport_t *transport, packet_type_t type, const void *payload, size_t payload_len, const acip_client_callbacks_t *callbacks)
Client-side packet handler callbacks.
Definition handlers.c:203
asciichat_error_t acip_client_receive_packet(acip_transport_t *transport, packet_envelope_t *out)
#define ASCII_OTEL_SCOPE(id)
Definition otel.h:72
Packet envelope containing received packet data.
Definition packet.h:1185

References acip_client_receive_packet(), acip_handle_client_packet(), ASCII_OTEL_SCOPE, ASCIICHAT_OK, buffer_release, ERROR_INVALID_PARAM, and SET_ERRNO.

◆ acip_client_receive_packet()

asciichat_error_t acip_client_receive_packet ( acip_transport_t * transport,
packet_envelope_t * envelope )

Definition at line 33 of file lib/network/acip/client.c.

33 {
34 if (!transport || !out) {
35 log_error("[ACIP_RECV] ❌ INVALID_PARAMS: transport=%p, output=%p", (void *)transport, (void *)out);
36 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or packet output");
37 }
38
39 *out = (packet_envelope_t){0};
40 if (!acip_transport_is_connected(transport) && !acip_transport_has_pending_data(transport))
41 return SET_ERRNO(ERROR_NETWORK, "Transport not connected");
42 return packet_receive_via_transport(transport, &out->type, &out->data, &out->len, &out->allocated_buffer);
43}
@ ERROR_NETWORK
Definition error_codes.h:72
#define log_error(...)
Log an ERROR message.
Definition log/log.h:634
static bool size_t gotel_query_t * out
Definition queries.h:8
asciichat_error_t packet_receive_via_transport(acip_transport_t *transport, packet_type_t *type, void **payload, size_t *payload_len, void **alloc_buffer)
Receive a packet via transport with header parsing and validation.
Definition send.c:200

References ERROR_INVALID_PARAM, ERROR_NETWORK, log_error, out, packet_receive_via_transport(), and SET_ERRNO.

Referenced by acip_client_receive_and_dispatch().

◆ acip_send_capabilities()

asciichat_error_t acip_send_capabilities ( acip_transport_t * transport,
const void * cap_data,
size_t cap_len )

Send terminal capabilities to server (client → server).

Reports client's terminal capabilities (color support, dimensions, etc.)

Parameters
transportTransport instance
cap_dataCapability data buffer
cap_lenCapability data length
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 180 of file lib/network/acip/client.c.

180 {
181 if (!transport || !cap_data) {
182 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or cap_data");
183 }
184
185 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_CAPABILITIES, cap_data, cap_len, 0);
186}
@ PACKET_TYPE_CLIENT_CAPABILITIES
Client reports terminal capabilities.
Definition packet.h:405
asciichat_error_t packet_send_via_transport(acip_transport_t *transport, packet_type_t type, const void *payload, size_t payload_len, uint32_t client_id)
Definition send.c:190

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

◆ acip_send_image_frame()

asciichat_error_t acip_send_image_frame ( acip_transport_t * transport,
const void * pixel_data,
uint32_t width,
uint32_t height,
uint32_t pixel_format )

Send image frame to server (client → server).

Sends webcam video frame as RGB24 pixel data.

Parameters
transportTransport instance
pixel_dataRGB24 pixel data (width * height * 3 bytes)
widthFrame width in pixels
heightFrame height in pixels
pixel_formatPixel format (e.g., RGB24)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 63 of file lib/network/acip/client.c.

64 {
65 ASCII_OTEL_SCOPE(ACIP_SEND_IMAGE_FRAME);
66 log_dev("★ ACIP_SEND_IMAGE_FRAME: Called with %ux%u, transport=%p, pixel_data=%p", width, height, (void *)transport,
67 pixel_data);
68
69 if (!transport || !pixel_data) {
70 log_dev("★ ACIP_SEND_IMAGE_FRAME: Invalid params");
71 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or pixel_data");
72 }
73
74 // Calculate pixel data size (3 bytes per pixel for RGB24)
75 size_t pixel_size = (size_t)width * height * 3;
76 log_dev("★ ACIP_SEND_IMAGE_FRAME: pixel_size=%zu", pixel_size);
77
78 // Create image frame packet header
80 header.width = HOST_TO_NET_U32(width);
81 header.height = HOST_TO_NET_U32(height);
82 header.pixel_format = HOST_TO_NET_U32(pixel_format);
83 header.compressed_size = 0;
84 header.checksum = 0;
85 header.timestamp = 0;
86
87 socket_buffer_t slices[] = {{&header, sizeof(header)}, {pixel_data, pixel_size}};
88 return packet_send_via_transportv(transport, PACKET_TYPE_IMAGE_FRAME, slices, 2, 0);
89}
#define HOST_TO_NET_U32(val)
Definition endian.h:66
unsigned int height
Definition fft.c:23
unsigned int width
Definition fft.c:23
#define log_dev(...)
Log a DEV message (most verbose, development only).
Definition log/log.h:581
@ PACKET_TYPE_IMAGE_FRAME
Complete RGB image with dimensions.
Definition packet.h:385
asciichat_error_t packet_send_via_transportv(acip_transport_t *transport, packet_type_t type, const socket_buffer_t *payload, size_t count, uint32_t client_id)
Send arbitrary packet via transport (generic packet sender).
Definition send.c:155
Describes one compressed image sent through ACIP. width, height, and pixel_format tell the decoder ho...
Definition packet.h:931
uint32_t width
Image width in pixels.
Definition packet.h:933

References ASCII_OTEL_SCOPE, ERROR_INVALID_PARAM, height, HOST_TO_NET_U32, log_dev, packet_send_via_transportv(), PACKET_TYPE_IMAGE_FRAME, SET_ERRNO, image_frame_packet_t::width, and width.

Referenced by threaded_send_image_frame().

◆ acip_send_image_frame_h265()

asciichat_error_t acip_send_image_frame_h265 ( acip_transport_t * transport,
h265_encoder_t * encoder,
const void * pixel_data,
uint32_t width,
uint32_t height )

Send H.265-encoded video frame to server (client → server).

Encodes RGB frame to H.265 and transmits as PACKET_TYPE_IMAGE_FRAME_H265. Much more efficient than raw pixel transmission for bandwidth-limited connections.

PACKET FORMAT: [flags: u8][width: u16][height: u16][h265_data...]

  • flags: H.265 encoding flags (keyframe, size_change)
  • width: Frame width in pixels
  • height: Frame height in pixels
  • h265_data: x265-encoded frame payload
Parameters
transportTransport instance
encoderH.265 encoder (initialized with initial frame dimensions)
pixel_dataRGB pixel data from camera/source
widthFrame width in pixels
heightFrame height in pixels
Returns
ASCIICHAT_OK on success, error code on failure
Note
Encoder is responsible for RGB → YUV420 conversion internally
Encoder handles frame dimension changes transparently (reconfigures on size change)

Send H.265-encoded video frame to server (client → server).

Encodes frame using H.265 codec and sends as PACKET_TYPE_IMAGE_FRAME_H265. Packet format: [flags:u8][width:u16][height:u16][h265_encoded_data...]

Parameters
transportACIP transport
encoderH.265 encoder instance
pixel_dataRGB pixel data from capture
widthFrame width in pixels
heightFrame height in pixels
Returns
Error code

Definition at line 104 of file lib/network/acip/client.c.

105 {
106 ASCII_OTEL_SCOPE(ACIP_SEND_IMAGE_FRAME_H265);
107 if (!transport || !encoder || !pixel_data) {
108 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Invalid params");
109 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport, encoder, or pixel_data");
110 }
111
112 // Allocate output buffer for H.265 encoding
113 // H.265 can produce output larger than input due to codec overhead
114 // Use 2x multiplier to account for worst-case frame content
115 size_t output_buffer_size = 5 + (width * height * 2);
116 log_dev("[ACIP_SEND_H265_1] About to allocate output buffer (%zu bytes)", output_buffer_size);
117 uint8_t *output_buffer = buffer_alloc(NULL, output_buffer_size);
118 log_dev("[ACIP_SEND_H265_2] ✅ Allocated output buffer");
119 if (!output_buffer) {
120 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Failed to allocate output buffer");
121 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate H.265 output buffer: %zu bytes", output_buffer_size);
122 }
123 defer(buffer_release(output_buffer));
124
125 // Admission expiry can invalidate a previously accepted reference chain.
126#ifndef __EMSCRIPTEN__
129#endif
130 size_t encoded_size = output_buffer_size;
131 log_dev("[ACIP_SEND_H265_3] Calling h265_encode");
132 asciichat_error_t encode_result = h265_encode(encoder, (uint16_t)width, (uint16_t)height, (const uint8_t *)pixel_data,
133 output_buffer, &encoded_size);
134 log_dev("[ACIP_SEND_H265_4] h265_encode returned: %d, encoded_size=%zu", encode_result, encoded_size);
135
136 if (encode_result != ASCIICHAT_OK) {
137 log_error("H.265 encoding failed: %s", asciichat_error_format(NULL, encode_result));
138 return encode_result;
139 }
140
141 // h265_encode includes flags, dimensions, and the encoded picture already.
142 size_t total_size = encoded_size;
143 if (!total_size) {
144 return ASCIICHAT_OK;
145 }
146
147 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Encoded %ux%u → %zu bytes", width, height, total_size);
148
149 // Send via transport
150 log_dev("[ACIP_SEND_H265_5] Calling packet_send_via_transport with %zu bytes", total_size);
151 asciichat_error_t result =
152 packet_send_via_transport(transport, PACKET_TYPE_IMAGE_FRAME_H265, output_buffer, total_size, 0);
153 log_dev("[ACIP_SEND_H265_6] packet_send_via_transport returned: %d", result);
154
155 return result;
156}
const char * asciichat_error_format(const char *message, asciichat_error_t code)
bool acip_outbound_needs_keyframe(acip_transport_t *transport, uint16_t type, uint32_t id)
void * buffer_alloc(buffer_domain_t *domain, size_t size)
Definition buffer.c:274
asciichat_error_t h265_encode(h265_encoder_t *encoder, uint16_t width, uint16_t height, const uint8_t *ascii_data, uint8_t *output_buf, size_t *output_size)
Definition encoder.c:317
void h265_encoder_request_keyframe(h265_encoder_t *encoder)
Definition encoder.c:439
unsigned short uint16_t
Definition common.h:61
unsigned char uint8_t
Definition common.h:60
@ ERROR_MEMORY
Definition error_codes.h:51
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:595
@ PACKET_TYPE_IMAGE_FRAME_H265
H.265-encoded frame from client (HEVC/H.265 codec).
Definition packet.h:387

References acip_outbound_needs_keyframe(), ASCII_OTEL_SCOPE, asciichat_error_format(), ASCIICHAT_OK, buffer_alloc(), buffer_release, ERROR_INVALID_PARAM, ERROR_MEMORY, h265_encode(), h265_encoder_request_keyframe(), height, log_debug, log_dev, log_error, packet_send_via_transport(), PACKET_TYPE_IMAGE_FRAME_H265, SET_ERRNO, and width.

◆ acip_send_protocol_version()

asciichat_error_t acip_send_protocol_version ( acip_transport_t * transport,
const protocol_version_packet_t * version )

Send protocol version to server (client → server).

Negotiates protocol version with server.

Parameters
transportTransport instance
versionProtocol version structure
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 188 of file lib/network/acip/client.c.

188 {
189 if (!transport || !version) {
190 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or version");
191 }
192
193 return packet_send_via_transport(transport, PACKET_TYPE_PROTOCOL_VERSION, version, sizeof(*version), 0);
194}
@ PACKET_TYPE_PROTOCOL_VERSION
Protocol version and capabilities negotiation.
Definition packet.h:303

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

◆ acip_send_stream_start()

asciichat_error_t acip_send_stream_start ( acip_transport_t * transport,
uint8_t stream_types )

Request to start media streaming (client → server).

Notifies server that client wants to start sending video/audio.

Parameters
transportTransport instance
stream_typesStream type bitmask (video, audio, etc.)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 158 of file lib/network/acip/client.c.

158 {
159 ASCII_OTEL_SCOPE(ACIP_SEND_STREAM_START);
160 if (!transport) {
161 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
162 }
163
164 // Server expects uint32_t (4 bytes), not uint8_t
165 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
166 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_START, &stream_types_net, sizeof(stream_types_net), 0);
167}
unsigned int uint32_t
Definition common.h:62
@ PACKET_TYPE_STREAM_START
Client requests to start sending video/audio.
Definition packet.h:415

References ASCII_OTEL_SCOPE, ERROR_INVALID_PARAM, HOST_TO_NET_U32, packet_send_via_transport(), PACKET_TYPE_STREAM_START, and SET_ERRNO.

◆ acip_send_stream_stop()

asciichat_error_t acip_send_stream_stop ( acip_transport_t * transport,
uint8_t stream_types )

Request to stop media streaming (client → server).

Notifies server that client wants to stop sending video/audio.

Parameters
transportTransport instance
stream_typesStream type bitmask (video, audio, etc.)
Returns
ASCIICHAT_OK on success, error code on failure

Definition at line 169 of file lib/network/acip/client.c.

169 {
170 ASCII_OTEL_SCOPE(ACIP_SEND_STREAM_STOP);
171 if (!transport) {
172 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
173 }
174
175 // Server expects uint32_t (4 bytes), not uint8_t
176 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
177 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_STOP, &stream_types_net, sizeof(stream_types_net), 0);
178}
@ PACKET_TYPE_STREAM_STOP
Client stops sending media.
Definition packet.h:417

References ASCII_OTEL_SCOPE, ERROR_INVALID_PARAM, HOST_TO_NET_U32, packet_send_via_transport(), PACKET_TYPE_STREAM_STOP, and SET_ERRNO.