1 // Copyright 2022 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 #ifndef QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_ 6 #define QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_ 7 8 #include <cstdint> 9 #include <optional> 10 #include <string> 11 #include <tuple> 12 13 #include "absl/strings/string_view.h" 14 #include "absl/types/variant.h" 15 #include "quiche/quic/core/quic_types.h" 16 #include "quiche/common/platform/api/quiche_bug_tracker.h" 17 #include "quiche/common/platform/api/quiche_export.h" 18 19 namespace quic { 20 21 // Represents HTTP priorities as defined by RFC 9218. 22 struct QUICHE_EXPORT HttpStreamPriority { 23 static constexpr int kMinimumUrgency = 0; 24 static constexpr int kMaximumUrgency = 7; 25 static constexpr int kDefaultUrgency = 3; 26 static constexpr bool kDefaultIncremental = false; 27 28 // Parameter names for Priority Field Value. 29 static constexpr absl::string_view kUrgencyKey = "u"; 30 static constexpr absl::string_view kIncrementalKey = "i"; 31 32 int urgency = kDefaultUrgency; 33 bool incremental = kDefaultIncremental; 34 35 bool operator==(const HttpStreamPriority& other) const { 36 return std::tie(urgency, incremental) == 37 std::tie(other.urgency, other.incremental); 38 } 39 40 bool operator!=(const HttpStreamPriority& other) const { 41 return !(*this == other); 42 } 43 }; 44 45 // Represents WebTransport priorities as defined by 46 // <https://w3c.github.io/webtransport/>. 47 struct QUICHE_EXPORT WebTransportStreamPriority { 48 enum class StreamType : uint8_t { 49 // WebTransport data streams. 50 kData = 0, 51 // Regular HTTP traffic. Since we're currently only supporting dedicated 52 // HTTP/3 transport, this means that all HTTP traffic is control traffic, 53 // and thus should always go first. 54 kHttp = 1, 55 // Streams that the QUIC stack declares as static. 56 kStatic = 2, 57 }; 58 59 // Allows prioritizing control streams over the data streams. 60 StreamType stream_type = StreamType::kData; 61 // https://w3c.github.io/webtransport/#dom-webtransportsendstreamoptions-sendorder 62 int64_t send_order = 0; 63 64 bool operator==(const WebTransportStreamPriority& other) const { 65 return stream_type == other.stream_type && send_order == other.send_order; 66 } 67 bool operator!=(const WebTransportStreamPriority& other) const { 68 return !(*this == other); 69 } 70 }; 71 72 // A class that wraps different types of priorities that can be used for 73 // scheduling QUIC streams. 74 class QUICHE_EXPORT QuicStreamPriority { 75 public: QuicStreamPriority(HttpStreamPriority priority)76 explicit QuicStreamPriority(HttpStreamPriority priority) : value_(priority) {} QuicStreamPriority(WebTransportStreamPriority priority)77 explicit QuicStreamPriority(WebTransportStreamPriority priority) 78 : value_(priority) {} 79 Default(QuicPriorityType type)80 static QuicStreamPriority Default(QuicPriorityType type) { 81 switch (type) { 82 case QuicPriorityType::kHttp: 83 return QuicStreamPriority(HttpStreamPriority()); 84 case QuicPriorityType::kWebTransport: 85 return QuicStreamPriority(WebTransportStreamPriority()); 86 } 87 88 QUICHE_BUG(unhandled_quic_priority_type_518918225) 89 << "Tried to create QuicStreamPriority for unknown QuicPriorityType " 90 << type; 91 return QuicStreamPriority(HttpStreamPriority()); 92 } 93 type()94 QuicPriorityType type() const { return absl::visit(TypeExtractor(), value_); } 95 http()96 HttpStreamPriority http() const { 97 if (absl::holds_alternative<HttpStreamPriority>(value_)) { 98 return absl::get<HttpStreamPriority>(value_); 99 } 100 QUICHE_BUG(invalid_priority_type_http) 101 << "Tried to access HTTP priority for a priority type" << type(); 102 return HttpStreamPriority(); 103 } web_transport()104 WebTransportStreamPriority web_transport() const { 105 if (absl::holds_alternative<WebTransportStreamPriority>(value_)) { 106 return absl::get<WebTransportStreamPriority>(value_); 107 } 108 QUICHE_BUG(invalid_priority_type_wt) 109 << "Tried to access WebTransport priority for a priority type" 110 << type(); 111 return WebTransportStreamPriority(); 112 } 113 114 bool operator==(const QuicStreamPriority& other) const { 115 return value_ == other.value_; 116 } 117 118 private: 119 struct TypeExtractor { operatorTypeExtractor120 QuicPriorityType operator()(const HttpStreamPriority&) { 121 return QuicPriorityType::kHttp; 122 } operatorTypeExtractor123 QuicPriorityType operator()(const WebTransportStreamPriority&) { 124 return QuicPriorityType::kWebTransport; 125 } 126 }; 127 128 absl::variant<HttpStreamPriority, WebTransportStreamPriority> value_; 129 }; 130 131 // Serializes the Priority Field Value for a PRIORITY_UPDATE frame. 132 QUICHE_EXPORT std::string SerializePriorityFieldValue( 133 HttpStreamPriority priority); 134 135 // Parses the Priority Field Value field of a PRIORITY_UPDATE frame. 136 // Returns nullopt on failure. 137 QUICHE_EXPORT std::optional<HttpStreamPriority> ParsePriorityFieldValue( 138 absl::string_view priority_field_value); 139 140 } // namespace quic 141 142 #endif // QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_ 143