Skip to main content

AboveCodecRule

Enum AboveCodecRule 

Source
pub enum AboveCodecRule {
Show 28 variants PropertiesOnNonNormalStatus, PayloadOnStatusDatagram, BidiStreamOpener, MessageOnTheWrongStream, ResponseNamesAnotherRequest, ResponseBeforeItsFirstResponse, GoAwayAtServer, RepeatedGoAway, RedirectUriAtServer, RedirectTrackNameOnNamespaceRequest, RequestIdParity, RequestIdOutOfSequence, RequestIdCeiling, MaxRequestIdDecreased, SetupParameterValue, DuplicateTrackAlias, MixedForwardingPreference, EndOfTrackOutOfPlace, ObjectPastFinalObject, RequestUpdateForTheWrongRequest, TooManyRequestUpdates, TrackPropertiesOnNonTrackStatus, StateNotifyOnTheWrongRequest, UnrequestedFillStream, SubscribeAfterAnnounceCancel, TrackStatusIsNotASubscription, MessageNamesAnUnknownRequest, NamespacePrefixOverlap,
}
Expand description

A rule a peer broke that no decoder could have caught.

Deliberately not #[non_exhaustive]. A consumer matching on this — a conformance report deciding what it will name a relay for — should find out about a new rule by failing to build, not by silently filing it under a wildcard arm.

The close that travels beside it in crate::dispatch::ErrorCause::PeerViolation is the negotiated draft’s own, and several of these are stated with a close on some drafts and without one on others. The rule is the same rule either way; what the draft does about it is the other field.

Variants§

§

PropertiesOnNonNormalStatus

An Object arrived carrying properties on a status that is not Normal.

Drafts 15 and 16 state it of extension headers and drafts 17 through 20 of properties; the block was renamed and the rule was not. Every draft that states it answers it with a close, so a caller reading crate::dispatch::ErrorCause::PeerViolation finds close: Some on all six.

§

PayloadOnStatusDatagram

A datagram whose header declared a status permitting no payload arrived with bytes after the header.

The one rule here the drafts state as a property of a conforming Object rather than as a “MUST close the session” case, so close is None on every draft that states it, and the datagram is refused with the session left running. A caller that gates on close: Some will therefore never see this one, which is the correct behaviour and not an oversight: a relay cannot be published for breaking a rule its draft attaches no consequence to.

§

BidiStreamOpener

A bidirectional stream the peer opened began with a message type the draft does not permit one to begin with.

The permitted set differs — draft-16 allows the control stream and SUBSCRIBE_NAMESPACE, drafts 17 through 20 allow any message that begins a request stream — and the sentence that forbids the rest is the same on all four. The offending stream is reset and the session closed before the error is returned.

Reached from both halves of this module: a draft’s own ConnectionError raises it where the connection owns the stream, and EndpointError where the endpoint does. One rule, so one name.

§

MessageOnTheWrongStream

A message arrived on a stream the draft does not place it on.

The control stream carrying one the draft puts on a request stream, a request stream carrying one that may not follow a request there, a response arriving where no request is outstanding. Draft-16 states it of NAMESPACE and NAMESPACE_DONE; drafts 18 through 20 state it of every message their Table 5 gives a Stream value to.

Distinct from Self::BidiStreamOpener, which is about the first message on a stream and is what decides what that stream is. This is about a later one arriving somewhere it does not belong.

§No draft states a close for it

The rule is real — a NAMESPACE on the control stream names no request and there is nothing for a receiver to do with it — and the consequence would be ours to invent. The tempting one is Some(PROTOCOL_VIOLATION), on the reading that Section 3.3’s opener sentence covers a message on the wrong stream. It does not: that sentence is about what a bidirectional stream may begin with, and a message arriving on the control stream begins nothing.

Read across all texts for a sentence that closes a session over a message being in the wrong place, there is none. The drafts state placement per message, mostly descriptively; drafts 18 through 20 add a Stream column to their message table, whose only MUST is that a message marked First is the first message on a new request stream — which is Self::BidiStreamOpener’s subject and names no code; and the only sentence in the range that closes a session over misplacement is drafts 19 and 20’s REQUEST_UPDATE sentence, which is Self::RequestUpdateForTheWrongRequest’s.

So a close here would be this build’s model of the protocol rather than a draft’s. session_error_code answers None for every variant that reaches this rule on every draft that raises it, and the receive paths that raise them do not fail the session: the message is refused, the caller is told, and the session runs on — which it can, because a control message carries its own length and the next boundary on the stream is known however this one was refused.

One variant is covered by a draft sentence and is filed under the rule that carries it rather than here. A REQUEST_UPDATE on the control stream is, on drafts 19 and 20, squarely inside the sentence that closes over a REQUEST_UPDATE outside the two cases those drafts permit — the first of which is the request’s own bidi stream — so it is Self::RequestUpdateForTheWrongRequest there, with the citation that rule already carries. On drafts 17 and 18 the same message answers None, because those drafts describe the placement and attach no consequence to it.

The rule stays named. It is enforced, it is the peer’s doing, and a draft that attaches a consequence to it should arrive here as a citation rather than as a rediscovery.

§

ResponseNamesAnotherRequest

A response arrived on one request’s stream naming a different request.

Draft-16 only, and only because that draft has both halves at once: a stream per namespace subscription and a Request ID on the messages that travel it, so the two can disagree. Drafts 17 and later deleted the id from responses, which deletes the disagreement.

§

ResponseBeforeItsFirstResponse

A request stream’s response half opened with something other than the response the draft requires first.

Drafts 18 through 20, of SUBSCRIBE_NAMESPACE and SUBSCRIBE_TRACKS: “If the subscriber receives any message other than a REQUEST_OK or a REQUEST_ERROR as the first message on the response half of the stream, then it MUST close the session with a PROTOCOL_VIOLATION.”

§

GoAwayAtServer

A GOAWAY arrived at a server that had no standing to be sent one.

Draft-07 states the rule about the message — a server may not be sent a GOAWAY at all — and drafts 08 through 20 about the migration URI it carries, since only a server may tell a client where to reconnect. The rename is the same shape as Self::PropertiesOnNonNormalStatus’s: the text moved the prohibition onto the field, and what a conforming client may send did not change.

§

RepeatedGoAway

A second GOAWAY arrived where the draft allows one.

Per session on every draft, and from draft-18 also per request stream — that draft lets a GOAWAY migrate a single request, so one on each of two request streams is two first GOAWAYs and not a repeat. Both are the same sentence read at two scopes.

§

RedirectUriAtServer

A server received a Redirect carrying a Connect URI.

Drafts 18 through 20. The same standing Self::GoAwayAtServer is about, stated of the message that replaced GOAWAY’s migration half.

§

RedirectTrackNameOnNamespaceRequest

A Redirect answering a namespace-scoped request carried a Track Name.

Drafts 18 through 20: “an endpoint that receives a non-empty Track Name in a Redirect for a namespace-scoped request MUST close the session with a PROTOCOL_VIOLATION.”

Which requests are namespace-scoped is named in the first half of that same sentence, and is described here rather than quoted because the list is the half of it that moves: draft-18 names SUBSCRIBE_NAMESPACE and PUBLISH_NAMESPACE, and drafts 19 and 20 add SUBSCRIBE_TRACKS. An ellipsis across that list would join the clause before it to the clause after it and make a sentence none of the three drafts has — which a checker reports as in no draft at all, and which a reader cannot tell from a transcription.

§

RequestIdParity

A Request ID arrived whose least significant bit belongs to this endpoint’s half of the number space.

Drafts 11 and later, which split the space by parity. Drafts 07 through 10 have one shared sequence and state no parity rule, so they cannot break this one.

§

RequestIdOutOfSequence

A new request carried a Request ID that is not the next one the peer’s own sequence calls for.

A repeat and a skip alike. Drafts 11 through 16 state it as “a new request with a Request ID that is not expected” and drafts 17 through 20 as “a duplicate Request ID”; drafts 07 through 10 require the shared Subscribe ID to be “unique and monotonically increasing”. Three phrasings of one requirement — that an id identifies exactly one request for the life of a session.

§

RequestIdCeiling

A request carried a Request ID at or above the ceiling this endpoint advertised.

Drafts 07 through 16. The number measured against is the one this endpoint sent, not the one the peer sent it, and the two are different values. Draft-17 removed MAX_REQUEST_ID and the drafts after it have not brought it back, so there is no ceiling left to exceed.

§

MaxRequestIdDecreased

A ceiling the peer raised did not increase.

Every draft from 07 to 16 states it, and no one sentence covers them. Drafts 11 through 13: “The Maximum Request ID MUST only increase within a session, and receipt of a MAX_REQUEST_ID message with an equal or smaller Request ID value is a ‘Protocol Violation’.”

The other three eras say the same thing in different words. Drafts 07 through 10 state it of the Maximum Subscribe Id and MAX_SUBSCRIBE_ID; drafts 14 and 15 carry draft-14’s rename of the code, so the sentence ends is a PROTOCOL_VIOLATION with no quotation marks on it; and draft-16 splits it in two, keeping the first clause as a sentence of its own and answering the second with a close. Draft-17 removed MAX_REQUEST_ID and nothing after it restored one, so there is no ceiling left for a peer to lower. A setup parameter carrying the same field is held to the same sentence.

The mirror — this endpoint asked to send a ceiling of its own that does not increase — is a separate EndpointError variant on every draft that has this one, so that the two never arrive as the same value. See EndpointFault for why one variant covering both would have been a silent wrong answer rather than an imprecise one.

§

SetupParameterValue

A setup parameter arrived with a value of a kind the draft does not give that parameter.

Drafts 07 through 10, where MAX_SUBSCRIBE_ID is read out of the setup block by hand. The frame decodes — a key-value pair holding bytes where a varint was meant is a well-formed key-value pair — so the decoder cannot see it and the endpoint reading the parameter is what does.

§

DuplicateTrackAlias

The peer used one Track Alias for two different tracks at once.

Every draft states it, and every draft names a code of its own for it rather than the general one — which is why the code travels beside the rule instead of being assumed from it.

§

MixedForwardingPreference

Objects of one track arrived under more than one forwarding preference.

Drafts 07 through 11: “it SHOULD close the session with an error of ‘Protocol Violation’”. SHOULD, so the close is the caller’s to make and this build’s is opt-in. The condition the drafts state it of narrows at draft-11, from any two differing preferences to Objects arriving on both Subgroup streams and datagrams for one SUBSCRIBE; the consequence is the same clause either way, which is why the clause and not the whole sentence is what is quoted.

Drafts 12 through 15 raise it as well and answer it with nothing. That is where a differing Forwarding Preference became one entry in the Malformed Track list, and what those drafts require of a subscriber that detects one is an UNSUBSCRIBE and an error to the application — see Self::ObjectPastFinalObject, which is another entry in the same list. The quotation is held to drafts 07 through 11 for that reason: ranging it across all nine would file four drafts’ silence under a sentence they dropped.

§

EndOfTrackOutOfPlace

An Object with status END_OF_TRACK arrived somewhere the draft does not allow one.

Drafts 08 through 13: “the receiver MUST terminate the session”.

§

ObjectPastFinalObject

An Object arrived past the Object the track had already ended at.

Drafts 12 and later. A Malformed Track rather than a session error, and what the drafts require of a subscriber that detects one moves twice across that range. The words here are drafts 17 through 20’s: “it MUST cancel any corresponding subscription or fetches for that Track from that publisher”.

Drafts 12 and 13 say UNSUBSCRIBE from the Track; drafts 14 through 16 say UNSUBSCRIBE any subscription and FETCH_CANCEL any fetch for that Track from that publisher, which is the same operation named by the two messages that perform it. All three are transport operations on the requests and none of them is a close, so close is None wherever this appears — the reading the range shares, and the reason one quotation stands for the whole of it here.

Past is the drafts’ own Location comparison and not a reading of the word: an Object in a later group is past the end whatever its own Object ID is.

§

RequestUpdateForTheWrongRequest

An update arrived naming a request that cannot take one.

A request the session has never carried, one that has already ended, one of a kind the draft does not let a subscriber update. Drafts 12 through 20 state some of these; drafts 19 and 20 gather them into one sentence — “An endpoint that receives a REQUEST_UPDATE other than in the two cases above MUST close the session with a PROTOCOL_VIOLATION.”

§

TooManyRequestUpdates

More outstanding REQUEST_UPDATEs on one stream than this endpoint advertised room for.

Drafts 19 and 20: “If an endpoint receives a REQUEST_UPDATE on a stream that already has MAX_REQUEST_UPDATES outstanding REQUEST_UPDATEs, it MUST close the session with TOO_MANY_REQUEST_UPDATES.”

The ceiling beside it in the same section, MAX_FILTER_RANGES, is answered with a REQUEST_ERROR instead, and nothing about either sentence signals which — see EndpointFault::ThisEndpoint, which is where that one lands.

§

TrackPropertiesOnNonTrackStatus

Track Properties arrived on a REQUEST_OK answering something that is not a TRACK_STATUS.

Drafts 18 through 20: they “are empty in PUBLISH_OK, REQUEST_UPDATE_OK, SUBSCRIBE_NAMESPACE_OK and PUBLISH_NAMESPACE_OK. If an endpoint receives Track Properties in one of these messages it MUST close the session with a PROTOCOL_VIOLATION.”

§

StateNotifyOnTheWrongRequest

A PUBLISH_STATE_NOTIFY arrived for something that is not a subscription, or from the end of one that may not send it.

Draft-20, one sentence covering both: “PUBLISH_STATE_NOTIFY applies only to subscriptions, and is sent only by the publisher. An endpoint that receives a PUBLISH_STATE_NOTIFY for any other request type, or from the subscriber, MUST close the session with a PROTOCOL_VIOLATION.”

§

UnrequestedFillStream

A fill fetch stream opened against a request that asked for no fill.

Draft-20, where FILL_PARAMETERS is the whole of the request: “Its presence is what requests a fill fetch stream; a subscription with no FILL_PARAMETERS opens none.” Not a close — the draft states no consequence, and the honest handling is STOP_SENDING on that stream alone.

§

SubscribeAfterAnnounceCancel

A SUBSCRIBE arrived for a namespace the peer had cancelled.

Draft-07 alone: “it SHOULD close the session as a ‘Protocol Violation’”. The mechanism it is stated about, ANNOUNCE_CANCEL against a namespace the subscriber then subscribes under, survives the later drafts; the sentence does not.

§

TrackStatusIsNotASubscription

An UNSUBSCRIBE or REQUEST_UPDATE arrived naming a TRACK_STATUS.

Drafts 13 through 18: a track status request is answered once and is never a subscription, so there is nothing for either message to act on. The drafts state it without a code, so close is None.

§

MessageNamesAnUnknownRequest

A message arrived naming a request this session has no record of.

Stated by every draft of the messages that carry an id, and answered by none of them with a code, so close is None throughout.

This is narrower than it looks. Most of the variants that could carry it are raised on both a receive path and a send path and answer EndpointFault::EitherEnd instead; only the ones a draft raises on a receive path alone reach this rule.

§

NamespacePrefixOverlap

The peer subscribed to a namespace prefix overlapping one it already has.

Drafts 07 through 10, which catch it as the message arrives. From draft-11 the same condition is caught where the answer is built, which makes it a refusal this endpoint owes rather than a fault it observed — see EndpointFault::ThisEndpoint.

Never a close on any draft: “it MUST respond with REQUEST_ERROR with error code PREFIX_OVERLAP” is a reply, and a reply needs the request it answers to have been taken.

Implementations§

Source§

impl AboveCodecRule

Source

pub fn citations(self) -> &'static [RuleCitation]

Every draft run this rule has a checked citation for, oldest first.

Exhaustive with no wildcard arm, for the reason the enum is not #[non_exhaustive]: a rule added to this file arrives here as an E0004 and a decision about which drafts state it, rather than as an empty slice nobody chose.

An empty slice is one of those decisions and not an oversight. Nine rules answer with one, in two groups.

Eight are rules no draft in range answers with a session close. The datagram payload rule, a response naming another request, a setup parameter whose value is not of its type’s kind, an Object past the one the track ended at, a fill stream nobody asked for, an UNSUBSCRIBE or REQUEST_UPDATE naming a TRACK_STATUS, a message naming a request the session has no record of, and a namespace prefix overlapping one the peer already has. Every one is a real rule this endpoint enforces, and session_error_code already answers None for all of them, so nothing downstream could publish one whatever this table said. They are written out so that a draft attaching a consequence to one arrives here as a build failure.

The ninth is Self::MessageOnTheWrongStream. It is enforced on drafts 16 through 20 and no draft in that range states it, so it is named, enforced and attributed to the peer while publishing nothing: there is no sentence to publish and close is None on every draft. The variant’s own doc carries the reading across all texts that establishes it, and the one variant that really is covered by a draft sentence is filed under the rule whose sentence covers it. A draft that attaches a consequence to this one arrives as a citation rather than as a rediscovery.

Source

pub fn citation(self, draft: u8) -> Option<&'static RuleCitation>

This rule as draft states it, or None where that draft does not.

None has two readings and the caller does not need to tell them apart: the draft may not state the rule at all, or it may state it in words nobody has yet checked. Both mean the same thing downstream — there is no sentence to publish, so there is no accusation to make — and that is the whole of why this returns an Option rather than falling back on a neighbouring draft’s wording. A fallback publishes a sentence the negotiated draft does not contain, which is the defect this table exists to prevent.

Trait Implementations§

Source§

impl Clone for AboveCodecRule

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for AboveCodecRule

Source§

impl Debug for AboveCodecRule

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for AboveCodecRule

Source§

impl Hash for AboveCodecRule

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for AboveCodecRule

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for AboveCodecRule

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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