Skip to main content

Writer

Struct Writer 

Source
pub struct Writer { /* private fields */ }
Expand description

The sending half of a split request stream.

Implementations§

Source§

impl Writer

Source

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.

Source

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.

Source

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.

Source

pub fn reset(&mut self, code: Code)

Abruptly resets the sending side with an error code.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more