42static bool g_webrtc_initialized =
false;
48static void rtc_log_callback(rtcLogLevel level,
const char *message) {
52 log_error(
"[libdatachannel] %s", message);
55 log_warn(
"[libdatachannel] %s", message);
58 log_info(
"[libdatachannel] %s", message);
62 log_debug(
"[libdatachannel] %s", message);
69static void on_state_change_adapter(
int pc_id, rtcState state,
void *user_data) {
87 case RTC_DISCONNECTED:
101 pc->
state = new_state;
108static void on_local_description_adapter(
int pc_id,
const char *sdp,
const char *type,
void *user_data) {
119static void on_local_candidate_adapter(
int pc_id,
const char *candidate,
const char *mid,
void *user_data) {
130static void on_datachannel_adapter(
int pc_id,
int dc_id,
void *user_data) {
139 log_error(
"Failed to allocate data channel wrapper");
140 rtcDeleteDataChannel(dc_id);
152 log_debug(
"Received DataChannel (id=%d) from remote peer", dc_id);
155static void on_datachannel_open_adapter(
int dc_id,
void *user_data) {
161 log_debug(
"DataChannel opened (id=%d)", dc_id);
168static void on_datachannel_message_adapter(
int dc_id,
const char *data,
int size,
void *user_data) {
179static void on_datachannel_error_adapter(
int dc_id,
const char *error,
void *user_data) {
184 log_error(
"DataChannel error (id=%d): %s", dc_id, error);
196 if (g_webrtc_initialized) {
201 rtcInitLogger(RTC_LOG_INFO, rtc_log_callback);
206 g_webrtc_initialized =
true;
207 log_info(
"WebRTC library initialized (libdatachannel)");
212 if (!g_webrtc_initialized) {
217 g_webrtc_initialized =
false;
218 log_info(
"WebRTC library cleaned up");
226 if (!config || !pc_out) {
230 if (!g_webrtc_initialized) {
245 const char **ice_servers = NULL;
246 size_t ice_count = 0;
250 ice_servers =
SAFE_MALLOC(ice_count *
sizeof(
char *),
const char **);
257 for (
size_t i = 0; i < config->
stun_count; i++) {
262 for (
size_t i = 0; i < config->
turn_count; i++) {
268 rtcConfiguration rtc_config;
269 memset(&rtc_config, 0,
sizeof(rtc_config));
270 rtc_config.iceServers = ice_servers;
271 rtc_config.iceServersCount = (int)ice_count;
272 rtc_config.iceTransportPolicy = RTC_TRANSPORT_POLICY_ALL;
275 int pc_id = rtcCreatePeerConnection(&rtc_config);
290 rtcSetUserPointer(pc_id, pc);
291 rtcSetStateChangeCallback(pc_id, on_state_change_adapter);
292 rtcSetLocalDescriptionCallback(pc_id, on_local_description_adapter);
293 rtcSetLocalCandidateCallback(pc_id, on_local_candidate_adapter);
294 rtcSetDataChannelCallback(pc_id, on_datachannel_adapter);
297 log_debug(
"Created WebRTC peer connection (id=%d)", pc_id);
313 rtcDeletePeerConnection(pc->
rtc_id);
343 int result = rtcSetLocalDescription(pc->
rtc_id, NULL);
344 if (result != RTC_ERR_SUCCESS) {
353 if (!pc || !sdp || !type) {
357 int result = rtcSetRemoteDescription(pc->
rtc_id, sdp, type);
358 if (result != RTC_ERR_SUCCESS) {
362 log_debug(
"Set remote SDP description (pc_id=%d, type=%s)", pc->
rtc_id, type);
371 if (!pc || !candidate) {
375 int result = rtcAddRemoteCandidate(pc->
rtc_id, candidate, mid);
376 if (result != RTC_ERR_SUCCESS) {
390 if (!pc || !label || !dc_out) {
395 int dc_id = rtcCreateDataChannel(pc->
rtc_id, label);
403 rtcDeleteDataChannel(dc_id);
412 rtcSetUserPointer(dc_id, dc);
413 rtcSetOpenCallback(dc_id, on_datachannel_open_adapter);
414 rtcSetMessageCallback(dc_id, on_datachannel_message_adapter);
415 rtcSetErrorCallback(dc_id, on_datachannel_error_adapter);
420 log_debug(
"Created DataChannel '%s' (dc_id=%d, pc_id=%d)", label, dc_id, pc->
rtc_id);
433 int result = rtcSendMessage(dc->
rtc_id, (
const char *)data, (
int)size);
450 static char label[256];
451 int result = rtcGetDataChannelLabel(dc->
rtc_id, label,
sizeof(label));
464 rtcDeleteDataChannel(dc->
rtc_id);
486#pragma clang diagnostic push
487#pragma clang diagnostic ignored "-Wcast-function-type-mismatch"
489 rtcSetOpenCallback(dc->
rtc_id, (rtcOpenCallbackFunc)callbacks->
on_open);
493 rtcSetClosedCallback(dc->
rtc_id, (rtcClosedCallbackFunc)callbacks->
on_close);
497 rtcSetErrorCallback(dc->
rtc_id, (rtcErrorCallbackFunc)callbacks->
on_error);
501 rtcSetMessageCallback(dc->
rtc_id, (rtcMessageCallbackFunc)callbacks->
on_message);
503#pragma clang diagnostic pop
543 rtcDeletePeerConnection(pc->
rtc_id);
#define SAFE_MALLOC(size, cast)
#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)
#define log_warn(...)
Log a WARN message.
#define log_error(...)
Log an ERROR message.
#define log_info(...)
Log an INFO message.
#define log_debug(...)
Log a DEBUG message.
asciichat_error_t webrtc_create_datachannel(webrtc_peer_connection_t *pc, const char *label, webrtc_data_channel_t **dc_out)
Create a DataChannel (for connection initiator)
void webrtc_close_peer_connection(webrtc_peer_connection_t *pc)
Close and destroy a peer connection.
void webrtc_cleanup(void)
Cleanup WebRTC library resources.
asciichat_error_t webrtc_create_offer(webrtc_peer_connection_t *pc)
Create and set local SDP offer (for connection initiator)
asciichat_error_t webrtc_datachannel_set_callbacks(webrtc_data_channel_t *dc, const webrtc_datachannel_callbacks_t *callbacks)
Set DataChannel callbacks.
asciichat_error_t webrtc_add_remote_candidate(webrtc_peer_connection_t *pc, const char *candidate, const char *mid)
Add remote ICE candidate.
webrtc_state_t webrtc_get_state(webrtc_peer_connection_t *pc)
Get current connection state.
asciichat_error_t webrtc_init(void)
Initialize WebRTC library (libdatachannel)
void webrtc_datachannel_destroy(webrtc_data_channel_t *dc)
Destroy a DataChannel and free resources.
asciichat_error_t webrtc_create_peer_connection(const webrtc_config_t *config, webrtc_peer_connection_t **pc_out)
Create a new WebRTC peer connection.
const char * webrtc_datachannel_get_label(webrtc_data_channel_t *dc)
Get DataChannel label.
void * webrtc_get_user_data(webrtc_peer_connection_t *pc)
Get user data pointer from connection.
void webrtc_peer_connection_close(webrtc_peer_connection_t *pc)
Close a peer connection.
webrtc_state_t
WebRTC connection state.
void webrtc_peer_connection_destroy(webrtc_peer_connection_t *pc)
Destroy a peer connection and free resources.
asciichat_error_t webrtc_set_remote_description(webrtc_peer_connection_t *pc, const char *sdp, const char *type)
Set remote SDP offer/answer.
void webrtc_close_datachannel(webrtc_data_channel_t *dc)
Close a DataChannel.
bool webrtc_datachannel_is_open(webrtc_data_channel_t *dc)
Check if DataChannel is open and ready.
asciichat_error_t webrtc_datachannel_send(webrtc_data_channel_t *dc, const uint8_t *data, size_t size)
Send data over DataChannel.
@ WEBRTC_STATE_NEW
Connection created but not started.
@ WEBRTC_STATE_DISCONNECTED
Connection lost.
@ WEBRTC_STATE_FAILED
Connection failed (fatal)
@ WEBRTC_STATE_CLOSED
Connection closed cleanly.
@ WEBRTC_STATE_CONNECTING
ICE gathering/connection in progress.
@ WEBRTC_STATE_CONNECTED
DataChannel established and ready.
📝 Logging API with multiple log levels and terminal output control
webrtc_datachannel_message_callback_t on_datachannel_message
webrtc_local_description_callback_t on_local_description
webrtc_local_candidate_callback_t on_local_candidate
size_t stun_count
Number of STUN servers.
webrtc_state_callback_t on_state_change
webrtc_datachannel_error_callback_t on_datachannel_error
turn_server_t * turn_servers
Array of TURN servers.
stun_server_t * stun_servers
Array of STUN servers.
void * user_data
Passed to all callbacks.
size_t turn_count
Number of TURN servers.
webrtc_datachannel_open_callback_t on_datachannel_open
bool is_open
Channel open state.
webrtc_peer_connection_t * pc
Parent peer connection.
int rtc_id
libdatachannel data channel ID
DataChannel callback structure.
void(* on_close)(webrtc_data_channel_t *dc, void *user_data)
Channel closed.
void(* on_error)(webrtc_data_channel_t *dc, const char *error, void *user_data)
Error occurred.
void * user_data
Passed to all callbacks.
void(* on_open)(webrtc_data_channel_t *dc, void *user_data)
Channel opened.
void(* on_message)(webrtc_data_channel_t *dc, const uint8_t *data, size_t len, void *user_data)
Message received.
webrtc_data_channel_t * dc
Primary data channel (if created/received)
int rtc_id
libdatachannel peer connection ID
webrtc_state_t state
Current connection state.
webrtc_config_t config
Configuration with callbacks.