# `Quic.IO.Endpoint`
[🔗](https://github.com/gsmlg-dev/http_fetch/blob/v1.0.0-rc.9/apps/elixir_quic/lib/quic/io/endpoint.ex#L1)

Pure bounded endpoint state for QUIC external IO.

The first UDP adapter binds a concrete local address. Wildcard and
ancillary destination/interface metadata are intentionally unsupported.
`enqueue/4` is admission only; `local_send/4` reports the later local
writer result. Peer ACKs belong to `Quic.Recovery`, never this IO budget.

At most two paths retain independent received, reserved, and spent byte
ledgers. The legacy arities use the selected path, while top-level byte
counters remain lifetime totals across paths. Send receipts retain the path
chosen at admission even if the selected path subsequently changes.

# `initial_state`

```elixir
@type initial_state() :: %Quic.IO.Endpoint{
  active_path: path_id(),
  address_validated: false,
  bytes_pending: 0,
  bytes_received: 0,
  bytes_sent: 0,
  closed: false,
  generation: 0,
  handshake_deadline: term(),
  idle_deadline: term(),
  in_flight: %{},
  max_queue: pos_integer(),
  max_queue_bytes: pos_integer(),
  paths: %{required(path_id()) =&gt; path_ledger()},
  queue: {[], []},
  queue_bytes: 0,
  timers: %{}
}
```

# `path_id`

```elixir
@type path_id() :: term()
```

# `path_ledger`

```elixir
@type path_ledger() :: %{
  bytes_received: non_neg_integer(),
  bytes_pending: non_neg_integer(),
  bytes_sent: non_neg_integer(),
  address_validated: boolean()
}
```

# `send_ref`

```elixir
@type send_ref() :: reference()
```

# `t`

```elixir
@type t() :: %Quic.IO.Endpoint{
  active_path: term(),
  address_validated: boolean(),
  bytes_pending: term(),
  bytes_received: non_neg_integer(),
  bytes_sent: term(),
  closed: term(),
  generation: term(),
  handshake_deadline: term(),
  idle_deadline: term(),
  in_flight: term(),
  max_queue: term(),
  max_queue_bytes: term(),
  paths: %{optional(path_id()) =&gt; path_ledger()},
  queue: term(),
  queue_bytes: term(),
  timers: term()
}
```

# `add_path`

```elixir
@spec add_path(t(), path_id(), boolean()) :: {:ok, t()} | {:error, :path_limit}
```

# `bump_generation`

# `dequeue`

# `drop_path`

```elixir
@spec drop_path(t(), path_id()) ::
  {:ok, t()} | {:error, :active_path | :unknown_path | :path_busy}
```

# `enqueue`

# `enqueue`

```elixir
@spec enqueue(t(), binary(), term(), integer(), path_id()) ::
  {:ok, t(),
   %Quic.IO.Endpoint.Send{
     bytes: term(),
     completed_at: term(),
     error: term(),
     generation: term(),
     path_id: term(),
     ref: term(),
     remote: term(),
     status: term()
   }}
  | {:error, atom()}
```

# `local_send`

# `new`

```elixir
@spec new(keyword()) ::
  {:ok, initial_state()}
  | {:error, {:max_queue | :max_queue_bytes, :must_be_positive}}
```

# `path`

```elixir
@spec path(t(), path_id()) :: path_ledger() | nil
```

The path's independent amplification ledger, or nil after retirement.

# `receive_bytes`

# `receive_bytes`

```elixir
@spec receive_bytes(t(), non_neg_integer(), path_id()) ::
  {:ok, t()} | {:error, :unknown_path}
```

# `select_path`

```elixir
@spec select_path(t(), path_id()) :: {:ok, t()} | {:error, :unknown_path}
```

# `selected_path`

```elixir
@spec selected_path(t()) :: path_id()
```

Selected path used by the legacy IO arities.

# `shutdown`

# `timer`

# `timer_expired?`

# `validate_address`

# `validate_address`

```elixir
@spec validate_address(t(), path_id()) :: {:ok, t()} | {:error, :unknown_path}
```

---

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