Object.NATTraversal (object v0.1.2)

NAT traversal mechanisms for P2P Object communication.

Implements STUN, TURN, and ICE protocols to enable direct peer-to-peer connections through NATs and firewalls. Supports UDP hole punching, TCP simultaneous open, and relay fallback.

Features

  • STUN client for address discovery
  • TURN client for relay allocation
  • ICE agent for connection negotiation
  • UDP hole punching
  • TCP simultaneous open
  • UPnP/NAT-PMP port mapping
  • Relay server fallback

Summary

Functions

Allocates a TURN relay for incoming connections.

Returns a specification to start this module under a supervisor.

Discovers NAT type and external address.

Gathers ICE candidates for establishing a connection.

Establishes a direct connection using hole punching.

Starts ICE negotiation with remote candidates.

Starts the NAT traversal service.

Types

candidate()

@type candidate() :: %{
  type: :host | :srflx | :prflx | :relay,
  protocol: :udp | :tcp,
  address: String.t(),
  port: non_neg_integer(),
  priority: non_neg_integer(),
  foundation: String.t(),
  related_address: String.t() | nil,
  related_port: non_neg_integer() | nil
}

connection()

@type connection() :: %{
  local_candidates: [candidate()],
  remote_candidates: [candidate()],
  selected_pair: {candidate(), candidate()} | nil,
  state: ice_state(),
  controlling: boolean(),
  tie_breaker: binary()
}

ice_state()

@type ice_state() :: :new | :gathering | :complete | :connected | :failed

nat_type()

@type nat_type() ::
  :none | :full_cone | :restricted_cone | :port_restricted | :symmetric

relay_allocation()

@type relay_allocation() :: %{
  server: {String.t(), non_neg_integer()},
  relayed_address: {String.t(), non_neg_integer()},
  lifetime: non_neg_integer(),
  permissions: MapSet.t()
}

state()

@type state() :: %{
  stun_servers: [{String.t(), non_neg_integer()}],
  turn_servers: [{String.t(), non_neg_integer(), map()}],
  nat_type: nat_type() | nil,
  external_address: {String.t(), non_neg_integer()} | nil,
  connections: %{required(String.t()) => connection()},
  relay_allocations: %{required(String.t()) => relay_allocation()},
  upnp_mappings: %{required(non_neg_integer()) => upnp_mapping()},
  config: map()
}

upnp_mapping()

@type upnp_mapping() :: %{
  internal_port: non_neg_integer(),
  external_port: non_neg_integer(),
  protocol: :udp | :tcp,
  description: String.t()
}

Functions

allocate_relay()

@spec allocate_relay() :: {:ok, {String.t(), non_neg_integer()}} | {:error, term()}

Allocates a TURN relay for incoming connections.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

create_port_mapping(internal_port, protocol, description)

@spec create_port_mapping(non_neg_integer(), :udp | :tcp, String.t()) ::
  {:ok, non_neg_integer()} | {:error, term()}

Creates a UPnP port mapping.

discover_nat()

@spec discover_nat() ::
  {:ok, {nat_type(), String.t(), non_neg_integer()}} | {:error, term()}

Discovers NAT type and external address.

gather_candidates(connection_id)

@spec gather_candidates(String.t()) :: {:ok, [candidate()]} | {:error, term()}

Gathers ICE candidates for establishing a connection.

hole_punch(local_port, remote_address, remote_port)

@spec hole_punch(non_neg_integer(), String.t(), non_neg_integer()) ::
  {:ok, port()} | {:error, term()}

Establishes a direct connection using hole punching.

start_ice_negotiation(connection_id, remote_candidates, controlling)

@spec start_ice_negotiation(String.t(), [candidate()], boolean()) ::
  :ok | {:error, term()}

Starts ICE negotiation with remote candidates.

start_link(opts \\ [])

Starts the NAT traversal service.