# `XGW.Demux`
[🔗](https://github.com/Lazarus404/xgw/blob/main/lib/xgw/demux.ex#L1)

Separates mixed UDP packets that share one socket into STUN, DTLS, and media.

## Why demux exists

WebRTC reuses a single 5-tuple (same IP/port pair) for several protocols at
once: connectivity probes (**STUN**), the security handshake (**DTLS**), and
the media itself (**RTP** / **RTCP**). The first byte of each datagram tells
you which protocol it is (RFC 7983). This module only classifies bytes; it
does not parse STUN attributes or decrypt SRTP.

RTP and RTCP can also share the same port (**RTCP-mux**, RFC 5761). When the
first-byte range is the media bucket (128-191), `classify_media/1` looks at
the RTP payload type field: values 64-95 mean RTCP, otherwise RTP.

## RFCs

* RFC 7983 -- first-byte demultiplexing of STUN, DTLS, ZRTP, TURN ChannelData, RTP/RTCP
* RFC 5761 -- RTP/RTCP multiplexing (payload-type split in the media range)

# `kind`

```elixir
@type kind() :: :stun | :zrtp | :dtls | :turn_channel | :rtp | :rtcp | :unknown
```

Full ingress classification including RTP vs RTCP split.

# `protocol`

```elixir
@type protocol() :: :stun | :zrtp | :dtls | :turn_channel | :rtp_rtcp | :unknown
```

RFC 7983 first-byte protocol bucket.

# `classify`

```elixir
@spec classify(binary()) :: {:ok, protocol()} | {:error, :empty}
```

Classifies a packet by its first byte (RFC 7983).

## Examples

    iex> XGW.Demux.classify(<<0, 0, 0, 0>>)
    {:ok, :stun}

    iex> XGW.Demux.classify(<<22, 0>>)
    {:ok, :dtls}

    iex> XGW.Demux.classify(<<128, 0>>)
    {:ok, :rtp_rtcp}

    iex> XGW.Demux.classify(<<>>)
    {:error, :empty}

# `classify_kind`

```elixir
@spec classify_kind(binary()) :: {:ok, kind()} | {:error, :empty | :too_short}
```

Full ingress classification: RFC 7983 first byte, then media PT split when applicable.

## Examples

    iex> XGW.Demux.classify_kind(<<0, 1, 2>>)
    {:ok, :stun}

    iex> XGW.Demux.classify_kind(<<22, 0>>)
    {:ok, :dtls}

    iex> XGW.Demux.classify_kind(<<128, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>)
    {:ok, :rtp}

# `classify_media`

```elixir
@spec classify_media(binary()) :: {:ok, :rtp | :rtcp} | {:error, :too_short}
```

Classifies an RFC 7983 RTP/RTCP-range packet as RTP or RTCP (RFC 5761 mux PT rule).

## Examples

    iex> XGW.Demux.classify_media(<<2::2, 0::6, 0::1, 63::7, 0::16, 0::32, 0::32>>)
    {:ok, :rtp}

    iex> XGW.Demux.classify_media(<<2::2, 0::6, 0::1, 64::7, 0::16, 0::32, 0::32>>)
    {:ok, :rtcp}

    iex> XGW.Demux.classify_media(<<128>>)
    {:error, :too_short}

---

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