Skip to main content

moqtap_client/draft16/
event.rs

1//! Client event types emitted by a MoQT connection.
2
3use moqtap_codec::dispatch::{
4    AnyControlMessage, AnyDatagramHeader, AnyFetchHeader, AnySubgroupHeader,
5};
6use moqtap_codec::draft16::data_stream::{FetchHeader, SubgroupHeader, SubgroupObject};
7
8/// Direction of a message or stream relative to this endpoint.
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub enum Direction {
11    /// Sent (outgoing).
12    Send,
13    /// Received (incoming).
14    Receive,
15}
16
17/// Data stream type.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum StreamKind {
20    /// Subgroup data stream.
21    Subgroup,
22    /// Fetch data stream.
23    Fetch,
24    /// Datagram.
25    Datagram,
26    /// Namespace subscription stream: the bidirectional stream a
27    /// SUBSCRIBE_NAMESPACE and everything answering it travel on.
28    ///
29    /// Draft-16 Section 3.3 names the only two things a bidirectional stream
30    /// may be — "the control stream, which begins with CLIENT_SETUP, and
31    /// SUBSCRIBE_NAMESPACE" — and this is the second of them. It is the only
32    /// kind here that is not a data stream, and it is named because an
33    /// observer that could not name it would see a SUBSCRIBE_NAMESPACE with no
34    /// stream to attach it to.
35    NamespaceSubscription,
36}
37
38/// Events emitted by a MoQT connection.
39///
40/// This enum is `#[non_exhaustive]` -- new variants may be added in minor
41/// releases. Downstream `match` arms should include a wildcard `_ =>` branch.
42#[non_exhaustive]
43#[derive(Debug, Clone)]
44pub enum ClientEvent {
45    /// MoQT setup handshake completed.
46    SetupComplete {
47        /// The negotiated MoQT version (from ALPN in draft-16).
48        negotiated_version: u64,
49    },
50
51    /// A control message was sent or received.
52    ControlMessage {
53        /// Whether the message was sent or received.
54        direction: Direction,
55        /// The decoded control message.
56        message: AnyControlMessage,
57        /// The stream it travelled on, when that is not the control stream.
58        ///
59        /// `Some` for the SUBSCRIBE_NAMESPACE that opens a namespace
60        /// subscription's own bidirectional stream and for everything
61        /// answering it there. `None` for the control stream, which every
62        /// other message uses.
63        ///
64        /// NAMESPACE and NAMESPACE_DONE carry no Request ID, so without this
65        /// an observer would see a namespace reported and have nothing to
66        /// attribute it to.
67        stream_id: Option<u64>,
68        /// The raw wire bytes of the framed message (type + length + payload).
69        /// `None` if raw capture is not available.
70        raw: Option<Vec<u8>>,
71    },
72
73    /// A data stream was opened.
74    StreamOpened {
75        /// Whether we opened (Send) or accepted (Receive) the stream.
76        direction: Direction,
77        /// The type of data stream.
78        stream_kind: StreamKind,
79        /// Transport-level stream identifier.
80        stream_id: u64,
81    },
82
83    /// A data stream header was decoded after the stream opened.
84    DataStreamHeader {
85        /// Transport-level stream identifier.
86        stream_id: u64,
87        /// Whether we opened (Send) or accepted (Receive) the stream.
88        direction: Direction,
89        /// The parsed subgroup header.
90        header: AnySubgroupHeader,
91    },
92
93    /// A fetch response stream header was decoded.
94    FetchStreamHeader {
95        /// Transport-level stream identifier.
96        stream_id: u64,
97        /// Whether we opened (Send) or accepted (Receive) the stream.
98        direction: Direction,
99        /// The parsed fetch header.
100        header: AnyFetchHeader,
101    },
102
103    /// A subgroup object header was decoded on a subgroup stream.
104    SubgroupObjectReceived {
105        /// Transport-level stream identifier.
106        stream_id: u64,
107        /// Direction (Send when emitted from a writer, Receive from a reader).
108        direction: Direction,
109        /// The decoded subgroup header (for context).
110        subgroup_header: SubgroupHeader,
111        /// The decoded subgroup object.
112        object: SubgroupObject,
113    },
114
115    /// A fetch header was decoded on a fetch stream.
116    FetchHeaderReceived {
117        /// Transport-level stream identifier.
118        stream_id: u64,
119        /// Direction (Send when emitted from a writer, Receive from a reader).
120        direction: Direction,
121        /// The decoded fetch header.
122        header: FetchHeader,
123    },
124
125    /// A datagram was sent or received.
126    DatagramReceived {
127        /// Whether sent or received.
128        direction: Direction,
129        /// The parsed datagram header.
130        header: AnyDatagramHeader,
131        /// Size of the payload in bytes.
132        payload_len: usize,
133    },
134
135    /// A data stream was closed.
136    StreamClosed {
137        /// Transport-level stream identifier.
138        stream_id: u64,
139        /// Error code (0 = clean close).
140        error_code: u64,
141    },
142
143    /// Session entered draining state (GOAWAY received).
144    Draining {
145        /// The new session URI from the GOAWAY message.
146        new_session_uri: Vec<u8>,
147    },
148
149    /// Connection was closed.
150    Closed {
151        /// Application error code.
152        code: u32,
153        /// Human-readable reason.
154        reason: Vec<u8>,
155    },
156
157    /// A transport or protocol error occurred.
158    Error {
159        /// Error description.
160        error: String,
161    },
162}