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:
- Set
end_of_stream
to 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§
source§impl<B: Buf> SendStream<B>
impl<B: Buf> SendStream<B>
sourcepub fn reserve_capacity(&mut self, capacity: usize)
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.
sourcepub fn capacity(&self) -> usize
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.
sourcepub fn poll_capacity(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Option<Result<usize, Error>>>
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.
sourcepub fn send_data(&mut self, data: B, end_of_stream: bool) -> Result<(), Error>
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.
sourcepub fn send_trailers(&mut self, trailers: HeaderMap) -> Result<(), Error>
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.
sourcepub fn send_reset(&mut self, reason: Reason)
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.
sourcepub fn poll_reset(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<Reason, Error>>
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
.