# `XGW.Peer.Turn`
[🔗](https://github.com/Lazarus404/xgw/blob/main/lib/xgw/peer/turn.ex#L1)

Peer-side TURN lifecycle: allocate, refresh, unwrap, and encode relay traffic.

## How this fits

When local candidates include **relay** addresses, the Peer must keep TURN
allocations alive, create permissions / channel bindings toward the selected
remote, and wrap outbound UDP (including DTLS/SRTP) as Send Indication or
ChannelData. Inbound TURN Data Indications are unwrapped before demux.

Pure helpers and state transforms used by `XGW.Peer` (not a GenServer).

## RFCs

* RFC 8656 -- TURN allocations, permissions, ChannelBind, Send Indication, ChannelData
* RFC 8489 -- STUN encoding of TURN methods

# `allocations_cover_relay_locals?`

```elixir
@spec allocations_cover_relay_locals?(list(), list()) :: boolean()
```

Returns true when every relay local candidate has a covering TURN allocation.

# `allocations_cover_relays?`

```elixir
@spec allocations_cover_relays?(map()) :: boolean()
```

Returns true when peer state allocations cover current ICE relay locals.

# `apply_relay_results`

```elixir
@spec apply_relay_results(map(), list()) :: map()
```

Merges gather_relay results into ICE/allocations and notifies the handler.

Schedules TURN refresh; caller schedules connectivity-check ticks.

# `cancel_refresh_timer`

```elixir
@spec cancel_refresh_timer(map()) :: map()
```

Cancels the TURN refresh timer when present.

# `clear_channels`

```elixir
@spec clear_channels(map()) :: map()
```

Resets channel number maps.

# `delete_allocations`

```elixir
@spec delete_allocations(map()) :: map()
```

Deletes all TURN allocations and clears channel maps.

# `encode_relay_app_data`

```elixir
@spec encode_relay_app_data(map(), map(), term(), binary()) :: binary()
```

Encodes app data as Send Indication or ChannelData for the peer.

# `find_allocation`

```elixir
@spec find_allocation(map(), map()) :: map() | nil
```

Looks up a TURN allocation by relay local candidate.

# `gather_relay`

```elixir
@spec gather_relay(map()) :: list()
```

Synchronous relay gather for prefetch.

# `maybe_create_permission`

```elixir
@spec maybe_create_permission(map(), map()) :: map()
```

After nomination on a relay pair, create permission + ChannelBind.

# `maybe_delete_allocations`

```elixir
@spec maybe_delete_allocations(map(), map()) :: map()
```

Deletes allocations when they do not cover answer relay locals.

# `refresh_allocations`

```elixir
@spec refresh_allocations(map()) :: map()
```

Best-effort TURN Refresh for each live allocation.

# `relay_send_allocation`

```elixir
@spec relay_send_allocation(map()) :: map() | nil
```

Allocation used for outbound relay send, or nil when host path should win.

# `schedule_refresh_tick`

```elixir
@spec schedule_refresh_tick(map()) :: map()
```

Arms `:turn_refresh_tick` from the first allocation lifetime.

# `unwrap_data_indication`

```elixir
@spec unwrap_data_indication(binary()) ::
  {:ok, binary(), {tuple(), integer()}} | :not_turn_data
```

Unwraps a TURN Data Indication to `{inner, peer_from}` or `:not_turn_data`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
