Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion MODULE.bazel.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions build/source_list.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -895,9 +895,12 @@ quiche_test_support_hdrs = [
"quic/test_tools/test_certificates.h",
"quic/test_tools/test_ip_packets.h",
"quic/test_tools/test_ticket_crypter.h",
"quic/test_tools/quic_spdy_session_test_utils.h",
"quic/test_tools/web_transport_resets_backend.h",
"quic/test_tools/web_transport_test_tools.h",
"quic/core/http/web_transport_draft15_test_utils.h",
"web_transport/test_tools/in_memory_stream.h",
"web_transport/test_tools/draft15_constants.h",
"web_transport/test_tools/mock_web_transport.h",
]
quiche_test_support_srcs = [
Expand Down Expand Up @@ -1402,6 +1405,17 @@ quiche_tests_srcs = [
"web_transport/test_tools/in_memory_stream_test.cc",
"web_transport/web_transport_headers_test.cc",
"web_transport/web_transport_priority_scheduler_test.cc",
"common/capsule_draft15_test.cc",
"quic/core/http/web_transport_buffering_draft15_test.cc",
"quic/core/http/web_transport_capsule_dispatch_draft15_test.cc",
"quic/core/http/web_transport_error_codes_draft15_test.cc",
"quic/core/http/web_transport_flow_control_draft15_test.cc",
"quic/core/http/web_transport_keying_material_draft15_test.cc",
"quic/core/http/web_transport_session_establishment_draft15_test.cc",
"quic/core/http/web_transport_session_limiting_draft15_test.cc",
"quic/core/http/web_transport_streams_draft15_test.cc",
"quic/core/http/web_transport_version_negotiation_draft15_test.cc",
"web_transport/web_transport_headers_draft15_test.cc",
]
io_tests_hdrs = [
]
Expand Down
109 changes: 109 additions & 0 deletions quiche/common/capsule.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ std::string CapsuleTypeToString(CapsuleType capsule_type) {
return "WT_MAX_STREAMS_BIDI";
case CapsuleType::WT_MAX_STREAMS_UNIDI:
return "WT_MAX_STREAMS_UNIDI";
case CapsuleType::WT_MAX_DATA:
return "WT_MAX_DATA";
case CapsuleType::WT_DATA_BLOCKED:
return "WT_DATA_BLOCKED";
case CapsuleType::WT_STREAM_DATA_BLOCKED:
return "WT_STREAM_DATA_BLOCKED";
case CapsuleType::WT_STREAMS_BLOCKED_BIDI:
return "WT_STREAMS_BLOCKED_BIDI";
case CapsuleType::WT_STREAMS_BLOCKED_UNIDI:
return "WT_STREAMS_BLOCKED_UNIDI";
case CapsuleType::COMPRESSION_ASSIGN:
return "COMPRESSION_ASSIGN";
case CapsuleType::COMPRESSION_CLOSE:
Expand Down Expand Up @@ -229,6 +239,24 @@ std::string WebTransportMaxStreamsCapsule::ToString() const {
" (max_streams=", max_stream_count, ")");
}

std::string WebTransportMaxDataCapsule::ToString() const {
return absl::StrCat("WT_MAX_DATA (max_data=", max_data, ")");
}

std::string WebTransportDataBlockedCapsule::ToString() const {
return absl::StrCat("WT_DATA_BLOCKED (data_limit=", data_limit, ")");
}

std::string WebTransportStreamDataBlockedCapsule::ToString() const {
return absl::StrCat("WT_STREAM_DATA_BLOCKED (stream_id=", stream_id,
", stream_data_limit=", stream_data_limit, ")");
}

std::string WebTransportStreamsBlockedCapsule::ToString() const {
return absl::StrCat(CapsuleTypeToString(capsule_type()),
" (stream_limit=", stream_limit, ")");
}

std::string Capsule::ToString() const {
return std::visit([](const auto& capsule) { return capsule.ToString(); },
capsule_);
Expand Down Expand Up @@ -375,6 +403,27 @@ absl::StatusOr<quiche::QuicheBuffer> SerializeCapsuleWithStatus(
return SerializeCapsuleFields(
capsule.capsule_type(), allocator,
WireVarInt62(capsule.web_transport_max_streams().max_stream_count));
case CapsuleType::WT_MAX_DATA:
return SerializeCapsuleFields(
capsule.capsule_type(), allocator,
WireVarInt62(capsule.web_transport_max_data().max_data));
case CapsuleType::WT_DATA_BLOCKED:
return SerializeCapsuleFields(
capsule.capsule_type(), allocator,
WireVarInt62(capsule.web_transport_data_blocked().data_limit));
case CapsuleType::WT_STREAM_DATA_BLOCKED:
return SerializeCapsuleFields(
capsule.capsule_type(), allocator,
WireVarInt62(
capsule.web_transport_stream_data_blocked().stream_id),
WireVarInt62(
capsule.web_transport_stream_data_blocked().stream_data_limit));
case CapsuleType::WT_STREAMS_BLOCKED_BIDI:
case CapsuleType::WT_STREAMS_BLOCKED_UNIDI:
return SerializeCapsuleFields(
capsule.capsule_type(), allocator,
WireVarInt62(
capsule.web_transport_streams_blocked().stream_limit));
case CapsuleType::COMPRESSION_ASSIGN:
QUICHE_DCHECK(capsule.compression_assign_capsule().ip_address_port ==
quiche::QuicheSocketAddress() ||
Expand Down Expand Up @@ -702,6 +751,44 @@ absl::StatusOr<Capsule> ParseCapsulePayload(QuicheDataReader& reader,
}
return Capsule(std::move(capsule));
}
case CapsuleType::WT_MAX_DATA: {
WebTransportMaxDataCapsule capsule;
if (!reader.ReadVarInt62(&capsule.max_data)) {
return absl::InvalidArgumentError(
"Failed to parse the max data field");
}
return Capsule(std::move(capsule));
}
case CapsuleType::WT_DATA_BLOCKED: {
WebTransportDataBlockedCapsule capsule;
if (!reader.ReadVarInt62(&capsule.data_limit)) {
return absl::InvalidArgumentError(
"Failed to parse the data blocked limit field");
}
return Capsule(std::move(capsule));
}
case CapsuleType::WT_STREAM_DATA_BLOCKED: {
WebTransportStreamDataBlockedCapsule capsule;
QUICHE_RETURN_IF_ERROR(
ReadWebTransportStreamId(reader, capsule.stream_id));
if (!reader.ReadVarInt62(&capsule.stream_data_limit)) {
return absl::InvalidArgumentError(
"Failed to parse the stream data blocked limit field");
}
return Capsule(std::move(capsule));
}
case CapsuleType::WT_STREAMS_BLOCKED_UNIDI:
case CapsuleType::WT_STREAMS_BLOCKED_BIDI: {
WebTransportStreamsBlockedCapsule capsule;
capsule.stream_type = type == CapsuleType::WT_STREAMS_BLOCKED_UNIDI
? webtransport::StreamType::kUnidirectional
: webtransport::StreamType::kBidirectional;
if (!reader.ReadVarInt62(&capsule.stream_limit)) {
return absl::InvalidArgumentError(
"Failed to parse the streams blocked limit field");
}
return Capsule(std::move(capsule));
}
case CapsuleType::COMPRESSION_ASSIGN: {
CompressionAssignCapsule capsule;
if (!reader.ReadVarInt62(&capsule.context_id)) {
Expand Down Expand Up @@ -879,4 +966,26 @@ bool WebTransportMaxStreamsCapsule::operator==(
max_stream_count == other.max_stream_count;
}

bool WebTransportMaxDataCapsule::operator==(
const WebTransportMaxDataCapsule& other) const {
return max_data == other.max_data;
}

bool WebTransportDataBlockedCapsule::operator==(
const WebTransportDataBlockedCapsule& other) const {
return data_limit == other.data_limit;
}

bool WebTransportStreamDataBlockedCapsule::operator==(
const WebTransportStreamDataBlockedCapsule& other) const {
return stream_id == other.stream_id &&
stream_data_limit == other.stream_data_limit;
}

bool WebTransportStreamsBlockedCapsule::operator==(
const WebTransportStreamsBlockedCapsule& other) const {
return stream_type == other.stream_type &&
stream_limit == other.stream_limit;
}

} // namespace quiche
83 changes: 73 additions & 10 deletions quiche/common/capsule.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,17 @@ enum class CapsuleType : uint64_t {
WT_STOP_SENDING = 0x190b4d3a,
WT_STREAM = 0x190b4d3b,
WT_STREAM_WITH_FIN = 0x190b4d3c,
// Should be removed as a result of
// <https://github.com/ietf-wg-webtrans/draft-webtransport-http2/issues/27>.
// WT_MAX_DATA = 0x190b4d3d,
WT_MAX_DATA = 0x190b4d3d,
WT_MAX_STREAM_DATA = 0x190b4d3e,
WT_MAX_STREAMS_BIDI = 0x190b4d3f,
WT_MAX_STREAMS_UNIDI = 0x190b4d40,

// TODO(b/264263113): implement those.
// TODO(b/264263113): PADDING not yet implemented.
// PADDING = 0x190b4d38,
// WT_DATA_BLOCKED = 0x190b4d41,
// WT_STREAM_DATA_BLOCKED = 0x190b4d42,
// WT_STREAMS_BLOCKED_BIDI = 0x190b4d43,
// WT_STREAMS_BLOCKED_UNIDI = 0x190b4d44,
WT_DATA_BLOCKED = 0x190b4d41,
WT_STREAM_DATA_BLOCKED = 0x190b4d42,
WT_STREAMS_BLOCKED_BIDI = 0x190b4d43,
WT_STREAMS_BLOCKED_UNIDI = 0x190b4d44,
};

QUICHE_EXPORT std::string CapsuleTypeToString(CapsuleType capsule_type);
Expand Down Expand Up @@ -215,6 +213,43 @@ struct QUICHE_EXPORT WebTransportMaxStreamsCapsule {
}
};

struct QUICHE_EXPORT WebTransportMaxDataCapsule {
uint64_t max_data;

bool operator==(const WebTransportMaxDataCapsule& other) const;
std::string ToString() const;
CapsuleType capsule_type() const { return CapsuleType::WT_MAX_DATA; }
};
struct QUICHE_EXPORT WebTransportDataBlockedCapsule {
uint64_t data_limit;

bool operator==(const WebTransportDataBlockedCapsule& other) const;
std::string ToString() const;
CapsuleType capsule_type() const { return CapsuleType::WT_DATA_BLOCKED; }
};
struct QUICHE_EXPORT WebTransportStreamDataBlockedCapsule {
webtransport::StreamId stream_id;
uint64_t stream_data_limit;

bool operator==(const WebTransportStreamDataBlockedCapsule& other) const;
std::string ToString() const;
CapsuleType capsule_type() const {
return CapsuleType::WT_STREAM_DATA_BLOCKED;
}
};
struct QUICHE_EXPORT WebTransportStreamsBlockedCapsule {
webtransport::StreamType stream_type;
uint64_t stream_limit;

bool operator==(const WebTransportStreamsBlockedCapsule& other) const;
std::string ToString() const;
CapsuleType capsule_type() const {
return stream_type == webtransport::StreamType::kBidirectional
? CapsuleType::WT_STREAMS_BLOCKED_BIDI
: CapsuleType::WT_STREAMS_BLOCKED_UNIDI;
}
};

struct QUICHE_EXPORT CompressionAssignCapsule {
uint64_t context_id;
QuicheSocketAddress ip_address_port;
Expand Down Expand Up @@ -356,6 +391,32 @@ class QUICHE_EXPORT Capsule {
const WebTransportMaxStreamsCapsule& web_transport_max_streams() const {
return std::get<WebTransportMaxStreamsCapsule>(capsule_);
}
WebTransportMaxDataCapsule& web_transport_max_data() {
return std::get<WebTransportMaxDataCapsule>(capsule_);
}
const WebTransportMaxDataCapsule& web_transport_max_data() const {
return std::get<WebTransportMaxDataCapsule>(capsule_);
}
WebTransportDataBlockedCapsule& web_transport_data_blocked() {
return std::get<WebTransportDataBlockedCapsule>(capsule_);
}
const WebTransportDataBlockedCapsule& web_transport_data_blocked() const {
return std::get<WebTransportDataBlockedCapsule>(capsule_);
}
WebTransportStreamDataBlockedCapsule& web_transport_stream_data_blocked() {
return std::get<WebTransportStreamDataBlockedCapsule>(capsule_);
}
const WebTransportStreamDataBlockedCapsule&
web_transport_stream_data_blocked() const {
return std::get<WebTransportStreamDataBlockedCapsule>(capsule_);
}
WebTransportStreamsBlockedCapsule& web_transport_streams_blocked() {
return std::get<WebTransportStreamsBlockedCapsule>(capsule_);
}
const WebTransportStreamsBlockedCapsule& web_transport_streams_blocked()
const {
return std::get<WebTransportStreamsBlockedCapsule>(capsule_);
}
UnknownCapsule& unknown_capsule() {
return std::get<UnknownCapsule>(capsule_);
}
Expand All @@ -371,8 +432,10 @@ class QUICHE_EXPORT Capsule {
RouteAdvertisementCapsule, WebTransportStreamDataCapsule,
WebTransportResetStreamCapsule, WebTransportStopSendingCapsule,
WebTransportMaxStreamsCapsule, WebTransportMaxStreamDataCapsule,
UnknownCapsule, CompressionAssignCapsule,
CompressionCloseCapsule>
WebTransportMaxDataCapsule, WebTransportDataBlockedCapsule,
WebTransportStreamDataBlockedCapsule,
WebTransportStreamsBlockedCapsule, UnknownCapsule,
CompressionAssignCapsule, CompressionCloseCapsule>
capsule_;
};

Expand Down
Loading