Skip to content

Conversation

@iadev09
Copy link
Contributor

@iadev09 iadev09 commented Nov 12, 2025

Summary

  • Adds is_0rtt() method to RequestStream to detect streams opened during 0-RTT
  • Implements Is0rtt trait for QUIC stream types
  • Exposes 0-RTT detection through the h3-quinn adapter layer

Motivation

Applications need to detect 0-RTT streams to properly handle replay-attack risks (RFC 8470 § 5.2).
For example, non-idempotent operations such as POST, PUT, or DELETE should be rejected or handled with extra care on 0-RTT streams.

@iadev09 iadev09 force-pushed the feature/stream-level-0rtt branch from 95fc57a to f97258d Compare November 12, 2025 19:22
@iadev09 iadev09 force-pushed the feature/stream-level-0rtt branch from f077a14 to b2939cf Compare November 12, 2025 19:33
Copy link
Contributor

@Ruben2424 Ruben2424 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. I left some comments below.

@iadev09
Copy link
Contributor Author

iadev09 commented Nov 12, 2025

Thanks a lot for the detailed review!

I initially introduced the Is0rtt trait in server/stream.rs just to make the 0-RTT capability explicit and clearly separated from data I/O. The idea was to show it as a simple additive feature rather than a core stream operation.

That said, your points about consistency make sense — I’ll move the trait into quic.rs, simplify the impls, and clean up the unwrap_or(false) logic accordingly. Let’s update this version and keep it aligned with the existing conventions.

@seanmonstar
Copy link
Member

I had a thought while looking at this. Does it have to be something known by h3? Like, do we need to make it a trait about it? I see in HTTP/3 RFC mention to take a precaution, like you said, but it doesn't otherwise interact with HTTP things.

What if you could peek at specific &S type in a RequestStream, and thus if you knew it was quinn, you could use the quinn method to look at it.

@Ruben2424
Copy link
Contributor

What if you could peek at specific &S type in a RequestStream, and thus if you knew it was quinn, you could use the quinn method to look at it.

Could be useful generally. But in this case having a trait could allow libraries also generic over quic transport to use this information for example to automatically return 425 status code. Maybe something for hyper?

Address review feedback by refactoring 0-RTT detection:

- Move Is0rtt trait from h3::server to h3::quic module
  All QUIC transport traits belong in the quic abstraction layer,
  allowing libraries like hyper to use 0-RTT detection generically
  across different QUIC implementations.

- Fix RecvStream::is_0rtt() to cache value at construction time
  Previously used unwrap_or(false) which could incorrectly return
  false for 0-RTT streams if poll API was misused. Now stores the
  0-RTT flag in a dedicated field initialized in new().

- Implement Is0rtt trait for both BidiStream and RecvStream
  Ensures consistent 0-RTT detection across all stream types.

- Simplify BidiStream implementation
  Remove redundant public is_0rtt() method, keep only trait impl
  that delegates to recv.is_0rtt().

- Keep RequestStream::is_0rtt() convenience method for ergonomic
  stream-level access in server applications.

This maintains backward compatibility for users while fixing the
potential security issue where 0-RTT status could be lost.

Refs: PR hyperium#323
@iadev09
Copy link
Contributor Author

iadev09 commented Nov 12, 2025

For reference, this topic was also discussed in quinn-rs/quinn#2440
.
In that context we concluded that 0-RTT state is best observed at the stream level.

@iadev09 iadev09 requested a review from Ruben2424 November 12, 2025 23:32
@Ruben2424 Ruben2424 merged commit e75b509 into hyperium:master Nov 30, 2025
16 checks passed
@Ruben2424
Copy link
Contributor

merged it, thanks.

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.

3 participants