ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
WebRTC Peer Manager

Manage WebRTC peer connections for session participants. More...

Data Structures

struct  webrtc_peer_manager_config_t
 Peer manager configuration. More...
 
struct  webrtc_signaling_callbacks_t
 Signaling callbacks for sending SDP/ICE. More...
 

Typedefs

typedef struct webrtc_peer_manager webrtc_peer_manager_t
 
typedef void(* webrtc_transport_ready_callback_t) (acip_transport_t *transport, const uint8_t participant_id[16], void *user_data)
 Callback when DataChannel is ready and wrapped in ACIP transport.
 
typedef asciichat_error_t(* webrtc_send_sdp_callback_t) (const uint8_t session_id[16], const uint8_t recipient_id[16], const char *sdp_type, const char *sdp, void *user_data)
 Callback to send SDP via ACDS signaling.
 
typedef asciichat_error_t(* webrtc_send_ice_callback_t) (const uint8_t session_id[16], const uint8_t recipient_id[16], const char *candidate, const char *mid, void *user_data)
 Callback to send ICE candidate via ACDS signaling.
 

Enumerations

enum  webrtc_peer_role_t { WEBRTC_ROLE_CREATOR = 0 , WEBRTC_ROLE_JOINER = 1 }
 Peer connection role (server or client) More...
 

Functions

asciichat_error_t webrtc_peer_manager_create (const webrtc_peer_manager_config_t *config, const webrtc_signaling_callbacks_t *signaling_callbacks, webrtc_peer_manager_t **manager_out)
 Create a WebRTC peer manager.
 
void webrtc_peer_manager_destroy (webrtc_peer_manager_t *manager)
 Destroy peer manager and close all connections.
 
asciichat_error_t webrtc_peer_manager_handle_sdp (webrtc_peer_manager_t *manager, const acip_webrtc_sdp_t *sdp)
 Handle incoming SDP message from ACDS.
 
asciichat_error_t webrtc_peer_manager_handle_ice (webrtc_peer_manager_t *manager, const acip_webrtc_ice_t *ice)
 Handle incoming ICE candidate from ACDS.
 
asciichat_error_t webrtc_peer_manager_connect (webrtc_peer_manager_t *manager, const uint8_t session_id[16], const uint8_t participant_id[16])
 Initiate connection to remote peer (joiner role only)
 

Detailed Description

Manage WebRTC peer connections for session participants.

Typedef Documentation

◆ webrtc_peer_manager_t

#include <peer_manager.h>

Definition at line 50 of file peer_manager.h.

◆ webrtc_send_ice_callback_t

typedef asciichat_error_t(* webrtc_send_ice_callback_t) (const uint8_t session_id[16], const uint8_t recipient_id[16], const char *candidate, const char *mid, void *user_data)

#include <peer_manager.h>

Callback to send ICE candidate via ACDS signaling.

Parameters
session_idSession UUID (16 bytes)
recipient_idRecipient participant UUID (16 bytes, all zeros for broadcast)
candidateICE candidate string (null-terminated)
midMedia stream ID (null-terminated)
user_dataUser context pointer
Returns
ASCIICHAT_OK on success, error code on failure

Implementation should send PACKET_TYPE_ACIP_WEBRTC_ICE via ACDS.

Definition at line 112 of file peer_manager.h.

◆ webrtc_send_sdp_callback_t

typedef asciichat_error_t(* webrtc_send_sdp_callback_t) (const uint8_t session_id[16], const uint8_t recipient_id[16], const char *sdp_type, const char *sdp, void *user_data)

#include <peer_manager.h>

Callback to send SDP via ACDS signaling.

Parameters
session_idSession UUID (16 bytes)
recipient_idRecipient participant UUID (16 bytes, all zeros for broadcast)
sdp_typeSDP type ("offer" or "answer")
sdpSDP string (null-terminated)
user_dataUser context pointer
Returns
ASCIICHAT_OK on success, error code on failure

Implementation should send PACKET_TYPE_ACIP_WEBRTC_SDP via ACDS.

Definition at line 98 of file peer_manager.h.

◆ webrtc_transport_ready_callback_t

typedef void(* webrtc_transport_ready_callback_t) (acip_transport_t *transport, const uint8_t participant_id[16], void *user_data)

#include <peer_manager.h>

Callback when DataChannel is ready and wrapped in ACIP transport.

Parameters
transportACIP transport wrapping the WebRTC DataChannel
participant_idRemote participant UUID (16 bytes)
user_dataUser context pointer

The callback receives ownership of the transport and must either:

Definition at line 70 of file peer_manager.h.

Enumeration Type Documentation

◆ webrtc_peer_role_t

#include <peer_manager.h>

Peer connection role (server or client)

Enumerator
WEBRTC_ROLE_CREATOR 

Session creator - accepts offers, generates answers.

WEBRTC_ROLE_JOINER 

Session joiner - generates offers, receives answers.

Definition at line 55 of file peer_manager.h.

55 {
webrtc_peer_role_t
Peer connection role (server or client)
@ WEBRTC_ROLE_JOINER
Session joiner - generates offers, receives answers.
@ WEBRTC_ROLE_CREATOR
Session creator - accepts offers, generates answers.

Function Documentation

◆ webrtc_peer_manager_connect()

asciichat_error_t webrtc_peer_manager_connect ( webrtc_peer_manager_t manager,
const uint8_t  session_id[16],
const uint8_t  participant_id[16] 
)

#include <peer_manager.h>

Initiate connection to remote peer (joiner role only)

Parameters
managerPeer manager
session_idSession UUID (16 bytes)
participant_idRemote participant UUID to connect to (16 bytes)
Returns
ASCIICHAT_OK on success, error code on failure

Creates peer connection, generates SDP offer, and sends via signaling. Only valid for WEBRTC_ROLE_JOINER (session joiners initiate connections).

Creator role uses webrtc_peer_manager_handle_sdp() to accept offers instead.

Definition at line 417 of file peer_manager.c.

418 {
419 if (!manager || !session_id || !participant_id) {
420 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
421 }
422
423 if (manager->role != WEBRTC_ROLE_JOINER) {
424 return SET_ERRNO(ERROR_INVALID_PARAM, "Only joiners can initiate connections");
425 }
426
427 mutex_lock(&manager->peers_mutex);
428
429 // Create peer connection
430 peer_entry_t *peer;
431 asciichat_error_t result = create_peer_connection_locked(manager, session_id, participant_id, &peer);
432 if (result != ASCIICHAT_OK) {
433 mutex_unlock(&manager->peers_mutex);
434 return SET_ERRNO(result, "Failed to create peer connection");
435 }
436
437 mutex_unlock(&manager->peers_mutex);
438
439 // Create SDP offer (triggers on_local_description callback)
440 result = webrtc_create_offer(peer->pc);
441 if (result != ASCIICHAT_OK) {
442 return SET_ERRNO(result, "Failed to create SDP offer");
443 }
444
445 log_info("Initiated WebRTC connection to participant");
446
447 return ASCIICHAT_OK;
448}
#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
@ ASCIICHAT_OK
Definition error_codes.h:48
@ ERROR_INVALID_PARAM
#define log_info(...)
Log an INFO message.
#define mutex_lock(mutex)
Lock a mutex (with debug tracking in debug builds)
Definition mutex.h:140
#define mutex_unlock(mutex)
Unlock a mutex (with debug tracking in debug builds)
Definition mutex.h:175
asciichat_error_t webrtc_create_offer(webrtc_peer_connection_t *pc)
Create and set local SDP offer (for connection initiator)
uint8_t session_id[16]
uint8_t participant_id[16]
Per-peer connection state.
webrtc_peer_connection_t * pc
WebRTC peer connection.
webrtc_peer_role_t role
Session role.
mutex_t peers_mutex
Protect peers hash table.

References ASCIICHAT_OK, ERROR_INVALID_PARAM, log_info, mutex_lock, mutex_unlock, participant_id, peer_entry_t::pc, peers_mutex, role, session_id, SET_ERRNO, webrtc_create_offer(), and WEBRTC_ROLE_JOINER.

◆ webrtc_peer_manager_create()

asciichat_error_t webrtc_peer_manager_create ( const webrtc_peer_manager_config_t config,
const webrtc_signaling_callbacks_t signaling_callbacks,
webrtc_peer_manager_t **  manager_out 
)

#include <peer_manager.h>

Create a WebRTC peer manager.

Parameters
configManager configuration
signaling_callbacksCallbacks for sending SDP/ICE
manager_outOutput parameter for manager handle
Returns
ASCIICHAT_OK on success, error code on failure

Creates a manager for WebRTC peer connections. The manager handles:

  • Peer connection creation and lifecycle
  • SDP offer/answer generation and processing
  • ICE candidate exchange
  • ACIP transport wrapping when DataChannel opens

Definition at line 293 of file peer_manager.c.

295 {
296 if (!config || !signaling_callbacks || !manager_out) {
297 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
298 }
299
300 if (!signaling_callbacks->send_sdp || !signaling_callbacks->send_ice) {
301 return SET_ERRNO(ERROR_INVALID_PARAM, "Signaling callbacks required");
302 }
303
304 // Allocate manager
306 if (!manager) {
307 return SET_ERRNO(ERROR_MEMORY, "Failed to allocate peer manager");
308 }
309
310 memcpy(&manager->config, config, sizeof(*config));
311 memcpy(&manager->signaling, signaling_callbacks, sizeof(*signaling_callbacks));
312 manager->role = config->role;
313 manager->peers = NULL;
314
315 if (mutex_init(&manager->peers_mutex) != 0) {
316 SAFE_FREE(manager);
317 return SET_ERRNO(ERROR_INTERNAL, "Failed to initialize peers mutex");
318 }
319
320 log_info("Created WebRTC peer manager (role: %s)", manager->role == WEBRTC_ROLE_CREATOR ? "creator" : "joiner");
321
322 *manager_out = manager;
323 return ASCIICHAT_OK;
324}
#define SAFE_FREE(ptr)
Definition common.h:320
#define SAFE_MALLOC(size, cast)
Definition common.h:208
@ ERROR_MEMORY
Definition error_codes.h:53
@ ERROR_INTERNAL
Definition error_codes.h:84
int mutex_init(mutex_t *mutex)
Initialize a mutex.
webrtc_peer_role_t role
Session role (creator or joiner)
WebRTC peer manager structure.
peer_entry_t * peers
Hash table of peer connections.
webrtc_peer_manager_config_t config
Manager configuration.
webrtc_signaling_callbacks_t signaling
Signaling callbacks.
webrtc_send_sdp_callback_t send_sdp
Send SDP via ACDS.
webrtc_send_ice_callback_t send_ice
Send ICE via ACDS.

References ASCIICHAT_OK, config, ERROR_INTERNAL, ERROR_INVALID_PARAM, ERROR_MEMORY, log_info, mutex_init(), peers, peers_mutex, role, webrtc_peer_manager_config_t::role, SAFE_FREE, SAFE_MALLOC, webrtc_signaling_callbacks_t::send_ice, webrtc_signaling_callbacks_t::send_sdp, SET_ERRNO, signaling, and WEBRTC_ROLE_CREATOR.

Referenced by server_main().

◆ webrtc_peer_manager_destroy()

void webrtc_peer_manager_destroy ( webrtc_peer_manager_t manager)

#include <peer_manager.h>

Destroy peer manager and close all connections.

Parameters
managerPeer manager to destroy

Closes all active peer connections gracefully and frees resources. Safe to call with NULL pointer.

Definition at line 326 of file peer_manager.c.

326 {
327 if (!manager) {
328 return;
329 }
330
331 mutex_lock(&manager->peers_mutex);
332
333 // Close all peer connections
334 peer_entry_t *peer, *tmp;
335 HASH_ITER(hh, manager->peers, peer, tmp) {
336 remove_peer_locked(manager, peer);
337 }
338
339 mutex_unlock(&manager->peers_mutex);
340 mutex_destroy(&manager->peers_mutex);
341
342 SAFE_FREE(manager);
343
344 log_debug("Destroyed WebRTC peer manager");
345}
#define log_debug(...)
Log a DEBUG message.
int mutex_destroy(mutex_t *mutex)
Destroy a mutex.

References log_debug, mutex_destroy(), mutex_lock, mutex_unlock, peers, peers_mutex, and SAFE_FREE.

Referenced by connection_context_cleanup(), and server_main().

◆ webrtc_peer_manager_handle_ice()

asciichat_error_t webrtc_peer_manager_handle_ice ( webrtc_peer_manager_t manager,
const acip_webrtc_ice_t ice 
)

#include <peer_manager.h>

Handle incoming ICE candidate from ACDS.

Parameters
managerPeer manager
iceICE candidate message received from ACDS
Returns
ASCIICHAT_OK on success, error code on failure

Adds remote ICE candidate to the appropriate peer connection. If peer connection doesn't exist yet, queues candidate for later.

Definition at line 385 of file peer_manager.c.

385 {
386 if (!manager || !ice) {
387 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
388 }
389
390 // Extract ICE candidate and mid
391 const char *candidate = (const char *)(ice + 1); // After header
392 const char *mid = candidate + ice->candidate_len;
393
394 log_debug("Handling incoming ICE candidate from remote peer");
395
396 mutex_lock(&manager->peers_mutex);
397
398 // Find peer connection
399 peer_entry_t *peer = find_peer_locked(manager, ice->sender_id);
400 if (!peer) {
401 mutex_unlock(&manager->peers_mutex);
402 log_warn("ICE candidate for unknown peer, ignoring");
403 return ASCIICHAT_OK;
404 }
405
406 mutex_unlock(&manager->peers_mutex);
407
408 // Add remote ICE candidate
409 asciichat_error_t result = webrtc_add_remote_candidate(peer->pc, candidate, mid);
410 if (result != ASCIICHAT_OK) {
411 return SET_ERRNO(result, "Failed to add remote ICE candidate");
412 }
413
414 return ASCIICHAT_OK;
415}
#define log_warn(...)
Log a WARN message.
asciichat_error_t webrtc_add_remote_candidate(webrtc_peer_connection_t *pc, const char *candidate, const char *mid)
Add remote ICE candidate.

References ASCIICHAT_OK, ERROR_INVALID_PARAM, log_debug, log_warn, mutex_lock, mutex_unlock, peer_entry_t::pc, peers_mutex, SET_ERRNO, and webrtc_add_remote_candidate().

◆ webrtc_peer_manager_handle_sdp()

asciichat_error_t webrtc_peer_manager_handle_sdp ( webrtc_peer_manager_t manager,
const acip_webrtc_sdp_t sdp 
)

#include <peer_manager.h>

Handle incoming SDP message from ACDS.

Parameters
managerPeer manager
sdpSDP message received from ACDS
Returns
ASCIICHAT_OK on success, error code on failure

Processes SDP offer or answer from remote peer:

  • Creator role + offer: Create peer connection, set remote SDP, generate answer
  • Joiner role + answer: Set remote SDP on existing peer connection

Sends response SDP via signaling callbacks.

Definition at line 347 of file peer_manager.c.

347 {
348 if (!manager || !sdp) {
349 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters");
350 }
351
352 // Extract SDP string and type
353 const char *sdp_str = (const char *)(sdp + 1); // After header
354 const char *sdp_type = (sdp->sdp_type == 0) ? "offer" : "answer";
355
356 log_debug("Handling incoming SDP %s from remote peer", sdp_type);
357
358 mutex_lock(&manager->peers_mutex);
359
360 // Find or create peer connection
361 peer_entry_t *peer;
362 asciichat_error_t result = create_peer_connection_locked(manager, sdp->session_id, sdp->sender_id, &peer);
363 if (result != ASCIICHAT_OK) {
364 mutex_unlock(&manager->peers_mutex);
365 return SET_ERRNO(result, "Failed to create peer connection for SDP");
366 }
367
368 mutex_unlock(&manager->peers_mutex);
369
370 // Set remote SDP
371 result = webrtc_set_remote_description(peer->pc, sdp_str, sdp_type);
372 if (result != ASCIICHAT_OK) {
373 return SET_ERRNO(result, "Failed to set remote SDP");
374 }
375
376 // If this is an offer and we're the creator, generate answer automatically
377 // (libdatachannel triggers on_local_description callback with answer)
378 if (sdp->sdp_type == 0 && manager->role == WEBRTC_ROLE_CREATOR) {
379 log_debug("Offer received, answer will be generated automatically");
380 }
381
382 return ASCIICHAT_OK;
383}
asciichat_error_t webrtc_set_remote_description(webrtc_peer_connection_t *pc, const char *sdp, const char *type)
Set remote SDP offer/answer.

References ASCIICHAT_OK, ERROR_INVALID_PARAM, log_debug, mutex_lock, mutex_unlock, peer_entry_t::pc, peers_mutex, role, SET_ERRNO, WEBRTC_ROLE_CREATOR, and webrtc_set_remote_description().