pub enum EndpointError {
Show 28 variants
GoAwayUriAtServer,
Session(SessionError),
RequestId(RequestIdError),
Subscription(SubscriptionError),
Fetch(FetchError),
Namespace(NamespaceError),
TrackStatus(TrackStatusError),
PublishFlow(PublishError),
Setup(SetupError),
UnknownRequest(u64),
UnknownNamespace,
NotActive,
Draining,
FilterNeedsRange,
RepeatedGoAway,
DuplicateTrackAlias {
alias: u64,
established: u64,
offered: u64,
},
TrackAliasInUse {
alias: u64,
held: u64,
},
MixedForwardingPreference {
alias: u64,
established: ObjectForwardingPreference,
offered: ObjectForwardingPreference,
},
EndOfTrackOutOfPlace {
alias: u64,
group: u64,
object: u64,
placement: EndOfTrackPlacement,
},
ObjectPastFinalObject {
alias: u64,
group: u64,
object: u64,
final_group: u64,
final_object: u64,
},
UpdateForUnknownRequest(u64),
UnjoinableSubscription {
fetch: u64,
joining: u64,
},
WrongJoiningRefusal {
fetch: u64,
required: u64,
},
UnknownPeerNamespace,
UnknownPeerNamespaceSubscription,
PeerPrefixOverlap {
request: u64,
established: u64,
},
OwnPrefixOverlap {
established: u64,
},
WrongOverlapRefusal {
request: u64,
required: u64,
},
}Expand description
Errors that can occur during draft-12 endpoint operations.
Variants§
GoAwayUriAtServer
A GOAWAY carrying a New Session URI arrived at a server.
Section 8.4: “If a server receives a GOAWAY with a non-zero New Session URI Length it MUST terminate the session with a Protocol Violation.” Migration is something a server offers a client, never the other way round.
Session(SessionError)
A session-level state machine error.
RequestId(RequestIdError)
A request ID allocation or validation error.
Subscription(SubscriptionError)
A subscription state machine error.
Fetch(FetchError)
A fetch state machine error.
Namespace(NamespaceError)
A namespace state machine error.
TrackStatus(TrackStatusError)
A track status state machine error.
PublishFlow(PublishError)
A publish flow state machine error.
Setup(SetupError)
A setup negotiation error.
UnknownRequest(u64)
The request ID does not match any known state machine.
UnknownNamespace
The track namespace does not match any known state machine.
NotActive
The session is not in the Active state.
Draining
The session is draining and cannot accept new requests.
FilterNeedsRange
A filter that names a start location was asked for through a helper that has no start location to give it.
RepeatedGoAway
A second GOAWAY arrived on the control stream.
The GOAWAY that says the peer is going away is one message, and the draft answers a repeat of it with a session close rather than with an error about the second message: there is no state a second one could move that the first has not already moved.
DuplicateTrackAlias
The peer named a Track Alias it is already using for another track.
Draft-12 states it twice, once per message. Section 8.8: “The same Track Alias MUST NOT be used to refer to two different Tracks simultaneously. If a subscriber receives a SUBSCRIBE_OK that uses the same Track Alias as a different track with an active subscription, it MUST close the session with error ‘Duplicate Track Alias’.” Section 8.13 is the same sentence with PUBLISH in place of SUBSCRIBE_OK.
The session is over: this endpoint’s own state has moved to Closed and
the code the transport should close with is in
EndpointError::session_error_code.
Fields
TrackAliasInUse
This endpoint was asked to hand out a Track Alias that a live track of its own already holds.
Section 8.8 states the rule as a prohibition before it states what the receiver does about one: “The same Track Alias MUST NOT be used to refer to two different Tracks simultaneously.”
The message is refused instead of built, and nothing else moves: the subscription the peer opened is still waiting for an answer, and the session stays as it was. The alias never reaches the peer, so there is nothing for the peer to close over.
Fields
MixedForwardingPreference
A track’s objects were framed two different ways.
Section 9: “Every Track has a single ‘Object Forwarding Preference’ and the Original Publisher MUST NOT mix different forwarding preferences within a single track (see Section 2.5).”
The framing is the preference: an object on a subgroup stream has the Subgroup preference and an object in a datagram has the Datagram one, so the track’s first object settles the property and this is every later object measured against it.
§Why this one ends no session
Drafts 07 through 11 finish that paragraph with a close and a code. This draft replaces the sentence with the cross-reference above, and what it points at is a different answer rather than the same one worded differently. Section 2.5 lists “An Object is received with a different Forwarding Preference than previously observed from the same Track” among the conditions that make a track malformed, and says of all of them: “When a subscriber detects a Malformed Track, it MUST UNSUBSCRIBE from the Track and SHOULD deliver an error to the application”.
So this error carries no code in EndpointError::session_error_code,
and the connection’s close_for_data_stream declines it. Ending the
session over it would be this crate inventing a consequence the draft
withdrew.
This is half of that answer and not all of it. “SHOULD deliver an error
to the application” is what this error is. The unsubscribe the same
sentence requires is not done: those are control messages, and a data
path holding &self has no way to send one. It is also one condition
of eight in that section rather than a rule of its own, so the answer
belongs to the family and not to this arm. A caller that wants it has
the error to act on.
Fields
established: ObjectForwardingPreferenceThe framing the track’s earlier objects settled on.
offered: ObjectForwardingPreferenceThe framing the offending object used.
EndOfTrackOutOfPlace
An object saying the track ended somewhere the track has already passed.
Section 9.2.1.1 describes Object Status 0x4, end of Track, as one whose “GroupID is either the largest group produced in this track and the ObjectID is one greater than the largest object produced in that group, or GroupID is one greater than the largest group produced in this track and the ObjectID is zero”, and states the consequence: “An object with this status that has a Group ID less than any other GroupID, or an ObjectID less than or equal to the largest in the specified group, is a protocol error, and the receiver MUST terminate the session.”
§What this draft merged
Drafts 08 through 10 spell this against a status that means end of Track and Group, and carry a second status beside it for the end of the Track alone. This draft folded the two into 0x4 and kept the looser of the two conditions, which is why the Group ID may equal the largest group here and may not there.
Fields
placement: EndOfTrackPlacementWhich half of the condition it broke, and what it was measured against.
ObjectPastFinalObject
An object arriving after the track’s final object.
Section 2.5 lists the condition: “An Object is received on a Track whose Group and Object ID are larger than the final Object in the Track. The final Object in a Track is the Object with Status END_OF_TRACK or the last Object sent in a FETCH whose response indicated End of Track.”
Larger is Section 1.3.1’s comparison and not a reading of the words. That section puts one Location below another when “A.Group < B.Group || (A.Group == B.Group && A.Object < B.Object)”, so an Object in a later group is past the end whatever its own Object ID is.
A Malformed Track and not a session error, which is the whole difference between this arm and the one above it. They are the same record’s two answers about the same pair of numbers: that one asks whether an end-of-track object is behind what the track has carried and ends the session, this one asks whether an ordinary object is past where the track ended and gives up one track.
This is the error half of the answer Section 2.5 states once for its whole list — “it MUST UNSUBSCRIBE from the Track and SHOULD deliver an error to the application”. The UNSUBSCRIBE is the connection’s, for the reason the mixed-framing arm gives.
Fields
UpdateForUnknownRequest(u64)
SUBSCRIBE_UPDATE named a Request ID this session has never carried a request under.
Section 8.10: “A publisher MUST terminate the session with a ‘Protocol Violation’ if the SUBSCRIBE_UPDATE violates these rules or if the subscriber specifies a request ID that has not existed within the Session.”
A request that has ended is not this: it existed. That is why the record of an inbound SUBSCRIBE outlives the subscription, and why an update naming an ended one is refused by the flow rather than by the session.
UnjoinableSubscription
A Joining Fetch named a subscription this session cannot join.
Section 8.16: “If a publisher receives a Joining Fetch with a Request ID that does not correspond to an existing Subscribe in the same session, it MUST respond with a Fetch Error with code Invalid Joining Request ID.”
A refusal and not a session close, so the session runs on and the error names both identifiers: the fetch to refuse, and the subscription it asked to join.
WrongJoiningRefusal
A Joining Fetch was refused under a code other than the one the same sentence names for it.
The reason travels with the refusal, so a subscriber told the wrong one retries the wrong thing: it can rebuild a fetch whose range was refused, and cannot rebuild one whose subscription is gone.
UnknownPeerNamespace
A message about an announcement named a namespace the peer has not announced.
Section 8.26 says what a cancellation is for: the subscriber “will stop sending new subscriptions for tracks within the provided Track Namespace”. What a withdrawal ends and a cancellation revokes is an announcement the peer made, so the record they reach for is the one this endpoint keeps of the peer’s announcements.
Separate from EndpointError::UnknownNamespace, which is the same
miss on the announcements this endpoint made, so a caller can tell which
of the two maps came up empty.
UnknownPeerNamespaceSubscription
A message about a namespace subscription named a prefix the peer has not subscribed to.
Section 5.1: “An UNSUBSCRIBE_ANNOUNCES withdraws a previous SUBSCRIBE_ANNOUNCES.”
What a withdrawal ends is a namespace subscription the peer made,
so the record it reaches for is the one this endpoint keeps of the
peer’s. A namespace subscription this endpoint made is withdrawn by
Endpoint::unsubscribe_announces, which is the same message travelling the other
way and answers with EndpointError::UnknownNamespace.
PeerPrefixOverlap
The peer subscribed to a namespace prefix overlapping one it is already subscribed to.
Section 8.27: “A subscriber cannot make overlapping namespace subscriptions on a single session. Within a session, if a publisher receives a SUBSCRIBE_ANNOUNCES with a Track Namespace Prefix that is a prefix of, suffix of, or equal to an active SUBSCRIBE_ANNOUNCES, it MUST respond with SUBSCRIBE_ANNOUNCES_ERROR, with error code Namespace Prefix Overlap.”
Taken when the message arrives, which is the moment the sentence names, and read again when an answer is built: a request this endpoint may not accept is one no later call can accept.
The refusal itself is not this error. It is a message the peer is owed, so the request is recorded like any other and refused through the same call that refuses any other, under the code the sentence names.
Fields
OwnPrefixOverlap
This endpoint was asked to subscribe to a namespace prefix overlapping one it is already subscribed to.
The first half of the same sentence, which is addressed to the subscriber: “A subscriber cannot make overlapping namespace subscriptions on a single session.”
The message is refused instead of built, and nothing else moves: no Request ID is spent, no state machine is created and the session stays as it was. The request never reaches the peer, so there is nothing for the peer to refuse.
WrongOverlapRefusal
A namespace subscription that overlaps another was refused under a code other than the one the sentence names.
The same shape as EndpointError::WrongJoiningRefusal: a rule that
names the code its refusal carries is not satisfied by a refusal under
any other, because the peer reads the code to learn what went wrong.
Implementations§
Source§impl EndpointError
impl EndpointError
Sourcepub fn session_error_code(&self) -> Option<SessionErrorCode>
pub fn session_error_code(&self) -> Option<SessionErrorCode>
The code to close the session with, when draft-12 answers this error with a close rather than leaving it to the one request it concerns.
None means the error is recoverable: the caller may report it, give
up on the request it concerns, and keep the session running. Some
means the draft ends the session, and the endpoint has already moved
its own state to Closed - the code is what the transport should carry.
The table grows one rule at a time, and a rule joins it with a gate that drives the bytes at a real connection and reads the close code back off the wire. An arm added without one asserts nothing: from inside the process the session ends either way, and only the peer can tell the difference.
Source§impl EndpointError
impl EndpointError
Sourcepub(crate) fn for_track_fault(
alias: u64,
at: ObjectLocation,
fault: TrackFault,
) -> Self
pub(crate) fn for_track_fault( alias: u64, at: ObjectLocation, fault: TrackFault, ) -> Self
The endpoint’s report of a fault a track’s record found.
Written once because the two data paths reach it from different places:
a datagram through Endpoint::note_received_object, and a subgroup
object through the stream that decoded it, which holds a record handle
and no endpoint. Two translations would be two chances for the same
fault to be reported as different rules.
Trait Implementations§
Source§impl Debug for EndpointError
impl Debug for EndpointError
Source§impl Display for EndpointError
impl Display for EndpointError
Source§impl Error for EndpointError
impl Error for EndpointError
Source§fn source(&self) -> Option<&(dyn Error + 'static)>
fn source(&self) -> Option<&(dyn Error + 'static)>
1.0.0 · Source§fn description(&self) -> &str
fn description(&self) -> &str
use the Display impl or to_string()