Skip to content

row 132 (piece 3d): a datagram-framer claim is a duplex session on its claim door - #847

Merged
MattJackson merged 11 commits into
predevfrom
lane-webrtc-terminate-session
Oct 15, 2026
Merged

MattJackson merged 11 commits into
predevfrom
lane-webrtc-terminate-session

Conversation

@MattJackson

Copy link
Copy Markdown
Collaborator

Status row 132, piece 3d: on the root's serve path, a claim over a datagram framer becomes a duplex session. This follows the ARCHITECT row-132 rulings: seam (a)/(b), channels, and pairing.

Stacked: #819 → #825 → #827 → #834 → #837 → this PR. It is a draft.

What

  • The route. In serve.rs, when a door plane's claim has a carrier that a datagram framer answers, the claim is served as a duplex session on the driver's one SessionCaller path:
    1. The request body is the far end's description.
    2. The accepting association on the claim's claim door is settled by that description before the unit is admitted. A description the framer refuses refuses the unit.
    3. Once the unit is admitted, the association joins the door and the session's pairing is registered in the connector's session book under the unit key, before the session runs.
    4. The answer is the plane's head (201 when the plane states none) with the framer's own description as the body.
    5. The session's cleanup unpairs once, which closes both legs.
  • session() is generic over its caller, with an Attach: the status the caller was answered with, the hook run on admission, and the cleanup hook. The upgrade path keeps 101 and no hooks.
  • serve_datagram.rs:
    • ClaimDoor: one port, whose task demultiplexes datagrams to associations and keeps their clock.
    • CallerLeg: the leg's LegSink and its channel.
    • DatagramCaller: the session's caller side. Channel messages are its pieces; line frames never reach it.
  • Served.claim_doors stays empty until the transport's inbound need binds a door. That binding happens at boot (ruling (d)) and lands with the plane's datagram claim, after FLIP-STREAMING: the streaming plane served through its door; busbar-voice deleted #503.

RED-able tests (crates/busbar/src/root/tests/serve_datagram.rs)

  • A channel's messages are the session's pieces. Writes made before the channel opens wait for it. The description is never a piece.
  • RED: a plane that falls behind its caller ends the session. The pairing closes and the caller side ends.

Ledgers

None.

…, verified, and sends only where the secure layer allows (row 132, piece 2)

One association's datagram framer, driven over the host's dtls engine with the datagram lane on
every call (THE DESIGN l.758-766): paths are host numbers, told once, and only for addresses
the secure layer knows; the rendezvous terms build the association; the exported keying
material crosses once, on a call whose lane says the far end is verified, and is dropped
(zeroed) after it; clear routes leave only where may_send_clear allows, secured routes are
sealed to the bound path; path requests bind only a proven path. Every answer is judged by
check_datagram before a byte of it is used. Sans-IO; accepting side.

Tests (src/tests/datagram_tests.rs), a scripted framer over a real ring handshake against a
second dtls engine: the item crosses exactly once, verified, equal to the far end's export
(RED: never or every call); a spoofed source never reaches the framer (RED: the honest check
does); a rebind to an unanswered path is not applied and a non-answer clear route is dropped
(RED: answered, it binds); a lane-breaking answer is a FAULT.
…efore a byte goes there and binds one only once proven (row 132, piece 2b)

ARCHITECT ruling (row 132, condition 1): the upstream leg is a WebRTC dial, back to back, Opus
passed through. A dialling association hears nothing before it sends, so the far end's
advertised candidates are judged by the host's one destination judge (DialJudge, under the
dialling need's egress class) before any probe; a refused candidate is never numbered, told
or sent a byte. An admitted one is an Association candidate: core probes it (ICE-CONTROLLING
on this side), the framer's own checks may go to it, and a bind to it applies only once
core's probe is answered from that path (l.762, a spoof is a RED).

DatagramFraming::dial (opening fields, judge, class); Association::admit_candidate;
may_send_clear admits a check to an admitted candidate; media up from the bound path.

Tests: dialling, the metadata candidate is judged and refused and receives nothing, the
admitted one binds and the keying item crosses once (RED: refused candidate never told or sent);
an admitted candidate never binds unanswered or answered from another source (RED arm:
answered from itself, it binds); dtls unit test for the admitted candidate's terms.
… its check's user name then by its path; the port on the worker's reactor (row 132, piece 3a)

ARCHITECT ruling (row 132 seam): DatagramPort — one port, demux by local ufrag then path,
reactor readiness. Associations (datagram.rs): a connectivity check finds the association its
USERNAME names (the association still verifies it); anything else finds the association by a
path its secure layer knows; a dialled association is found by its admitted candidates before
they speak; a datagram neither finds is dropped before any association sees it; a failed
association is removed. ReadyPort (udp.rs, the datagram carrier): the bound port on the
calling worker's reactor, a read waits on readiness, a send that would block drops.

Tests: two associations on one port each see only their own checks and paths (RED: an unknown
user name, an unclaimed path and a failed check's path reach nothing); a dialled association is
found by its candidate (RED: the refused candidate finds nothing); the ready port is refused off
a worker and reads on readiness.
…send_answered, not a fn named route (kind-isolation:control-path)

The connector is a control surface and runs no data-path step; the driver's helper only sends a
datagram the framer answered where the secure layer allows it, so it no longer borrows the
kernel's route-step name.
…r, and only it is driven over the port (row 132, piece 3b-i)

The loader reads FRAMING_DATAGRAM off a transport's tail (TransportFacts::datagram) and the
root carries it into the connector's DoorFacts. A datagram framer's claim row states a session
(an association is one), so the claim-stream path would have handed it a stream it cannot
frame (its begin refuses with no lane): stream_framer now never answers a datagram framer, and
DatagramFraming refuses a door that is no datagram framer before any call crosses.

Tests: root serve_framed: the same session rows frame a stream on a stream framer (RED arm) and
never on a datagram framer; connector datagram: a stream framer is refused with nothing crossed
(RED), a datagram framer is driven.
…eir frames unread, and stops both ways at once (row 132, piece 3b-ii)

ARCHITECT ruling (row 132 channels): media never enters the plane; the host bridges the two
associations' lines under the session's one admission. Bridge (datagram.rs): a stream's head
block names a line (kind) or a channel (label); the upstream dial's opening mirrors the caller's
lines (same count, kind, order) then names the session's channels; legs that do not mirror never
half-bridge; a line frame crosses unread to the paired line (each leg seals with its own keys),
is dropped rather than queued when it cannot cross, and nothing crosses after stop. Channel
heads, messages and the description go to the session. Neutral names only: bridge, line.

Tests: head blocks read; frames cross line-for-line both ways and channels go to the session
(RED: nothing crosses after stop); mismatched legs never half-bridge (RED: a paired line 0 still
carries nothing while the set does not mirror).
…over a datagram framer's need, paired by its unit key (row 132, piece 3c)

ARCHITECT ruling (row 132, pairing): OpenDesc gains unit: u64, the kernel-minted unit key an
open serves (0 = none); EgressFarEnd fills it from UnitRoute.unit on every open; a stream framer
ignores it. The connector's session book keys each held session's Pairing by unit
(Connector::pair before the session runs, Connector::unpair in its once-only cleanup).

An open over a datagram framer's need: refused with unit 0 or an unregistered unit; otherwise
the dialling association begins on its own port (the caller leg's host address), its candidates
judged by the one judge; ONE exchange carries its description as the body over the framer
serving the target's scheme, through the same dial path (judged, pinned, secured, auth fields
and member as the walk sent them; never pooled). The head is the reader's. A success answer's
body settles the association and the upstream lines must mirror the caller's before the leg is
attached; any other answer is relayed whole and the pairing closes (no partial bridge). Then
reads are the leg's channel messages and writes go to its channel; the open's timeout_ms bounds
the leg until it is keyed. Close (or a dropped connection) closes the pairing: the bridge stops
and both legs close once.

Tests: the session book refuses unit 0 and an unregistered unit, registers a unit once and
forgets a closed one (RED: the reused key finds no stale leg); two sessions never cross and a
close closes both legs once (RED: nothing after close); a refused exchange is relayed whole and
leaves no bridge, an answered one runs (RED arm); unmirrored lines refuse the open.
… door, admitted before its association joins (row 132, piece 3d)

ARCHITECT rulings (row 132 seam (a)/(b), channels, pairing): a door plane's claim whose carrier a
datagram framer answers is served as a duplex session on the driver's one SessionCaller path.
The request body is the far end's description; the accepting association over the claim's
claim door is settled by it before the unit is admitted (a refused description refuses the
unit). Once admitted, the association joins the door and the session's pairing is registered
in the connector's session book under the unit key, before the session runs; the unit is
answered with the plane's head (201 when it states none) and the framer's own description.
The session's cleanup unpairs once, which closes both legs.

session() is generic over its caller with an Attach (the answered status, the admitted hook,
the cleanup hook); the upgrade path keeps 101 and no hooks. serve_datagram.rs: ClaimDoor (one
port, its task demultiplexing to associations and keeping their clock), CallerLeg (the leg's
LegSink and its channel), DatagramCaller (the session's caller side). Served.claim_doors is
empty until the transport's inbound need binds one.

Tests: a channel's messages are the session's pieces and writes before the channel opens wait
for it (the description is never a piece); RED: a plane that falls behind its caller ends the
session (pairing closed, caller side ended).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stacked stacked on another open PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant