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

Certificate-based QUIC v1 reliable streams with bounded pull consumption.

See `docs/consumer-contract.md` for ownership, generation handles, deadlines,
admission outcomes and limitations. ALPN is metadata; application protocols
are provided by consumers.

Endpoints created with `listen/1` or `client/1` accept `idle_timeout` as
positive milliseconds (default `30_000`) or `:infinity`. The latter advertises
a disabled local idle limit; both endpoints must disable their limits to avoid
a finite idle timer. A peer's finite limit still applies. Handshake, operation,
closing and draining deadlines remain finite. `info/1` and ready metadata expose
`idle_timeout` with `local_ms`, `peer_ms`, `negotiated_ms`, and `effective_ms`
(milliseconds or `:infinity`); the effective period includes a three-PTO floor.
Callers can use `ping/2` at a finite cadence below the peer limit. Admission is
not a peer ACK, and repeated sends without processing peer packets cannot
postpone local idle expiry indefinitely. No automatic keepalive task is created.

# `failure`

```elixir
@type failure() :: {:error, term()} | {:blocked, term()} | {:unknown, reference()}
```

# `operation_options`

```elixir
@type operation_options() :: keyword()
```

# `accept`

```elixir
@spec accept(pid(), non_neg_integer() | operation_options()) ::
  {:ok, Quic.Runtime.ConnectionHandle.t()} | failure()
```

# `attach`

```elixir
@spec attach(Quic.Runtime.ConnectionHandle.t(), pid(), keyword()) :: :ok | failure()
```

# `capabilities`

```elixir
@spec capabilities() :: %{
  datagram: true,
  delivery: :pull,
  http3: false,
  io: [:external | :standalone, ...],
  max_write_bytes: 16384,
  migration: %{peer: [:server, ...], local: []},
  resumption: false,
  streams: [:bidi | :uni, ...],
  version: 1
}
```

# `client`

```elixir
@spec client(keyword()) :: GenServer.on_start()
```

# `close`

```elixir
@spec close(
  Quic.Runtime.ConnectionHandle.t(),
  non_neg_integer(),
  binary(),
  operation_options()
) ::
  :ok | failure()
```

# `connect`

```elixir
@spec connect(pid(), {:inet.ip_address(), :inet.port_number()}, operation_options()) ::
  {:ok, Quic.Runtime.ConnectionHandle.t()} | failure()
```

# `events`

```elixir
@spec events(Quic.Runtime.ConnectionHandle.t(), pos_integer(), operation_options()) ::
  {:ok, list()} | failure()
```

# `info`

```elixir
@spec info(Quic.Runtime.ConnectionHandle.t()) :: {:ok, map()} | failure()
```

# `listen`

```elixir
@spec listen(keyword()) :: GenServer.on_start()
```

# `local`

```elixir
@spec local(pid()) :: {:inet.ip_address(), :inet.port_number()} | {:error, term()}
```

# `open_stream`

```elixir
@spec open_stream(
  Quic.Runtime.ConnectionHandle.t(),
  :bidi | :uni,
  operation_options()
) ::
  {:ok, Quic.Runtime.StreamHandle.t()} | failure()
```

# `operation_status`

```elixir
@spec operation_status(Quic.Runtime.ConnectionHandle.t() | pid(), reference()) ::
  map() | :unknown | failure()
```

# `ping`

```elixir
@spec ping(Quic.Runtime.ConnectionHandle.t(), operation_options()) ::
  {:ok, reference()} | failure()
```

Admit one QUIC PING for caller-managed keepalive.

Uses the same finite operation deadlines, deduplication, bounded send queue and
recovery as stream sends. `{:ok, ref}` reports admission, not peer receipt or ACK.
Choose a finite cadence below the peer's advertised idle limit, available in
`info/1`. Sending without successfully processing peer packets cannot postpone
local idle expiry indefinitely. No periodic task or timer is created.

# `read`

```elixir
@spec read(Quic.Runtime.StreamHandle.t(), pos_integer(), operation_options()) ::
  {:ok, list()} | failure()
```

# `read_datagrams`

```elixir
@spec read_datagrams(
  Quic.Runtime.ConnectionHandle.t(),
  pos_integer(),
  operation_options()
) ::
  {:ok, [binary()]} | failure()
```

# `ready`

```elixir
@spec ready(Quic.Runtime.ConnectionHandle.t()) :: :ready | :pending | failure()
```

# `reset_stream`

```elixir
@spec reset_stream(
  Quic.Runtime.StreamHandle.t(),
  non_neg_integer(),
  operation_options()
) ::
  {:ok, reference()} | failure()
```

# `send_datagram`

```elixir
@spec send_datagram(Quic.Runtime.ConnectionHandle.t(), binary(), operation_options()) ::
  {:ok, reference()} | failure()
```

# `send_stream`

```elixir
@spec send_stream(
  Quic.Runtime.StreamHandle.t(),
  binary(),
  boolean(),
  operation_options()
) ::
  {:ok, reference()} | failure()
```

# `stop_stream`

```elixir
@spec stop_stream(
  Quic.Runtime.StreamHandle.t(),
  non_neg_integer(),
  operation_options()
) ::
  {:ok, reference()} | failure()
```

---

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