ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
transport.c File Reference

Go to the source code of this file.

Data Structures

struct  webrtc_recv_msg_t
 Receive queue element (variable-length message) More...
 
struct  webrtc_transport_data_t
 WebRTC transport implementation data. More...
 

Macros

#define WEBRTC_RECV_QUEUE_SIZE   512
 Maximum receive queue size (messages buffered before recv())
 
#define WEBRTC_RECV_QUEUE_HIGH_WATER   12
 
#define WEBRTC_SEND_VIDEO_HIGH_WATER   (256 * 1024)
 
#define WEBRTC_DISCONNECTED_GRACE_NS   (30 * NS_PER_SEC_INT)
 

Functions

acip_transport_t * acip_webrtc_transport_create (webrtc_peer_connection_t *peer_conn, webrtc_data_channel_t *data_channel, crypto_context_t *crypto_ctx)
 

Macro Definition Documentation

◆ WEBRTC_DISCONNECTED_GRACE_NS

#define WEBRTC_DISCONNECTED_GRACE_NS   (30 * NS_PER_SEC_INT)

Definition at line 62 of file webrtc/transport.c.

◆ WEBRTC_RECV_QUEUE_HIGH_WATER

#define WEBRTC_RECV_QUEUE_HIGH_WATER   12

Definition at line 53 of file webrtc/transport.c.

◆ WEBRTC_RECV_QUEUE_SIZE

#define WEBRTC_RECV_QUEUE_SIZE   512

Maximum receive queue size (messages buffered before recv())

Power of 2 for ringbuffer optimization. Completed ACIP packets are queued here. On overflow, retain control packets and recent media so the connection can recover.

Definition at line 50 of file webrtc/transport.c.

◆ WEBRTC_SEND_VIDEO_HIGH_WATER

#define WEBRTC_SEND_VIDEO_HIGH_WATER   (256 * 1024)

Definition at line 58 of file webrtc/transport.c.

Function Documentation

◆ acip_webrtc_transport_create()

acip_transport_t * acip_webrtc_transport_create ( webrtc_peer_connection_t *  peer_conn,
webrtc_data_channel_t *  data_channel,
crypto_context_t *  crypto_ctx 
)

Definition at line 614 of file webrtc/transport.c.

615 {
616 if (!peer_conn || !data_channel) {
617 SET_ERRNO(ERROR_INVALID_PARAM, "peer_conn and data_channel are required");
618 return NULL;
619 }
620
621 // Allocate transport structure
623 if (!transport) {
624 SET_ERRNO(ERROR_MEMORY, "Failed to allocate WebRTC transport");
625 return NULL;
626 }
627
628 // Allocate WebRTC-specific data
630 if (!wrtc_data) {
631 SAFE_FREE(transport);
632 SET_ERRNO(ERROR_MEMORY, "Failed to allocate WebRTC transport data");
633 return NULL;
634 }
635
636 // Create receive queue
638 if (!wrtc_data->recv_queue) {
639 SAFE_FREE(wrtc_data);
640 SAFE_FREE(transport);
641 SET_ERRNO(ERROR_MEMORY, "Failed to create receive queue");
642 return NULL;
643 }
644
645 // Initialize synchronization primitives
646 if (mutex_init(&wrtc_data->queue_mutex, "webrtc_queue") != 0) {
647 ringbuffer_destroy(wrtc_data->recv_queue);
648 SAFE_FREE(wrtc_data);
649 SAFE_FREE(transport);
650 SET_ERRNO(ERROR_INTERNAL, "Failed to initialize queue mutex");
651 return NULL;
652 }
653
654 if (cond_init(&wrtc_data->queue_cond, "queue") != 0) {
655 mutex_destroy(&wrtc_data->queue_mutex);
656 ringbuffer_destroy(wrtc_data->recv_queue);
657 SAFE_FREE(wrtc_data);
658 SAFE_FREE(transport);
659 SET_ERRNO(ERROR_INTERNAL, "Failed to initialize queue condition variable");
660 return NULL;
661 }
662
663 if (mutex_init(&wrtc_data->state_mutex, "webrtc_state") != 0) {
664 cond_destroy(&wrtc_data->queue_cond);
665 mutex_destroy(&wrtc_data->queue_mutex);
666 ringbuffer_destroy(wrtc_data->recv_queue);
667 SAFE_FREE(wrtc_data);
668 SAFE_FREE(transport);
669 SET_ERRNO(ERROR_INTERNAL, "Failed to initialize state mutex");
670 return NULL;
671 }
672
673 if (mutex_init(&wrtc_data->send_mutex, "webrtc_send") != 0) {
674 mutex_destroy(&wrtc_data->state_mutex);
675 cond_destroy(&wrtc_data->queue_cond);
676 mutex_destroy(&wrtc_data->queue_mutex);
677 ringbuffer_destroy(wrtc_data->recv_queue);
678 SAFE_FREE(wrtc_data);
679 SAFE_FREE(transport);
680 SET_ERRNO(ERROR_INTERNAL, "Failed to initialize send mutex");
681 return NULL;
682 }
683
684 // Initialize WebRTC data
685 wrtc_data->peer_conn = peer_conn;
686 wrtc_data->data_channel = data_channel;
687 wrtc_data->is_connected = false; // Will be set to true in on_open callback
688
689 // Register DataChannel callbacks
691 .on_open = webrtc_on_open,
692 .on_close = webrtc_on_close,
693 .on_error = webrtc_on_error,
694 .on_message = webrtc_on_message,
695 .user_data = wrtc_data,
696 };
697
698 asciichat_error_t result = webrtc_datachannel_set_callbacks(data_channel, &callbacks);
699 if (result != ASCIICHAT_OK) {
700 mutex_destroy(&wrtc_data->send_mutex);
701 mutex_destroy(&wrtc_data->state_mutex);
702 cond_destroy(&wrtc_data->queue_cond);
703 mutex_destroy(&wrtc_data->queue_mutex);
704 ringbuffer_destroy(wrtc_data->recv_queue);
705 SAFE_FREE(wrtc_data);
706 SAFE_FREE(transport);
707 SET_ERRNO(ERROR_INTERNAL, "Failed to set DataChannel callbacks");
708 return NULL;
709 }
710
711 // IMPORTANT: The transport is always created from peer_manager's on_datachannel_open callback,
712 // which means the DataChannel is ALREADY OPEN when we get here. However, by setting our own
713 // callbacks above (webrtc_datachannel_set_callbacks), we replaced the callbacks that would
714 // have set dc->is_open=true. So we need to manually mark both the transport AND the DataChannel
715 // as open/connected now.
716 //
717 // We cannot rely on webrtc_on_open being called later because:
718 // 1. The DataChannel is already open
719 // 2. libdatachannel won't fire the open event again
720 // 3. Setting callbacks after open doesn't trigger a retroactive open event
721
722 // Mark DataChannel as open (needed for webrtc_datachannel_send() check)
723 webrtc_datachannel_set_open_state(data_channel, true);
724
725 // Mark transport as connected
726 mutex_lock(&wrtc_data->state_mutex);
727 wrtc_data->is_connected = true;
728 mutex_unlock(&wrtc_data->state_mutex);
729 log_debug("Transport and DataChannel marked as connected/open (already open from peer_manager callback)");
730
731 // Initialize transport
732 transport->methods = &webrtc_methods;
733 transport->crypto_ctx = crypto_ctx;
734 transport->impl_data = wrtc_data;
735
736 log_info("Created WebRTC transport (crypto: %s)", crypto_ctx ? "enabled" : "disabled");
737
738 // Register WebRTC transport implementation data with transport as parent
739 NAMED_REGISTER(wrtc_data, "impl", "webrtc_impl", "0x%tx", (uintptr_t)(const void *)(transport));
740
741 return transport;
742}
#define SAFE_FREE(ptr)
Definition common.h:376
#define SAFE_MALLOC(size, cast)
Definition common.h:264
#define SAFE_CALLOC(count, size, cast)
Definition common.h:274
#define NAMED_REGISTER(ptr, name, type, fmt, parent_ptr)
Register any pointer with base name, type, format spec, and location (auto-suffix)
#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_MEMORY
Definition error_codes.h:56
@ ASCIICHAT_OK
Definition error_codes.h:51
@ ERROR_INVALID_PARAM
@ ERROR_INTERNAL
Definition error_codes.h:92
#define log_info(...)
Log an INFO message.
Definition log/log.h:561
#define log_debug(...)
Log a DEBUG message.
Definition log/log.h:548
#define mutex_lock(mutex)
Lock a mutex (with debug tracking in debug builds)
int mutex_init(mutex_t *mutex, const char *name)
Initialize a mutex with a name.
Definition threading.c:16
int cond_init(cond_t *cond, const char *name)
Initialize a condition variable with a name.
#define mutex_unlock(mutex)
Unlock a mutex (with debug tracking in debug builds)
int cond_destroy(cond_t *cond)
Destroy a condition variable.
int mutex_destroy(mutex_t *mutex)
Destroy a mutex.
Definition threading.c:22
ringbuffer_t * ringbuffer_create(size_t element_size, size_t capacity)
Create a new ring buffer.
Definition ringbuffer.c:29
void ringbuffer_destroy(ringbuffer_t *rb)
Destroy a ring buffer and free its memory.
Definition ringbuffer.c:53
asciichat_error_t webrtc_datachannel_set_callbacks(webrtc_data_channel_t *dc, const webrtc_datachannel_callbacks_t *callbacks)
Set DataChannel callbacks.
void webrtc_datachannel_set_open_state(webrtc_data_channel_t *dc, bool is_open)
Set DataChannel open state (internal use)
Transport instance structure.
Definition transport.h:214
void * impl_data
Transport-specific state.
Definition transport.h:218
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
void(* on_open)(webrtc_data_channel_t *dc, void *user_data)
Channel opened.
Receive queue element (variable-length message)
WebRTC transport implementation data.
webrtc_peer_connection_t * peer_conn
Borrowed peer connection.
bool is_connected
Connection state.
mutex_t queue_mutex
Protect queue operations.
webrtc_data_channel_t * data_channel
Borrowed data channel.
mutex_t send_mutex
Keep chunks from concurrent packets together.
mutex_t state_mutex
Protect state changes.
cond_t queue_cond
Signal when messages arrive.
ringbuffer_t * recv_queue
Receive message queue.
#define WEBRTC_RECV_QUEUE_SIZE
Maximum receive queue size (messages buffered before recv())

References ASCIICHAT_OK, cond_destroy(), cond_init(), acip_transport::crypto_ctx, webrtc_transport_data_t::data_channel, ERROR_INTERNAL, ERROR_INVALID_PARAM, ERROR_MEMORY, acip_transport::impl_data, webrtc_transport_data_t::is_connected, log_debug, log_info, acip_transport::methods, mutex_destroy(), mutex_init(), mutex_lock, mutex_unlock, NAMED_REGISTER, webrtc_datachannel_callbacks_t::on_open, webrtc_transport_data_t::peer_conn, webrtc_transport_data_t::queue_cond, webrtc_transport_data_t::queue_mutex, webrtc_transport_data_t::recv_queue, ringbuffer_create(), ringbuffer_destroy(), SAFE_CALLOC, SAFE_FREE, SAFE_MALLOC, webrtc_transport_data_t::send_mutex, SET_ERRNO, webrtc_transport_data_t::state_mutex, webrtc_datachannel_set_callbacks(), webrtc_datachannel_set_open_state(), and WEBRTC_RECV_QUEUE_SIZE.