ascii-chat 0.11.33
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_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_client_join (acip_transport_t *transport, uint8_t capabilities)
 Announce client join to server (client → server)
 
asciichat_error_t acip_send_client_leave (acip_transport_t *transport)
 Notify server of client leaving (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 30 of file lib/network/acip/client.c.

31 {
32 if (!transport || !callbacks) {
33 log_error("[ACIP_RECV] ❌ INVALID_PARAMS: transport=%p, callbacks=%p", (void *)transport, (void *)callbacks);
34 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or callbacks");
35 }
36
37 log_debug("[ACIP_RECV] 📥 RECV_START: transport=%p, checking connection state", (void *)transport);
38
39 // Check if transport is connected
40 if (!transport->methods->is_connected(transport)) {
41 log_error("[ACIP_RECV] ❌ NOT_CONNECTED: transport not ready for receive");
42 return SET_ERRNO(ERROR_NETWORK, "Transport not connected");
43 }
44
45 log_debug("[ACIP_RECV] ✅ CONNECTED: transport ready, checking transport type");
46
47 packet_envelope_t envelope;
48 bool enforce_encryption = (transport->crypto_ctx != NULL);
49 log_debug("[ACIP_RECV] 🔐 CRYPTO_MODE: enforce_encryption=%s", enforce_encryption ? "yes" : "no");
50
51 socket_t sock = transport->methods->get_socket(transport);
52 log_debug("[ACIP_RECV] 🔌 TRANSPORT_SOCKET: socket=%d (INVALID=%d)", sock, INVALID_SOCKET_VALUE);
53
54 void *packet_data = NULL;
55 void *allocated_buffer = NULL;
56 size_t packet_len = 0;
57
58 log_debug("[ACIP_RECV] 📥 RECV_CALL: using transport->methods->recv()");
59 asciichat_error_t recv_result = acip_transport_recv(transport, &packet_data, &packet_len, &allocated_buffer);
60 log_debug("[ACIP_RECV] 📥 RECV_RESULT: error=%d, packet_len=%zu, data=%p, alloc=%p", recv_result, packet_len,
61 packet_data, allocated_buffer);
62
63 if (recv_result != ASCIICHAT_OK) {
64 if (recv_result == ERROR_NETWORK_TIMEOUT) {
65 log_debug("[ACIP_RECV] Receive timed out while waiting for signaling data");
66 } else {
67 log_error("[ACIP_RECV] ❌ RECV_FAILED: error code %d", recv_result);
68 }
69 return recv_result;
70 }
71
72 // Parse packet header
73 log_debug("[ACIP_RECV] HEADER_CHECK: packet_len=%zu, header_size=%zu", packet_len, sizeof(packet_header_t));
74 if (packet_len < sizeof(packet_header_t)) {
75 log_error("[ACIP_RECV] ❌ HEADER_TOO_SMALL: %zu < %zu", packet_len, sizeof(packet_header_t));
76 buffer_pool_free(NULL, allocated_buffer, packet_len);
77 return SET_ERRNO(ERROR_NETWORK, "Packet too small: %zu < %zu", packet_len, sizeof(packet_header_t));
78 }
79
80 const packet_header_t *header = (const packet_header_t *)packet_data;
81 envelope.type = NET_TO_HOST_U16(header->type);
82 envelope.len = NET_TO_HOST_U32(header->length);
83 envelope.data = (uint8_t *)packet_data + sizeof(packet_header_t);
84 envelope.allocated_buffer = allocated_buffer;
85 envelope.allocated_size = packet_len;
86 envelope.was_encrypted = false;
87
88 log_debug("[ACIP_RECV] HEADER_PARSED: type=%u (0x%04x), len=%u, total_size=%zu", envelope.type, envelope.type,
89 envelope.len, packet_len);
90
91 log_dev_every(4500 * US_PER_MS_INT, "ACIP received packet: type=%u, len=%u, total_size=%zu", envelope.type,
92 envelope.len, packet_len);
93
94 // Validate packet length
95 log_debug("[ACIP_RECV] LENGTH_VALIDATION: payload_size=%u vs actual=%zu", envelope.len,
96 packet_len - sizeof(packet_header_t));
97 if (envelope.len != packet_len - sizeof(packet_header_t)) {
98 log_error("[ACIP_RECV] ❌ LENGTH_MISMATCH: header=%u, actual=%zu", envelope.len,
99 packet_len - sizeof(packet_header_t));
100 buffer_pool_free(NULL, allocated_buffer, packet_len);
101 return SET_ERRNO(ERROR_NETWORK, "Packet length mismatch: header says %u, actual %zu", envelope.len,
102 packet_len - sizeof(packet_header_t));
103 }
104
105 // Handle PACKET_TYPE_ENCRYPTED from server (decrypt and extract inner packet)
106 if (envelope.type == PACKET_TYPE_ENCRYPTED) {
107 log_debug("[ACIP_RECV] 🔐 ENCRYPTED_PACKET: decrypting PACKET_TYPE_ENCRYPTED (len=%u)", envelope.len);
108 asciichat_error_t decrypt_result = packet_decrypt_envelope(&envelope, transport->crypto_ctx);
109 if (decrypt_result != ASCIICHAT_OK) {
110 log_error("[ACIP_RECV] ❌ DECRYPT_FAILED: %d", decrypt_result);
111 buffer_pool_free(NULL, envelope.allocated_buffer, envelope.allocated_size);
112 return decrypt_result;
113 }
114 }
115
116 // Dispatch packet to appropriate ACIP handler
117 log_debug("[ACIP_RECV] 🎯 DISPATCH_START: type=%u (0x%04x), data_len=%u, callbacks=%p", envelope.type, envelope.type,
118 envelope.len, (void *)callbacks);
119 asciichat_error_t dispatch_result =
120 acip_handle_client_packet(transport, envelope.type, envelope.data, envelope.len, callbacks);
121
122 if (dispatch_result != ASCIICHAT_OK) {
123 log_error("[ACIP_RECV] ❌ DISPATCH_FAILED: type=%u, error=%d", envelope.type, dispatch_result);
124 } else {
125 log_debug("[ACIP_RECV] ✅ DISPATCH_OK: type=%u (0x%04x) handled by callbacks", envelope.type, envelope.type);
126 }
127
128 // Always free the allocated buffer (even if handler failed)
129 log_debug("[ACIP_RECV] 🗑️ CLEANUP: freeing buffer %p (size=%zu)", envelope.allocated_buffer,
130 envelope.allocated_size);
131 if (envelope.allocated_buffer) {
132 buffer_pool_free(NULL, envelope.allocated_buffer, envelope.allocated_size);
133 }
134
135 log_debug("[ACIP_RECV] ✅ RECV_COMPLETE: type=%u, result=%d", envelope.type,
136 dispatch_result != ASCIICHAT_OK ? -1 : 0);
137
138 // Return handler result
139 return dispatch_result;
140}
#define NET_TO_HOST_U16(val)
Definition endian.h:111
#define NET_TO_HOST_U32(val)
Definition endian.h:81
void buffer_pool_free(buffer_pool_t *pool, const void *data, size_t size)
Free a buffer back to the pool (lock-free)
unsigned char uint8_t
Definition common.h:56
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ERROR_NETWORK
Definition error_codes.h:77
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
@ ERROR_NETWORK_TIMEOUT
Definition error_codes.h:80
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define US_PER_MS_INT
Definition time.h:160
asciichat_error_t packet_decrypt_envelope(packet_envelope_t *envelope, void *crypto_ctx)
Send a clear console packet.
Definition packet.c:842
@ PACKET_TYPE_ENCRYPTED
Encrypted packet (after handshake completion)
Definition packet.h:333
#define INVALID_SOCKET_VALUE
Invalid socket value (POSIX: -1)
Definition socket.h:278
int socket_t
#define log_dev_every(interval_us, fmt,...)
Rate-limited DEV logging.
Definition log/log.h:699
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)
Handle incoming packet on client side.
bool(* is_connected)(acip_transport_t *transport)
Check if transport is connected.
Definition transport.h:183
socket_t(* get_socket)(acip_transport_t *transport)
Get underlying socket (if applicable)
Definition transport.h:175
const acip_transport_methods_t * methods
Method table (virtual functions)
Definition transport.h:215
crypto_context_t * crypto_ctx
Optional encryption context.
Definition transport.h:216
Packet envelope containing received packet data.
Definition packet.h:1129
void * allocated_buffer
Buffer that needs to be freed by caller (may be NULL if not allocated)
Definition packet.h:1139
size_t allocated_size
Size of allocated buffer in bytes.
Definition packet.h:1141
size_t len
Length of payload data in bytes.
Definition packet.h:1135
void * data
Packet payload data (decrypted and decompressed if applicable)
Definition packet.h:1133
packet_type_t type
Packet type (from packet_types.h)
Definition packet.h:1131
bool was_encrypted
True if packet was encrypted (decrypted before envelope creation)
Definition packet.h:1137
Network packet header structure.
Definition packet.h:598
uint32_t length
Payload data length in bytes (0 for header-only packets)
Definition packet.h:604
uint16_t type
Packet type (packet_type_t enumeration)
Definition packet.h:602

References acip_handle_client_packet(), packet_envelope_t::allocated_buffer, packet_envelope_t::allocated_size, ASCIICHAT_OK, buffer_pool_free(), acip_transport::crypto_ctx, packet_envelope_t::data, ERROR_INVALID_PARAM, ERROR_NETWORK, ERROR_NETWORK_TIMEOUT, ERROR_NOT_SUPPORTED, acip_transport_methods_t::get_socket, INVALID_SOCKET_VALUE, acip_transport_methods_t::is_connected, packet_envelope_t::len, packet_header_t::length, log_debug, log_dev_every, log_error, acip_transport::methods, NET_TO_HOST_U16, NET_TO_HOST_U32, packet_decrypt_envelope(), PACKET_TYPE_ENCRYPTED, SET_ERRNO, packet_header_t::type, packet_envelope_t::type, US_PER_MS_INT, and packet_envelope_t::was_encrypted.

◆ 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 306 of file lib/network/acip/client.c.

306 {
307 if (!transport || !cap_data) {
308 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or cap_data");
309 }
310
311 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_CAPABILITIES, cap_data, cap_len, 0);
312}
@ PACKET_TYPE_CLIENT_CAPABILITIES
Client reports terminal capabilities.
Definition packet.h:381
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)
Send packet via transport with proper header (exported for generic wrappers)
Definition send.c:41

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

◆ acip_send_client_join()

asciichat_error_t acip_send_client_join ( acip_transport_t *  transport,
uint8_t  capabilities 
)

Announce client join to server (client → server)

Notifies server that client is ready to participate in session.

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

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

266 {
267 if (!transport) {
268 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
269 }
270
271 client_info_packet_t join = {0};
272 SAFE_STRNCPY(join.display_name, "ascii-chat", sizeof(join.display_name));
273 join.capabilities = HOST_TO_NET_U32(capabilities);
274 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_JOIN, &join, sizeof(join), 0);
275}
#define HOST_TO_NET_U32(val)
Definition endian.h:66
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:414
@ PACKET_TYPE_CLIENT_JOIN
Client announces capability to send media.
Definition packet.h:387
Client information packet structure.
Definition packet.h:653
char display_name[32]
User display name (null-terminated, max MAX_DISPLAY_NAME_LEN bytes)
Definition packet.h:657
uint32_t capabilities
Client capabilities bitmask (CLIENT_CAP_VIDEO | CLIENT_CAP_AUDIO | CLIENT_CAP_COLOR | CLIENT_CAP_STRE...
Definition packet.h:660

References client_info_packet_t::capabilities, client_info_packet_t::display_name, ERROR_INVALID_PARAM, HOST_TO_NET_U32, packet_send_via_transport(), PACKET_TYPE_CLIENT_JOIN, SAFE_STRNCPY, and SET_ERRNO.

◆ acip_send_client_leave()

asciichat_error_t acip_send_client_leave ( acip_transport_t *  transport)

Notify server of client leaving (client → server)

Clean disconnect notification to server.

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

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

277 {
278 if (!transport) {
279 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
280 }
281
282 // Leave has no payload
283 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_LEAVE, NULL, 0, 0);
284}
@ PACKET_TYPE_CLIENT_LEAVE
Clean disconnect notification.
Definition packet.h:389

References ERROR_INVALID_PARAM, packet_send_via_transport(), PACKET_TYPE_CLIENT_LEAVE, 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 146 of file lib/network/acip/client.c.

147 {
148 log_dev("★ ACIP_SEND_IMAGE_FRAME: Called with %ux%u, transport=%p, pixel_data=%p", width, height, (void *)transport,
149 pixel_data);
150
151 if (!transport || !pixel_data) {
152 log_dev("★ ACIP_SEND_IMAGE_FRAME: Invalid params");
153 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or pixel_data");
154 }
155
156 // Calculate pixel data size (3 bytes per pixel for RGB24)
157 size_t pixel_size = (size_t)width * height * 3;
158 log_dev("★ ACIP_SEND_IMAGE_FRAME: pixel_size=%zu", pixel_size);
159
160 // Create image frame packet header
162 header.width = HOST_TO_NET_U32(width);
163 header.height = HOST_TO_NET_U32(height);
164 header.pixel_format = HOST_TO_NET_U32(pixel_format);
165 header.compressed_size = 0;
166 header.checksum = 0;
167 header.timestamp = 0;
168
169 // Calculate total size
170 size_t total_size;
171 if (checked_size_add(sizeof(header), pixel_size, &total_size) != ASCIICHAT_OK) {
172 log_dev("★ ACIP_SEND_IMAGE_FRAME: Overflow in size calculation");
173 return SET_ERRNO(ERROR_INVALID_PARAM, "Packet size overflow");
174 }
175
176 log_dev("★ ACIP_SEND_IMAGE_FRAME: total_size=%zu, allocating buffer", total_size);
177
178 // Allocate buffer
179 uint8_t *buffer = buffer_pool_alloc(NULL, total_size);
180 if (!buffer) {
181 log_dev("★ ACIP_SEND_IMAGE_FRAME: Failed to allocate %zu bytes", total_size);
182 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate buffer: %zu bytes", total_size);
183 }
184
185 // Build packet
186 memcpy(buffer, &header, sizeof(header));
187 memcpy(buffer + sizeof(header), pixel_data, pixel_size);
188
189 log_dev("★ ACIP_SEND_IMAGE_FRAME: About to send packet");
190 // Send via transport
191 asciichat_error_t result = packet_send_via_transport(transport, PACKET_TYPE_IMAGE_FRAME, buffer, total_size, 0);
192
193 log_dev("★ ACIP_SEND_IMAGE_FRAME: packet_send_via_transport returned %d", result);
194
195 buffer_pool_free(NULL, buffer, total_size);
196 return result;
197}
void * buffer_pool_alloc(buffer_pool_t *pool, size_t size)
Allocate a buffer from the pool (lock-free fast path)
@ ERROR_MEMORY
Definition error_codes.h:56
#define log_dev(...)
Log a DEV message (most verbose, development only)
Definition log/log.h:534
@ PACKET_TYPE_IMAGE_FRAME
Complete RGB image with dimensions.
Definition packet.h:363
Image frame packet structure (Packet Type 3)
Definition packet.h:876
uint32_t pixel_format
Pixel format enum (1=RGB24, 2=RGBA32, 3=BGR24, 4=BGRA32)
Definition packet.h:882
uint32_t timestamp
Timestamp when frame was captured (milliseconds since epoch)
Definition packet.h:888
uint32_t compressed_size
Compressed data size (0 = not compressed, >0 = compressed)
Definition packet.h:884
uint32_t checksum
CRC32 checksum of pixel data.
Definition packet.h:886
uint32_t height
Image height in pixels.
Definition packet.h:880
uint32_t width
Image width in pixels.
Definition packet.h:878

References ASCIICHAT_OK, buffer_pool_alloc(), buffer_pool_free(), image_frame_packet_t::checksum, image_frame_packet_t::compressed_size, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_NOT_SUPPORTED, image_frame_packet_t::height, HOST_TO_NET_U32, log_dev, packet_send_via_transport(), PACKET_TYPE_IMAGE_FRAME, image_frame_packet_t::pixel_format, SET_ERRNO, image_frame_packet_t::timestamp, and image_frame_packet_t::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 212 of file lib/network/acip/client.c.

213 {
214 if (!transport || !encoder || !pixel_data) {
215 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Invalid params");
216 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport, encoder, or pixel_data");
217 }
218
219 // Allocate output buffer for H.265 encoding
220 // H.265 can produce output larger than input due to codec overhead
221 // Use 2x multiplier to account for worst-case frame content
222 size_t output_buffer_size = 5 + (width * height * 2);
223 log_dev("[ACIP_SEND_H265_1] About to allocate output buffer (%zu bytes)", output_buffer_size);
224 uint8_t *output_buffer = buffer_pool_alloc(NULL, output_buffer_size);
225 log_dev("[ACIP_SEND_H265_2] ✅ Allocated output buffer");
226 if (!output_buffer) {
227 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Failed to allocate output buffer");
228 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate H.265 output buffer: %zu bytes", output_buffer_size);
229 }
230
231 // Encode frame
232 size_t encoded_size = output_buffer_size - 5;
233 log_dev("[ACIP_SEND_H265_3] Calling h265_encode");
234 asciichat_error_t encode_result = h265_encode(encoder, (uint16_t)width, (uint16_t)height, (const uint8_t *)pixel_data,
235 output_buffer + 5, &encoded_size);
236 log_dev("[ACIP_SEND_H265_4] h265_encode returned: %d, encoded_size=%zu", encode_result, encoded_size);
237
238 if (encode_result != ASCIICHAT_OK) {
239 log_error("H.265 encoding failed: %s", asciichat_error_string(encode_result));
240 buffer_pool_free(NULL, output_buffer, output_buffer_size);
241 return encode_result;
242 }
243
244 // Prepare H.265 packet: [flags:u8][width:u16][height:u16][h265_data...]
245 output_buffer[0] = 0; // flags: no flags set by default
246 output_buffer[1] = (width >> 8) & 0xFF;
247 output_buffer[2] = width & 0xFF;
248 output_buffer[3] = (height >> 8) & 0xFF;
249 output_buffer[4] = height & 0xFF;
250
251 size_t total_size = 5 + encoded_size;
252
253 log_debug("★ ACIP_SEND_IMAGE_FRAME_H265: Encoded %ux%u → %zu bytes", width, height, total_size);
254
255 // Send via transport
256 log_dev("[ACIP_SEND_H265_5] Calling packet_send_via_transport with %zu bytes", total_size);
257 asciichat_error_t result =
258 packet_send_via_transport(transport, PACKET_TYPE_IMAGE_FRAME_H265, output_buffer, total_size, 0);
259 log_dev("[ACIP_SEND_H265_6] packet_send_via_transport returned: %d", result);
260
261 buffer_pool_free(NULL, output_buffer, output_buffer_size);
262 log_dev("[ACIP_SEND_H265_7] ✅ Freed output buffer, returning from acip_send_image_frame_h265");
263 return result;
264}
asciichat_error_t h265_encode(h265_encoder_t *encoder, uint16_t width, uint16_t height, const uint8_t *pixel_data, uint8_t *out_data, size_t *out_len)
unsigned short uint16_t
Definition common.h:57
@ PACKET_TYPE_IMAGE_FRAME_H265
H.265-encoded frame from client (HEVC/H.265 codec)
Definition packet.h:365

References ASCIICHAT_OK, buffer_pool_alloc(), buffer_pool_free(), ERROR_INVALID_PARAM, ERROR_MEMORY, h265_encode(), log_debug, log_dev, log_error, packet_send_via_transport(), PACKET_TYPE_IMAGE_FRAME_H265, and SET_ERRNO.

◆ 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 314 of file lib/network/acip/client.c.

314 {
315 if (!transport || !version) {
316 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or version");
317 }
318
319 return packet_send_via_transport(transport, PACKET_TYPE_PROTOCOL_VERSION, version, sizeof(*version), 0);
320}
@ PACKET_TYPE_PROTOCOL_VERSION
Protocol version and capabilities negotiation.
Definition packet.h:288

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 286 of file lib/network/acip/client.c.

286 {
287 if (!transport) {
288 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
289 }
290
291 // Server expects uint32_t (4 bytes), not uint8_t
292 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
293 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_START, &stream_types_net, sizeof(stream_types_net), 0);
294}
unsigned int uint32_t
Definition common.h:58
@ PACKET_TYPE_STREAM_START
Client requests to start sending video/audio.
Definition packet.h:391

References 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 296 of file lib/network/acip/client.c.

296 {
297 if (!transport) {
298 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
299 }
300
301 // Server expects uint32_t (4 bytes), not uint8_t
302 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
303 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_STOP, &stream_types_net, sizeof(stream_types_net), 0);
304}
@ PACKET_TYPE_STREAM_STOP
Client stops sending media.
Definition packet.h:393

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