flare_mlake · API · quic

flare.quic.timers

flare.quic.timers -- per-connection timer kinds + token encoding for the QUIC reactor.

The reactor reuses the shared :class:flare.runtime.timer_wheel.TimerWheel for every timeout it needs to track. The wheel's per-entry payload is a single UInt64 token, which means each in-flight QUIC timeout needs a self-describing encoding that:

  1. tells the reactor which kind of timeout fired (PTO vs idle vs ack-delay) so the right :class:flare.quic.server.QuicConnection callback runs, and
  2. tells it which connection slot the timeout belongs to so the right :class:QuicConnection in the listener slab gets the call.

encode_timer_token(kind, slot) packs the two values into the high + low halves of the UInt64 token:

| 63                    32 | 31                       0 |
|  KIND (UInt32)           |  SLOT (UInt32)             |

decode_timer_token(token) -> (kind, slot) is the inverse. The split keeps both fields wide enough for any reasonable QUIC server (4 billion concurrent connections, 4 billion timer kinds) while letting the reactor dispatch with a single arithmetic comparison on the high-half kind.

Three kinds ship here; the comments name the RFC sections the reactor dispatch wires each one against:

  • :data:TIMER_KIND_PTO -- RFC 9002 §6.2 PTO probe timer.
  • :data:TIMER_KIND_IDLE -- RFC 9000 §10.1 idle timeout.
  • :data:TIMER_KIND_ACK_DELAY -- RFC 9000 §13.2 deferred-ACK timer.

Additional kinds (key-update, path-validation challenge, etc.) plug into the same encoding; the dispatcher checks kind against the known constants and falls back to a debug log for unknown kinds.

Structs

DecodedTimerToken

struct DecodedTimerToken

(kind, slot) pair returned by :func:decode_timer_token.

Kept as a named struct so callers can destructure cleanly and the dispatcher's intent is obvious at the call site -- token.kind instead of token[0].

Implements Copyable, Movable

Fields
kind: Int
slot: Int

Functions

encode_timer_token

def encode_timer_token(kind: Int, slot: Int) -> UInt64

Pack (kind, slot) into a single :class:UInt64 token.

Both fields must fit in their 32-bit halves; the function raises on out-of-range inputs so a misuse fails loudly rather than silently aliasing a different timer kind on dispatch.

decode_timer_token

def decode_timer_token(token: UInt64) -> DecodedTimerToken

Unpack the high-half kind + low-half slot.

Raises if kind is outside the registered range so the dispatcher catches a stale wheel entry from a removed kind instead of silently misdispatching.

timer_kind_name

def timer_kind_name(kind: Int) -> String

Human-readable name for log + assertion messages. Returns "UNKNOWN" for unregistered kinds so the dispatcher's debug paths don't fail.

Aliases

comptime TIMER_KIND_PTO = Int(1)

RFC 9002 §6.2 PTO (Probe Timeout) timer.

Fires when the sender hasn't received an ACK for the longest-RTT- worth of time after an ack-eliciting packet was sent. On expiry the connection emits one or two PING/PADDING packets (a "PTO probe") so the peer is forced to send an ACK that recovers the lost packet numbers.

comptime TIMER_KIND_IDLE = Int(2)

RFC 9000 §10.1 idle timeout. Fires after max_idle_timeout of no activity in either direction; on expiry the connection silently transitions to CLOSED per RFC 9000 §10.1.2.

comptime TIMER_KIND_ACK_DELAY = Int(3)

RFC 9000 §13.2.1 deferred-ACK timer. Fires when the receiver has queued an ACK but is waiting up to max_ack_delay to coalesce it with other frames. On expiry the receiver emits the queued ACK as its own packet.