ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
lib/network/acip/client.c
Go to the documentation of this file.
1
13#include "network/acip/client.h"
14#include "network/acip/send.h"
16#include "network/packet.h"
17#include "buffer_pool.h"
18#include "log/logging.h"
19#include "common.h"
20#include "util/endian.h"
21#include "util/overflow.h"
22#include <string.h>
23
24// =============================================================================
25// Client Receive (from server)
26// =============================================================================
27
29 const acip_client_callbacks_t *callbacks) {
30 if (!transport || !callbacks) {
31 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or callbacks");
32 }
33
34 // Get socket from transport for low-level packet reception
35 socket_t sock = transport->methods->get_socket(transport);
36 if (sock == INVALID_SOCKET_VALUE) {
37 return SET_ERRNO(ERROR_NETWORK, "Transport has no valid socket");
38 }
39
40 // Check if transport is connected
41 if (!transport->methods->is_connected(transport)) {
42 return SET_ERRNO(ERROR_NETWORK, "Transport not connected");
43 }
44
45 // Receive packet with automatic decryption
46 packet_envelope_t envelope;
47 bool enforce_encryption = (transport->crypto_ctx != NULL);
48 packet_recv_result_t result = receive_packet_secure(sock, transport->crypto_ctx, enforce_encryption, &envelope);
49
50 // Handle receive errors
51 if (result != PACKET_RECV_SUCCESS) {
52 if (result == PACKET_RECV_EOF) {
53 return SET_ERRNO(ERROR_NETWORK, "Connection closed (EOF)");
54 } else if (result == PACKET_RECV_SECURITY_VIOLATION) {
55 return SET_ERRNO(ERROR_CRYPTO, "Security violation: unencrypted packet when encryption required");
56 } else {
57 return SET_ERRNO(ERROR_NETWORK, "Failed to receive packet");
58 }
59 }
60
61 // Dispatch packet to appropriate ACIP handler
62 asciichat_error_t dispatch_result =
63 acip_handle_client_packet(transport, envelope.type, envelope.data, envelope.len, callbacks);
64
65 // Always free the allocated buffer (even if handler failed)
66 if (envelope.allocated_buffer) {
67 buffer_pool_free(NULL, envelope.allocated_buffer, envelope.allocated_size);
68 }
69
70 // Return handler result
71 return dispatch_result;
72}
73
74// =============================================================================
75// Client Send (to server)
76// =============================================================================
77
78asciichat_error_t acip_send_image_frame(acip_transport_t *transport, const void *pixel_data, uint32_t width,
79 uint32_t height, uint32_t pixel_format) {
80 if (!transport || !pixel_data) {
81 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or pixel_data");
82 }
83
84 // Calculate pixel data size (3 bytes per pixel for RGB24)
85 size_t pixel_size = (size_t)width * height * 3;
86
87 // Create image frame packet header
89 header.width = HOST_TO_NET_U32(width);
90 header.height = HOST_TO_NET_U32(height);
91 header.pixel_format = HOST_TO_NET_U32(pixel_format);
92 header.compressed_size = 0;
93 header.checksum = 0;
94 header.timestamp = 0;
95
96 // Calculate total size
97 size_t total_size;
98 if (checked_size_add(sizeof(header), pixel_size, &total_size) != ASCIICHAT_OK) {
99 return SET_ERRNO(ERROR_INVALID_PARAM, "Packet size overflow");
100 }
101
102 // Allocate buffer
103 uint8_t *buffer = buffer_pool_alloc(NULL, total_size);
104 if (!buffer) {
105 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate buffer: %zu bytes", total_size);
106 }
107
108 // Build packet
109 memcpy(buffer, &header, sizeof(header));
110 memcpy(buffer + sizeof(header), pixel_data, pixel_size);
111
112 // Send via transport
113 asciichat_error_t result = packet_send_via_transport(transport, PACKET_TYPE_IMAGE_FRAME, buffer, total_size);
114
115 buffer_pool_free(NULL, buffer, total_size);
116 return result;
117}
118
120 if (!transport) {
121 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
122 }
123
124 // Simple capability byte payload
125 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_JOIN, &capabilities, sizeof(capabilities));
126}
127
129 if (!transport) {
130 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
131 }
132
133 // Leave has no payload
134 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_LEAVE, NULL, 0);
135}
136
138 if (!transport) {
139 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
140 }
141
142 // Server expects uint32_t (4 bytes), not uint8_t
143 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
144 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_START, &stream_types_net, sizeof(stream_types_net));
145}
146
148 if (!transport) {
149 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport");
150 }
151
152 // Server expects uint32_t (4 bytes), not uint8_t
153 uint32_t stream_types_net = HOST_TO_NET_U32((uint32_t)stream_types);
154 return packet_send_via_transport(transport, PACKET_TYPE_STREAM_STOP, &stream_types_net, sizeof(stream_types_net));
155}
156
157asciichat_error_t acip_send_capabilities(acip_transport_t *transport, const void *cap_data, size_t cap_len) {
158 if (!transport || !cap_data) {
159 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or cap_data");
160 }
161
162 return packet_send_via_transport(transport, PACKET_TYPE_CLIENT_CAPABILITIES, cap_data, cap_len);
163}
164
166 if (!transport || !version) {
167 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid transport or version");
168 }
169
170 return packet_send_via_transport(transport, PACKET_TYPE_PROTOCOL_VERSION, version, sizeof(*version));
171}
🗃️ Lock-Free Unified Memory Buffer Pool with Lazy Allocation
🔄 Network byte order conversion helpers
#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_NETWORK
Definition error_codes.h:69
@ ERROR_MEMORY
Definition error_codes.h:53
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_CRYPTO
Definition error_codes.h:88
@ ERROR_INVALID_PARAM
uint32_t pixel_format
Pixel format enum (0=RGB24, 1=RGBA32, 2=BGR24, etc.)
Definition packet.h:774
uint32_t timestamp
Timestamp when frame was captured (milliseconds since epoch)
Definition packet.h:780
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
uint32_t compressed_size
Compressed data size (0 = not compressed, >0 = compressed)
Definition packet.h:776
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
uint32_t checksum
CRC32 checksum of pixel data.
Definition packet.h:778
uint32_t height
Image height in pixels.
Definition packet.h:772
packet_type_t type
Packet type (from packet_types.h)
Definition packet.h:982
uint32_t width
Image width in pixels.
Definition packet.h:770
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
@ PACKET_TYPE_CLIENT_LEAVE
Clean disconnect notification.
Definition packet.h:302
@ PACKET_TYPE_IMAGE_FRAME
Complete RGB image with dimensions.
Definition packet.h:288
@ PACKET_TYPE_STREAM_START
Client requests to start sending video/audio.
Definition packet.h:304
@ PACKET_TYPE_PROTOCOL_VERSION
Protocol version and capabilities negotiation.
Definition packet.h:283
@ PACKET_TYPE_CLIENT_JOIN
Client announces capability to send media.
Definition packet.h:300
@ PACKET_TYPE_CLIENT_CAPABILITIES
Client reports terminal capabilities.
Definition packet.h:293
@ PACKET_TYPE_STREAM_STOP
Client stops sending media.
Definition packet.h:306
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_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.
Definition handlers.c:119
ACIP protocol packet handlers (transport-agnostic)
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_stream_stop(acip_transport_t *transport, uint8_t stream_types)
Request to stop media streaming (client → server)
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_stream_start(acip_transport_t *transport, uint8_t stream_types)
Request to start 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_client_leave(acip_transport_t *transport)
Notify server of client leaving (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)
asciichat_error_t acip_send_client_join(acip_transport_t *transport, uint8_t capabilities)
Announce client join to server (client → server)
ACIP client-side protocol library.
📝 Logging API with multiple log levels and terminal output control
✅ Safe Integer Arithmetic and Overflow Detection
Packet protocol implementation with encryption and compression support.
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
ACIP shared/bidirectional packet sending functions.
Client-side packet handler callbacks.
Definition handlers.h:51
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
Transport instance structure.
Definition transport.h:169
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
Image frame packet structure (Packet Type 3)
Definition packet.h:768
Packet envelope containing received packet data.
Definition packet.h:980
Protocol version negotiation packet structure (Packet Type 1)
Definition packet.h:710