pub struct Writer { /* private fields */ }Expand description
The sending half of a split request stream.
Implementations§
Source§impl Writer
impl Writer
Sourcepub async fn send_data(&mut self, data: Bytes) -> Result<(), StreamError>
pub async fn send_data(&mut self, data: Bytes) -> Result<(), StreamError>
Sends body data, applying the peer’s flow-control backpressure.
The frame header and the payload go out as two chunks of one write, so
the payload is never copied: what arrives here as a Bytes is what
quinn queues.
Not cancel-safe, unlike Reader::recv_data. A peer that grants no
flow-control credit parks this for as long as it likes, so both tunnels
do abandon it, under a teardown signal or a timeout; what they may not
do afterwards is finish the stream. Abandoning the write part-way leaves
the header written and the payload not, which is a truncated DATA frame,
and RFC 9114 §7.1 says what that costs: “When a stream terminates
cleanly, if the last frame on the stream was truncated, this MUST be
treated as a connection error of type H3_FRAME_ERROR. Streams that
terminate abruptly may be reset at any point in a frame.” So a reset
behind an abandoned send is not tidying up after the fact; it is what
makes the truncation legal, and a FIN in its place is the connection
error that sentence names.
Sourcepub fn finish(&mut self) -> Result<(), StreamError>
pub fn finish(&mut self) -> Result<(), StreamError>
Ends the sending side cleanly (a QUIC stream FIN), without awaiting.
Synchronous for the reason Stream::finish gives.
Sourcepub fn stopped(
&self,
) -> impl Future<Output = StreamError> + Send + 'static + use<>
pub fn stopped( &self, ) -> impl Future<Output = StreamError> + Send + 'static + use<>
Resolves when the peer stops this stream, or the connection under it ends.
The mirror of Reader::reset_by_peer on the sending half, and it
exists for the mirror of that reason. Self::send_data already reports
a STOP_SENDING – it is the error a write fails with – but only to a
caller that is writing, and a CONNECT tunnel spends much of its life not
writing: with the client’s half of the tunnel finished and a target that
has yet to say anything, the pump is parked in a read of the target,
and nothing there watches the request stream. This is what such a read
can select on.
§Why this one may be held across writes
The future borrows nothing – [quinn::SendStream::stopped] clones the
connection handle and the stream id into an owned future – so a caller
builds it once, before its loop, and keeps polling the same one while
writing to the same stream through &mut self. That is the point: a
fresh future per iteration would take the connection lock on every pass,
where one that is kept registers once and is a bare Notified poll
afterwards.
It is also why this is safe where quinn::RecvStream::received_reset is
not (that comparison, and the panic it caused, is on
Reader::reset_by_peer): quinn keeps no single-slot waker for it, but
a Notify per stream that the connection wakes and removes when the
stream is stopped or finished.
Cancel-safe, so a select! may poll it and set it aside repeatedly.
§What it resolves to
Only endings. Ok(Some(code)) is the peer’s STOP_SENDING and is the
case this exists for; a lost connection is reported as such; and quinn’s
Ok(None) – the stream gone from the transport, which on a live tunnel
means this endpoint finished it and the peer acknowledged every byte –
is reported as this endpoint’s own clean ending, since no peer said
anything. All three mean the same thing to a caller: nothing more will be
sent on this stream.