Struct SendStream
struct SendStream<B> { ... }
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:
- Set
end_of_streamto true when callingsend_request,send_response, orsend_data. - Send trailers with
send_trailers. - Explicitly reset the stream with
send_reset.
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
impl<B: Buf> SendStream<B>
fn reserve_capacity(self: &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
capacityargument is the total amount of requested capacity. Sequential calls toreserve_capacityare not additive. Given the following:# use *; #After the second call to
reserve_capacity, the total requested capacity will be 200.reserve_capacityis also used to cancel previous capacity requests. Given the following:# use *; #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_capacityis 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:
# use *; # asyncSee Flow control for an overview of how send flow control works.
fn capacity(self: &Self) -> usizeReturns the stream's current send capacity.
This allows the caller to check the current amount of available capacity before sending data.
fn poll_capacity(self: &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 returnsReady(Some(n))whennhas been increased by the connection. Note thatnhere represents the total amount of assigned capacity at that point in time. It is also possible thatnis lower than the previous call if, since then, the caller has sent data.fn send_data(self: &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_streamis set tofalse. Settingend_of_streamtotruesets the end stream flag on the data frame. Any further calls tosend_dataorsend_trailerswill return anError.send_datacan 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.fn send_trailers(self: &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.
fn send_reset(self: &mut Self, reason: Reason)Resets the stream.
This cancels the request / response exchange. If the response has not yet been received, the associated
ResponseFuturewill return anErrorto reflect the canceled exchange.fn poll_reset(self: &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 aRST_STREAMis received.If a
RST_STREAMframe is received for this stream, calling this method will yield theReasonfor the reset.Error
If connection sees an error, this returns that error instead of a
Reason.fn stream_id(self: &Self) -> StreamIdReturns the stream ID of this
SendStream.Panics
If the lock on the stream store has been poisoned.
impl<B> Freeze for SendStream<B>
impl<B> RefUnwindSafe for SendStream<B>
impl<B> Send for SendStream<B>
impl<B> Sync for SendStream<B>
impl<B> Unpin for SendStream<B>
impl<B> UnsafeUnpin for SendStream<B>
impl<B> UnwindSafe for SendStream<B>
impl<B: $crate::fmt::Debug> Debug for SendStream<B>
fn fmt(self: &Self, f: &mut Formatter<'_>) -> Result
impl<T> Any for SendStream<B>
fn type_id(self: &Self) -> TypeId
impl<T> Borrow for SendStream<B>
fn borrow(self: &Self) -> &T
impl<T> BorrowMut for SendStream<B>
fn borrow_mut(self: &mut Self) -> &mut T
impl<T> From for SendStream<B>
fn from(t: T) -> TReturns the argument unchanged.
impl<T> Instrument for SendStream<B>
impl<T> WithSubscriber for SendStream<B>
impl<T, U> Into for SendStream<B>
fn into(self: Self) -> UCalls
U::from(self).That is, this conversion is whatever the implementation of
[From]<T> for Uchooses to do.
impl<T, U> TryFrom for SendStream<B>
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto for SendStream<B>
fn try_into(self: Self) -> Result<U, <U as TryFrom<T>>::Error>