Skip to main content

RequestIdAllocator

Struct RequestIdAllocator 

Source
pub struct RequestIdAllocator {
    role: Role,
    next_id: u64,
    max_id: u64,
    peer_next_id: u64,
}
Expand description

Allocates this endpoint’s request IDs and checks the parity of the peer’s.

Draft-14 Section 9.1: “The client’s Request ID starts at 0 and are even and the server’s Request ID starts at 1 and are odd. The Request ID increments by 2 with each FETCH, SUBSCRIBE, SUBSCRIBE_UPDATE, SUBSCRIBE_NAMESPACE, PUBLISH, PUBLISH_NAMESPACE or TRACK_STATUS request.” The step of two is what keeps the two endpoints’ ID spaces disjoint, so it is not a spacing convention an implementation may tighten: one that steps by one starts issuing the IDs reserved for its peer on its second request, and the same section makes that a session close with INVALID_REQUEST_ID.

The ceiling is exclusive. Section 9.5 describes the MAX_REQUEST_ID message’s Request ID field as “The new Maximum Request ID for the session plus 1”, and closes the session with TOO_MANY_REQUESTS on a request ID “equal to or larger than this”. Section 9.3.2.3 gives the setup parameter of the same name a default of 0 and reads that as “the peer MUST NOT send requests”, which only holds if a ceiling of 0 forbids the ID 0 as well.

Fields§

§role: Role§next_id: u64§max_id: u64§peer_next_id: u64

Implementations§

Source§

impl RequestIdAllocator

Source

pub fn new(role: Role) -> Self

Create an allocator for the given role, starting at ID 0 or 1 with a ceiling of 0 - blocked until the peer raises it.

Source

pub fn role(&self) -> Role

The role this allocator allocates for.

Source

pub fn allocate(&mut self) -> Result<VarInt, RequestIdError>

Allocate the next request ID.

§Errors

RequestIdError::Blocked when the next ID would reach the ceiling.

Source

pub fn update_max(&mut self, new_max: u64) -> Result<(), RequestIdError>

Update the maximum allowed request ID (can only increase).

§Errors

RequestIdError::Decreased if the new value is not strictly greater than the current one, which Section 9.5 calls a protocol violation.

Source

pub fn validate_peer_id(&self, id: u64) -> Result<(), RequestIdError>

Check the parity of a request ID the peer put on the wire.

The parity checked here is the peer’s, the opposite of this allocator’s own, so a client accepts only odd IDs.

This deliberately does not check the ID against a ceiling. The ceiling that applies to a peer’s request ID is the MAX_REQUEST_ID this endpoint advertised, which the allocator does not hold - max_id here is the budget the peer granted us, a different number that may be larger or smaller. The endpoint owns that check.

§Errors

RequestIdError::WrongParity carrying the ID and the peer’s role, so the message names the endpoint that broke the rule rather than the one that caught it.

Source

pub fn is_blocked(&self) -> bool

Whether the next allocation would reach the ceiling.

A ceiling of 0 needs no special case: the client’s first ID is 0 and the server’s is 1, and neither is below 0.

Source

pub fn peer_next_id(&self) -> u64

The Request ID the peer’s next new request must carry.

Section 9.1 starts each endpoint’s sequence at 0 or 1 by role and steps it by 2 per request, so the whole sequence is fixed from the outset and the next value is a number rather than a guess.

Source

pub fn record_peer_id(&mut self, id: u64) -> Result<(), RequestIdError>

Take the Request ID of a new request the peer sent, holding it to the sequence Section 9.1 fixes.

“If an endpoint receives a Request ID that is not valid for the peer, or a new request with a Request ID that is not expected, it MUST close the session with INVALID_REQUEST_ID.”

One counter answers both halves of that. A repeat is below the next value and a skip is above it, and neither is the value the peer’s own step of two produces, so nothing further has to be remembered: the set of IDs already spent is every value of this parity below the counter.

Only a new request advances this. A message that names a request already open - a response, a cancellation, an update that carries the original’s ID rather than one of its own - reuses an ID on purpose, and passing one here would refuse it.

§Errors

RequestIdError::OutOfSequence carrying the ID that arrived and the one the sequence called for.

Source

pub fn max_id(&self) -> u64

Get the current maximum request ID.

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 = !

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

fn try_from(value: U) -> Result<T, !>

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