estun_client Module¶
STUN client state machine (gen_statem).
Overview¶
estun_client is a gen_statem implementation that manages the STUN client lifecycle:
┌──────┐ bind ┌─────────┐ success ┌───────┐
│ idle │ ──────────► │ binding │ ────────────► │ bound │
└──────┘ └─────────┘ └───────┘
▲ │ │
│ │ timeout/error │ transfer
│ ▼ ▼
└─────────────────────┴────────────────────────┘
Functions¶
start_link/1, start_link/2¶
Start a client process.
-spec start_link(map()) -> {ok, pid()} | {error, term()}.
-spec start_link(map(), map()) -> {ok, pid()} | {error, term()}.
Socket Options:
| Option | Type | Default | Description |
|---|---|---|---|
family |
inet \| inet6 |
inet |
Address family |
local_addr |
inet:ip_address() |
any |
Local bind address |
local_port |
inet:port_number() |
0 |
Local port (0 = system assigned) |
reuse_port |
boolean() |
true |
Enable SO_REUSEPORT |
stop/1¶
Stop a client process.
bind/2, bind/3¶
Perform STUN binding to discover public address.
-spec bind(pid(), #stun_server{}) -> {ok, #stun_addr{}} | {error, term()}.
-spec bind(pid(), #stun_server{}, timeout()) -> {ok, #stun_addr{}} | {error, term()}.
get_mapped_address/1¶
Get current mapped address.
get_binding_info/1¶
Get detailed binding information.
get_socket/1¶
Get the underlying socket.
set_event_handler/2¶
Set event handler for notifications.
start_keepalive/2¶
Start periodic binding refresh.
Parameters:
pid()- Client processpos_integer()- Interval in milliseconds
stop_keepalive/1¶
Stop periodic binding refresh.
transfer/1¶
Transfer socket ownership to caller.
States¶
idle¶
Initial state. Socket may or may not be open.
Handles:
bind- Start binding processget_socket- Return socket (opens if needed)
binding¶
Waiting for STUN response.
Handles:
- Socket data - Process response
- State timeout - Retransmit or fail
Retransmission:
- Initial RTO: 500ms
- Doubles each retry up to 8000ms
- Maximum 7 retries (RFC 5389)
bound¶
Have valid binding.
Handles:
get_mapped_address- Return addressget_binding_info- Return full infostart_keepalive- Begin refreshtransfer- Hand off socket- Keepalive responses - Update state
Event Types¶
-type event() ::
{binding_created, #stun_addr{}} |
{binding_refreshed, #stun_addr{}} |
{binding_expiring, pos_integer()} |
{binding_expired} |
{binding_changed, #stun_addr{}, #stun_addr{}} |
{error, term()}.
Example Usage¶
%% Start client
{ok, Pid} = estun_client:start_link(#{family => inet}),
%% Set event handler
ok = estun_client:set_event_handler(Pid, self()),
%% Create server config
Server = #stun_server{
host = "stun.l.google.com",
port = 19302
},
%% Bind
{ok, Addr} = estun_client:bind(Pid, Server),
io:format("Mapped: ~p:~p~n", [Addr#stun_addr.address, Addr#stun_addr.port]),
%% Start keepalive
ok = estun_client:start_keepalive(Pid, 25000),
%% ... use connection ...
%% Transfer for direct use
{ok, Socket, Addr} = estun_client:transfer(Pid).
Supervision¶
Clients are typically started via estun_client_sup: