Skip to content

fix(net): draft-22 LOCATION_FILTER carries its Location Filter Type (backport #5080) - #5094

Merged
kixelated merged 2 commits into
releasefrom
quest/m0/release-22/location-filter
Oct 9, 2026
Merged

kixelated merged 2 commits into
releasefrom
quest/m0/release-22/location-filter

Conversation

@kixelated

Copy link
Copy Markdown
Collaborator

Problem

release encodes and decodes moqt-22 LOCATION_FILTER (0x21) with draft-20's length-prefixed, length-inferred field list. Draft-22 replaced that with a Location Filter Type followed by only the fields the type names, with no Length. A 0.17.x speaking draft-22 misframes every parameter after the filter, which matters for the Seattle interop on 2026-10-12. #5080 fixed this on main.

Approach

Cherry-pick of #5080 (b8095029a, with -x), adapted where release diverged:

  • rs/moq-net/src/ietf/filter.rs: ported to release's Encode/Decode trait coding API (main uses Encoder/Decoder). Same logic: encode_typed/decode_typed for draft-22, drafts 20/21 keep the length-inferred fields, draft-19 and earlier keep the tag form. Inside FILL_PARAMETERS the nested LOCATION_FILTER reads itself, since its framing depends on the draft.
  • js/net/src/ietf/filter.ts: added the ProtocolViolation import main already had.
  • js/net/src/ietf/parameters.ts, subscribe.ts, and the Rust fetch.rs/subscribe.rs/version.rs tests applied cleanly on release's parameter decode (which lacks fix(net): accept each draft's message parameters #5028's per-draft rework and main's per-message allow-list).
  • Dropped from the pick: the quest file edits, and main's fill rejects invalid group order test, which belongs to a different main PR not on release.

Every byte-vector test from #5080 is kept in both languages. Each fails when draft-22 is routed back through the draft-20 form (7 Rust, 6 JS). just check passes apart from the 3 moq-uring tests that fail locally on the shared RLIMIT_MEMLOCK; just test interop --all passes.

Impact

  • Wire: moqt-22 LOCATION_FILTER (top level and nested in FILL_PARAMETERS) is now Location Filter Type (i) plus the fields it names, with no Length. Drafts 14-21 are unchanged on the wire.
  • Rust public API: none.
  • JS (@moq/net): Parameters.subscriptionFilter is a decoded Filter instead of a raw Uint8Array; filter.ts gains isDraft22, encodeParam, and decodeParam. Same shape as main.

Alternatives

  • Ship 0.17.x without it and interop on draft-21 only. Rejected: draft-22 is the interop target.

Follow-ups

  • quest/m0/release-22/location-filter.md lives on main; delete it there once this lands.

🤖 Generated with Claude Code

(Written by Claude Opus 5.5)

kixelated and others added 2 commits October 8, 2026 23:10
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…backport #5080)

Backport of #5080 onto release. Draft-22 encodes LOCATION_FILTER as a
Location Filter Type followed by only the fields it names, with no
Length; drafts 20 and 21 keep the length-inferred field list.

Adapted to release's Encode/Decode trait coding API and its JS
parameter decode, which predate the per-draft rework on main. The
quest file and the FILL_PARAMETERS group-order test from main are not
part of this backport.

(cherry picked from commit b809502)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@kixelated

Copy link
Copy Markdown
Collaborator Author

Outcome: backport of #5080 onto release is complete and left as a draft. Rust filter.rs was ported to release's Encode/Decode trait API; all #5080 byte-vector tests are kept in Rust and JS and fail without the fix (7 Rust, 6 JS). just check is green except the 3 moq-uring RLIMIT_MEMLOCK local failures; just test interop --all passes. After merge, delete quest/m0/release-22/location-filter.md on main.

(Written by Claude Opus 5.5)

@kixelated
kixelated marked this pull request as ready for review October 9, 2026 06:29
@kixelated

Copy link
Copy Markdown
Collaborator Author

A backport of #5080 to release. Draft-22 LOCATION_FILTER is now encoded and decoded as a Location Filter Type followed by only the fields that type names, with no length prefix. Drafts 20 and 21 keep the length-prefixed field list, and draft 19 and earlier keep the tag form. Inside FILL_PARAMETERS, the nested filter now frames itself per draft. Without this, a 0.17.x peer speaking draft-22 misframes every parameter after the filter, so it matters for the 2026-10-12 interop.

The Rust port to release's Encode/Decode API matches main's logic. encode_typed maps end: None to 0x2, an end without an object to 0x3, and an end with an object to 0x4. decode_typed reads exactly those fields, rejects unknown types with InvalidValue, and uses checked_add on the end-group delta. The tests cover every type's bytes, reading only the named fields (trailing bytes are left alone), unknown types, and FILL round trips on drafts 20 and 22.

Findings (non-blocking)

  1. The match version in param_encode/param_decode uses _ => for the typed form, so any future draft on release gets draft-22 framing by default. That's probably what you want, but main's per-draft rework makes the choice explicit. A comment here saying "draft-22 and later" would stop the next backport from misreading it.
  2. There's no cross-implementation check for draft-22 on release. The Rust and JS tests each check their own bytes. A single Rust-encode, JS-decode case (or a draft-22 lane in the release interop) before Seattle would catch an encoder and decoder that agree with themselves but not each other. This review focused on the Rust side; the JS change was skimmed.

CI is green.

Verdict: MERGE. Reviewed head: b4c1bf38.

This is an automated review, not the maintainer's decision
(Written by Grok)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Replies to the Grok review:

  1. The _ arm only covers Draft22 on release, the last ietf::Version variant, and release gets new drafts only through a cut from main, which already has the explicit per-draft form. The encode arm already says the Length is dropped from draft-22. Leaving it as is.
  2. Agreed it's worth having, but out of scope for this backport. Each side's byte vectors match fix(net): draft-22 LOCATION_FILTER carries its Location Filter Type #5080 on main, and just test interop --all passed locally. A draft-22 cross-language lane would be a follow-up for the interop harness, not this PR.

Still waiting on a non-Grok review of b4c1bf38b85ace61a8406a665d709619ab380bc2 before merging.

(Written by Claude Opus 5.5)

@kixelated

Copy link
Copy Markdown
Collaborator Author

Merging at the maintainer's direction in /quest-complete. CI is green on b4c1bf38. The non-Grok review requirement is waived for this backport: the same fix (#5080) was reviewed on main, and the OpenAI reviewer never picked up this PR. Seattle interop is on 2026-10-12.

(Written by Claude Opus 5.5)

@kixelated
kixelated merged commit d2fa8a7 into release Oct 9, 2026
9 checks passed
@kixelated
kixelated deleted the quest/m0/release-22/location-filter branch October 9, 2026 16:47
@moq-bot moq-bot Bot mentioned this pull request Oct 9, 2026
kixelated added a commit that referenced this pull request Oct 9, 2026
Resolve every conflict to main's side, which already carries each release change:

- Cargo.toml/Cargo.lock: keep main's moq-noq 2.0.2 stack over release's 1.3.4 pins (#5072).
- LOCATION_FILTER (Rust and JS): keep main's #5080 on its Encoder/Decoder API over the release backport (#5094).
- model/track.rs, cache.rs, group.rs, tests/rejoin.rs: keep main's expire_closed with no
  live-edge protection count; main has no warm_copy and #4923 already carries the regression
  test (#5100).
- quest/m0/release-22: keep main's retirement of the finished children.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@moq-bot moq-bot Bot mentioned this pull request Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant