XGW.ICE.Lite (xgw v0.1.0)

Copy Markdown View Source

ICE-lite agent: answer inbound STUN checks in the controlled role.

Lite vs full

Many media servers sit on a public IP and never need to punch outbound NAT holes themselves. ICE-lite (RFC 8445) is that mode: the agent publishes host candidates, verifies MESSAGE-INTEGRITY with its local ice-pwd, optionally checks USERNAME, merges trickle remote candidates, and responds to Binding requests. Connectivity is declared when inbound checks include ICE role attributes (and nomination when required).

Use ice_lite: false on the Peer for XGW.ICE.Full instead.

RFCs

  • RFC 8445 -- ICE-lite (controlled role, inbound checks only)
  • RFC 8489 -- STUN Binding responses
  • RFC 7675 -- consent freshness

Summary

Types

Remote UDP endpoint {ip, port}.

t()

ICE-lite agent state.

Functions

Adds a trickle remote candidate or records end-of-candidates.

Returns {ip, port} for a parsed candidate (delegates to XGW.ICE.endpoint/1).

Builds ICE-lite state from XGW.Descriptions config.

Handles one STUN datagram from from.

Merges remote candidates (delegates to XGW.ICE.merge_remote/2).

Builds ICE-lite state with explicit credentials (tests and callers without SDP).

Seeds ICE-lite state with remote candidates from the initial offer SDP.

Types

from()

@type from() :: XGW.ICE.endpoint()

Remote UDP endpoint {ip, port}.

t()

@type t() :: %{
  ice_ufrag: String.t(),
  ice_pwd: String.t(),
  ice_tiebreaker: binary(),
  remote_ice_ufrag: String.t() | nil,
  remote_ice_pwd: String.t() | nil,
  bundle_mids: [String.t()],
  remote_candidates: [XMediaLib.SDP.Candidate.t()],
  remote_candidates_eoc?: boolean(),
  last_consent_at: integer() | nil,
  connected?: boolean(),
  selected: from() | nil
}

ICE-lite agent state.

  • ice_ufrag / ice_pwd - local credentials from the answer
  • remote_ice_ufrag - remote ufrag from the offer (username validation)
  • remote_ice_pwd - remote pwd from the offer (outbound STUN integrity)
  • remote_candidates - merged trickle + SDP remote candidates (priority order)
  • remote_candidates_eoc? - true after end-of-candidates
  • last_consent_at - monotonic ms of last consent refresh (RFC 7675)
  • connected? - true after first ICE connectivity check
  • selected - validated remote {ip, port} pair

Functions

add_remote_candidate(ice, cand)

@spec add_remote_candidate(t(), map() | XMediaLib.SDP.Candidate.t()) ::
  {:ok, t()} | {:error, term()}

Adds a trickle remote candidate or records end-of-candidates.

endpoint(cand)

@spec endpoint(XMediaLib.SDP.Candidate.t()) :: from()

Returns {ip, port} for a parsed candidate (delegates to XGW.ICE.endpoint/1).

from_config(config)

@spec from_config(map()) :: t()

Builds ICE-lite state from XGW.Descriptions config.

handle_binding(data, from, state)

@spec handle_binding(binary(), from(), t()) ::
  {:reply, binary(), t()}
  | {:connected, binary(), t()}
  | {:consent, t()}
  | {:ignore, t()}

Handles one STUN datagram from from.

Returns {:reply, wire, state} for a binding response, optionally {:connected, wire, state} when the first ICE connectivity check succeeds, or {:consent, state} for an inbound Binding success (RFC 7675).

merge_remote_candidates(existing, incoming)

@spec merge_remote_candidates([XMediaLib.SDP.Candidate.t()], [
  XMediaLib.SDP.Candidate.t()
]) :: [
  XMediaLib.SDP.Candidate.t()
]

Merges remote candidates (delegates to XGW.ICE.merge_remote/2).

new(opts)

@spec new(keyword()) :: t()

Builds ICE-lite state with explicit credentials (tests and callers without SDP).

seed_remote_candidates(ice, candidates)

@spec seed_remote_candidates(t(), [XMediaLib.SDP.Candidate.t()]) :: t()

Seeds ICE-lite state with remote candidates from the initial offer SDP.