xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/moqt/moqt_messages.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2023 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Structured data for message types in draft-ietf-moq-transport-02.
6 
7 #ifndef QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_
8 #define QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_
9 
10 #include <cstddef>
11 #include <cstdint>
12 #include <optional>
13 #include <string>
14 #include <utility>
15 #include <vector>
16 
17 #include "absl/strings/string_view.h"
18 #include "quiche/quic/core/quic_time.h"
19 #include "quiche/quic/core/quic_types.h"
20 #include "quiche/quic/core/quic_versions.h"
21 #include "quiche/common/platform/api/quiche_export.h"
22 
23 namespace moqt {
24 
GetMoqtSupportedQuicVersions()25 inline constexpr quic::ParsedQuicVersionVector GetMoqtSupportedQuicVersions() {
26   return quic::ParsedQuicVersionVector{quic::ParsedQuicVersion::RFCv1()};
27 }
28 
29 enum class MoqtVersion : uint64_t {
30   kDraft03 = 0xff000003,
31   kUnrecognizedVersionForTests = 0xfe0000ff,
32 };
33 
34 struct QUICHE_EXPORT MoqtSessionParameters {
35   // TODO: support multiple versions.
36   // TODO: support roles other than PubSub.
37   MoqtVersion version;
38   quic::Perspective perspective;
39   bool using_webtrans;
40   std::string path;
41   bool deliver_partial_objects;
42 };
43 
44 // The maximum length of a message, excluding any OBJECT payload. This prevents
45 // DoS attack via forcing the parser to buffer a large message (OBJECT payloads
46 // are not buffered by the parser).
47 inline constexpr size_t kMaxMessageHeaderSize = 2048;
48 
49 enum class QUICHE_EXPORT MoqtMessageType : uint64_t {
50   kObjectStream = 0x00,
51   kObjectDatagram = 0x01,
52   kSubscribe = 0x03,
53   kSubscribeOk = 0x04,
54   kSubscribeError = 0x05,
55   kAnnounce = 0x06,
56   kAnnounceOk = 0x7,
57   kAnnounceError = 0x08,
58   kUnannounce = 0x09,
59   kUnsubscribe = 0x0a,
60   kSubscribeDone = 0x0b,
61   kGoAway = 0x10,
62   kClientSetup = 0x40,
63   kServerSetup = 0x41,
64   kStreamHeaderTrack = 0x50,
65   kStreamHeaderGroup = 0x51,
66 };
67 
68 enum class QUICHE_EXPORT MoqtError : uint64_t {
69   kNoError = 0x0,
70   kInternalError = 0x1,
71   kUnauthorized = 0x2,
72   kProtocolViolation = 0x3,
73   kDuplicateTrackAlias = 0x4,
74   kParameterLengthMismatch = 0x5,
75   kGoawayTimeout = 0x10,
76 };
77 
78 enum class QUICHE_EXPORT MoqtRole : uint64_t {
79   kPublisher = 0x1,
80   kSubscriber = 0x2,
81   kPubSub = 0x3,
82   kRoleMax = 0x3,
83 };
84 
85 enum class QUICHE_EXPORT MoqtSetupParameter : uint64_t {
86   kRole = 0x0,
87   kPath = 0x1,
88 };
89 
90 enum class QUICHE_EXPORT MoqtTrackRequestParameter : uint64_t {
91   kAuthorizationInfo = 0x2,
92 };
93 
94 // TODO: those are non-standard; add standard error codes once those exist, see
95 // <https://github.com/moq-wg/moq-transport/issues/393>.
96 enum class MoqtAnnounceErrorCode : uint64_t {
97   kInternalError = 0,
98   kAnnounceNotSupported = 1,
99 };
100 
101 struct MoqtAnnounceErrorReason {
102   MoqtAnnounceErrorCode error_code;
103   std::string reason_phrase;
104 };
105 
106 struct FullTrackName {
107   std::string track_namespace;
108   std::string track_name;
FullTrackNameFullTrackName109   FullTrackName(absl::string_view ns, absl::string_view name)
110       : track_namespace(ns), track_name(name) {}
111   bool operator==(const FullTrackName& other) const {
112     return track_namespace == other.track_namespace &&
113            track_name == other.track_name;
114   }
115   bool operator<(const FullTrackName& other) const {
116     return track_namespace < other.track_namespace ||
117            (track_namespace == other.track_namespace &&
118             track_name < other.track_name);
119   }
120   FullTrackName& operator=(FullTrackName other) {
121     track_namespace = other.track_namespace;
122     track_name = other.track_name;
123     return *this;
124   }
125   template <typename H>
126   friend H AbslHashValue(H h, const FullTrackName& m);
127 };
128 
129 template <typename H>
AbslHashValue(H h,const FullTrackName & m)130 H AbslHashValue(H h, const FullTrackName& m) {
131   return H::combine(std::move(h), m.track_namespace, m.track_name);
132 }
133 
134 // These are absolute sequence numbers.
135 struct FullSequence {
136   uint64_t group = 0;
137   uint64_t object = 0;
138   bool operator==(const FullSequence& other) const {
139     return group == other.group && object == other.object;
140   }
141   bool operator<(const FullSequence& other) const {
142     return group < other.group ||
143            (group == other.group && object < other.object);
144   }
145   bool operator<=(const FullSequence& other) const {
146     return (group < other.group ||
147             (group == other.group && object <= other.object));
148   }
149   FullSequence& operator=(FullSequence other) {
150     group = other.group;
151     object = other.object;
152     return *this;
153   }
154   template <typename H>
155   friend H AbslHashValue(H h, const FullSequence& m);
156 };
157 
158 template <typename H>
AbslHashValue(H h,const FullSequence & m)159 H AbslHashValue(H h, const FullSequence& m) {
160   return H::combine(std::move(h), m.group, m.object);
161 }
162 
163 struct QUICHE_EXPORT MoqtClientSetup {
164   std::vector<MoqtVersion> supported_versions;
165   std::optional<MoqtRole> role;
166   std::optional<std::string> path;
167 };
168 
169 struct QUICHE_EXPORT MoqtServerSetup {
170   MoqtVersion selected_version;
171   std::optional<MoqtRole> role;
172 };
173 
174 // These codes do not appear on the wire.
175 enum class QUICHE_EXPORT MoqtForwardingPreference : uint8_t {
176   kTrack = 0x0,
177   kGroup = 0x1,
178   kObject = 0x2,
179   kDatagram = 0x3,
180 };
181 
182 // The data contained in every Object message, although the message type
183 // implies some of the values. |payload_length| has no value if the length
184 // is unknown (because it runs to the end of the stream.)
185 struct QUICHE_EXPORT MoqtObject {
186   uint64_t subscribe_id;
187   uint64_t track_alias;
188   uint64_t group_id;
189   uint64_t object_id;
190   uint64_t object_send_order;
191   MoqtForwardingPreference forwarding_preference;
192   std::optional<uint64_t> payload_length;
193 };
194 
195 enum class QUICHE_EXPORT MoqtSubscribeLocationMode : uint64_t {
196   kNone = 0x0,
197   kAbsolute = 0x1,
198   kRelativePrevious = 0x2,
199   kRelativeNext = 0x3,
200 };
201 
202 // kNone: std::optional<MoqtSubscribeLocation> is nullopt.
203 // kAbsolute: absolute = true
204 // kRelativePrevious: absolute is false; relative_value is negative
205 // kRelativeNext: absolute is true; relative_value is positive
206 struct QUICHE_EXPORT MoqtSubscribeLocation {
MoqtSubscribeLocationMoqtSubscribeLocation207   MoqtSubscribeLocation(bool is_absolute, uint64_t abs)
208       : absolute(is_absolute), absolute_value(abs) {}
MoqtSubscribeLocationMoqtSubscribeLocation209   MoqtSubscribeLocation(bool is_absolute, int64_t rel)
210       : absolute(is_absolute), relative_value(rel) {}
211   bool absolute;
212   union {
213     uint64_t absolute_value;
214     int64_t relative_value;
215   };
216   bool operator==(const MoqtSubscribeLocation& other) const {
217     return absolute == other.absolute &&
218            ((absolute && absolute_value == other.absolute_value) ||
219             (!absolute && relative_value == other.relative_value));
220   }
221 };
222 
GetModeForSubscribeLocation(const std::optional<MoqtSubscribeLocation> & location)223 inline MoqtSubscribeLocationMode GetModeForSubscribeLocation(
224     const std::optional<MoqtSubscribeLocation>& location) {
225   if (!location.has_value()) {
226     return MoqtSubscribeLocationMode::kNone;
227   }
228   if (location->absolute) {
229     return MoqtSubscribeLocationMode::kAbsolute;
230   }
231   return location->relative_value >= 0
232              ? MoqtSubscribeLocationMode::kRelativeNext
233              : MoqtSubscribeLocationMode::kRelativePrevious;
234 }
235 
236 struct QUICHE_EXPORT MoqtSubscribe {
237   uint64_t subscribe_id;
238   uint64_t track_alias;
239   std::string track_namespace;
240   std::string track_name;
241   // If the mode is kNone, the these are std::nullopt.
242   std::optional<MoqtSubscribeLocation> start_group;
243   std::optional<MoqtSubscribeLocation> start_object;
244   std::optional<MoqtSubscribeLocation> end_group;
245   std::optional<MoqtSubscribeLocation> end_object;
246   std::optional<std::string> authorization_info;
247 };
248 
249 struct QUICHE_EXPORT MoqtSubscribeOk {
250   uint64_t subscribe_id;
251   // The message uses ms, but expires is in us.
252   quic::QuicTimeDelta expires = quic::QuicTimeDelta::FromMilliseconds(0);
253   // If ContextExists on the wire is zero, largest_id has no value.
254   std::optional<FullSequence> largest_id;
255 };
256 
257 enum class QUICHE_EXPORT SubscribeErrorCode : uint64_t {
258   kInternalError = 0x0,
259   kInvalidRange = 0x1,
260   kRetryTrackAlias = 0x2,
261 };
262 
263 struct QUICHE_EXPORT MoqtSubscribeError {
264   uint64_t subscribe_id;
265   SubscribeErrorCode error_code;
266   std::string reason_phrase;
267   uint64_t track_alias;
268 };
269 
270 struct QUICHE_EXPORT MoqtUnsubscribe {
271   uint64_t subscribe_id;
272 };
273 
274 enum class QUICHE_EXPORT SubscribeDoneCode : uint64_t {
275   kUnsubscribed = 0x0,
276   kInternalError = 0x1,
277   kUnauthorized = 0x2,
278   kTrackEnded = 0x3,
279   kSubscriptionEnded = 0x4,
280   kGoingAway = 0x5,
281   kExpired = 0x6,
282 };
283 
284 struct QUICHE_EXPORT MoqtSubscribeDone {
285   uint64_t subscribe_id;
286   uint64_t status_code;
287   std::string reason_phrase;
288   std::optional<FullSequence> final_id;
289 };
290 
291 struct QUICHE_EXPORT MoqtAnnounce {
292   std::string track_namespace;
293   std::optional<std::string> authorization_info;
294 };
295 
296 struct QUICHE_EXPORT MoqtAnnounceOk {
297   std::string track_namespace;
298 };
299 
300 struct QUICHE_EXPORT MoqtAnnounceError {
301   std::string track_namespace;
302   MoqtAnnounceErrorCode error_code;
303   std::string reason_phrase;
304 };
305 
306 struct QUICHE_EXPORT MoqtUnannounce {
307   std::string track_namespace;
308 };
309 
310 struct QUICHE_EXPORT MoqtGoAway {
311   std::string new_session_uri;
312 };
313 
314 std::string MoqtMessageTypeToString(MoqtMessageType message_type);
315 
316 std::string MoqtForwardingPreferenceToString(
317     MoqtForwardingPreference preference);
318 
319 MoqtForwardingPreference GetForwardingPreference(MoqtMessageType type);
320 
321 MoqtMessageType GetMessageTypeForForwardingPreference(
322     MoqtForwardingPreference preference);
323 
324 }  // namespace moqt
325 
326 #endif  // QUICHE_QUIC_MOQT_MOQT_MESSAGES_H_
327