blob: 8b1df3c2e55f18318e04f8991c9f4f49d5a5e1c4 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_
#define QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_
#include <cstdint>
#include <optional>
#include <string>
#include <tuple>
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
#include "quiche/quic/core/quic_types.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_export.h"
namespace quic {
// Represents HTTP priorities as defined by RFC 9218.
struct QUICHE_EXPORT HttpStreamPriority {
static constexpr int kMinimumUrgency = 0;
static constexpr int kMaximumUrgency = 7;
static constexpr int kDefaultUrgency = 3;
static constexpr bool kDefaultIncremental = false;
// Parameter names for Priority Field Value.
static constexpr absl::string_view kUrgencyKey = "u";
static constexpr absl::string_view kIncrementalKey = "i";
int urgency = kDefaultUrgency;
bool incremental = kDefaultIncremental;
bool operator==(const HttpStreamPriority& other) const {
return std::tie(urgency, incremental) ==
std::tie(other.urgency, other.incremental);
}
bool operator!=(const HttpStreamPriority& other) const {
return !(*this == other);
}
};
// Represents WebTransport priorities as defined by
// <https://w3c.github.io/webtransport/>.
struct QUICHE_EXPORT WebTransportStreamPriority {
enum class StreamType : uint8_t {
// WebTransport data streams.
kData = 0,
// Regular HTTP traffic. Since we're currently only supporting dedicated
// HTTP/3 transport, this means that all HTTP traffic is control traffic,
// and thus should always go first.
kHttp = 1,
// Streams that the QUIC stack declares as static.
kStatic = 2,
};
// Allows prioritizing control streams over the data streams.
StreamType stream_type = StreamType::kData;
// https://w3c.github.io/webtransport/#dom-webtransportsendstreamoptions-sendorder
int64_t send_order = 0;
bool operator==(const WebTransportStreamPriority& other) const {
return stream_type == other.stream_type && send_order == other.send_order;
}
bool operator!=(const WebTransportStreamPriority& other) const {
return !(*this == other);
}
};
// A class that wraps different types of priorities that can be used for
// scheduling QUIC streams.
class QUICHE_EXPORT QuicStreamPriority {
public:
explicit QuicStreamPriority(HttpStreamPriority priority) : value_(priority) {}
explicit QuicStreamPriority(WebTransportStreamPriority priority)
: value_(priority) {}
static QuicStreamPriority Default(QuicPriorityType type) {
switch (type) {
case QuicPriorityType::kHttp:
return QuicStreamPriority(HttpStreamPriority());
case QuicPriorityType::kWebTransport:
return QuicStreamPriority(WebTransportStreamPriority());
}
QUICHE_BUG(unhandled_quic_priority_type_518918225)
<< "Tried to create QuicStreamPriority for unknown QuicPriorityType "
<< type;
return QuicStreamPriority(HttpStreamPriority());
}
QuicPriorityType type() const { return absl::visit(TypeExtractor(), value_); }
HttpStreamPriority http() const {
if (absl::holds_alternative<HttpStreamPriority>(value_)) {
return absl::get<HttpStreamPriority>(value_);
}
QUICHE_BUG(invalid_priority_type_http)
<< "Tried to access HTTP priority for a priority type" << type();
return HttpStreamPriority();
}
WebTransportStreamPriority web_transport() const {
if (absl::holds_alternative<WebTransportStreamPriority>(value_)) {
return absl::get<WebTransportStreamPriority>(value_);
}
QUICHE_BUG(invalid_priority_type_wt)
<< "Tried to access WebTransport priority for a priority type"
<< type();
return WebTransportStreamPriority();
}
bool operator==(const QuicStreamPriority& other) const {
return value_ == other.value_;
}
private:
struct TypeExtractor {
QuicPriorityType operator()(const HttpStreamPriority&) {
return QuicPriorityType::kHttp;
}
QuicPriorityType operator()(const WebTransportStreamPriority&) {
return QuicPriorityType::kWebTransport;
}
};
absl::variant<HttpStreamPriority, WebTransportStreamPriority> value_;
};
// Serializes the Priority Field Value for a PRIORITY_UPDATE frame.
QUICHE_EXPORT std::string SerializePriorityFieldValue(
HttpStreamPriority priority);
// Parses the Priority Field Value field of a PRIORITY_UPDATE frame.
// Returns nullopt on failure.
QUICHE_EXPORT std::optional<HttpStreamPriority> ParsePriorityFieldValue(
absl::string_view priority_field_value);
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_STREAM_PRIORITY_H_