1 // Copyright (c) 2021 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 #include "quiche/common/capsule.h"
6
7 #include <cstddef>
8 #include <cstdint>
9 #include <limits>
10 #include <ostream>
11 #include <string>
12 #include <type_traits>
13 #include <utility>
14
15 #include "absl/status/status.h"
16 #include "absl/status/statusor.h"
17 #include "absl/strings/escaping.h"
18 #include "absl/strings/str_cat.h"
19 #include "absl/strings/string_view.h"
20 #include "absl/types/span.h"
21 #include "absl/types/variant.h"
22 #include "quiche/common/platform/api/quiche_bug_tracker.h"
23 #include "quiche/common/platform/api/quiche_logging.h"
24 #include "quiche/common/quiche_buffer_allocator.h"
25 #include "quiche/common/quiche_data_reader.h"
26 #include "quiche/common/quiche_data_writer.h"
27 #include "quiche/common/quiche_ip_address.h"
28 #include "quiche/common/quiche_status_utils.h"
29 #include "quiche/common/wire_serialization.h"
30 #include "quiche/web_transport/web_transport.h"
31
32 namespace quiche {
33
CapsuleTypeToString(CapsuleType capsule_type)34 std::string CapsuleTypeToString(CapsuleType capsule_type) {
35 switch (capsule_type) {
36 case CapsuleType::DATAGRAM:
37 return "DATAGRAM";
38 case CapsuleType::LEGACY_DATAGRAM:
39 return "LEGACY_DATAGRAM";
40 case CapsuleType::LEGACY_DATAGRAM_WITHOUT_CONTEXT:
41 return "LEGACY_DATAGRAM_WITHOUT_CONTEXT";
42 case CapsuleType::CLOSE_WEBTRANSPORT_SESSION:
43 return "CLOSE_WEBTRANSPORT_SESSION";
44 case CapsuleType::DRAIN_WEBTRANSPORT_SESSION:
45 return "DRAIN_WEBTRANSPORT_SESSION";
46 case CapsuleType::ADDRESS_REQUEST:
47 return "ADDRESS_REQUEST";
48 case CapsuleType::ADDRESS_ASSIGN:
49 return "ADDRESS_ASSIGN";
50 case CapsuleType::ROUTE_ADVERTISEMENT:
51 return "ROUTE_ADVERTISEMENT";
52 case CapsuleType::WT_STREAM:
53 return "WT_STREAM";
54 case CapsuleType::WT_STREAM_WITH_FIN:
55 return "WT_STREAM_WITH_FIN";
56 case CapsuleType::WT_RESET_STREAM:
57 return "WT_RESET_STREAM";
58 case CapsuleType::WT_STOP_SENDING:
59 return "WT_STOP_SENDING";
60 case CapsuleType::WT_MAX_STREAM_DATA:
61 return "WT_MAX_STREAM_DATA";
62 case CapsuleType::WT_MAX_STREAMS_BIDI:
63 return "WT_MAX_STREAMS_BIDI";
64 case CapsuleType::WT_MAX_STREAMS_UNIDI:
65 return "WT_MAX_STREAMS_UNIDI";
66 }
67 return absl::StrCat("Unknown(", static_cast<uint64_t>(capsule_type), ")");
68 }
69
operator <<(std::ostream & os,const CapsuleType & capsule_type)70 std::ostream& operator<<(std::ostream& os, const CapsuleType& capsule_type) {
71 os << CapsuleTypeToString(capsule_type);
72 return os;
73 }
74
75 // static
Datagram(absl::string_view http_datagram_payload)76 Capsule Capsule::Datagram(absl::string_view http_datagram_payload) {
77 return Capsule(DatagramCapsule{http_datagram_payload});
78 }
79
80 // static
LegacyDatagram(absl::string_view http_datagram_payload)81 Capsule Capsule::LegacyDatagram(absl::string_view http_datagram_payload) {
82 return Capsule(LegacyDatagramCapsule{http_datagram_payload});
83 }
84
85 // static
LegacyDatagramWithoutContext(absl::string_view http_datagram_payload)86 Capsule Capsule::LegacyDatagramWithoutContext(
87 absl::string_view http_datagram_payload) {
88 return Capsule(LegacyDatagramWithoutContextCapsule{http_datagram_payload});
89 }
90
91 // static
CloseWebTransportSession(webtransport::SessionErrorCode error_code,absl::string_view error_message)92 Capsule Capsule::CloseWebTransportSession(
93 webtransport::SessionErrorCode error_code,
94 absl::string_view error_message) {
95 return Capsule(CloseWebTransportSessionCapsule({error_code, error_message}));
96 }
97
98 // static
AddressRequest()99 Capsule Capsule::AddressRequest() { return Capsule(AddressRequestCapsule()); }
100
101 // static
AddressAssign()102 Capsule Capsule::AddressAssign() { return Capsule(AddressAssignCapsule()); }
103
104 // static
RouteAdvertisement()105 Capsule Capsule::RouteAdvertisement() {
106 return Capsule(RouteAdvertisementCapsule());
107 }
108
109 // static
Unknown(uint64_t capsule_type,absl::string_view unknown_capsule_data)110 Capsule Capsule::Unknown(uint64_t capsule_type,
111 absl::string_view unknown_capsule_data) {
112 return Capsule(UnknownCapsule{capsule_type, unknown_capsule_data});
113 }
114
operator ==(const Capsule & other) const115 bool Capsule::operator==(const Capsule& other) const {
116 return capsule_ == other.capsule_;
117 }
118
ToString() const119 std::string DatagramCapsule::ToString() const {
120 return absl::StrCat("DATAGRAM[",
121 absl::BytesToHexString(http_datagram_payload), "]");
122 }
123
ToString() const124 std::string LegacyDatagramCapsule::ToString() const {
125 return absl::StrCat("LEGACY_DATAGRAM[",
126 absl::BytesToHexString(http_datagram_payload), "]");
127 }
128
ToString() const129 std::string LegacyDatagramWithoutContextCapsule::ToString() const {
130 return absl::StrCat("LEGACY_DATAGRAM_WITHOUT_CONTEXT[",
131 absl::BytesToHexString(http_datagram_payload), "]");
132 }
133
ToString() const134 std::string CloseWebTransportSessionCapsule::ToString() const {
135 return absl::StrCat("CLOSE_WEBTRANSPORT_SESSION(error_code=", error_code,
136 ",error_message=\"", error_message, "\")");
137 }
138
ToString() const139 std::string DrainWebTransportSessionCapsule::ToString() const {
140 return "DRAIN_WEBTRANSPORT_SESSION()";
141 }
142
ToString() const143 std::string AddressRequestCapsule::ToString() const {
144 std::string rv = "ADDRESS_REQUEST[";
145 for (auto requested_address : requested_addresses) {
146 absl::StrAppend(&rv, "(", requested_address.request_id, "-",
147 requested_address.ip_prefix.ToString(), ")");
148 }
149 absl::StrAppend(&rv, "]");
150 return rv;
151 }
152
ToString() const153 std::string AddressAssignCapsule::ToString() const {
154 std::string rv = "ADDRESS_ASSIGN[";
155 for (auto assigned_address : assigned_addresses) {
156 absl::StrAppend(&rv, "(", assigned_address.request_id, "-",
157 assigned_address.ip_prefix.ToString(), ")");
158 }
159 absl::StrAppend(&rv, "]");
160 return rv;
161 }
162
ToString() const163 std::string RouteAdvertisementCapsule::ToString() const {
164 std::string rv = "ROUTE_ADVERTISEMENT[";
165 for (auto ip_address_range : ip_address_ranges) {
166 absl::StrAppend(&rv, "(", ip_address_range.start_ip_address.ToString(), "-",
167 ip_address_range.end_ip_address.ToString(), "-",
168 static_cast<int>(ip_address_range.ip_protocol), ")");
169 }
170 absl::StrAppend(&rv, "]");
171 return rv;
172 }
173
ToString() const174 std::string UnknownCapsule::ToString() const {
175 return absl::StrCat("Unknown(", type, ") [", absl::BytesToHexString(payload),
176 "]");
177 }
178
ToString() const179 std::string WebTransportStreamDataCapsule::ToString() const {
180 return absl::StrCat(CapsuleTypeToString(capsule_type()),
181 " [stream_id=", stream_id,
182 ", data=", absl::BytesToHexString(data), "]");
183 }
184
ToString() const185 std::string WebTransportResetStreamCapsule::ToString() const {
186 return absl::StrCat("WT_RESET_STREAM(stream_id=", stream_id,
187 ", error_code=", error_code, ")");
188 }
189
ToString() const190 std::string WebTransportStopSendingCapsule::ToString() const {
191 return absl::StrCat("WT_STOP_SENDING(stream_id=", stream_id,
192 ", error_code=", error_code, ")");
193 }
194
ToString() const195 std::string WebTransportMaxStreamDataCapsule::ToString() const {
196 return absl::StrCat("WT_MAX_STREAM_DATA (stream_id=", stream_id,
197 ", max_stream_data=", max_stream_data, ")");
198 }
199
ToString() const200 std::string WebTransportMaxStreamsCapsule::ToString() const {
201 return absl::StrCat(CapsuleTypeToString(capsule_type()),
202 " (max_streams=", max_stream_count, ")");
203 }
204
ToString() const205 std::string Capsule::ToString() const {
206 return absl::visit([](const auto& capsule) { return capsule.ToString(); },
207 capsule_);
208 }
209
operator <<(std::ostream & os,const Capsule & capsule)210 std::ostream& operator<<(std::ostream& os, const Capsule& capsule) {
211 os << capsule.ToString();
212 return os;
213 }
214
CapsuleParser(Visitor * visitor)215 CapsuleParser::CapsuleParser(Visitor* visitor) : visitor_(visitor) {
216 QUICHE_DCHECK_NE(visitor_, nullptr);
217 }
218
219 // Serialization logic for quiche::PrefixWithId.
220 class WirePrefixWithId {
221 public:
222 using DataType = PrefixWithId;
223
WirePrefixWithId(const PrefixWithId & prefix)224 WirePrefixWithId(const PrefixWithId& prefix) : prefix_(prefix) {}
225
GetLengthOnWire()226 size_t GetLengthOnWire() {
227 return ComputeLengthOnWire(
228 WireVarInt62(prefix_.request_id),
229 WireUint8(prefix_.ip_prefix.address().IsIPv4() ? 4 : 6),
230 WireBytes(prefix_.ip_prefix.address().ToPackedString()),
231 WireUint8(prefix_.ip_prefix.prefix_length()));
232 }
233
SerializeIntoWriter(QuicheDataWriter & writer)234 absl::Status SerializeIntoWriter(QuicheDataWriter& writer) {
235 return AppendToStatus(
236 quiche::SerializeIntoWriter(
237 writer, WireVarInt62(prefix_.request_id),
238 WireUint8(prefix_.ip_prefix.address().IsIPv4() ? 4 : 6),
239 WireBytes(prefix_.ip_prefix.address().ToPackedString()),
240 WireUint8(prefix_.ip_prefix.prefix_length())),
241 " while serializing a PrefixWithId");
242 }
243
244 private:
245 const PrefixWithId& prefix_;
246 };
247
248 // Serialization logic for quiche::IpAddressRange.
249 class WireIpAddressRange {
250 public:
251 using DataType = IpAddressRange;
252
WireIpAddressRange(const IpAddressRange & range)253 explicit WireIpAddressRange(const IpAddressRange& range) : range_(range) {}
254
GetLengthOnWire()255 size_t GetLengthOnWire() {
256 return ComputeLengthOnWire(
257 WireUint8(range_.start_ip_address.IsIPv4() ? 4 : 6),
258 WireBytes(range_.start_ip_address.ToPackedString()),
259 WireBytes(range_.end_ip_address.ToPackedString()),
260 WireUint8(range_.ip_protocol));
261 }
262
SerializeIntoWriter(QuicheDataWriter & writer)263 absl::Status SerializeIntoWriter(QuicheDataWriter& writer) {
264 return AppendToStatus(
265 ::quiche::SerializeIntoWriter(
266 writer, WireUint8(range_.start_ip_address.IsIPv4() ? 4 : 6),
267 WireBytes(range_.start_ip_address.ToPackedString()),
268 WireBytes(range_.end_ip_address.ToPackedString()),
269 WireUint8(range_.ip_protocol)),
270 " while serializing an IpAddressRange");
271 }
272
273 private:
274 const IpAddressRange& range_;
275 };
276
277 template <typename... T>
SerializeCapsuleFields(CapsuleType type,QuicheBufferAllocator * allocator,T...fields)278 absl::StatusOr<quiche::QuicheBuffer> SerializeCapsuleFields(
279 CapsuleType type, QuicheBufferAllocator* allocator, T... fields) {
280 size_t capsule_payload_size = ComputeLengthOnWire(fields...);
281 return SerializeIntoBuffer(allocator, WireVarInt62(type),
282 WireVarInt62(capsule_payload_size), fields...);
283 }
284
SerializeCapsuleWithStatus(const Capsule & capsule,quiche::QuicheBufferAllocator * allocator)285 absl::StatusOr<quiche::QuicheBuffer> SerializeCapsuleWithStatus(
286 const Capsule& capsule, quiche::QuicheBufferAllocator* allocator) {
287 switch (capsule.capsule_type()) {
288 case CapsuleType::DATAGRAM:
289 return SerializeCapsuleFields(
290 capsule.capsule_type(), allocator,
291 WireBytes(capsule.datagram_capsule().http_datagram_payload));
292 case CapsuleType::LEGACY_DATAGRAM:
293 return SerializeCapsuleFields(
294 capsule.capsule_type(), allocator,
295 WireBytes(capsule.legacy_datagram_capsule().http_datagram_payload));
296 case CapsuleType::LEGACY_DATAGRAM_WITHOUT_CONTEXT:
297 return SerializeCapsuleFields(
298 capsule.capsule_type(), allocator,
299 WireBytes(capsule.legacy_datagram_without_context_capsule()
300 .http_datagram_payload));
301 case CapsuleType::CLOSE_WEBTRANSPORT_SESSION:
302 return SerializeCapsuleFields(
303 capsule.capsule_type(), allocator,
304 WireUint32(capsule.close_web_transport_session_capsule().error_code),
305 WireBytes(
306 capsule.close_web_transport_session_capsule().error_message));
307 case CapsuleType::DRAIN_WEBTRANSPORT_SESSION:
308 return SerializeCapsuleFields(capsule.capsule_type(), allocator);
309 case CapsuleType::ADDRESS_REQUEST:
310 return SerializeCapsuleFields(
311 capsule.capsule_type(), allocator,
312 WireSpan<WirePrefixWithId>(absl::MakeConstSpan(
313 capsule.address_request_capsule().requested_addresses)));
314 case CapsuleType::ADDRESS_ASSIGN:
315 return SerializeCapsuleFields(
316 capsule.capsule_type(), allocator,
317 WireSpan<WirePrefixWithId>(absl::MakeConstSpan(
318 capsule.address_assign_capsule().assigned_addresses)));
319 case CapsuleType::ROUTE_ADVERTISEMENT:
320 return SerializeCapsuleFields(
321 capsule.capsule_type(), allocator,
322 WireSpan<WireIpAddressRange>(absl::MakeConstSpan(
323 capsule.route_advertisement_capsule().ip_address_ranges)));
324 case CapsuleType::WT_STREAM:
325 case CapsuleType::WT_STREAM_WITH_FIN:
326 return SerializeCapsuleFields(
327 capsule.capsule_type(), allocator,
328 WireVarInt62(capsule.web_transport_stream_data().stream_id),
329 WireBytes(capsule.web_transport_stream_data().data));
330 case CapsuleType::WT_RESET_STREAM:
331 return SerializeCapsuleFields(
332 capsule.capsule_type(), allocator,
333 WireVarInt62(capsule.web_transport_reset_stream().stream_id),
334 WireVarInt62(capsule.web_transport_reset_stream().error_code));
335 case CapsuleType::WT_STOP_SENDING:
336 return SerializeCapsuleFields(
337 capsule.capsule_type(), allocator,
338 WireVarInt62(capsule.web_transport_stop_sending().stream_id),
339 WireVarInt62(capsule.web_transport_stop_sending().error_code));
340 case CapsuleType::WT_MAX_STREAM_DATA:
341 return SerializeCapsuleFields(
342 capsule.capsule_type(), allocator,
343 WireVarInt62(capsule.web_transport_max_stream_data().stream_id),
344 WireVarInt62(
345 capsule.web_transport_max_stream_data().max_stream_data));
346 case CapsuleType::WT_MAX_STREAMS_BIDI:
347 case CapsuleType::WT_MAX_STREAMS_UNIDI:
348 return SerializeCapsuleFields(
349 capsule.capsule_type(), allocator,
350 WireVarInt62(capsule.web_transport_max_streams().max_stream_count));
351 default:
352 return SerializeCapsuleFields(
353 capsule.capsule_type(), allocator,
354 WireBytes(capsule.unknown_capsule().payload));
355 }
356 }
357
SerializeDatagramCapsuleHeader(uint64_t datagram_size,QuicheBufferAllocator * allocator)358 QuicheBuffer SerializeDatagramCapsuleHeader(uint64_t datagram_size,
359 QuicheBufferAllocator* allocator) {
360 absl::StatusOr<QuicheBuffer> buffer =
361 SerializeIntoBuffer(allocator, WireVarInt62(CapsuleType::DATAGRAM),
362 WireVarInt62(datagram_size));
363 if (!buffer.ok()) {
364 return QuicheBuffer();
365 }
366 return *std::move(buffer);
367 }
368
SerializeCapsule(const Capsule & capsule,quiche::QuicheBufferAllocator * allocator)369 QuicheBuffer SerializeCapsule(const Capsule& capsule,
370 quiche::QuicheBufferAllocator* allocator) {
371 absl::StatusOr<QuicheBuffer> serialized =
372 SerializeCapsuleWithStatus(capsule, allocator);
373 if (!serialized.ok()) {
374 QUICHE_BUG(capsule_serialization_failed)
375 << "Failed to serialize the following capsule:\n"
376 << capsule << "Serialization error: " << serialized.status();
377 return QuicheBuffer();
378 }
379 return *std::move(serialized);
380 }
381
IngestCapsuleFragment(absl::string_view capsule_fragment)382 bool CapsuleParser::IngestCapsuleFragment(absl::string_view capsule_fragment) {
383 if (parsing_error_occurred_) {
384 return false;
385 }
386 absl::StrAppend(&buffered_data_, capsule_fragment);
387 while (true) {
388 const absl::StatusOr<size_t> buffered_data_read = AttemptParseCapsule();
389 if (!buffered_data_read.ok()) {
390 ReportParseFailure(buffered_data_read.status().message());
391 buffered_data_.clear();
392 return false;
393 }
394 if (*buffered_data_read == 0) {
395 break;
396 }
397 buffered_data_.erase(0, *buffered_data_read);
398 }
399 static constexpr size_t kMaxCapsuleBufferSize = 1024 * 1024;
400 if (buffered_data_.size() > kMaxCapsuleBufferSize) {
401 buffered_data_.clear();
402 ReportParseFailure("Refusing to buffer too much capsule data");
403 return false;
404 }
405 return true;
406 }
407
408 namespace {
ReadWebTransportStreamId(QuicheDataReader & reader,webtransport::StreamId & id)409 absl::Status ReadWebTransportStreamId(QuicheDataReader& reader,
410 webtransport::StreamId& id) {
411 uint64_t raw_id;
412 if (!reader.ReadVarInt62(&raw_id)) {
413 return absl::InvalidArgumentError("Failed to read WebTransport Stream ID");
414 }
415 if (raw_id > std::numeric_limits<uint32_t>::max()) {
416 return absl::InvalidArgumentError("Stream ID does not fit into a uint32_t");
417 }
418 id = static_cast<webtransport::StreamId>(raw_id);
419 return absl::OkStatus();
420 }
421
ParseCapsulePayload(QuicheDataReader & reader,CapsuleType type)422 absl::StatusOr<Capsule> ParseCapsulePayload(QuicheDataReader& reader,
423 CapsuleType type) {
424 switch (type) {
425 case CapsuleType::DATAGRAM:
426 return Capsule::Datagram(reader.ReadRemainingPayload());
427 case CapsuleType::LEGACY_DATAGRAM:
428 return Capsule::LegacyDatagram(reader.ReadRemainingPayload());
429 case CapsuleType::LEGACY_DATAGRAM_WITHOUT_CONTEXT:
430 return Capsule::LegacyDatagramWithoutContext(
431 reader.ReadRemainingPayload());
432 case CapsuleType::CLOSE_WEBTRANSPORT_SESSION: {
433 CloseWebTransportSessionCapsule capsule;
434 if (!reader.ReadUInt32(&capsule.error_code)) {
435 return absl::InvalidArgumentError(
436 "Unable to parse capsule CLOSE_WEBTRANSPORT_SESSION error code");
437 }
438 capsule.error_message = reader.ReadRemainingPayload();
439 return Capsule(std::move(capsule));
440 }
441 case CapsuleType::DRAIN_WEBTRANSPORT_SESSION:
442 return Capsule(DrainWebTransportSessionCapsule());
443 case CapsuleType::ADDRESS_REQUEST: {
444 AddressRequestCapsule capsule;
445 while (!reader.IsDoneReading()) {
446 PrefixWithId requested_address;
447 if (!reader.ReadVarInt62(&requested_address.request_id)) {
448 return absl::InvalidArgumentError(
449 "Unable to parse capsule ADDRESS_REQUEST request ID");
450 }
451 uint8_t address_family;
452 if (!reader.ReadUInt8(&address_family)) {
453 return absl::InvalidArgumentError(
454 "Unable to parse capsule ADDRESS_REQUEST family");
455 }
456 if (address_family != 4 && address_family != 6) {
457 return absl::InvalidArgumentError("Bad ADDRESS_REQUEST family");
458 }
459 absl::string_view ip_address_bytes;
460 if (!reader.ReadStringPiece(&ip_address_bytes,
461 address_family == 4
462 ? QuicheIpAddress::kIPv4AddressSize
463 : QuicheIpAddress::kIPv6AddressSize)) {
464 return absl::InvalidArgumentError(
465 "Unable to read capsule ADDRESS_REQUEST address");
466 }
467 quiche::QuicheIpAddress ip_address;
468 if (!ip_address.FromPackedString(ip_address_bytes.data(),
469 ip_address_bytes.size())) {
470 return absl::InvalidArgumentError(
471 "Unable to parse capsule ADDRESS_REQUEST address");
472 }
473 uint8_t ip_prefix_length;
474 if (!reader.ReadUInt8(&ip_prefix_length)) {
475 return absl::InvalidArgumentError(
476 "Unable to parse capsule ADDRESS_REQUEST IP prefix length");
477 }
478 if (ip_prefix_length > QuicheIpPrefix(ip_address).prefix_length()) {
479 return absl::InvalidArgumentError("Invalid IP prefix length");
480 }
481 requested_address.ip_prefix =
482 QuicheIpPrefix(ip_address, ip_prefix_length);
483 capsule.requested_addresses.push_back(requested_address);
484 }
485 return Capsule(std::move(capsule));
486 }
487 case CapsuleType::ADDRESS_ASSIGN: {
488 AddressAssignCapsule capsule;
489 while (!reader.IsDoneReading()) {
490 PrefixWithId assigned_address;
491 if (!reader.ReadVarInt62(&assigned_address.request_id)) {
492 return absl::InvalidArgumentError(
493 "Unable to parse capsule ADDRESS_ASSIGN request ID");
494 }
495 uint8_t address_family;
496 if (!reader.ReadUInt8(&address_family)) {
497 return absl::InvalidArgumentError(
498 "Unable to parse capsule ADDRESS_ASSIGN family");
499 }
500 if (address_family != 4 && address_family != 6) {
501 return absl::InvalidArgumentError("Bad ADDRESS_ASSIGN family");
502 }
503 absl::string_view ip_address_bytes;
504 if (!reader.ReadStringPiece(&ip_address_bytes,
505 address_family == 4
506 ? QuicheIpAddress::kIPv4AddressSize
507 : QuicheIpAddress::kIPv6AddressSize)) {
508 return absl::InvalidArgumentError(
509 "Unable to read capsule ADDRESS_ASSIGN address");
510 }
511 quiche::QuicheIpAddress ip_address;
512 if (!ip_address.FromPackedString(ip_address_bytes.data(),
513 ip_address_bytes.size())) {
514 return absl::InvalidArgumentError(
515 "Unable to parse capsule ADDRESS_ASSIGN address");
516 }
517 uint8_t ip_prefix_length;
518 if (!reader.ReadUInt8(&ip_prefix_length)) {
519 return absl::InvalidArgumentError(
520 "Unable to parse capsule ADDRESS_ASSIGN IP prefix length");
521 }
522 if (ip_prefix_length > QuicheIpPrefix(ip_address).prefix_length()) {
523 return absl::InvalidArgumentError("Invalid IP prefix length");
524 }
525 assigned_address.ip_prefix =
526 QuicheIpPrefix(ip_address, ip_prefix_length);
527 capsule.assigned_addresses.push_back(assigned_address);
528 }
529 return Capsule(std::move(capsule));
530 }
531 case CapsuleType::ROUTE_ADVERTISEMENT: {
532 RouteAdvertisementCapsule capsule;
533 while (!reader.IsDoneReading()) {
534 uint8_t address_family;
535 if (!reader.ReadUInt8(&address_family)) {
536 return absl::InvalidArgumentError(
537 "Unable to parse capsule ROUTE_ADVERTISEMENT family");
538 }
539 if (address_family != 4 && address_family != 6) {
540 return absl::InvalidArgumentError("Bad ROUTE_ADVERTISEMENT family");
541 }
542 IpAddressRange ip_address_range;
543 absl::string_view start_ip_address_bytes;
544 if (!reader.ReadStringPiece(&start_ip_address_bytes,
545 address_family == 4
546 ? QuicheIpAddress::kIPv4AddressSize
547 : QuicheIpAddress::kIPv6AddressSize)) {
548 return absl::InvalidArgumentError(
549 "Unable to read capsule ROUTE_ADVERTISEMENT start address");
550 }
551 if (!ip_address_range.start_ip_address.FromPackedString(
552 start_ip_address_bytes.data(), start_ip_address_bytes.size())) {
553 return absl::InvalidArgumentError(
554 "Unable to parse capsule ROUTE_ADVERTISEMENT start address");
555 }
556 absl::string_view end_ip_address_bytes;
557 if (!reader.ReadStringPiece(&end_ip_address_bytes,
558 address_family == 4
559 ? QuicheIpAddress::kIPv4AddressSize
560 : QuicheIpAddress::kIPv6AddressSize)) {
561 return absl::InvalidArgumentError(
562 "Unable to read capsule ROUTE_ADVERTISEMENT end address");
563 }
564 if (!ip_address_range.end_ip_address.FromPackedString(
565 end_ip_address_bytes.data(), end_ip_address_bytes.size())) {
566 return absl::InvalidArgumentError(
567 "Unable to parse capsule ROUTE_ADVERTISEMENT end address");
568 }
569 if (!reader.ReadUInt8(&ip_address_range.ip_protocol)) {
570 return absl::InvalidArgumentError(
571 "Unable to parse capsule ROUTE_ADVERTISEMENT IP protocol");
572 }
573 capsule.ip_address_ranges.push_back(ip_address_range);
574 }
575 return Capsule(std::move(capsule));
576 }
577 case CapsuleType::WT_STREAM:
578 case CapsuleType::WT_STREAM_WITH_FIN: {
579 WebTransportStreamDataCapsule capsule;
580 capsule.fin = (type == CapsuleType::WT_STREAM_WITH_FIN);
581 QUICHE_RETURN_IF_ERROR(
582 ReadWebTransportStreamId(reader, capsule.stream_id));
583 capsule.data = reader.ReadRemainingPayload();
584 return Capsule(std::move(capsule));
585 }
586 case CapsuleType::WT_RESET_STREAM: {
587 WebTransportResetStreamCapsule capsule;
588 QUICHE_RETURN_IF_ERROR(
589 ReadWebTransportStreamId(reader, capsule.stream_id));
590 if (!reader.ReadVarInt62(&capsule.error_code)) {
591 return absl::InvalidArgumentError(
592 "Failed to parse the RESET_STREAM error code");
593 }
594 return Capsule(std::move(capsule));
595 }
596 case CapsuleType::WT_STOP_SENDING: {
597 WebTransportStopSendingCapsule capsule;
598 QUICHE_RETURN_IF_ERROR(
599 ReadWebTransportStreamId(reader, capsule.stream_id));
600 if (!reader.ReadVarInt62(&capsule.error_code)) {
601 return absl::InvalidArgumentError(
602 "Failed to parse the STOP_SENDING error code");
603 }
604 return Capsule(std::move(capsule));
605 }
606 case CapsuleType::WT_MAX_STREAM_DATA: {
607 WebTransportMaxStreamDataCapsule capsule;
608 QUICHE_RETURN_IF_ERROR(
609 ReadWebTransportStreamId(reader, capsule.stream_id));
610 if (!reader.ReadVarInt62(&capsule.max_stream_data)) {
611 return absl::InvalidArgumentError(
612 "Failed to parse the max stream data field");
613 }
614 return Capsule(std::move(capsule));
615 }
616 case CapsuleType::WT_MAX_STREAMS_UNIDI:
617 case CapsuleType::WT_MAX_STREAMS_BIDI: {
618 WebTransportMaxStreamsCapsule capsule;
619 capsule.stream_type = type == CapsuleType::WT_MAX_STREAMS_UNIDI
620 ? webtransport::StreamType::kUnidirectional
621 : webtransport::StreamType::kBidirectional;
622 if (!reader.ReadVarInt62(&capsule.max_stream_count)) {
623 return absl::InvalidArgumentError(
624 "Failed to parse the max streams field");
625 }
626 return Capsule(std::move(capsule));
627 }
628 default:
629 return Capsule(UnknownCapsule{static_cast<uint64_t>(type),
630 reader.ReadRemainingPayload()});
631 }
632 }
633 } // namespace
634
AttemptParseCapsule()635 absl::StatusOr<size_t> CapsuleParser::AttemptParseCapsule() {
636 QUICHE_DCHECK(!parsing_error_occurred_);
637 if (buffered_data_.empty()) {
638 return 0;
639 }
640 QuicheDataReader capsule_fragment_reader(buffered_data_);
641 uint64_t capsule_type64;
642 if (!capsule_fragment_reader.ReadVarInt62(&capsule_type64)) {
643 QUICHE_DVLOG(2) << "Partial read: not enough data to read capsule type";
644 return 0;
645 }
646 absl::string_view capsule_data;
647 if (!capsule_fragment_reader.ReadStringPieceVarInt62(&capsule_data)) {
648 QUICHE_DVLOG(2)
649 << "Partial read: not enough data to read capsule length or "
650 "full capsule data";
651 return 0;
652 }
653 QuicheDataReader capsule_data_reader(capsule_data);
654 absl::StatusOr<Capsule> capsule = ParseCapsulePayload(
655 capsule_data_reader, static_cast<CapsuleType>(capsule_type64));
656 QUICHE_RETURN_IF_ERROR(capsule.status());
657 if (!visitor_->OnCapsule(*capsule)) {
658 return absl::AbortedError("Visitor failed to process capsule");
659 }
660 return capsule_fragment_reader.PreviouslyReadPayload().length();
661 }
662
ReportParseFailure(absl::string_view error_message)663 void CapsuleParser::ReportParseFailure(absl::string_view error_message) {
664 if (parsing_error_occurred_) {
665 QUICHE_BUG(multiple parse errors) << "Experienced multiple parse failures";
666 return;
667 }
668 parsing_error_occurred_ = true;
669 visitor_->OnCapsuleParseFailure(error_message);
670 }
671
ErrorIfThereIsRemainingBufferedData()672 void CapsuleParser::ErrorIfThereIsRemainingBufferedData() {
673 if (parsing_error_occurred_) {
674 return;
675 }
676 if (!buffered_data_.empty()) {
677 ReportParseFailure("Incomplete capsule left at the end of the stream");
678 }
679 }
680
operator ==(const PrefixWithId & other) const681 bool PrefixWithId::operator==(const PrefixWithId& other) const {
682 return request_id == other.request_id && ip_prefix == other.ip_prefix;
683 }
684
operator ==(const IpAddressRange & other) const685 bool IpAddressRange::operator==(const IpAddressRange& other) const {
686 return start_ip_address == other.start_ip_address &&
687 end_ip_address == other.end_ip_address &&
688 ip_protocol == other.ip_protocol;
689 }
690
operator ==(const AddressAssignCapsule & other) const691 bool AddressAssignCapsule::operator==(const AddressAssignCapsule& other) const {
692 return assigned_addresses == other.assigned_addresses;
693 }
694
operator ==(const AddressRequestCapsule & other) const695 bool AddressRequestCapsule::operator==(
696 const AddressRequestCapsule& other) const {
697 return requested_addresses == other.requested_addresses;
698 }
699
operator ==(const RouteAdvertisementCapsule & other) const700 bool RouteAdvertisementCapsule::operator==(
701 const RouteAdvertisementCapsule& other) const {
702 return ip_address_ranges == other.ip_address_ranges;
703 }
704
operator ==(const WebTransportStreamDataCapsule & other) const705 bool WebTransportStreamDataCapsule::operator==(
706 const WebTransportStreamDataCapsule& other) const {
707 return stream_id == other.stream_id && data == other.data && fin == other.fin;
708 }
709
operator ==(const WebTransportResetStreamCapsule & other) const710 bool WebTransportResetStreamCapsule::operator==(
711 const WebTransportResetStreamCapsule& other) const {
712 return stream_id == other.stream_id && error_code == other.error_code;
713 }
714
operator ==(const WebTransportStopSendingCapsule & other) const715 bool WebTransportStopSendingCapsule::operator==(
716 const WebTransportStopSendingCapsule& other) const {
717 return stream_id == other.stream_id && error_code == other.error_code;
718 }
719
operator ==(const WebTransportMaxStreamDataCapsule & other) const720 bool WebTransportMaxStreamDataCapsule::operator==(
721 const WebTransportMaxStreamDataCapsule& other) const {
722 return stream_id == other.stream_id &&
723 max_stream_data == other.max_stream_data;
724 }
725
operator ==(const WebTransportMaxStreamsCapsule & other) const726 bool WebTransportMaxStreamsCapsule::operator==(
727 const WebTransportMaxStreamsCapsule& other) const {
728 return stream_type == other.stream_type &&
729 max_stream_count == other.max_stream_count;
730 }
731
732 } // namespace quiche
733