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}