Skip to content

No independently pollable peer STOP_SENDING notification #350

Description

@spotdemo4

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions