Skip to main content

moqtap_client/draft18/
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::draft18::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/// The kind of stream an event refers to.
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    /// Request stream: the bidirectional stream one request and its response
27    /// travel on.
28    ///
29    /// Draft-18 Section 3.3 moved requests off the control plane and gave each
30    /// one a bidirectional stream that begins with the request message. This
31    /// is the only kind here that is not a data stream, and it is named
32    /// because an observer that could not name it would see a request message
33    /// with no stream to attach it to.
34    Request,
35}
36
37/// Events emitted by a MoQT connection.
38///
39/// This enum is `#[non_exhaustive]` -- new variants may be added in minor
40/// releases. Downstream `match` arms should include a wildcard `_ =>` branch.
41#[non_exhaustive]
42#[derive(Debug, Clone)]
43pub enum ClientEvent {
44    /// MoQT setup handshake completed.
45    SetupComplete {
46        /// The negotiated MoQT version (from ALPN in draft-18).
47        negotiated_version: u64,
48    },
49
50    /// A control message was sent or received.
51    ControlMessage {
52        /// Whether the message was sent or received.
53        direction: Direction,
54        /// The decoded control message.
55        message: AnyControlMessage,
56        /// The transport-level identifier of the stream the message travelled
57        /// on when that stream is a request stream, and `None` when it is the
58        /// control stream.
59        ///
60        /// Draft-18 responses carry no request id: the stream is the
61        /// correlation. Without this an observer sees a SUBSCRIBE_OK with
62        /// nothing to say which SUBSCRIBE it answers, and cannot tell a
63        /// message on the control stream from one on a request stream.
64        stream_id: Option<u64>,
65        /// The raw wire bytes of the framed message (type + length + payload).
66        /// `None` if raw capture is not available.
67        raw: Option<Vec<u8>>,
68    },
69
70    /// A data stream was opened.
71    StreamOpened {
72        /// Whether we opened (Send) or accepted (Receive) the stream.
73        direction: Direction,
74        /// The type of data stream.
75        stream_kind: StreamKind,
76        /// Transport-level stream identifier.
77        stream_id: u64,
78    },
79
80    /// A data stream header was decoded after the stream opened.
81    DataStreamHeader {
82        /// Transport-level stream identifier.
83        stream_id: u64,
84        /// Whether we opened (Send) or accepted (Receive) the stream.
85        direction: Direction,
86        /// The parsed subgroup header.
87        header: AnySubgroupHeader,
88    },
89
90    /// A fetch response stream header was decoded.
91    FetchStreamHeader {
92        /// Transport-level stream identifier.
93        stream_id: u64,
94        /// Whether we opened (Send) or accepted (Receive) the stream.
95        direction: Direction,
96        /// The parsed fetch header.
97        header: AnyFetchHeader,
98    },
99
100    /// A subgroup object header was decoded on a subgroup stream.
101    SubgroupObjectReceived {
102        /// Transport-level stream identifier.
103        stream_id: u64,
104        /// Direction (Send when emitted from a writer, Receive from a reader).
105        direction: Direction,
106        /// The decoded subgroup header (for context).
107        subgroup_header: SubgroupHeader,
108        /// The decoded subgroup object.
109        object: SubgroupObject,
110    },
111
112    /// A fetch header was decoded on a fetch stream.
113    FetchHeaderReceived {
114        /// Transport-level stream identifier.
115        stream_id: u64,
116        /// Direction (Send when emitted from a writer, Receive from a reader).
117        direction: Direction,
118        /// The decoded fetch header.
119        header: FetchHeader,
120    },
121
122    /// A datagram was sent or received.
123    DatagramReceived {
124        /// Whether sent or received.
125        direction: Direction,
126        /// The parsed datagram header.
127        header: AnyDatagramHeader,
128        /// Size of the payload in bytes.
129        payload_len: usize,
130    },
131
132    /// A data stream was closed.
133    StreamClosed {
134        /// Transport-level stream identifier.
135        stream_id: u64,
136        /// Error code (0 = clean close).
137        error_code: u64,
138    },
139
140    /// Session entered draining state (GOAWAY received).
141    Draining {
142        /// The new session URI from the GOAWAY message.
143        new_session_uri: Vec<u8>,
144    },
145
146    /// Connection was closed.
147    Closed {
148        /// Application error code.
149        code: u32,
150        /// Human-readable reason.
151        reason: Vec<u8>,
152    },
153
154    /// A transport or protocol error occurred.
155    Error {
156        /// Error description.
157        error: String,
158    },
159}