Bidirectional UDP + SRTP trunk between media edges.
What problem this solves
Multi-home rooms need an SFU-to-SFU media path that is not WebRTC/ICE and not
Distributed Erlang. This GenServer owns one UDP socket, encrypts RTP/RTCP with
a pre-shared key, multiplexes opaque datachannel frames, and delivers inbound
plaintext to a handler pid.
RFCs
- RFC 3711 -- SRTP on RTP/RTCP frames
- RFC 3550 -- RTP payloads after unprotect
Summary
Functions
Returns a specification to start this module under a supervisor.
Sets the remote edge UDP address for outbound frames.
Registers a label and returns a channel_ref for SendHandle / Forwarder.
SendHandle datachannel MFA sink (apply(mod, fun, [pipe, ref, data, type])).
SendHandle RTP MFA sink (apply(mod, fun, [pipe, ssrc, rtp])).
Returns the local {ip, port} of the UDP socket.
Publishes RTP + datachannel SendHandle trunk passthrough for this pipe pid.
Sends an opaque datachannel payload labeled for demux on the far edge.
Encrypts and sends one RTP packet to the connected peer.
Replaces the inbound handler pid (e.g. your edge-to-edge bridge process).
Starts a trunk pipe.
UDP in/out packet counters (lab assertion that media used UDP).
Types
@type stats() :: %{udp_in: non_neg_integer(), udp_out: non_neg_integer()}
Functions
Returns a specification to start this module under a supervisor.
See Supervisor.
@spec connect(pid(), :inet.ip_address(), :inet.port_number()) :: :ok
Sets the remote edge UDP address for outbound frames.
Registers a label and returns a channel_ref for SendHandle / Forwarder.
SendHandle datachannel MFA sink (apply(mod, fun, [pipe, ref, data, type])).
@spec hot_send_rtp(pid(), non_neg_integer(), XMediaLib.Rtp.t()) :: :ok | {:error, term()}
SendHandle RTP MFA sink (apply(mod, fun, [pipe, ssrc, rtp])).
@spec local_addr(pid()) :: {:ok, {:inet.ip_address(), :inet.port_number()}} | {:error, term()}
Returns the local {ip, port} of the UDP socket.
@spec publish_send_handles(pid()) :: :ok
Publishes RTP + datachannel SendHandle trunk passthrough for this pipe pid.
Sends an opaque datachannel payload labeled for demux on the far edge.
@spec send_rtp(pid(), non_neg_integer(), XMediaLib.Rtp.t() | binary()) :: :ok | {:error, term()}
Encrypts and sends one RTP packet to the connected peer.
Replaces the inbound handler pid (e.g. your edge-to-edge bridge process).
@spec start_link(keyword()) :: GenServer.on_start()
Starts a trunk pipe.
Opts:
:handler- pid that receives inbound{__MODULE__, kind, pipe, ...}messages:master_key/:master_salt- shared lab keys (both directions):local_write_key/:local_write_salt/:remote_write_key/:remote_write_salt- directional write keys (preferred):port- optional bind port (default0ephemeral)
UDP in/out packet counters (lab assertion that media used UDP).