Skip to main content

Module rendezvous

Module rendezvous 

Source
Expand description

Rendezvous handshake engine — draft-sharabayko-srt-01 §4.3.2 (Rendezvous Handshake), curated at specs/rules/srt-rendezvous.md. Line cites below (LNNNN) are the source draft’s line numbers, exactly as recorded in that curation.

RendezvousHandshake is symmetric: both peers run the same engine (unlike crate::caller::CallerHandshake / crate::listener::ListenerHandshake, which run different code for different roles). Which of the two logical roles — Initiator or Responder — a given instance ends up playing is decided at runtime by the cookie contest (§4.3.2, L2107-2135): each side supplies its own 32-bit cookie to RendezvousHandshake::new (this crate never reads a clock or a socket address — see crate::handshake_sm::derive_cookie for a ready-made, non-standardized derivation helper, exactly as for crate::listener::ListenerHandshake), and the greater cookie value wins (“becomes Initiator”, L2133-2135).

§State machine

States are named exactly as the draft’s Parallel Handshake Flow diagram (§4.3.2.2, L2280, quoted verbatim): Waving → Attention → Initiated → Connected (plus Idle before RendezvousHandshake::start is called — not spec-named, mirrors crate::caller::CallerHandshakeState::Idle — and Rejected/TimedOut terminal states, also not spec-named). Every transition below is the Initiator table (L2301-2334) or Responder table (L2336-2382), or a missing-packet recovery rule (L2383-2432).

§Serial vs Parallel flow: one engine, not two

The draft narrates two “flows” (§4.3.2.1 Serial, L2140-2269; §4.3.2.2 Parallel, L2270-2432) that differ only in message interleaving, not in any new transition rule: the Parallel flow’s Initiator/Responder tables are complete state × received-message tables, driven purely by message content — so they already cover the Serial flow’s crossing case. That case is: a peer still in Waving (having sent its own WAVEAHAND but never having received the other side’s) receives a CONCLUSION directly instead of a WAVEAHAND (§4.3.2.1 step 3, L2203-2219 — the draft calls the resulting state “fine”). Tracing the draft’s own worked example confirms the action taken is identical to applying the Parallel Attention row to that CONCLUSION: an Initiator receiving an extension-less CONCLUSION here behaves exactly like the Initiator-Attention-row “no extensions” case (L2312-2318); a Responder receiving a CONCLUSION+HSREQ here behaves exactly like the Responder-Attention-row HSREQ case (L2360-2364) — because by this point in the exchange the peer’s role-appropriate first CONCLUSION already carries whatever extension its role dictates (Initiator: HSREQ immediately, L2286-2287; Responder: none until it has seen HSREQ, L2357-2360/L2287-2288). This implementation therefore has no separate “Fine” state — a received CONCLUSION while still in Waving dispatches straight into the same Attention-row logic used when genuinely in Attention, rather than inventing a fourth, behaviourally-divergent state the tables do not define.

§Resolved ambiguities (not explicit in the curated rules)

  • Cookie collision → rejection. The draft says only “the connection will not be made until new, unique cookies are generated” (L2119-2124), describing an out-of-band retry, not a wire action. This engine surfaces it as RejectionReason::RdvCookie (Table 7 code 1009, “rendezvous cookie collision” — an exact fit) rather than blocking or retrying internally; a driver that wants the “regenerate and retry” behaviour builds a fresh RendezvousHandshake with a new cookie.
  • CONCLUSION SYN Cookie field. The draft specifies WAVEAHAND’s SYN Cookie (L2156-2165) but not what later CONCLUSION/AGREEMENT messages carry in that field. Every message this engine sends after WAVEAHAND continues to carry this side’s own cookie (never an echo of the peer’s, unlike the Caller-Listener flood-protection cookie) — consistent with the cookie’s role here being mutual identification/contest, not a flood-protection echo-token.
  • No Stream ID / Group Membership exchange. Neither extension is mentioned anywhere in §4.3.2; unlike crate::handshake_sm::NegotiatedParams from the Caller-Listener flow, this engine never sends them and always reports stream_id: None, group: None — flagged rather than fabricated.
  • Latency/flags reconciliation. §4.3.2 does not restate the greater-latency / AND-flags rule from §4.3.1.2, but it is a property of the Handshake Extension Message itself (§3.2.1.1), not of the flow that carried it, so the same shared handshake_sm reconciliation helper used by the Caller-Listener flow is reused unchanged.
  • Duplicate WAVEAHAND while already Attention. Not covered by either table (which only fire on the first WAVEAHAND). Treated as a benign duplicate: resend the last message, no state change.
  • Recovery rule 3 (data packet promotes a stuck Responder, L2413-2422) is exposed as RendezvousHandshake::on_recovery_trigger, since this engine’s feed takes a ControlPacket (matching crate::caller::CallerHandshake / crate::listener::ListenerHandshake), not the data-plane crate::packet::SrtPacket; a driver that receives a SrtPacket::Data (or any Control packet normally only sent between connected parties — RendezvousHandshake::feed already treats any inbound non-Handshake ControlPacket this way for exactly this reason) calls it directly.

Explicit non-goals, unchanged from the crate root: ARQ/loss, TSBPD delivery, congestion control, AES key-wrap/unwrap crypto, a tokio socket adapter, and the Version-4 legacy Rendezvous path (L2101-2105, out of scope of the draft excerpt this crate implements against).

Structs§

RendezvousHandshake
A driveable, symmetric SRT Rendezvous handshake (draft-sharabayko-srt-01 §4.3.2). See the module docs for the state machine and the design decisions not explicit in the curated rules.

Enums§

RendezvousHandshakeState
Rendezvous handshake lifecycle state (draft-sharabayko-srt-01 §4.3.2). State names are exactly the Parallel Handshake Flow diagram (§4.3.2.2, L2280): Waving -> Attention -> Initiated -> Connected. See the module doc “Serial vs Parallel flow” note for why there is no separate state for the Serial flow’s “fine”.
RendezvousRole
The role a RendezvousHandshake plays, resolved by the cookie contest (draft-sharabayko-srt-01 §4.3.2, L2107-2135): “When one party’s cookie value is greater than its peer’s, it wins the cookie contest and becomes Initiator (the other party becomes the Responder).”