Skip to main content

Module dispatch

Module dispatch 

Source
Expand description

Per-source connection rate limiting for all deCDN QUIC protocol handlers.

§Problem

iroh’s Router spawns one task per accepted QUIC connection with no concurrency cap. Its incoming_filter hook can refuse a connection before the handshake, but it carries no rate state of its own. A single attacker can exhaust the node’s task capacity by flooding connections faster than the idle timeout reaps them.

§Solution

ConnectionLimiter enforces two independent layers at the top of every deCDN-authored ProtocolHandler::accept implementation:

  1. Global semaphore — hard cap on total in-flight handler tasks.
  2. Per-source rate limit — bounds the connection rate from any one source. Today the source axis is the remote IpAddr (/64-grouped for IPv6); the layer’s name is intentionally generic so future keying axes (e.g. NodeID, ASN) can land without renaming the operator-visible config and metrics surface.

Relay connections that have no resolvable direct IP at accept time bypass the per-source layer (no key to charge); the dispatch_per_source_skipped_no_addr counter records the bypass so operators chasing rejection anomalies can distinguish “layer didn’t fire” from “layer wasn’t applicable”.

The keyed rate limiter is provided by the governor crate. Hot- reload of the rate/burst quota rebuilds the limiter from scratch and swaps the whole PerSource in through an ArcSwap — the acquire read path is lock-free, matching the rest of the reload surface (semaphore is an ArcSwapOption; the reload-fed serve structures are ArcSwap/atomic). Token-bucket state is not preserved across a reload (operators changing live quotas should expect the next acquire from each source to start with a fresh burst budget).

The keyspace prune (retain_recent, an O(n) walk over the keyed map) never runs on the accept path. An accept does only the constant-time bucket check plus an O(1) keyspace-length comparison; when the keyspace grows past cap + cap/10 the accept offloads one single- flighted retain_recent sweep to a background task, so connection admission stays constant-time regardless of keyspace size.

Structs§

ConnectionLimiter
Shared rate limiter used by all deCDN-authored ProtocolHandler implementations.
Permit
RAII permit that holds a semaphore slot for the lifetime of a handler task.

Enums§

RejectReason
Reason a connection was rejected.