hyperium / hyperium/h3

No independently pollable peer `STOP_SENDING` notification

Open
#350 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
890
Forks
136
Avg merge
14d 20h
Merged PRs (30d)
2

Description

Version

h3 0.0.8, h3-webtransport 0.1.2

Platform

Linux desktop 7.1.7 NixOS x86_64 GNU/Linux

Summary

h3 provides no independently pollable peer STOP_SENDING notification. Servers cannot promptly cancel a response handler while no write is pending, they must fall back to the next response write, RPC deadline, connection close, or server shutdown.

Code Sample
// Server has read request FIN and is waiting for the handler to produce a response.
let next_response = std::future::pending::<Bytes>();
tokio::pin!(next_response);

// Client sends STOP_SENDING for the server-to-client half here.
client.stop_response(STREAM_CANCEL_CODE)?;

// There is no h3 SendStream method to poll in this select for that event.
tokio::select! {
    bytes = &mut next_response => send_bytes(&mut send, bytes).await?,
    _ = connection.closed() => return Err(ConnectionLost),
    // Missing: stopped = send.stopped()
}

To observe the reset with the current API, force a transport operation after the client's STOP_SENDING:

let error = poll_fn(|cx| SendStreamUnframed::poll_send(&mut send, cx, &mut bytes))
    .await
    .unwrap_err();
assert!(matches!(error, StreamErrorIncoming::StreamTerminated { .. }));

The second snippet demonstrates that the error can be classified when a write occurs; the issue is the absence of an independent observer.

Expected Behavior

A send stream should expose a cancellation/closure signal that can be selected concurrently with application work:

select! {
    _ = send.stopped() => cancel_handler(),
    item = response.next() => write(item).await?,
}
Actual Behavior

h3::quic::SendStream provides send, readiness, finish, reset, and stream-ID operations, but no future or poll method for observing peer STOP_SENDING independently of a write. On a bidirectional RPC where the request side has already reached FIN, the server can be waiting for application response data with no transport operation to poll. A client can stop the response direction, but the server learns about it only on a later write/finish, deadline, whole-connection close, or shutdown.

Suggested upstream fix

Extend the QUIC send-stream contract with a transport-agnostic poll_stopped/stopped operation carrying the peer application error code and connection failures. Expose it through request and WebTransport stream wrappers without requiring a dummy write.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the h3::quic::SendStream contract and the SendStreamUnframed polling path shown in the issue. Trace how request and WebTransport stream wrappers expose send-stream operations, then determine how a peer STOP_SENDING event and connection failures should be surfaced independently. Done means the signal is selectable while application work is pending and is exposed through the relevant wrappers without a dummy write.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend-api-design, networking
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.