Commit Graph
3 Commits
Author SHA1 Message Date
lockbitchat 7754f6ba15 docs: record SBQ2 phases 2 and 3 as shipped in v5.9.0 2026-08-06 18:42:40 -04:00
lockbitchat fb959d7ca7 fix(descriptor): rebuild SDP that Firefox accepts; release v5.8.1
Live cross-browser testing found three defects in the SBQ2 SDP template, all
invisible to Chrome and all fatal to Firefox.

The candidate lines omitted raddr/rport on srflx and relay candidates. RFC 8839
section 5.1 makes rel-addr and rel-port mandatory for non-host candidates even
though ICE never reads them; Chrome tolerates the omission and Firefox drops the
candidate. Relay-only connections to Firefox failed 0/8 against 8/8 for the
browser's own SDP. The STUN and TURN profiles hid it because a host pair
connected instead -- the relay candidates were never actually needed there.

The template also advertised ice-options:trickle without ever closing the
candidate set, though a descriptor is a complete one-shot set with no channel to
trickle over, and hard-coded the m= port and c= line to the 9 / 0.0.0.0 null
default candidate, which is the trickle convention for "nothing gathered yet".
Both are now correct: no trickle, an explicit a=end-of-candidates, and the most
publicly reachable candidate as the default.

All three are serializer-side and cost zero descriptor bytes; sizes are
unchanged at 98-149 bytes, QR version 6-8. Verified 48/48 across all 16
combinations of {Chrome, Firefox} squared and four network profiles, with every
relay-only pair now connecting over the relay.
2026-08-06 17:25:46 -04:00
lockbitchat 6e82cfcae2 feat(descriptor): SBQ2 connection descriptor format; release v5.8.0
The SB1 invitation runs 2000-2400 characters and needs QR version 38-40, past
the point where a single code is scannable, so the app falls back to an
animated multi-frame QR. SBQ2 is a fixed binary layout carrying only what
brings up DTLS -- ICE credentials, certificate fingerprint, candidates -- with
the SDP rebuilt from a template by a strict serializer. Measured on real Chrome
and Firefox SDP across four network profiles: 98-149 bytes, QR version 6-8.

Key material is meant to move to the DataChannel, bound by a commitment in the
descriptor. That half does not exist yet, so nothing calls this module: the
format is landed for review and freeze, not wired into the connection path.
doc/DESCRIPTOR-SBQ2.md records the gate on phase 3.

The decoder is a parser of hostile input: fixed offsets, explicit lengths,
deny-by-default on reserved values and unknown TLV extension types, trailing
bytes rejected, ICE credentials alphabet-checked so a CRLF cannot reach the
serializer. No compression -- DEFLATE adds bytes on this payload, and dropping
it removes the decompression-bomb surface with it.

Candidate pruning keeps coverage before count: one candidate per (family, type,
transport) survives before any surplus, so an IPv6-only or UDP-blocked path
cannot be pruned away by a v4-first sort.

Tests cover round-trip against captured Chrome and Firefox SDP, IPv6 and NAT64
addresses, ICE-TCP candidates, the TLV area, clock skew, one-shot binding and
SAS transcript coverage.
2026-08-06 11:54:05 -04:00