Struct h2::SendStream

source ·
pub struct SendStream<B> { /* private fields */ }
Expand description

Sends the body stream and trailers to the remote peer.

§Overview

A SendStream is provided by SendRequest and SendResponse once the HTTP/2 message header has been sent sent. It is used to stream the message body and send the message trailers. See method level documentation for more details.

The SendStream instance is also used to manage outbound flow control.

If a SendStream is dropped without explicitly closing the send stream, a RST_STREAM frame will be sent. This essentially cancels the request / response exchange.

The ways to explicitly close the send stream are:

§Flow control

In HTTP/2, data cannot be sent to the remote peer unless there is available window capacity on both the stream and the connection. When a data frame is sent, both the stream window and the connection window are decremented. When the stream level window reaches zero, no further data can be sent on that stream. When the connection level window reaches zero, no further data can be sent on any stream for that connection.

When the remote peer is ready to receive more data, it sends WINDOW_UPDATE frames. These frames increment the windows. See the specification for more details on the principles of HTTP/2 flow control.

The implications for sending data are that the caller should ensure that both the stream and the connection has available window capacity before loading the data to send into memory. The SendStream instance provides the necessary APIs to perform this logic. This, however, is not an obligation. If the caller attempts to send data on a stream when there is no available window capacity, the library will buffer the data until capacity becomes available, at which point the buffer will be flushed to the connection.

NOTE: There is no bound on the amount of data that the library will buffer. If you are sending large amounts of data, you really should hook into the flow control lifecycle. Otherwise, you risk using up significant amounts of memory.

To hook into the flow control lifecycle, the caller signals to the library that it intends to send data by calling reserve_capacity, specifying the amount of data, in octets, that the caller intends to send. After this, poll_capacity is used to be notified when the requested capacity is assigned to the stream. Once poll_capacity returns Ready with the number of octets available to the stream, the caller is able to actually send the data using send_data.

Because there is also a connection level window that applies to all streams on a connection, when capacity is assigned to a stream (indicated by poll_capacity returning Ready), this capacity is reserved on the connection and will not be assigned to any other stream. If data is never written to the stream, that capacity is effectively lost to other streams and this introduces the risk of deadlocking a connection.

To avoid throttling data on a connection, the caller should not reserve capacity until ready to send data and once any capacity is assigned to the stream, the caller should immediately send data consuming this capacity. There is no guarantee as to when the full capacity requested will become available. For example, if the caller requests 64 KB of data and 512 bytes become available, the caller should immediately send 512 bytes of data.

See reserve_capacity documentation for more details.

Implementations§

source§

impl<B: Buf> SendStream<B>

source

pub fn reserve_capacity(&mut self, capacity: usize)

Requests capacity to send data.

This function is used to express intent to send data. This requests connection level capacity. Once the capacity is available, it is assigned to the stream and not reused by other streams.

This function may be called repeatedly. The capacity argument is the total amount of requested capacity. Sequential calls to reserve_capacity are not additive. Given the following:

send_stream.reserve_capacity(100);
send_stream.reserve_capacity(200);

After the second call to reserve_capacity, the total requested capacity will be 200.

reserve_capacity is also used to cancel previous capacity requests. Given the following:

send_stream.reserve_capacity(100);
send_stream.reserve_capacity(0);

After the second call to reserve_capacity, the total requested capacity will be 0, i.e. there is no requested capacity for the stream.

If reserve_capacity is called with a lower value than the amount of capacity currently assigned to the stream, this capacity will be returned to the connection to be re-assigned to other streams.

Also, the amount of capacity that is reserved gets decremented as data is sent. For example:

send_stream.reserve_capacity(100);

send_stream.send_data(b"hello", false).unwrap();
// At this point, the total amount of requested capacity is 95 bytes.

// Calling `reserve_capacity` with `100` again essentially requests an
// additional 5 bytes.
send_stream.reserve_capacity(100);

See Flow control for an overview of how send flow control works.

source

pub fn capacity(&self) -> usize

Returns the stream’s current send capacity.

This allows the caller to check the current amount of available capacity before sending data.

source

pub fn poll_capacity( &mut self, cx: &mut Context<'_>, ) -> Poll<Option<Result<usize, Error>>>

Requests to be notified when the stream’s capacity increases.

Before calling this, capacity should be requested with reserve_capacity. Once capacity is requested, the connection will assign capacity to the stream as it becomes available. There is no guarantee as to when and in what increments capacity gets assigned to the stream.

To get notified when the available capacity increases, the caller calls poll_capacity, which returns Ready(Some(n)) when n has been increased by the connection. Note that n here represents the total amount of assigned capacity at that point in time. It is also possible that n is lower than the previous call if, since then, the caller has sent data.

source

pub fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), Error>

Sends a single data frame to the remote peer.

This function may be called repeatedly as long as end_of_stream is set to false. Setting end_of_stream to true sets the end stream flag on the data frame. Any further calls to send_data or send_trailers will return an Error.

send_data can be called without reserving capacity. In this case, the data is buffered and the capacity is implicitly requested. Once the capacity becomes available, the data is flushed to the connection. However, this buffering is unbounded. As such, sending large amounts of data without reserving capacity before hand could result in large amounts of data being buffered in memory.

source

pub fn send_trailers(&mut self, trailers: HeaderMap) -> Result<(), Error>

Sends trailers to the remote peer.

Sending trailers implicitly closes the send stream. Once the send stream is closed, no more data can be sent.

source

pub fn send_reset(&mut self, reason: Reason)

Resets the stream.

This cancels the request / response exchange. If the response has not yet been received, the associated ResponseFuture will return an Error to reflect the canceled exchange.

source

pub fn poll_reset( &mut self, cx: &mut Context<'_>, ) -> Poll<Result<Reason, Error>>

Polls to be notified when the client resets this stream.

If stream is still open, this returns Poll::Pending, and registers the task to be notified if a RST_STREAM is received.

If a RST_STREAM frame is received for this stream, calling this method will yield the Reason for the reset.

§Error

If connection sees an error, this returns that error instead of a Reason.

source

pub fn stream_id(&self) -> StreamId

Returns the stream ID of this SendStream.

§Panics

If the lock on the stream store has been poisoned.

Trait Implementations§

source§

impl<B: Debug> Debug for SendStream<B>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<B> Freeze for SendStream<B>

§

impl<B> RefUnwindSafe for SendStream<B>

§

impl<B> Send for SendStream<B>
where B: Send,

§

impl<B> Sync for SendStream<B>
where B: Send,

§

impl<B> Unpin for SendStream<B>

§

impl<B> UnwindSafe for SendStream<B>

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.

source§

impl<T> Instrument for T

source§

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

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

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>,

§

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>,

§

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.
source§

impl<T> WithSubscriber for T

source§

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
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

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