cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
webrtc.c File Reference

WebRTC DataChannel context: UDP I/O, ICE-lite, DTLS, SCTP driving. More...

#include "webrtc_internal.h"
#include <cwist/core/mem/alloc.h>
#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <ifaddrs.h>
#include <openssl/rand.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
Include dependency graph for webrtc.c:

Go to the source code of this file.

Macros

#define RX_BUDGET   256
 
#define UDP_SOCKBUF   (4 << 20)
 
Timing
#define STUN_RTO_INITIAL_MS   300
 
#define STUN_RTO_MAX_MS   3000
 
#define STUN_MAX_ATTEMPTS   7
 
#define PARK_TIMEOUT_MS   30000
 
#define HANDSHAKE_TIMEOUT_MS   30000
 
#define LIVENESS_TIMEOUT_MS   30000
 
#define SCTP_TICK_ACTIVE_MS   10
 
#define SCTP_TICK_IDLE_MS   250
 
#define SCTP_ACTIVE_WINDOW_MS   1000
 

Functions

void cwist_webrtc_conn_retain (cwist_webrtc_conn *conn)
 Take a reference on conn so it stays valid outside a callback.
 
void cwist_webrtc_conn_release (cwist_webrtc_conn *conn)
 Drop a reference taken with cwist_webrtc_conn_retain().
 
bool cwist_webrtc_on_owner (const cwist_webrtc_ctx *ctx)
 true when the calling thread is servicing ctx right now.
 
void cwist_webrtc_conn_on_message (struct cwist_webrtc_conn *conn, uint16_t channel, const uint8_t *data, size_t len, int is_string)
 Deliver a complete inbound message to the message handler.
 
void cwist_webrtc_conn_on_channel_open (struct cwist_webrtc_conn *conn, uint16_t channel, const char *label)
 Report a channel the peer opened to the channel handler.
 
void cwist_webrtc_conn_dtls_out (struct cwist_webrtc_conn *conn, const uint8_t *data, size_t len)
 Queue one datagram to the conn's peer (owner thread).
 
void cwist_webrtc_conn_sctp_out (struct cwist_webrtc_conn *conn, const void *buffer, size_t len)
 usrsctp output for conn; marshalled to the owner thread when needed.
 
cwist_webrtc_ctx * cwist_webrtc_ctx_new (uint16_t port)
 Create a WebRTC context bound to a UDP port (0 picks an ephemeral port), running on its own reactor thread.
 
cwist_webrtc_ctx * cwist_webrtc_ctx_new_on (cwist_reactor_t *reactor, uint16_t port)
 Create a WebRTC context on a reactor the caller runs.
 
void cwist_webrtc_ctx_free (cwist_webrtc_ctx *ctx)
 Close every connection and free the context.
 
uint16_t cwist_webrtc_ctx_port (const cwist_webrtc_ctx *ctx)
 UDP port the context is bound to.
 
const char * cwist_webrtc_ctx_fingerprint (const cwist_webrtc_ctx *ctx)
 Local certificate fingerprint (SHA-256, colon-separated hex).
 
void cwist_webrtc_ctx_set_message_handler (cwist_webrtc_ctx *ctx, cwist_webrtc_message_cb cb, void *user)
 Set the callback for incoming DataChannel messages. Set handlers before answering the first offer.
 
void cwist_webrtc_ctx_set_channel_handler (cwist_webrtc_ctx *ctx, cwist_webrtc_channel_cb cb, void *user)
 Set the callback for incoming DataChannel open (DCEP) events.
 
void cwist_webrtc_ctx_set_close_handler (cwist_webrtc_ctx *ctx, cwist_webrtc_close_cb cb, void *user)
 Set the callback for closed connections.
 
int cwist_webrtc_ctx_connection_count (const cwist_webrtc_ctx *ctx)
 Number of connections whose SCTP association is up.
 
size_t cwist_webrtc_conn_buffered_amount (const cwist_webrtc_conn *conn)
 Bytes accepted by cwist_webrtc_conn_send() and not yet handed to SCTP (like RTCDataChannel.bufferedAmount, summed over channels).
 
int cwist_webrtc_handle_offer (cwist_webrtc_ctx *ctx, const char *offer, char *answer_out, size_t out_len)
 Answer a browser SDP offer (ICE-lite, setup:passive).
 
cwist_webrtc_conn * cwist_webrtc_connect (cwist_webrtc_ctx *ctx, const struct sockaddr_in *remote, const char *peer_ufrag, const char *peer_pwd)
 Offering-side dialer used by the loopback tests: registers a client conn to remote and starts ICE.
 
int cwist_webrtc_conn_send (cwist_webrtc_conn *conn, uint16_t channel_id, const uint8_t *data, size_t len, cwist_webrtc_data_type type)
 Send a message on a DataChannel.
 
void cwist_webrtc_conn_close (cwist_webrtc_conn *conn)
 Close a connection (SCTP abort, DTLS teardown). Safe from any thread; the close handler runs on the reactor thread.
 

Detailed Description

WebRTC DataChannel context: UDP I/O, ICE-lite, DTLS, SCTP driving.

A ctx is one UDP socket served by one cwist reactor (see webrtc_internal.h for the threading and lifetime rules). Work happens only in reactor callbacks, and every callback follows the same shape:

ctx_enter() - mark this thread as servicing the ctx, cache the time ... - handle datagrams / a timer / a posted request ctx_leave() - service conns touched this round (drain SCTP, flush queued sends, apply closes), then send every queued datagram in one sendmmsg()

Datagrams are read in batches with recvmmsg(). A DTLS record is decrypted and fed to usrsctp right away, but draining SCTP and flushing sends waits until the batch is done, so a burst of packets for one conn costs one drain. Nothing runs on a fixed tick: each conn has one timer (STUN retransmit, DTLS retransmit, liveness or park expiry, whichever applies) and the ctx drives usrsctp's clock only while it holds associations, every 10 ms after recent traffic and every 250 ms otherwise.

Definition in file webrtc.c.

Macro Definition Documentation

◆ HANDSHAKE_TIMEOUT_MS

#define HANDSHAKE_TIMEOUT_MS   30000

ICE + DTLS must finish within this.

Definition at line 42 of file webrtc.c.

◆ LIVENESS_TIMEOUT_MS

#define LIVENESS_TIMEOUT_MS   30000

Silence before an established conn is dropped.

Definition at line 43 of file webrtc.c.

◆ PARK_TIMEOUT_MS

#define PARK_TIMEOUT_MS   30000

Answered offer with no nomination.

Definition at line 41 of file webrtc.c.

◆ RX_BUDGET

#define RX_BUDGET   256

Most datagrams read in one readiness callback before yielding.

Definition at line 50 of file webrtc.c.

◆ SCTP_ACTIVE_WINDOW_MS

#define SCTP_ACTIVE_WINDOW_MS   1000

"Recent" for the tick choice.

Definition at line 46 of file webrtc.c.

◆ SCTP_TICK_ACTIVE_MS

#define SCTP_TICK_ACTIVE_MS   10

usrsctp clock step after recent traffic.

Definition at line 44 of file webrtc.c.

◆ SCTP_TICK_IDLE_MS

#define SCTP_TICK_IDLE_MS   250

usrsctp clock step when quiet.

Definition at line 45 of file webrtc.c.

◆ STUN_MAX_ATTEMPTS

#define STUN_MAX_ATTEMPTS   7

Binding requests before giving up.

Definition at line 40 of file webrtc.c.

◆ STUN_RTO_INITIAL_MS

#define STUN_RTO_INITIAL_MS   300

First Binding retransmit (client role).

Definition at line 38 of file webrtc.c.

◆ STUN_RTO_MAX_MS

#define STUN_RTO_MAX_MS   3000

Retransmit backoff cap.

Definition at line 39 of file webrtc.c.

◆ UDP_SOCKBUF

#define UDP_SOCKBUF   (4 << 20)

Socket buffer requested for the UDP socket (the kernel may clamp it).

Definition at line 52 of file webrtc.c.

Function Documentation

◆ cwist_webrtc_conn_buffered_amount()

size_t cwist_webrtc_conn_buffered_amount ( const cwist_webrtc_conn *  conn)

Bytes accepted by cwist_webrtc_conn_send() and not yet handed to SCTP (like RTCDataChannel.bufferedAmount, summed over channels).

Definition at line 1019 of file webrtc.c.

References cwist_webrtc_conn::buffered, and cap.

◆ cwist_webrtc_conn_close()

void cwist_webrtc_conn_close ( cwist_webrtc_conn *  conn)

◆ cwist_webrtc_conn_dtls_out()

void cwist_webrtc_conn_dtls_out ( struct cwist_webrtc_conn *  conn,
const uint8_t *  data,
size_t  len 
)

Queue one datagram to the conn's peer (owner thread).

Definition at line 554 of file webrtc.c.

References cwist_webrtc_conn::ctx, and cwist_webrtc_conn::remote.

◆ cwist_webrtc_conn_on_channel_open()

void cwist_webrtc_conn_on_channel_open ( struct cwist_webrtc_conn *  conn,
uint16_t  channel,
const char *  label 
)

Report a channel the peer opened to the channel handler.

Definition at line 548 of file webrtc.c.

References cap, cwist_webrtc_ctx::ch_cb, cwist_webrtc_ctx::ch_user, and cwist_webrtc_conn::ctx.

◆ cwist_webrtc_conn_on_message()

void cwist_webrtc_conn_on_message ( struct cwist_webrtc_conn *  conn,
uint16_t  channel,
const uint8_t *  data,
size_t  len,
int  is_string 
)

Deliver a complete inbound message to the message handler.

Definition at line 540 of file webrtc.c.

References cwist_webrtc_conn::ctx, CWIST_WEBRTC_DATA_BINARY, CWIST_WEBRTC_DATA_STRING, cwist_webrtc_ctx::msg_cb, and cwist_webrtc_ctx::msg_user.

◆ cwist_webrtc_conn_release()

◆ cwist_webrtc_conn_retain()

void cwist_webrtc_conn_retain ( cwist_webrtc_conn *  conn)

Take a reference on conn so it stays valid outside a callback.

Definition at line 82 of file webrtc.c.

References cap, and cwist_webrtc_conn::refs.

Referenced by cwist_webrtc_conn_close(), cwist_webrtc_conn_sctp_out(), cwist_webrtc_conn_send(), and cwist_webrtc_connect().

◆ cwist_webrtc_conn_sctp_out()

void cwist_webrtc_conn_sctp_out ( struct cwist_webrtc_conn *  conn,
const void *  buffer,
size_t  len 
)

usrsctp output for conn; marshalled to the owner thread when needed.

Definition at line 577 of file webrtc.c.

References cap, cwist_webrtc_conn::ctx, cwist_alloc(), cwist_webrtc_conn_retain(), cwist_webrtc_on_owner(), cwist_webrtc_ctx::reactor, cwist_webrtc_conn::ssl, and SSL_write.

◆ cwist_webrtc_conn_send()

int cwist_webrtc_conn_send ( cwist_webrtc_conn *  conn,
uint16_t  channel_id,
const uint8_t *  data,
size_t  len,
cwist_webrtc_data_type  type 
)

Send a message on a DataChannel.

Safe from any thread. The message is queued if SCTP is not ready or its send buffer is full; queued bytes are reported by cwist_webrtc_conn_buffered_amount().

Returns
0 when sent or queued; -1 if the conn is closed, len exceeds 262144 bytes (the advertised max-message-size), or the queue already holds 4 MiB.

Definition at line 1158 of file webrtc.c.

References cwist_webrtc_conn::buffered, cap, cwist_reactor_post::cb, cwist_reactor_post::ctx, cwist_webrtc_conn::ctx, cwist_alloc(), cwist_sctp_send(), cwist_webrtc_conn_retain(), CWIST_WEBRTC_DATA_STRING, CWIST_WEBRTC_MAX_MESSAGE, cwist_webrtc_on_owner(), cwist_webrtc_conn::detached, head, cwist_webrtc_conn::kick_post, cwist_webrtc_conn::pending_head, cwist_webrtc_ctx::reactor, and cwist_webrtc_conn::sctp_ready.

◆ cwist_webrtc_connect()

cwist_webrtc_conn * cwist_webrtc_connect ( cwist_webrtc_ctx *  ctx,
const struct sockaddr_in *  remote,
const char *  peer_ufrag,
const char *  peer_pwd 
)

Offering-side dialer used by the loopback tests: registers a client conn to remote and starts ICE.

Returns
A conn reference owned by the caller (cwist_webrtc_conn_release()), or NULL.

Definition at line 1078 of file webrtc.c.

References cap, cwist_reactor_post::cb, cwist_reactor_post::ctx, cwist_webrtc_conn::ctx, cwist_webrtc_conn_retain(), cwist_webrtc_conn::peer_pwd, cwist_webrtc_conn::peer_ufrag, RAND_bytes, cwist_webrtc_ctx::reactor, cwist_webrtc_conn::reg_post, cwist_webrtc_conn::remote, and cwist_webrtc_conn::stun_txid.

◆ cwist_webrtc_ctx_connection_count()

int cwist_webrtc_ctx_connection_count ( const cwist_webrtc_ctx *  ctx)

Number of connections whose SCTP association is up.

Definition at line 1015 of file webrtc.c.

References cap, and cwist_webrtc_ctx::ready_count.

◆ cwist_webrtc_ctx_fingerprint()

const char * cwist_webrtc_ctx_fingerprint ( const cwist_webrtc_ctx *  ctx)

Local certificate fingerprint (SHA-256, colon-separated hex).

Definition at line 993 of file webrtc.c.

References cwist_webrtc_ctx::fingerprint.

◆ cwist_webrtc_ctx_free()

void cwist_webrtc_ctx_free ( cwist_webrtc_ctx *  ctx)

Close every connection and free the context.

Safe from any thread. For a ctx made with cwist_webrtc_ctx_new_on() and called off the reactor thread, this waits for the reactor to finish the teardown, so the reactor must still be running.

Definition at line 944 of file webrtc.c.

References cap, cwist_reactor_post::cb, cwist_reactor_post::ctx, cwist_reactor_destroy(), cwist_webrtc_ctx::fd_closed, cwist_webrtc_ctx::free_cv, cwist_webrtc_ctx::free_mu, cwist_webrtc_ctx::free_post, cwist_webrtc_ctx::owner_pid, cwist_webrtc_ctx::owns_reactor, cwist_webrtc_ctx::reactor, cwist_webrtc_ctx::thread, cwist_webrtc_ctx::thread_running, and cwist_webrtc_ctx::udp_fd.

Referenced by cwist_webrtc_ctx_new().

◆ cwist_webrtc_ctx_new()

cwist_webrtc_ctx * cwist_webrtc_ctx_new ( uint16_t  port)

Create a WebRTC context bound to a UDP port (0 picks an ephemeral port), running on its own reactor thread.

Returns
NULL on failure.

Definition at line 879 of file webrtc.c.

References cap, cwist_reactor_create(), cwist_reactor_destroy(), cwist_webrtc_ctx_free(), cwist_webrtc_ctx::thread, and cwist_webrtc_ctx::thread_running.

◆ cwist_webrtc_ctx_new_on()

cwist_webrtc_ctx * cwist_webrtc_ctx_new_on ( cwist_reactor_t *  reactor,
uint16_t  port 
)

Create a WebRTC context on a reactor the caller runs.

The ctx registers its UDP socket and timers with reactor and does all of its work inside that reactor's callbacks; no thread is created. The reactor must keep running until cwist_webrtc_ctx_free() returns.

Returns
NULL on failure.

Definition at line 895 of file webrtc.c.

References cap, and cwist_webrtc_ctx::udp_fd.

◆ cwist_webrtc_ctx_port()

uint16_t cwist_webrtc_ctx_port ( const cwist_webrtc_ctx *  ctx)

UDP port the context is bound to.

Definition at line 989 of file webrtc.c.

References cwist_webrtc_ctx::port.

◆ cwist_webrtc_ctx_set_channel_handler()

void cwist_webrtc_ctx_set_channel_handler ( cwist_webrtc_ctx *  ctx,
cwist_webrtc_channel_cb  cb,
void *  user 
)

Set the callback for incoming DataChannel open (DCEP) events.

Definition at line 1003 of file webrtc.c.

References cap, cwist_webrtc_ctx::ch_cb, and cwist_webrtc_ctx::ch_user.

◆ cwist_webrtc_ctx_set_close_handler()

void cwist_webrtc_ctx_set_close_handler ( cwist_webrtc_ctx *  ctx,
cwist_webrtc_close_cb  cb,
void *  user 
)

Set the callback for closed connections.

Definition at line 1009 of file webrtc.c.

References cap, cwist_webrtc_ctx::close_cb, and cwist_webrtc_ctx::close_user.

◆ cwist_webrtc_ctx_set_message_handler()

void cwist_webrtc_ctx_set_message_handler ( cwist_webrtc_ctx *  ctx,
cwist_webrtc_message_cb  cb,
void *  user 
)

Set the callback for incoming DataChannel messages. Set handlers before answering the first offer.

Definition at line 997 of file webrtc.c.

References cap, cwist_webrtc_ctx::msg_cb, and cwist_webrtc_ctx::msg_user.

◆ cwist_webrtc_handle_offer()

int cwist_webrtc_handle_offer ( cwist_webrtc_ctx *  ctx,
const char *  offer,
char *  answer_out,
size_t  out_len 
)

Answer a browser SDP offer (ICE-lite, setup:passive).

Parameters
offerThe remote SDP offer.
answer_outBuffer receiving the generated SDP answer.
out_lenSize of answer_out.
Returns
0 on success, -1 on error.

Safe from any thread. The connection completes asynchronously (ICE nomination, DTLS, SCTP) on the ctx's reactor thread. An answered offer whose peer never shows up is dropped after 30 seconds.

Definition at line 1042 of file webrtc.c.

References cap, cwist_reactor_post::cb, cwist_reactor_post::ctx, cwist_webrtc_conn::ctx, cwist_sdp_parse(), cwist_sdp_write_answer(), cwist_webrtc_ctx::fingerprint, cwist_webrtc_ctx::host_ip, cwist_webrtc_ctx::ice_lite_server, cwist_webrtc_ctx::ice_pwd, cwist_webrtc_ctx::ice_ufrag, cwist_sdp_info::mid, cwist_webrtc_ctx::owner_pid, cwist_webrtc_conn::peer_pwd, cwist_webrtc_conn::peer_ufrag, cwist_webrtc_ctx::port, cwist_webrtc_ctx::reactor, and cwist_webrtc_conn::reg_post.

◆ cwist_webrtc_on_owner()

bool cwist_webrtc_on_owner ( const cwist_webrtc_ctx *  ctx)

true when the calling thread is servicing ctx right now.

Definition at line 100 of file webrtc.c.

Referenced by cwist_webrtc_conn_close(), cwist_webrtc_conn_sctp_out(), and cwist_webrtc_conn_send().