31#include <ascii-chat/network/acip/transport.h>
32#include <ascii-chat/network/webrtc/webrtc.h>
33#include <ascii-chat/log/logging.h>
34#include <ascii-chat/ringbuffer.h>
35#include <ascii-chat/buffer_pool.h>
36#include <ascii-chat/platform/mutex.h>
37#include <ascii-chat/platform/cond.h>
47#define WEBRTC_RECV_QUEUE_SIZE 512
77static void webrtc_on_message(webrtc_data_channel_t *channel,
const uint8_t *data,
size_t len,
void *user_data) {
81 if (!wrtc || !data || len == 0) {
93 memcpy(msg.
data, data, len);
124static void webrtc_on_open(webrtc_data_channel_t *channel,
void *user_data) {
136 log_info(
"WebRTC DataChannel opened, transport ready");
142static void webrtc_on_error(webrtc_data_channel_t *channel,
const char *error_msg,
void *user_data) {
146 log_error(
"WebRTC DataChannel error: %s", error_msg ? error_msg :
"unknown error");
163static void webrtc_on_close(webrtc_data_channel_t *channel,
void *user_data) {
167 log_info(
"WebRTC DataChannel closed");
185static asciichat_error_t webrtc_send(acip_transport_t *transport,
const void *data,
size_t len) {
193 return SET_ERRNO(ERROR_NETWORK,
"WebRTC transport not connected");
199 if (result != ASCIICHAT_OK) {
200 return SET_ERRNO(ERROR_NETWORK,
"Failed to send on WebRTC DataChannel");
206static asciichat_error_t webrtc_recv(acip_transport_t *transport,
void **buffer,
size_t *out_len,
207 void **out_allocated_buffer) {
220 return SET_ERRNO(ERROR_NETWORK,
"Connection closed while waiting for data");
233 return SET_ERRNO(ERROR_NETWORK,
"Failed to read from receive queue");
239 *out_allocated_buffer = msg.
data;
244static asciichat_error_t webrtc_close(acip_transport_t *transport) {
270 log_debug(
"WebRTC transport closed");
274static acip_transport_type_t webrtc_get_type(acip_transport_t *transport) {
276 return ACIP_TRANSPORT_WEBRTC;
279static socket_t webrtc_get_socket(acip_transport_t *transport) {
281 return INVALID_SOCKET_VALUE;
284static bool webrtc_is_connected(acip_transport_t *transport) {
307static void webrtc_destroy_impl(acip_transport_t *transport) {
308 if (!transport || !transport->impl_data) {
346 log_debug(
"Destroyed WebRTC transport resources");
353static const acip_transport_methods_t webrtc_methods = {
356 .close = webrtc_close,
357 .get_type = webrtc_get_type,
358 .get_socket = webrtc_get_socket,
359 .is_connected = webrtc_is_connected,
360 .destroy_impl = webrtc_destroy_impl,
368 crypto_context_t *crypto_ctx) {
369 if (!peer_conn || !data_channel) {
370 SET_ERRNO(ERROR_INVALID_PARAM,
"peer_conn and data_channel are required");
375 acip_transport_t *transport = SAFE_MALLOC(
sizeof(acip_transport_t), acip_transport_t *);
377 SET_ERRNO(ERROR_MEMORY,
"Failed to allocate WebRTC transport");
384 SAFE_FREE(transport);
385 SET_ERRNO(ERROR_MEMORY,
"Failed to allocate WebRTC transport data");
392 SAFE_FREE(wrtc_data);
393 SAFE_FREE(transport);
394 SET_ERRNO(ERROR_MEMORY,
"Failed to create receive queue");
401 SAFE_FREE(wrtc_data);
402 SAFE_FREE(transport);
403 SET_ERRNO(ERROR_INTERNAL,
"Failed to initialize queue mutex");
410 SAFE_FREE(wrtc_data);
411 SAFE_FREE(transport);
412 SET_ERRNO(ERROR_INTERNAL,
"Failed to initialize queue condition variable");
420 SAFE_FREE(wrtc_data);
421 SAFE_FREE(transport);
422 SET_ERRNO(ERROR_INTERNAL,
"Failed to initialize state mutex");
432 webrtc_datachannel_callbacks_t callbacks = {
433 .on_open = webrtc_on_open,
434 .on_close = webrtc_on_close,
435 .on_error = webrtc_on_error,
436 .on_message = webrtc_on_message,
437 .user_data = wrtc_data,
441 if (result != ASCIICHAT_OK) {
446 SAFE_FREE(wrtc_data);
447 SAFE_FREE(transport);
448 SET_ERRNO(ERROR_INTERNAL,
"Failed to set DataChannel callbacks");
470 log_debug(
"Transport and DataChannel marked as connected/open (already open from peer_manager callback)");
473 transport->methods = &webrtc_methods;
474 transport->crypto_ctx = crypto_ctx;
475 transport->impl_data = wrtc_data;
477 log_info(
"Created WebRTC transport (crypto: %s)", crypto_ctx ?
"enabled" :
"disabled");
void buffer_pool_free(buffer_pool_t *pool, void *data, size_t size)
void * buffer_pool_alloc(buffer_pool_t *pool, size_t size)
asciichat_error_t webrtc_datachannel_set_callbacks(webrtc_data_channel_t *dc, const webrtc_datachannel_callbacks_t *callbacks)
void webrtc_datachannel_destroy(webrtc_data_channel_t *dc)
void webrtc_peer_connection_close(webrtc_peer_connection_t *pc)
void webrtc_peer_connection_destroy(webrtc_peer_connection_t *pc)
asciichat_error_t webrtc_datachannel_send(webrtc_data_channel_t *dc, const uint8_t *data, size_t size)
void webrtc_datachannel_set_open_state(webrtc_data_channel_t *dc, bool is_open)
ringbuffer_t * ringbuffer_create(size_t element_size, size_t capacity)
void ringbuffer_destroy(ringbuffer_t *rb)
bool ringbuffer_is_empty(const ringbuffer_t *rb)
bool ringbuffer_read(ringbuffer_t *rb, void *data)
bool ringbuffer_write(ringbuffer_t *rb, const void *data)
Receive queue element (variable-length message)
size_t len
Message length in bytes.
uint8_t * data
Message data (allocated, caller must free)
WebRTC transport implementation data.
webrtc_peer_connection_t * peer_conn
Peer connection (owned)
bool is_connected
Connection state.
mutex_t queue_mutex
Protect queue operations.
webrtc_data_channel_t * data_channel
Data channel (owned)
mutex_t state_mutex
Protect state changes.
cond_t queue_cond
Signal when messages arrive.
ringbuffer_t * recv_queue
Receive message queue.
int mutex_init(mutex_t *mutex)
int mutex_destroy(mutex_t *mutex)
#define WEBRTC_RECV_QUEUE_SIZE
Maximum receive queue size (messages buffered before recv())
acip_transport_t * acip_webrtc_transport_create(webrtc_peer_connection_t *peer_conn, webrtc_data_channel_t *data_channel, crypto_context_t *crypto_ctx)