LibQuicR
ctrl_message_types.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) 2024 Cisco Systems
2 // SPDX-License-Identifier: BSD-2-Clause
3 
4 #pragma once
5 
7 #include "quicr/track_name.h"
8 
9 #include <algorithm>
10 #include <limits>
11 #include <map>
12 #include <optional>
13 #include <source_location>
14 #include <stdexcept>
15 #include <string>
16 #include <tuple>
17 #include <variant>
18 
19 namespace quicr {
28 
35  Bytes& operator<<(Bytes& buffer, const TrackNamespace& msg);
36 }
37 
38 namespace quicr::messages {
39 
41  enum class ControlMessageType : uint64_t
42  {
43  kRequestUpdate = 0x2,
44  kSubscribe = 0x3,
45  kSubscribeOk = 0x4,
46  kRequestError = 0x5,
47  kPublishNamespace = 0x6,
48  kRequestOk = 0x7,
49  kNamespace = 0x8,
50  kPublishNamespaceDone = 0x9,
51  kUnsubscribe = 0xa,
52  kPublishDone = 0xb,
54  kTrackStatus = 0xd,
55  kNamespaceDone = 0xe,
56  kPublishBlocked = 0xf,
57  kGoaway = 0x10,
58  kMaxRequestId = 0x15,
59  kFetch = 0x16,
60  kFetchCancel = 0x17,
61  kFetchOk = 0x18,
62  kRequestsBlocked = 0x1a,
63  kPublish = 0x1d,
64  kSubscribeNamespace = 0x50,
65  kSubscribeTracks = 0x51,
66  kSetup = 0x2F00,
67  };
68 
70  struct ProtocolViolationException : std::runtime_error
71  {
72  const std::string reason;
73 
78  ProtocolViolationException(const std::string& reason,
79  const std::source_location location = std::source_location::current())
80  : std::runtime_error("Protocol violation: " + reason + " (line " + std::to_string(location.line()) +
81  ", file " + location.file_name() + ")")
82  , reason(reason)
83  {
84  }
85  };
86 
93  Bytes& operator<<(Bytes& buffer, const Bytes& bytes);
94 
101  Bytes& operator<<(Bytes& buffer, const BytesSpan& bytes);
102 
110 
117  Bytes& operator<<(Bytes& buffer, std::uint64_t value);
118 
125  BytesSpan operator>>(BytesSpan buffer, std::uint64_t& value);
126 
133  Bytes& operator<<(Bytes& buffer, std::uint8_t value);
134 
142  BytesSpan operator>>(BytesSpan buffer, uint8_t& value);
143 
150  Bytes& operator<<(Bytes& buffer, std::uint16_t value);
151 
159  BytesSpan operator>>(BytesSpan buffer, std::uint16_t& value);
160 
167  Bytes& operator<<(Bytes& buffer, const UintVar& value);
168 
170  struct Location
171  {
172  std::uint64_t group{ 0 };
173  std::uint64_t object{ 0 };
174 
177  auto operator<=>(const Location& other) const
178  {
179  if (const auto cmp = group <=> other.group; cmp != 0) {
180  return cmp;
181  }
182  return object <=> other.object;
183  }
184 
187  bool operator==(const Location& other) const = default;
188  };
189 
196  Bytes& operator<<(Bytes& buffer, const Location& location);
197 
205 
208  {
209  std::uint64_t group{ 0 };
210  std::optional<std::uint64_t>
212  };
213 
218  template<typename T>
219  concept KeyType =
220  std::same_as<T, std::uint64_t> || (std::is_enum_v<T> && std::same_as<std::underlying_type_t<T>, std::uint64_t>);
221  template<KeyType T>
231  {
232  T type;
234 
241  std::size_t Size(const T prev_type) const
242  {
243  std::size_t size = 0;
244  const auto type_value = static_cast<std::uint64_t>(type);
245  const auto prev_type_value = static_cast<std::uint64_t>(prev_type);
246  const auto delta = type_value - prev_type_value;
247  size += UintVar(delta).size();
248 
249  if (type_value % 2 == 0) {
250  // Even types: single varint of value
251  if (value.size() > sizeof(std::uint64_t)) {
252  throw std::invalid_argument("Value too large to encode as uint64_t.");
253  }
254  std::uint64_t val = 0;
255  std::memcpy(&val, value.data(), value.size());
256  size += UintVar(val).size();
257  } else {
258  // Odd types: length + bytes
259  size += UintVar(value.size()).size();
260  size += value.size();
261  }
262  return size;
263  }
264 
271  bool operator==(const KeyValuePair<T>& other) const
272  {
273  if (type != other.type) {
274  return false;
275  }
276 
277  if (static_cast<std::uint64_t>(type) % 2 != 0) {
278  // Odd types are byte equality.
279  return value == other.value;
280  }
281 
282  // Even types are numeric equality.
283  if (value.size() > sizeof(std::uint64_t) || other.value.size() > sizeof(std::uint64_t)) {
284  throw std::invalid_argument("Even KVPs must be <= 8 bytes");
285  }
286 
287  // Compare numeric values.
288  const auto smaller = std::min(value.size(), other.value.size());
289  if (memcmp(value.data(), other.value.data(), smaller) != 0) {
290  return false;
291  }
292 
293  // Are there left over bytes to check?
294  const auto larger = std::max(value.size(), other.value.size());
295  if (larger == smaller) {
296  return true;
297  }
298 
299  // Any remaining bytes could be 0, but nothing else.
300  const auto& longer = (value.size() > other.value.size()) ? value : other.value;
301  const auto remaining = larger - smaller;
302  static constexpr std::uint8_t kZero[sizeof(std::uint64_t)] = { 0 };
303  return memcmp(longer.data() + smaller, kZero, remaining) == 0;
304  }
305  };
306 
314  template<KeyType T>
315  Bytes& operator<<(Bytes& buffer, const T value)
316  {
317  return buffer << UintVar(static_cast<std::uint64_t>(value));
318  }
319 
327  template<KeyType T>
328  BytesSpan operator>>(BytesSpan buffer, T& value)
329  {
330  std::uint64_t uvalue;
331  buffer = buffer >> uvalue;
332  value = static_cast<T>(uvalue);
333  return buffer;
334  }
335 
344  template<KeyType T>
345  void SerializeKvp(Bytes& buffer, const KeyValuePair<T>& kvp, const T prev_type)
346  {
347  // Delta encode the type.
348  const auto type_value = static_cast<std::uint64_t>(kvp.type);
349  const auto prev_type_value = static_cast<std::uint64_t>(prev_type);
350  const auto delta = type_value - prev_type_value;
351  buffer << UintVar(delta);
352 
353  if (type_value % 2 != 0) {
354  // Odd, encode bytes.
355  buffer << kvp.value;
356  } else {
357  // Even, single varint of value.
358  if (kvp.value.size() > sizeof(std::uint64_t)) {
359  throw std::invalid_argument("Value too large to encode as uint64_t.");
360  }
361  std::uint64_t val = 0;
362  std::memcpy(&val, kvp.value.data(), kvp.value.size());
363  buffer << UintVar(val);
364  }
365  }
366 
375  template<KeyType T>
376  void ParseKvp(BytesSpan& buffer, KeyValuePair<T>& kvp, const T prev_type)
377  {
378  // Delta to absolute.
379  const auto prev_type_value = static_cast<std::uint64_t>(prev_type);
380  std::uint64_t delta;
381  buffer = buffer >> delta;
382  if (delta > std::numeric_limits<std::uint64_t>::max() - prev_type_value) {
383  throw ProtocolViolationException("Delta encoding overflow: prev_type + delta exceeds 2^64-1");
384  }
385  const auto type_value = prev_type_value + delta;
386  kvp.type = static_cast<T>(type_value);
387 
388  if (type_value % 2 != 0) {
389  // Odd, decode bytes.
390  buffer = buffer >> kvp.value;
391  } else {
392  // Even, decode single varint of value.
393  UintVar uvar(buffer);
394  buffer = buffer.subspan(uvar.size());
395  std::uint64_t val(uvar);
396  const auto* p = reinterpret_cast<const std::uint8_t*>(&val);
397  kvp.value.assign(p, p + sizeof(val));
398  }
399  }
400 
402  enum struct SetupOptionType : uint64_t
403  {
404  kPath = 0x01,
405  kAuthorizationToken = 0x03,
406  kMaxAuthTokenCacheSize = 0x04,
407  kAuthority = 0x05,
408  kMoqtImplementation = 0x07,
409 
410  /*===================================================================*/
411  // Internal Use
412  /*===================================================================*/
413 
414  kEndpointId = 0xF1,
415  kInvalid = 0xFF,
416  };
417 
424  struct Token
425  {
427  enum class AliasType : std::uint64_t
428  {
429  kDelete = 0x0,
430  kRegister = 0x1,
431  kUseAlias = 0x2,
432  kUseValue = 0x3,
433  };
434 
436 
438  std::optional<std::uint64_t> token_alias;
439 
441  std::optional<std::uint64_t> token_type;
442 
445 
449  bool operator==(const Token& other) const = default;
450  };
451 
459  inline Bytes& operator<<(Bytes& buffer, const Token& token)
460  {
461  buffer << UintVar(static_cast<std::uint64_t>(token.alias_type));
462  switch (token.alias_type) {
465  buffer << UintVar(token.token_alias.value());
466  break;
468  buffer << UintVar(token.token_alias.value());
469  buffer << UintVar(token.token_type.value());
470  AppendBytes(buffer, token.token_value);
471  break;
473  buffer << UintVar(token.token_type.value());
474  AppendBytes(buffer, token.token_value);
475  break;
476  }
477  return buffer;
478  }
479 
491  inline BytesSpan operator>>(BytesSpan buffer, Token& token)
492  {
493  std::uint64_t alias_type = 0;
494  buffer = buffer >> alias_type;
495  token.alias_type = static_cast<Token::AliasType>(alias_type);
496 
497  switch (token.alias_type) {
500  std::uint64_t alias = 0;
501  buffer = buffer >> alias;
502  token.token_alias = alias;
503  break;
504  }
506  std::uint64_t alias = 0;
507  std::uint64_t type = 0;
508  buffer = buffer >> alias;
509  buffer = buffer >> type;
510  token.token_alias = alias;
511  token.token_type = type;
512  token.token_value.assign(buffer.begin(), buffer.end());
513  buffer = buffer.subspan(buffer.size());
514  break;
515  }
517  std::uint64_t type = 0;
518  buffer = buffer >> type;
519  token.token_type = type;
520  token.token_value.assign(buffer.begin(), buffer.end());
521  buffer = buffer.subspan(buffer.size());
522  break;
523  }
524  default:
525  throw ProtocolViolationException("Invalid AUTHORIZATION_TOKEN alias type");
526  }
527  return buffer;
528  }
529 
531  enum struct GroupOrder : uint8_t
532  {
533  kAscending = 0x1,
534  kDescending = 0x2
535  };
536 
538  Bytes& operator<<(Bytes& buffer, GroupOrder value);
539 
543 
545  enum struct FilterType : uint64_t
546  {
547  kNone,
549  kTrackFilter,
550  };
551 
553  enum class SubscriptionFilterType : std::uint64_t
554  {
555  kNextGroupStart = 0x1,
556  kLargestObject = 0x2,
557  kAbsoluteStart = 0x3,
558  kAbsoluteRange = 0x4,
559  };
560 
566  {
569 
572 
574  std::uint64_t end_group_delta{ 0 };
575 
577  auto operator<=>(const SubscriptionFilter&) const noexcept = default;
578  };
579 
580  inline Bytes& operator<<(Bytes& bytes, const SubscriptionFilter& filter)
581  {
582  bytes << UintVar(static_cast<std::uint64_t>(filter.type));
583  switch (filter.type) {
586  break;
588  bytes << filter.start_location;
589  break;
591  if (filter.end_group_delta > std::numeric_limits<std::uint64_t>::max() - filter.start_location.group) {
592  throw ProtocolViolationException("Subscription filter end group overflow");
593  }
594  bytes << filter.start_location << UintVar(filter.end_group_delta);
595  break;
596  default:
597  throw ProtocolViolationException("Invalid subscription filter type");
598  }
599  return bytes;
600  }
601 
609  {
610  filter = SubscriptionFilter{};
611  std::uint64_t type = 0;
612  bytes = bytes >> type;
613  filter.type = static_cast<SubscriptionFilterType>(type);
614  switch (filter.type) {
617  break;
619  bytes = bytes >> filter.start_location;
620  break;
622  bytes = bytes >> filter.start_location >> filter.end_group_delta;
623  if (filter.end_group_delta > std::numeric_limits<std::uint64_t>::max() - filter.start_location.group) {
624  throw ProtocolViolationException("Subscription filter end group overflow");
625  }
626  break;
627  default:
628  throw ProtocolViolationException("Invalid subscription filter type");
629  }
630  return bytes;
631  }
632 
634  struct TrackFilter
635  {
636  std::uint64_t property_type;
637  std::uint64_t max_tracks_selected;
638  std::uint64_t timeout;
639 
643  constexpr auto operator<=>(const TrackFilter& other) const noexcept = default;
644  };
645 
652  inline Bytes& operator<<(Bytes& bytes, const TrackFilter& filter)
653  {
654  AppendBytes(bytes, UintVar(filter.property_type));
655  AppendBytes(bytes, UintVar(filter.max_tracks_selected));
656  AppendBytes(bytes, UintVar(filter.timeout));
657 
658  return bytes;
659  }
660 
667  inline BytesSpan operator>>(BytesSpan bytes, TrackFilter& filter)
668  {
669  bytes = bytes >> filter.property_type;
670  bytes = bytes >> filter.max_tracks_selected;
671  bytes = bytes >> filter.timeout;
672 
673  return bytes;
674  }
675 
677  using Filter = std::variant<std::monostate, SubscriptionFilter, TrackFilter>;
678 
681  inline FilterType GetFilterType(const Filter& filter)
682  {
683  return std::visit(
684  [](auto&& f) {
685  using T = std::decay_t<decltype(f)>;
686  if constexpr (std::is_same_v<std::monostate, T>) {
687  return FilterType::kNone;
688  } else if constexpr (std::is_same_v<SubscriptionFilter, T>) {
690  } else if constexpr (std::is_same_v<TrackFilter, T>) {
692  }
693  },
694  filter);
695  }
696 
703  inline Bytes& operator<<(Bytes& bytes, const Filter& filter)
704  {
705  std::visit(
706  [&](auto&& f) {
707  using T = std::decay_t<decltype(f)>;
708  if constexpr (!std::is_same_v<std::monostate, T>) {
709  bytes << f;
710  }
711  },
712  filter);
713  return bytes;
714  }
715 
721  {
722  throw std::runtime_error("parsing a non specific filter is impossible, stream to a more specific filter type");
723  }
724 
732  inline Filter DeserializeFilter(FilterType filter_type, BytesSpan bytes)
733  {
734  switch (filter_type) {
736  SubscriptionFilter filter{};
737  bytes = bytes >> filter;
738  if (!bytes.empty()) {
739  throw ProtocolViolationException("Trailing bytes in subscription filter");
740  }
741  return filter;
742  }
744  TrackFilter filter{};
745  bytes = bytes >> filter;
746  return filter;
747  }
748  default:
749  return std::monostate{};
750  }
751 
752  return std::monostate{};
753  }
754 
756  enum class PublishDoneStatusCode : uint64_t
757  {
758  kInternalError = 0x0,
759  kUnauthorized = 0x1,
760  kTrackEnded = 0x2,
761  kSubscriptionEnded = 0x3,
762  kGoingAway = 0x4,
763  kTooFarBehind = 0x5,
764  kExpired = 0x6,
765  kMalformedTrack = 0x12,
766  kUpdateFailed = 0x8,
767  kExcessiveLoad = 0x9
768  };
769 
777 
785 
787  enum class FetchType : uint8_t
788  {
789  kStandalone = 0x1,
792  };
793 
800  Bytes& operator<<(Bytes& buffer, FetchType value);
801 
809 
811  enum class TerminationReason : uint64_t
812  {
813  kNoError = 0x0,
814  kInternalError = 0x1,
815  kUnauthorized = 0x2,
816  kProtocolViolation = 0x3,
817  kInvalidRequestId = 0x4,
818  kDuplicateTrackAlias = 0x5,
820  kTooManyRequests = 0x7,
821  kInvalidPath = 0x8,
822  kMalformedPath = 0x9,
823  kGoawayTimeout = 0x10,
824  kControlMessageTimeout = 0x11,
825  kDataStreamTimeout = 0x12,
826  kAuthTokenCacheOverflow = 0x13,
827  kDuplicateAuthTokenAlias = 0x14,
829  kMalformedAuthToken = 0x16,
830  kUnknownAuthTokenAlias = 0x17,
831  kExpiredAuthToken = 0x18,
832  kInvalidAuthority = 0x19,
833  kMalformedAuthority = 0x1A,
834  };
835 
837  enum class StreamResetError : uint64_t
838  {
839  kInternalError = 0x0,
840  kCancelled = 0x1,
841  kDeliveryTimeout = 0x2,
842  kSessionClosed = 0x3,
843  kUnknownObjectStatus = 0x4,
844  kMalformedTrack = 0x12,
845  };
846 
848  enum class ExtensionType : uint64_t
849  {
850  // Track Scope Extensions
851  kDeliveryTimeout = 0x02,
852  kMaxCacheDuration = 0x04,
855  kDynamicGroups = 0x30,
856 
857  // Object Scope Extensions
858  kPriorGroupIdGap = 0x3C,
859  kPriorObjectIdGap = 0x3E,
860 
861  // Dual Scope (Track and Object) Extensions
862  kImmutable = 0x0B,
863  };
864 
869  template<class T>
870  concept HasByteStreamOperators = requires(T& value, Bytes& bytes) {
871  { bytes << value } -> std::same_as<Bytes&>;
872  { BytesSpan{} >> value } -> std::same_as<BytesSpan>;
873  };
874 
879  template<class T>
880  concept ByteParameter = std::is_convertible_v<T, std::uint8_t> ||
881  (std::is_enum_v<T> && std::same_as<std::underlying_type_t<T>, std::uint8_t>);
882 
885  {
886  public:
888  KeyValuePairs() = default;
889 
891  KeyValuePairs(const std::map<std::uint64_t, Bytes>& pairs)
892  : pairs_(pairs)
893  {
894  }
895 
904  template<typename T, KeyType K>
905  KeyValuePairs& Add(K type, const T& value)
906  {
907  const auto type_value = static_cast<std::uint64_t>(type);
908  pairs_[type_value] = EncodeValue(type_value, value);
909  return *this;
910  }
911 
919  template<typename T, KeyType K>
920  std::optional<T> Get(K type) const
921  {
922  const auto it = pairs_.find(static_cast<std::uint64_t>(type));
923  if (it == pairs_.end()) {
924  return std::nullopt;
925  }
926  const auto& bytes = it->second;
927  if constexpr (std::is_arithmetic_v<T>) {
928  if (static_cast<std::uint64_t>(type) % 2 == 0) {
929  std::uint64_t val = 0;
930  std::memcpy(&val, bytes.data(), std::min(bytes.size(), sizeof(val)));
931  return static_cast<T>(val);
932  }
933  }
934 
935  if constexpr (HasByteStreamOperators<T>) {
936  T result;
937  bytes >> result;
938  return result;
939  }
940 
941  return FromBytes<T>(bytes);
942  }
943 
946  bool Contains(std::uint64_t type) const { return pairs_.contains(type); }
947 
949  auto begin() const noexcept { return pairs_.begin(); }
950 
952  auto end() const noexcept { return pairs_.end(); }
953 
955  const std::map<std::uint64_t, Bytes>& Pairs() const noexcept { return pairs_; }
956 
964  template<typename T>
965  static Bytes EncodeValue(std::uint64_t type, const T& value)
966  {
967  if constexpr (std::is_arithmetic_v<T> || std::is_enum_v<T>) {
968  if (type % 2 == 0) {
969  const std::uint64_t val = static_cast<std::uint64_t>(value);
970  auto* val_bytes = reinterpret_cast<const std::uint8_t*>(&val);
971  return Bytes{ val_bytes, val_bytes + sizeof(val) };
972  }
973  }
974 
975  if constexpr (HasByteStreamOperators<T>) {
976  Bytes bytes;
977  bytes << value;
978  return bytes;
979  }
980 
981  return AsOwnedBytes(value);
982  }
983 
984  private:
985  std::map<std::uint64_t, Bytes> pairs_;
986  };
987 
995 
1002  Bytes& operator<<(Bytes& buffer, const KeyValuePairs& msg);
1003 
1006  {
1007  public:
1009  TrackExtensions() = default;
1010 
1012  TrackExtensions(const std::map<std::uint64_t, Bytes>& ext)
1013  : extensions(ext)
1014  {
1015  }
1016 
1017  public:
1026  template<typename T>
1027  TrackExtensions& Add(ExtensionType type, const T& value)
1028  {
1029  if (type == ExtensionType::kImmutable) {
1030  throw std::invalid_argument("ExtensionType::kImmutable should not be used directly, use AddImmutable "
1031  "with the keytype you want to use");
1032  }
1033 
1034  extensions[static_cast<std::uint64_t>(type)] =
1035  KeyValuePairs::EncodeValue(static_cast<std::uint64_t>(type), value);
1036 
1037  return *this;
1038  }
1039 
1047  template<typename T>
1048  TrackExtensions& AddOptional(ExtensionType type, const std::optional<T>& value)
1049  {
1050  if (value.has_value()) {
1051  Add<T>(type, value.value());
1052  }
1053  return *this;
1054  }
1055 
1063  template<typename T>
1065  {
1066  immutable_extensions[static_cast<std::uint64_t>(type)] =
1067  KeyValuePairs::EncodeValue(static_cast<std::uint64_t>(type), value);
1068  return *this;
1069  }
1070 
1077  template<typename T>
1078  std::optional<T> Get(ExtensionType type) const
1079  {
1080  if (!extensions.contains(static_cast<std::uint64_t>(type))) {
1081  return std::nullopt;
1082  }
1083  if constexpr (std::is_arithmetic_v<T>) {
1084  if (static_cast<std::uint64_t>(type) % 2 == 0) {
1085  std::uint64_t val = 0;
1086  const auto& bytes = extensions.at(static_cast<std::uint64_t>(type));
1087  std::memcpy(&val, bytes.data(), std::min(bytes.size(), sizeof(val)));
1088  return static_cast<T>(val);
1089  }
1090  }
1091 
1092  if constexpr (HasByteStreamOperators<T>) {
1093  T result;
1094  extensions.at(static_cast<std::uint64_t>(type)) >> result;
1095  return result;
1096  }
1097 
1098  return FromBytes<T>(extensions.at(static_cast<std::uint64_t>(type)));
1099  }
1100 
1107  template<typename T>
1108  std::optional<T> GetImmutable(ExtensionType type) const
1109  {
1110  if (!immutable_extensions.contains(static_cast<std::uint64_t>(type))) {
1111  return std::nullopt;
1112  }
1113  if constexpr (std::is_arithmetic_v<T>) {
1114  if (static_cast<std::uint64_t>(type) % 2 == 0) {
1115  std::uint64_t val = 0;
1116  const auto& bytes = immutable_extensions.at(static_cast<std::uint64_t>(type));
1117  std::memcpy(&val, bytes.data(), std::min(bytes.size(), sizeof(val)));
1118  return static_cast<T>(val);
1119  }
1120  }
1121 
1122  if constexpr (HasByteStreamOperators<T>) {
1123  T result;
1124  immutable_extensions.at(static_cast<std::uint64_t>(type)) >> result;
1125  return result;
1126  }
1127 
1128  return FromBytes<T>(immutable_extensions.at(static_cast<std::uint64_t>(type)));
1129  }
1130 
1132  auto begin() const noexcept { return extensions.begin(); }
1133 
1135  auto end() const noexcept { return extensions.end(); }
1136 
1137  std::map<std::uint64_t, Bytes> extensions;
1138  std::map<std::uint64_t, Bytes> immutable_extensions;
1139  };
1140 
1148 
1155  Bytes& operator<<(Bytes& buffer, const TrackExtensions& msg);
1156 
1157 } // namespace
An N-tuple representation of a MOQ namespace.
Definition: track_name.h:22
Definition: uintvar.h:50
constexpr std::size_t size() const noexcept
Definition: uintvar.h:160
Draft 18 flat key-value pairs: a bounded, sorted KVP sequence without a leading count.
Definition: ctrl_message_types.h:885
const std::map< std::uint64_t, Bytes > & Pairs() const noexcept
Definition: ctrl_message_types.h:955
bool Contains(std::uint64_t type) const
Definition: ctrl_message_types.h:946
KeyValuePairs()=default
Creates an empty sequence.
static Bytes EncodeValue(std::uint64_t type, const T &value)
Definition: ctrl_message_types.h:965
std::optional< T > Get(K type) const
Definition: ctrl_message_types.h:920
auto end() const noexcept
Definition: ctrl_message_types.h:952
auto begin() const noexcept
Definition: ctrl_message_types.h:949
KeyValuePairs & Add(K type, const T &value)
Definition: ctrl_message_types.h:905
KeyValuePairs(const std::map< std::uint64_t, Bytes > &pairs)
Definition: ctrl_message_types.h:891
Mutable and immutable track-scoped extension maps.
Definition: ctrl_message_types.h:1006
TrackExtensions & AddImmutable(ExtensionType type, const T &value)
Definition: ctrl_message_types.h:1064
TrackExtensions(const std::map< std::uint64_t, Bytes > &ext)
Definition: ctrl_message_types.h:1012
TrackExtensions()=default
Creates empty extension maps.
std::optional< T > GetImmutable(ExtensionType type) const
Definition: ctrl_message_types.h:1108
auto end() const noexcept
Definition: ctrl_message_types.h:1135
TrackExtensions & Add(ExtensionType type, const T &value)
Definition: ctrl_message_types.h:1027
std::map< std::uint64_t, Bytes > extensions
Mutable extensions keyed by absolute type.
Definition: ctrl_message_types.h:1137
std::optional< T > Get(ExtensionType type) const
Definition: ctrl_message_types.h:1078
auto begin() const noexcept
Definition: ctrl_message_types.h:1132
TrackExtensions & AddOptional(ExtensionType type, const std::optional< T > &value)
Definition: ctrl_message_types.h:1048
std::map< std::uint64_t, Bytes > immutable_extensions
Immutable nested extensions keyed by absolute type.
Definition: ctrl_message_types.h:1138
Definition: ctrl_message_types.h:38
TerminationReason
Session termination reason codes.
Definition: ctrl_message_types.h:812
@ kMalformedAuthority
Authority encoding is malformed.
@ kKeyValueFormattingError
Malformed key/value sequence.
@ kInvalidAuthority
Authority is invalid.
@ kUnauthorized
Authorization failure.
@ kMalformedPath
Path encoding is malformed.
@ kExpiredAuthToken
Authorization token expired.
@ kDuplicateTrackAlias
Track alias was reused.
@ kMalformedAuthToken
Authorization token is malformed.
@ kDataStreamTimeout
Data-stream timeout.
@ kProtocolViolation
Peer violated the protocol.
@ kUnknownAuthTokenAlias
Authorization-token alias is unknown.
@ kControlMessageTimeout
Control-message timeout.
@ kVersionNegotiationFailed
No mutually supported version.
@ kTooManyRequests
Request limit exceeded.
@ kDuplicateAuthTokenAlias
Authorization-token alias was reused.
@ kAuthTokenCacheOverflow
Authorization-token cache is full.
@ kInvalidRequestId
Invalid request identifier.
@ kInternalError
Internal endpoint failure.
concept HasByteStreamOperators
Definition: ctrl_message_types.h:870
void SerializeKvp(Bytes &buffer, const KeyValuePair< T > &kvp, const T prev_type)
Definition: ctrl_message_types.h:345
PublishDoneStatusCode
Publish-done status codes.
Definition: ctrl_message_types.h:757
@ kUnauthorized
Authorization failed.
@ kGoingAway
Endpoint is going away.
@ kSubscriptionEnded
Subscription ended.
@ kTooFarBehind
Consumer fell too far behind.
Bytes & operator<<(Bytes &buffer, const Bytes &bytes)
Filter DeserializeFilter(FilterType filter_type, BytesSpan bytes)
Definition: ctrl_message_types.h:732
concept KeyType
Definition: ctrl_message_types.h:219
concept ByteParameter
Definition: ctrl_message_types.h:880
SetupOptionType
SETUP option type codes.
Definition: ctrl_message_types.h:403
@ kMaxAuthTokenCacheSize
Maximum authorization-token alias cache size.
@ kMoqtImplementation
Implementation identification bytes.
@ kPath
Request path bytes.
@ kAuthorizationToken
Sensitive opaque authorization token; never log its bytes.
@ kEndpointId
Internal endpoint identifier.
@ kInvalid
Internal invalid sentinel.
FilterType GetFilterType(const Filter &filter)
Definition: ctrl_message_types.h:681
ExtensionType
Known track/object extension type codes.
Definition: ctrl_message_types.h:849
@ kDefaultPublisherPriority
Default publisher priority.
@ kPriorObjectIdGap
Gap from the prior object identifier.
@ kDefaultPublisherGroupOrder
Default publisher group order.
@ kPriorGroupIdGap
Gap from the prior group identifier.
@ kDeliveryTimeout
Delivery timeout.
@ kImmutable
Container for immutable nested extension KVPs.
@ kDynamicGroups
Dynamic-groups flag.
@ kMaxCacheDuration
Maximum cache duration.
BytesSpan operator>>(BytesSpan buffer, Bytes &value)
std::variant< std::monostate, SubscriptionFilter, TrackFilter > Filter
Any supported filter representation; monostate means no/unsupported filter.
Definition: ctrl_message_types.h:677
FetchType
FETCH request form.
Definition: ctrl_message_types.h:788
@ kRelativeJoiningFetch
Joining fetch relative to a subscription.
@ kAbsoluteJoiningFetch
Joining fetch with absolute bounds.
@ kStandalone
Independent fetch.
void ParseKvp(BytesSpan &buffer, KeyValuePair< T > &kvp, const T prev_type)
Definition: ctrl_message_types.h:376
ControlMessageType
MoQ control-message wire type codes.
Definition: ctrl_message_types.h:42
@ kPublishNamespaceDone
PUBLISH_NAMESPACE_DONE.
@ kPublishNamespace
PUBLISH_NAMESPACE.
@ kPublishNamespaceCancel
PUBLISH_NAMESPACE_CANCEL.
@ kSubscribeNamespace
SUBSCRIBE_NAMESPACE.
FilterType
In-memory filter discriminator.
Definition: ctrl_message_types.h:546
@ kTrackFilter
Track-selection constraints.
@ kSubscriptionFilter
Location/subscription filter.
GroupOrder
Requested group traversal order.
Definition: ctrl_message_types.h:532
@ kAscending
Increasing group identifiers.
@ kDescending
Decreasing group identifiers.
StreamResetError
Data-stream reset error codes.
Definition: ctrl_message_types.h:838
@ kUnknownObjectStatus
Unknown object status.
@ kDeliveryTimeout
Delivery timed out.
@ kCancelled
Delivery was cancelled.
@ kMalformedTrack
Track data is malformed.
@ kInternalError
Internal failure.
SubscriptionFilterType
Subscription-filter form.
Definition: ctrl_message_types.h:554
@ kLargestObject
Start at the largest object.
@ kAbsoluteStart
Start at an absolute location.
@ kAbsoluteRange
Select an absolute range.
@ kNextGroupStart
Start at the next group.
Definition: attributes.h:13
Bytes & operator<<(Bytes &buffer, const TrackNamespace &msg)
std::vector< Byte > Bytes
Owning contiguous byte buffer.
Definition: bytes.h:18
std::span< const Byte > BytesSpan
Non-owning, read-only view of contiguous bytes.
Definition: bytes.h:21
requires std::is_standard_layout_v< T > std::is_same_v< std::decay_t< T >, std::string > Bytes AsOwnedBytes(const T &value)
Copies a value's native object representation into an owning byte buffer.
Definition: bytes.h:60
void AppendBytes(Bytes &buffer, BytesSpan bytes)
Appends bytes to an owning buffer.
Definition: bytes.h:99
BytesSpan operator>>(BytesSpan buffer, TrackNamespace &msg)
Inclusive terminal location for a fetch range.
Definition: ctrl_message_types.h:208
std::uint64_t group
The group ID of the fetch's end location (inclusive).
Definition: ctrl_message_types.h:209
std::optional< std::uint64_t > object
The object ID of the fetch's end location (inclusive), or null for the whole group.
Definition: ctrl_message_types.h:211
Definition: ctrl_message_types.h:231
Bytes value
Opaque odd-key bytes or host-order integer bytes for an even key.
Definition: ctrl_message_types.h:233
bool operator==(const KeyValuePair< T > &other) const
Definition: ctrl_message_types.h:271
std::size_t Size(const T prev_type) const
Definition: ctrl_message_types.h:241
T type
Absolute key type.
Definition: ctrl_message_types.h:232
Absolute group/object location ordered lexicographically by group then object.
Definition: ctrl_message_types.h:171
std::uint64_t object
Object identifier within the group.
Definition: ctrl_message_types.h:173
auto operator<=>(const Location &other) const
Definition: ctrl_message_types.h:177
std::uint64_t group
Group identifier.
Definition: ctrl_message_types.h:172
bool operator==(const Location &other) const =default
Exception indicating that received or constructed data violates the MoQ protocol.
Definition: ctrl_message_types.h:71
const std::string reason
Unformatted protocol-violation reason.
Definition: ctrl_message_types.h:72
ProtocolViolationException(const std::string &reason, const std::source_location location=std::source_location::current())
Definition: ctrl_message_types.h:78
Definition: ctrl_message_types.h:566
std::uint64_t end_group_delta
Inclusive end-group offset from start_location.group for kAbsoluteRange.
Definition: ctrl_message_types.h:574
SubscriptionFilterType type
Wire-format filter form.
Definition: ctrl_message_types.h:568
auto operator<=>(const SubscriptionFilter &) const noexcept=default
Location start_location
Absolute starting group and object for kAbsoluteStart and kAbsoluteRange.
Definition: ctrl_message_types.h:571
Definition: ctrl_message_types.h:425
std::optional< std::uint64_t > token_alias
Alias required for delete, register, and use-alias operations.
Definition: ctrl_message_types.h:438
AliasType
Operation encoded at the beginning of an authorization-token value.
Definition: ctrl_message_types.h:428
@ kRegister
Register alias, token type, and token value.
@ kUseAlias
Refer to a previously registered alias.
@ kUseValue
Carry a token type and token value directly.
@ kDelete
Delete the specified cached alias.
bool operator==(const Token &other) const =default
std::optional< std::uint64_t > token_type
Application-defined token type required when a value is present.
Definition: ctrl_message_types.h:441
AliasType alias_type
Alias operation.
Definition: ctrl_message_types.h:435
Bytes token_value
Sensitive opaque token bytes; never log this field.
Definition: ctrl_message_types.h:444
Selects tracks by property, count, and timeout constraints.
Definition: ctrl_message_types.h:635
constexpr auto operator<=>(const TrackFilter &other) const noexcept=default
std::uint64_t max_tracks_selected
Maximum number of selected tracks.
Definition: ctrl_message_types.h:637
std::uint64_t property_type
Property type used for selection.
Definition: ctrl_message_types.h:636
std::uint64_t timeout
Selection timeout.
Definition: ctrl_message_types.h:638