Dual-homed listen helpers for NAT behavior discovery.
What problem this solves
ICE agents test whether their NAT mapping depends on destination IP or port by sending Binding requests with CHANGE-REQUEST and reading OTHER-ADDRESS in the response. That requires the server to listen on two addresses (and often two ports) and reply from the alternate socket when asked.
This module decides when that mode is fully configured (armed?/0) and maps
CHANGE-REQUEST flags to a registered {transport, socket} via ListenRegistry.
Internal note
Enabled via application env (:other_ip, :other_port, concrete :server_ip);
operators configure listen tuples, not these functions.
RFCs
Summary
Functions
Returns whether dual-IP NAT discovery is fully armed.
Returns the STUN CHANGE-REQUEST attribute type (0x0003).
Returns primary and alternate listen endpoints when configuration is complete.
Returns OTHER-ADDRESS {ip, port} for Binding success when dual-IP is configured.
Resolves the socket and source address for a CHANGE-REQUEST reply.
Functions
@spec armed?() :: boolean()
Returns whether dual-IP NAT discovery is fully armed.
True only when endpoints/0 succeeds and ListenRegistry holds sockets for
all four (A1,P1), (A2,P2), (A1,P2), (A2,P1) combinations.
Examples
iex> is_boolean(Xirsys.XTurn.DualIp.armed?())
true
Returns the STUN CHANGE-REQUEST attribute type (0x0003).
Examples
iex> Xirsys.XTurn.DualIp.change_request_type()
0x0003
@spec endpoints() :: {:ok, tuple(), tuple(), pos_integer(), pos_integer()} | :error
Returns primary and alternate listen endpoints when configuration is complete.
Reads XSockets.Config.server_ip/0, :other_ip, STUN port, and :other_port.
Returns {:ok, a1, a2, p1, p2} or :error when any value is missing or wildcard.
Examples
iex> Xirsys.XTurn.DualIp.endpoints()
:error
@spec other_address(:inet.ip_address()) :: {:inet.ip_address(), :inet.port_number()} | nil
Returns OTHER-ADDRESS {ip, port} for Binding success when dual-IP is configured.
Given the destination address da the client used, returns the alternate
server address for the OTHER-ADDRESS attribute, or nil when not configured.
Examples
iex> Xirsys.XTurn.DualIp.other_address({127, 0, 0, 1})
nil
@spec reply_from(:inet.ip_address(), :inet.port_number(), [atom()]) :: {:ok, {module(), term()}, {:inet.ip_address(), :inet.port_number()}} | :error
Resolves the socket and source address for a CHANGE-REQUEST reply.
change_req is a list of flags (:ip, :port) from the decoded attribute.
Returns {:ok, {transport, socket}, {src_ip, src_port}} when the alternate
endpoint is registered, otherwise :error.
Examples
iex> Xirsys.XTurn.DualIp.reply_from({127, 0, 0, 1}, 3478, [:ip])
:error