rama::http::core::h2

Struct SendStream

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§

§

impl<B> SendStream<B>
where B: Buf,

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.

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.

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.

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.

pub fn send_trailers( &mut self, trailers: HeaderMap, trailer_order: OriginalHttp1Headers, ) -> 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.

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.

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.

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§

§

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

§

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

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
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> FutureExt for T

§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
§

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> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

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

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
§

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

§

fn and<S, P, B, E>(self, other: P) -> And<T, P>
where T: Policy<S, B, E>, P: Policy<S, B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
§

fn or<S, P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<S, B, E>, P: Policy<S, B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
source§

impl<T> Same for T

source§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
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<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

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
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> MaybeSendSync for T