xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/quic_stream_priority.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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