-
Notifications
You must be signed in to change notification settings - Fork 143
Fix subscriber losing App reset codes #946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
When a publisher aborts a track with Error::App(code), the subscriber now correctly receives Error::App(code) instead of Error::Cancel. The fix has two parts: 1. Error::from_transport() checks stream_error() on transport errors to decode QUIC stream reset codes back into the original Error variant via the new from_code() method, instead of wrapping everything as Error::Transport. 2. Subscribers no longer collapse Error::Transport into Error::Cancel, so decoded errors like Error::App propagate to consumers. Also simplifies Error by removing inner data from Transport, Decode, Version, RequiredExtension, and BoundsExceeded variants, making the error type fully round-trippable through to_code()/from_code(). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughThe PR refactors error representation and handling across the moq-lite crate: several Error variants (Transport, Decode, Version, RequiredExtension, BoundsExceeded) become unit-like, many new variants are added, and Error gains 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 🧹 Recent nitpick comments
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
rs/moq-lite/src/error.rs (1)
77-102:⚠️ Potential issue | 🟡 Minor
to_codecan overflow for largeAppvalues.
App(u32::MAX).to_code()computesu32::MAX + 64, which panics in debug builds and wraps in release builds. SinceApp(u32)is public, callers can construct any value. Consider either clamping/saturating or validating at construction time.Proposed fix: saturating arithmetic
- Self::App(app) => *app + 64, + Self::App(app) => app.saturating_add(64),Alternatively, you could cap
Appvalues infrom_codeor add a constructor that validatesapp < u32::MAX - 63.rs/moq-lite/src/coding/reader.rs (1)
92-110:⚠️ Potential issue | 🟠 Major
read_exactmay loop infinitely if the stream closes before the buffer is filled.The
RecvStream::read_bufmethod returnsResult<Option<usize>>, whereOk(None)signals EOF. On line 106, the result is only checked for errors via.map_err(Error::from_transport)?, butOk(None)is silently discarded and the loop continues. This causes an infinite loop if the stream closes prematurely. Theread_more()method (line 151) correctly handles this with a match statement that checks forOk(None).Proposed fix
while buf.has_remaining_mut() { - self.stream.read_buf(&mut buf).await.map_err(Error::from_transport)?; + match self.stream.read_buf(&mut buf).await { + Ok(Some(_)) => {} + Ok(None) => return Err(Error::Decode), + Err(e) => return Err(Error::from_transport(e)), + } }
- Change Error::App(u32) to Error::App(u16) to prevent overflow when encoding to wire format (code + 64). Out-of-range codes in from_code() now return ProtocolViolation instead of silently truncating. - Fix pre-existing infinite loop in read_exact when the stream closes before the buffer is filled. read_buf returning Ok(None) was silently ignored; now returns Error::Decode. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
roberte777
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this looks good to me, basically what I came up with as well.
Integrate UnknownAlpn variant and Version enum refactor from main, keeping our simplified Error::Version (no inner data). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
Fixes #936. When a publisher aborts a track with
Error::App(code), subscribers now correctly receiveError::App(code)instead ofError::Cancel.Error::from_transport()checksstream_error()on transport errors to decode QUIC stream reset codes back into the originalErrorvariant via the newfrom_code()method, instead of wrapping everything asError::TransportError::TransportintoError::Cancel, so decoded errors likeError::Apppropagate correctly to consumersErrorenum by removing inner data fromTransport,Decode,Version,RequiredExtension, andBoundsExceededvariants, making the error type fully round-trippable throughto_code()/from_code()Test plan
just checkpasses (compilation, tests, linting, formatting)track.abort(Error::App(42))→ subscriber receivesError::App(42)(notError::Cancel)🤖 Generated with Claude Code