Quic.IO.Endpoint (elixir_quic v1.0.0-rc.9)

Copy Markdown View Source

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.

Summary

Types

initial_state()

@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()) => path_ledger()},
  queue: {[], []},
  queue_bytes: 0,
  timers: %{}
}

path_id()

@type path_id() :: term()

path_ledger()

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

send_ref()

@type send_ref() :: reference()

t()

@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()) => path_ledger()},
  queue: term(),
  queue_bytes: term(),
  timers: term()
}

Functions

add_path(state, id, validated \\ false)

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

bump_generation(state)

dequeue(state)

drop_path(state, id)

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

enqueue(state, bytes, remote, now)

enqueue(state, bytes, remote, now, id)

@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(state, send, result, at)

new(opts \\ [])

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

path(state, id)

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

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

receive_bytes(state, bytes)

receive_bytes(state, bytes, id)

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

select_path(state, id)

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

selected_path(state)

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

Selected path used by the legacy IO arities.

shutdown(state)

timer(state, kind, deadline)

timer_expired?(state, timer, now)

validate_address(state)

validate_address(state, id)

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