1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * This source code is licensed under the MIT license found in the 5 * LICENSE file in the root directory of this source tree. 6 * 7 */ 8 9 #pragma once 10 11 #include <folly/Conv.h> 12 #include <folly/IPAddress.h> 13 #include <folly/Optional.h> 14 #include <folly/io/Cursor.h> 15 #include <quic/QuicConstants.h> 16 #include <quic/QuicException.h> 17 #include <quic/codec/QuicConnectionId.h> 18 #include <quic/codec/QuicInteger.h> 19 #include <quic/common/BufUtil.h> 20 #include <quic/common/IntervalSet.h> 21 #include <quic/common/SmallVec.h> 22 #include <quic/common/Variant.h> 23 24 /** 25 * This details the types of objects that can be serialized or deserialized 26 * over the wire. 27 */ 28 29 namespace quic { 30 31 using StreamId = uint64_t; 32 using PacketNum = uint64_t; 33 34 enum class PacketNumberSpace : uint8_t { 35 Initial, 36 Handshake, 37 AppData, 38 // MAX has to be updated whenever other enumerators are added to this enum 39 MAX = PacketNumberSpace::AppData 40 }; 41 42 constexpr uint8_t kHeaderFormMask = 0x80; 43 constexpr auto kMaxPacketNumEncodingSize = 4; 44 constexpr auto kNumInitialAckBlocksPerFrame = 32; 45 46 template <class T> 47 using IntervalSetVec = SmallVec<T, kNumInitialAckBlocksPerFrame, uint16_t>; 48 using AckBlocks = IntervalSet<PacketNum, 1, IntervalSetVec>; 49 50 struct PaddingFrame { 51 bool operator==(const PaddingFrame& /*rhs*/) const { 52 return true; 53 } 54 }; 55 56 struct PingFrame { 57 PingFrame() = default; 58 59 bool operator==(const PingFrame& /*rhs*/) const { 60 return true; 61 } 62 }; 63 64 struct KnobFrame { KnobFrameKnobFrame65 KnobFrame(uint64_t knobSpaceIn, uint64_t idIn, Buf blobIn) 66 : knobSpace(knobSpaceIn), id(idIn), blob(std::move(blobIn)) { 67 len = blob->length(); 68 } 69 70 bool operator==(const KnobFrame& rhs) const { 71 return knobSpace == rhs.knobSpace && id == rhs.id && len == rhs.len && 72 blob->length() == rhs.blob->length() && 73 memcmp(blob->data(), rhs.blob->data(), blob->length()) == 0; 74 } 75 76 KnobFrame& operator=(const KnobFrame& other) { 77 knobSpace = other.knobSpace; 78 id = other.id; 79 if (other.blob) { 80 blob = other.blob->clone(); 81 } 82 return *this; 83 } 84 85 KnobFrame& operator=(KnobFrame&& other) noexcept { 86 knobSpace = other.knobSpace; 87 id = other.id; 88 if (other.blob) { 89 blob = std::move(other.blob); 90 } 91 return *this; 92 } 93 KnobFrameKnobFrame94 KnobFrame(const KnobFrame& other) 95 : knobSpace(other.knobSpace), 96 id(other.id), 97 len(other.len), 98 blob(other.blob->clone()) {} 99 KnobFrameKnobFrame100 KnobFrame(KnobFrame&& other) noexcept 101 : knobSpace(other.knobSpace), 102 id(other.id), 103 len(other.len), 104 blob(std::move(other.blob)) {} 105 106 uint64_t knobSpace; 107 uint64_t id; 108 uint64_t len; 109 Buf blob; 110 }; 111 112 struct AckFrequencyFrame { 113 uint64_t sequenceNumber; // Used to identify newest. 114 uint64_t packetTolerance; // How many packets before ACKing. 115 uint64_t updateMaxAckDelay; // New max_ack_delay to use. 116 uint8_t ignoreOrder; // Whether to ignore reordering ACKs. 117 118 bool operator==(const AckFrequencyFrame& other) const { 119 return other.sequenceNumber == sequenceNumber && 120 other.packetTolerance == packetTolerance && 121 other.updateMaxAckDelay == updateMaxAckDelay && 122 other.ignoreOrder == ignoreOrder; 123 } 124 }; 125 126 /** 127 * AckBlock represents a series of continuous packet sequences from 128 * [startPacket, endPacket] 129 */ 130 struct AckBlock { 131 PacketNum startPacket; 132 PacketNum endPacket; 133 AckBlockAckBlock134 AckBlock(PacketNum start, PacketNum end) 135 : startPacket(start), endPacket(end) {} 136 }; 137 138 /** 139 0 1 2 3 140 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 141 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 142 | Largest Acknowledged (i) ... 143 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 144 | ACK Delay (i) ... 145 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 146 | ACK Block Count (i) ... 147 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 148 | ACK Blocks (*) ... 149 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 150 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 151 | First ACK Block (i) ... 152 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 153 | Gap (i) ... 154 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 155 | Additional ACK Block (i) ... 156 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 157 */ 158 struct ReadAckFrame { 159 PacketNum largestAcked; 160 std::chrono::microseconds ackDelay{0us}; 161 // Only true for the special case of packet number space dropping. 162 bool implicit{false}; 163 // Should have at least 1 block. 164 // These are ordered in descending order by start packet. 165 using Vec = SmallVec<AckBlock, kNumInitialAckBlocksPerFrame, uint16_t>; 166 Vec ackBlocks; 167 168 bool operator==(const ReadAckFrame& /*rhs*/) const { 169 // Can't compare ackBlocks, function is just here to appease compiler. 170 return false; 171 } 172 }; 173 174 struct WriteAckFrame { 175 // Since we don't need this to be an IntervalSet, they are stored directly 176 // in a vector, in reverse order. 177 // TODO should this be a small_vector? 178 using AckBlockVec = std::vector<Interval<PacketNum>>; 179 AckBlockVec ackBlocks; 180 // Delay in sending ack from time that packet was received. 181 std::chrono::microseconds ackDelay{0us}; 182 183 bool operator==(const WriteAckFrame& /*rhs*/) const { 184 // Can't compare ackBlocks, function is just here to appease compiler. 185 return false; 186 } 187 }; 188 189 struct RstStreamFrame { 190 StreamId streamId; 191 ApplicationErrorCode errorCode; 192 uint64_t offset; 193 RstStreamFrameRstStreamFrame194 RstStreamFrame( 195 StreamId streamIdIn, 196 ApplicationErrorCode errorCodeIn, 197 uint64_t offsetIn) 198 : streamId(streamIdIn), errorCode(errorCodeIn), offset(offsetIn) {} 199 200 bool operator==(const RstStreamFrame& rhs) const { 201 return streamId == rhs.streamId && errorCode == rhs.errorCode && 202 offset == rhs.offset; 203 } 204 }; 205 206 struct StopSendingFrame { 207 StreamId streamId; 208 ApplicationErrorCode errorCode; 209 StopSendingFrameStopSendingFrame210 StopSendingFrame(StreamId streamIdIn, ApplicationErrorCode errorCodeIn) 211 : streamId(streamIdIn), errorCode(errorCodeIn) {} 212 213 bool operator==(const StopSendingFrame& rhs) const { 214 return streamId == rhs.streamId && errorCode == rhs.errorCode; 215 } 216 }; 217 218 struct ReadCryptoFrame { 219 uint64_t offset; 220 Buf data; 221 ReadCryptoFrameReadCryptoFrame222 ReadCryptoFrame(uint64_t offsetIn, Buf dataIn) 223 : offset(offsetIn), data(std::move(dataIn)) {} 224 ReadCryptoFrameReadCryptoFrame225 explicit ReadCryptoFrame(uint64_t offsetIn) 226 : offset(offsetIn), data(folly::IOBuf::create(0)) {} 227 228 // Stuff stored in a variant type needs to be copyable. ReadCryptoFrameReadCryptoFrame229 ReadCryptoFrame(const ReadCryptoFrame& other) { 230 offset = other.offset; 231 if (other.data) { 232 data = other.data->clone(); 233 } 234 } 235 ReadCryptoFrameReadCryptoFrame236 ReadCryptoFrame(ReadCryptoFrame&& other) noexcept { 237 offset = other.offset; 238 data = std::move(other.data); 239 } 240 241 ReadCryptoFrame& operator=(const ReadCryptoFrame& other) { 242 offset = other.offset; 243 if (other.data) { 244 data = other.data->clone(); 245 } 246 return *this; 247 } 248 249 ReadCryptoFrame& operator=(ReadCryptoFrame&& other) { 250 offset = other.offset; 251 data = std::move(other.data); 252 return *this; 253 } 254 255 bool operator==(const ReadCryptoFrame& other) const { 256 folly::IOBufEqualTo eq; 257 return offset == other.offset && eq(data, other.data); 258 } 259 }; 260 261 struct WriteCryptoFrame { 262 uint64_t offset; 263 uint64_t len; 264 WriteCryptoFrameWriteCryptoFrame265 WriteCryptoFrame(uint64_t offsetIn, uint64_t lenIn) 266 : offset(offsetIn), len(lenIn) {} 267 268 bool operator==(const WriteCryptoFrame& rhs) const { 269 return offset == rhs.offset && len == rhs.len; 270 } 271 }; 272 273 struct ReadNewTokenFrame { 274 Buf token; 275 ReadNewTokenFrameReadNewTokenFrame276 ReadNewTokenFrame(Buf tokenIn) : token(std::move(tokenIn)) {} 277 278 // Stuff stored in a variant type needs to be copyable. ReadNewTokenFrameReadNewTokenFrame279 ReadNewTokenFrame(const ReadNewTokenFrame& other) { 280 if (other.token) { 281 token = other.token->clone(); 282 } 283 } 284 285 ReadNewTokenFrame& operator=(const ReadNewTokenFrame& other) { 286 if (other.token) { 287 token = other.token->clone(); 288 } 289 return *this; 290 } 291 292 bool operator==(const ReadNewTokenFrame& other) const { 293 folly::IOBufEqualTo eq; 294 return eq(token, other.token); 295 } 296 }; 297 298 /** 299 The structure of the stream frame used for writes. 300 0 1 2 3 301 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 302 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 303 | Stream ID (i) ... 304 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 305 | [Offset (i)] ... 306 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 307 | [Length (i)] ... 308 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 309 | Stream Data (*) ... 310 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 311 */ 312 struct WriteStreamFrame { 313 StreamId streamId; 314 uint64_t offset; 315 uint64_t len; 316 bool fin; 317 318 // Whether this WriteStreamFrame is created from a BufMeta, instead of real 319 // write buffer data. 320 bool fromBufMeta{false}; 321 322 WriteStreamFrame( 323 StreamId streamIdIn, 324 uint64_t offsetIn, 325 uint64_t lenIn, 326 bool finIn, 327 bool fromBufMetaIn = false) streamIdWriteStreamFrame328 : streamId(streamIdIn), 329 offset(offsetIn), 330 len(lenIn), 331 fin(finIn), 332 fromBufMeta(fromBufMetaIn) {} 333 334 bool operator==(const WriteStreamFrame& rhs) const { 335 return streamId == rhs.streamId && offset == rhs.offset && len == rhs.len && 336 fin == rhs.fin && fromBufMeta == rhs.fromBufMeta; 337 } 338 }; 339 340 /** 341 * The structure of the stream frame used for reads. 342 */ 343 struct ReadStreamFrame { 344 StreamId streamId; 345 uint64_t offset; 346 Buf data; 347 bool fin; 348 ReadStreamFrameReadStreamFrame349 ReadStreamFrame( 350 StreamId streamIdIn, 351 uint64_t offsetIn, 352 Buf dataIn, 353 bool finIn) 354 : streamId(streamIdIn), 355 offset(offsetIn), 356 data(std::move(dataIn)), 357 fin(finIn) {} 358 ReadStreamFrameReadStreamFrame359 ReadStreamFrame(StreamId streamIdIn, uint64_t offsetIn, bool finIn) 360 : streamId(streamIdIn), 361 offset(offsetIn), 362 data(folly::IOBuf::create(0)), 363 fin(finIn) {} 364 365 // Stuff stored in a variant type needs to be copyable. ReadStreamFrameReadStreamFrame366 ReadStreamFrame(const ReadStreamFrame& other) { 367 streamId = other.streamId; 368 offset = other.offset; 369 if (other.data) { 370 data = other.data->clone(); 371 } 372 fin = other.fin; 373 } 374 ReadStreamFrameReadStreamFrame375 ReadStreamFrame(ReadStreamFrame&& other) noexcept { 376 streamId = other.streamId; 377 offset = other.offset; 378 data = std::move(other.data); 379 fin = other.fin; 380 } 381 382 ReadStreamFrame& operator=(const ReadStreamFrame& other) { 383 streamId = other.streamId; 384 offset = other.offset; 385 if (other.data) { 386 data = other.data->clone(); 387 } 388 fin = other.fin; 389 return *this; 390 } 391 392 ReadStreamFrame& operator=(ReadStreamFrame&& other) { 393 streamId = other.streamId; 394 offset = other.offset; 395 data = std::move(other.data); 396 fin = other.fin; 397 return *this; 398 } 399 400 bool operator==(const ReadStreamFrame& other) const { 401 folly::IOBufEqualTo eq; 402 return streamId == other.streamId && offset == other.offset && 403 fin == other.fin && eq(data, other.data); 404 } 405 }; 406 407 struct MaxDataFrame { 408 uint64_t maximumData; 409 MaxDataFrameMaxDataFrame410 explicit MaxDataFrame(uint64_t maximumDataIn) : maximumData(maximumDataIn) {} 411 412 bool operator==(const MaxDataFrame& rhs) const { 413 return maximumData == rhs.maximumData; 414 } 415 }; 416 417 struct MaxStreamDataFrame { 418 StreamId streamId; 419 uint64_t maximumData; 420 MaxStreamDataFrameMaxStreamDataFrame421 MaxStreamDataFrame(StreamId streamIdIn, uint64_t maximumDataIn) 422 : streamId(streamIdIn), maximumData(maximumDataIn) {} 423 424 bool operator==(const MaxStreamDataFrame& rhs) const { 425 return streamId == rhs.streamId && maximumData == rhs.maximumData; 426 } 427 }; 428 429 struct MaxStreamsFrame { 430 // A count of the cumulative number of streams 431 uint64_t maxStreams; 432 bool isForBidirectional{false}; 433 MaxStreamsFrameMaxStreamsFrame434 explicit MaxStreamsFrame(uint64_t maxStreamsIn, bool isBidirectionalIn) 435 : maxStreams(maxStreamsIn), isForBidirectional(isBidirectionalIn) {} 436 isForBidirectionalStreamMaxStreamsFrame437 bool isForBidirectionalStream() const { 438 return isForBidirectional; 439 } 440 isForUnidirectionalStreamMaxStreamsFrame441 bool isForUnidirectionalStream() { 442 return !isForBidirectional; 443 } 444 445 bool operator==(const MaxStreamsFrame& rhs) const { 446 return maxStreams == rhs.maxStreams && 447 isForBidirectional == rhs.isForBidirectional; 448 } 449 }; 450 451 struct DataBlockedFrame { 452 // the connection-level limit at which blocking occurred 453 uint64_t dataLimit; 454 DataBlockedFrameDataBlockedFrame455 explicit DataBlockedFrame(uint64_t dataLimitIn) : dataLimit(dataLimitIn) {} 456 457 bool operator==(const DataBlockedFrame& rhs) const { 458 return dataLimit == rhs.dataLimit; 459 } 460 }; 461 462 struct StreamDataBlockedFrame { 463 StreamId streamId; 464 uint64_t dataLimit; 465 StreamDataBlockedFrameStreamDataBlockedFrame466 StreamDataBlockedFrame(StreamId streamIdIn, uint64_t dataLimitIn) 467 : streamId(streamIdIn), dataLimit(dataLimitIn) {} 468 469 bool operator==(const StreamDataBlockedFrame& rhs) const { 470 return streamId == rhs.streamId && dataLimit == rhs.dataLimit; 471 } 472 }; 473 474 struct StreamsBlockedFrame { 475 uint64_t streamLimit; 476 bool isForBidirectional{false}; 477 StreamsBlockedFrameStreamsBlockedFrame478 explicit StreamsBlockedFrame(uint64_t streamLimitIn, bool isBidirectionalIn) 479 : streamLimit(streamLimitIn), isForBidirectional(isBidirectionalIn) {} 480 isForBidirectionalStreamStreamsBlockedFrame481 bool isForBidirectionalStream() const { 482 return isForBidirectional; 483 } 484 isForUnidirectionalStreamStreamsBlockedFrame485 bool isForUnidirectionalStream() const { 486 return !isForBidirectional; 487 } 488 489 bool operator==(const StreamsBlockedFrame& rhs) const { 490 return streamLimit == rhs.streamLimit; 491 } 492 }; 493 494 struct NewConnectionIdFrame { 495 uint64_t sequenceNumber; 496 uint64_t retirePriorTo; 497 ConnectionId connectionId; 498 StatelessResetToken token; 499 NewConnectionIdFrameNewConnectionIdFrame500 NewConnectionIdFrame( 501 uint64_t sequenceNumberIn, 502 uint64_t retirePriorToIn, 503 ConnectionId connectionIdIn, 504 StatelessResetToken tokenIn) 505 : sequenceNumber(sequenceNumberIn), 506 retirePriorTo(retirePriorToIn), 507 connectionId(connectionIdIn), 508 token(std::move(tokenIn)) {} 509 510 bool operator==(const NewConnectionIdFrame& rhs) const { 511 return sequenceNumber == rhs.sequenceNumber && 512 retirePriorTo == rhs.retirePriorTo && 513 connectionId == rhs.connectionId && token == rhs.token; 514 } 515 }; 516 517 struct RetireConnectionIdFrame { 518 uint64_t sequenceNumber; RetireConnectionIdFrameRetireConnectionIdFrame519 explicit RetireConnectionIdFrame(uint64_t sequenceNumberIn) 520 : sequenceNumber(sequenceNumberIn) {} 521 522 bool operator==(const RetireConnectionIdFrame& rhs) const { 523 return sequenceNumber == rhs.sequenceNumber; 524 } 525 }; 526 527 struct PathChallengeFrame { 528 uint64_t pathData; 529 PathChallengeFramePathChallengeFrame530 explicit PathChallengeFrame(uint64_t pathDataIn) : pathData(pathDataIn) {} 531 532 bool operator==(const PathChallengeFrame& rhs) const { 533 return pathData == rhs.pathData; 534 } 535 536 bool operator!=(const PathChallengeFrame& rhs) const { 537 return !(*this == rhs); 538 } 539 }; 540 541 struct PathResponseFrame { 542 uint64_t pathData; 543 PathResponseFramePathResponseFrame544 explicit PathResponseFrame(uint64_t pathDataIn) : pathData(pathDataIn) {} 545 546 bool operator==(const PathResponseFrame& rhs) const { 547 return pathData == rhs.pathData; 548 } 549 }; 550 551 struct ConnectionCloseFrame { 552 // Members are not const to allow this to be movable. 553 QuicErrorCode errorCode; 554 std::string reasonPhrase; 555 // Per QUIC specification: type of frame that triggered the (close) error. 556 // A value of 0 (PADDING frame) implies the frame type is unknown 557 FrameType closingFrameType; 558 559 ConnectionCloseFrame( 560 QuicErrorCode errorCodeIn, 561 std::string reasonPhraseIn, 562 FrameType closingFrameTypeIn = FrameType::PADDING) errorCodeConnectionCloseFrame563 : errorCode(std::move(errorCodeIn)), 564 reasonPhrase(std::move(reasonPhraseIn)), 565 closingFrameType(closingFrameTypeIn) {} 566 getClosingFrameTypeConnectionCloseFrame567 FrameType getClosingFrameType() const noexcept { 568 return closingFrameType; 569 } 570 571 bool operator==(const ConnectionCloseFrame& rhs) const { 572 return errorCode == rhs.errorCode && reasonPhrase == rhs.reasonPhrase; 573 } 574 }; 575 576 struct HandshakeDoneFrame { 577 bool operator==(const HandshakeDoneFrame& /*rhs*/) const { 578 return true; 579 } 580 }; 581 582 struct DatagramFrame { 583 size_t length; 584 BufQueue data; 585 DatagramFrameDatagramFrame586 explicit DatagramFrame(size_t len, Buf buf) 587 : length(len), data(std::move(buf)) { 588 CHECK_EQ(length, data.chainLength()); 589 } 590 591 // Variant requirement: DatagramFrameDatagramFrame592 DatagramFrame(const DatagramFrame& other) 593 : length(other.length), 594 data(other.data.front() ? other.data.front()->clone() : nullptr) { 595 CHECK_EQ(length, data.chainLength()); 596 } 597 598 bool operator==(const DatagramFrame& other) const { 599 if (length != other.length) { 600 return false; 601 } 602 if (data.empty() && other.data.empty()) { 603 return true; 604 } 605 CHECK(data.front() && other.data.front()); 606 folly::IOBufEqualTo eq; 607 return eq(*data.front(), *other.data.front()); 608 } 609 }; 610 611 // Frame to represent ones we skip 612 struct NoopFrame { 613 bool operator==(const NoopFrame&) const { 614 return true; 615 } 616 }; 617 618 struct StatelessReset { 619 StatelessResetToken token; 620 StatelessResetStatelessReset621 explicit StatelessReset(StatelessResetToken tokenIn) 622 : token(std::move(tokenIn)) {} 623 }; 624 625 struct RetryToken { RetryTokenRetryToken626 RetryToken( 627 ConnectionId originalDstConnIdIn, 628 folly::IPAddress clientIpIn, 629 uint16_t clientPortIn, 630 uint64_t timestampInMsIn) 631 : originalDstConnId(originalDstConnIdIn), 632 clientIp(clientIpIn), 633 clientPort(clientPortIn), 634 timestampInMs(timestampInMsIn) {} 635 636 // We serialize the members to obtain a plaintext token. 637 // This token is encrypted before it's placed in the outgoing 638 // Retry packet. 639 Buf getPlaintextToken(); 640 641 ConnectionId originalDstConnId; 642 folly::IPAddress clientIp; 643 uint16_t clientPort; 644 uint64_t timestampInMs; 645 }; 646 647 #define QUIC_SIMPLE_FRAME(F, ...) \ 648 F(StopSendingFrame, __VA_ARGS__) \ 649 F(PathChallengeFrame, __VA_ARGS__) \ 650 F(PathResponseFrame, __VA_ARGS__) \ 651 F(NewConnectionIdFrame, __VA_ARGS__) \ 652 F(MaxStreamsFrame, __VA_ARGS__) \ 653 F(RetireConnectionIdFrame, __VA_ARGS__) \ 654 F(HandshakeDoneFrame, __VA_ARGS__) \ 655 F(KnobFrame, __VA_ARGS__) \ 656 F(AckFrequencyFrame, __VA_ARGS__) 657 658 DECLARE_VARIANT_TYPE(QuicSimpleFrame, QUIC_SIMPLE_FRAME) 659 660 #define QUIC_FRAME(F, ...) \ 661 F(PaddingFrame, __VA_ARGS__) \ 662 F(RstStreamFrame, __VA_ARGS__) \ 663 F(ConnectionCloseFrame, __VA_ARGS__) \ 664 F(MaxDataFrame, __VA_ARGS__) \ 665 F(MaxStreamDataFrame, __VA_ARGS__) \ 666 F(DataBlockedFrame, __VA_ARGS__) \ 667 F(StreamDataBlockedFrame, __VA_ARGS__) \ 668 F(StreamsBlockedFrame, __VA_ARGS__) \ 669 F(ReadAckFrame, __VA_ARGS__) \ 670 F(ReadStreamFrame, __VA_ARGS__) \ 671 F(ReadCryptoFrame, __VA_ARGS__) \ 672 F(ReadNewTokenFrame, __VA_ARGS__) \ 673 F(QuicSimpleFrame, __VA_ARGS__) \ 674 F(PingFrame, __VA_ARGS__) \ 675 F(NoopFrame, __VA_ARGS__) \ 676 F(DatagramFrame, __VA_ARGS__) 677 678 DECLARE_VARIANT_TYPE(QuicFrame, QUIC_FRAME) 679 680 #define QUIC_WRITE_FRAME(F, ...) \ 681 F(PaddingFrame, __VA_ARGS__) \ 682 F(RstStreamFrame, __VA_ARGS__) \ 683 F(ConnectionCloseFrame, __VA_ARGS__) \ 684 F(MaxDataFrame, __VA_ARGS__) \ 685 F(MaxStreamDataFrame, __VA_ARGS__) \ 686 F(DataBlockedFrame, __VA_ARGS__) \ 687 F(StreamDataBlockedFrame, __VA_ARGS__) \ 688 F(StreamsBlockedFrame, __VA_ARGS__) \ 689 F(WriteAckFrame, __VA_ARGS__) \ 690 F(WriteStreamFrame, __VA_ARGS__) \ 691 F(WriteCryptoFrame, __VA_ARGS__) \ 692 F(QuicSimpleFrame, __VA_ARGS__) \ 693 F(PingFrame, __VA_ARGS__) \ 694 F(NoopFrame, __VA_ARGS__) \ 695 F(DatagramFrame, __VA_ARGS__) 696 697 // Types of frames which are written. 698 DECLARE_VARIANT_TYPE(QuicWriteFrame, QUIC_WRITE_FRAME) 699 700 enum class HeaderForm : bool { 701 Long = 1, 702 Short = 0, 703 }; 704 705 enum class ProtectionType { 706 Initial, 707 Handshake, 708 ZeroRtt, 709 KeyPhaseZero, 710 KeyPhaseOne, 711 }; 712 713 struct LongHeaderInvariant { 714 QuicVersion version; 715 ConnectionId srcConnId; 716 ConnectionId dstConnId; 717 718 LongHeaderInvariant(QuicVersion ver, ConnectionId scid, ConnectionId dcid); 719 }; 720 721 struct LongHeader { 722 public: 723 virtual ~LongHeader() = default; 724 725 static constexpr uint8_t kFixedBitMask = 0x40; 726 static constexpr uint8_t kPacketTypeMask = 0x30; 727 static constexpr uint8_t kReservedBitsMask = 0x0c; 728 static constexpr uint8_t kPacketNumLenMask = 0x03; 729 static constexpr uint8_t kTypeBitsMask = 0x0F; 730 731 static constexpr uint8_t kTypeShift = 4; 732 enum class Types : uint8_t { 733 Initial = 0x0, 734 ZeroRtt = 0x1, 735 Handshake = 0x2, 736 Retry = 0x3, 737 }; 738 739 // Note this is defined in the header so it is inlined for performance. typeToPacketNumberSpaceLongHeader740 static PacketNumberSpace typeToPacketNumberSpace(Types longHeaderType) { 741 switch (longHeaderType) { 742 case LongHeader::Types::Initial: 743 case LongHeader::Types::Retry: 744 return PacketNumberSpace::Initial; 745 case LongHeader::Types::Handshake: 746 return PacketNumberSpace::Handshake; 747 case LongHeader::Types::ZeroRtt: 748 return PacketNumberSpace::AppData; 749 } 750 folly::assume_unreachable(); 751 } 752 753 LongHeader( 754 Types type, 755 const ConnectionId& srcConnId, 756 const ConnectionId& dstConnId, 757 PacketNum packetNum, 758 QuicVersion version, 759 std::string token = std::string()); 760 761 LongHeader( 762 Types type, 763 LongHeaderInvariant invariant, 764 std::string token = std::string()); 765 766 LongHeader(const LongHeader& other) = default; 767 LongHeader(LongHeader&& other) = default; 768 LongHeader& operator=(const LongHeader& other) = default; 769 LongHeader& operator=(LongHeader&& other) = default; 770 771 Types getHeaderType() const noexcept; 772 const ConnectionId& getSourceConnId() const; 773 const ConnectionId& getDestinationConnId() const; 774 QuicVersion getVersion() const; 775 // Note this is defined in the header so it is inlined for performance. getPacketNumberSpaceLongHeader776 PacketNumberSpace getPacketNumberSpace() const { 777 return typeToPacketNumberSpace(longHeaderType_); 778 } 779 ProtectionType getProtectionType() const; 780 bool hasToken() const; 781 const std::string& getToken() const; 782 // Note this is defined in the header so it is inlined for performance. getPacketSequenceNumLongHeader783 PacketNum getPacketSequenceNum() const { 784 return packetSequenceNum_; 785 } 786 787 void setPacketNumber(PacketNum packetNum); 788 789 private: 790 PacketNum packetSequenceNum_{0}; 791 Types longHeaderType_; 792 LongHeaderInvariant invariant_; 793 std::string token_; 794 }; 795 796 struct ShortHeaderInvariant { 797 ConnectionId destinationConnId; 798 799 explicit ShortHeaderInvariant(ConnectionId dcid); 800 }; 801 802 struct ShortHeader { 803 public: 804 virtual ~ShortHeader() = default; 805 806 // There is also a spin bit which is 0x20 that we don't currently implement. 807 static constexpr uint8_t kFixedBitMask = 0x40; 808 static constexpr uint8_t kReservedBitsMask = 0x18; 809 static constexpr uint8_t kKeyPhaseMask = 0x04; 810 static constexpr uint8_t kPacketNumLenMask = 0x03; 811 static constexpr uint8_t kTypeBitsMask = 0x1F; 812 813 /** 814 * The constructor for reading a packet. 815 */ 816 ShortHeader(ProtectionType protectionType, ConnectionId connId); 817 818 /** 819 * The constructor for writing a packet. 820 */ 821 ShortHeader( 822 ProtectionType protectionType, 823 ConnectionId connId, 824 PacketNum packetNum); 825 826 ProtectionType getProtectionType() const; getPacketNumberSpaceShortHeader827 PacketNumberSpace getPacketNumberSpace() const { 828 return PacketNumberSpace::AppData; 829 } getPacketSequenceNumShortHeader830 PacketNum getPacketSequenceNum() const { 831 return packetSequenceNum_; 832 } 833 const ConnectionId& getConnectionId() const; 834 835 void setPacketNumber(PacketNum packetNum); 836 837 private: 838 ShortHeader() = delete; 839 bool readInitialByte(uint8_t initalByte); 840 bool readConnectionId(folly::io::Cursor& cursor); 841 bool readPacketNum( 842 PacketNum largestReceivedPacketNum, 843 folly::io::Cursor& cursor); 844 845 private: 846 PacketNum packetSequenceNum_{0}; 847 ProtectionType protectionType_; 848 ConnectionId connectionId_; 849 }; 850 851 struct PacketHeader { 852 ~PacketHeader(); 853 854 /* implicit */ PacketHeader(LongHeader&& longHeader); 855 /* implicit */ PacketHeader(ShortHeader&& shortHeader); 856 857 PacketHeader(PacketHeader&& other) noexcept; 858 PacketHeader(const PacketHeader& other); 859 860 PacketHeader& operator=(PacketHeader&& other) noexcept; 861 PacketHeader& operator=(const PacketHeader& other); 862 863 LongHeader* asLong(); 864 ShortHeader* asShort(); 865 866 const LongHeader* asLong() const; 867 const ShortHeader* asShort() const; 868 869 // Note this is defined in the header so it is inlined for performance. getPacketSequenceNumPacketHeader870 PacketNum getPacketSequenceNum() const { 871 switch (headerForm_) { 872 case HeaderForm::Long: 873 return longHeader.getPacketSequenceNum(); 874 case HeaderForm::Short: 875 return shortHeader.getPacketSequenceNum(); 876 default: 877 folly::assume_unreachable(); 878 } 879 } 880 HeaderForm getHeaderForm() const; 881 ProtectionType getProtectionType() const; 882 // Note this is defined in the header so it is inlined for performance. getPacketNumberSpacePacketHeader883 PacketNumberSpace getPacketNumberSpace() const { 884 switch (headerForm_) { 885 case HeaderForm::Long: 886 return longHeader.getPacketNumberSpace(); 887 case HeaderForm::Short: 888 return shortHeader.getPacketNumberSpace(); 889 default: 890 folly::assume_unreachable(); 891 } 892 } 893 894 private: 895 void destroyHeader(); 896 897 union { 898 LongHeader longHeader; 899 ShortHeader shortHeader; 900 }; 901 902 HeaderForm headerForm_; 903 }; 904 905 ProtectionType longHeaderTypeToProtectionType(LongHeader::Types type); 906 PacketNumberSpace protectionTypeToPacketNumberSpace(ProtectionType type); 907 908 struct StreamTypeField { 909 public: StreamTypeFieldStreamTypeField910 explicit StreamTypeField(uint8_t field) : field_(field) {} 911 bool hasFin() const; 912 bool hasDataLength() const; 913 bool hasOffset() const; 914 uint8_t fieldValue() const; 915 916 struct Builder { 917 public: BuilderStreamTypeField::Builder918 Builder() : field_(static_cast<uint8_t>(FrameType::STREAM)) {} 919 Builder& setFin(); 920 Builder& setOffset(); 921 Builder& setLength(); 922 923 StreamTypeField build(); 924 925 private: 926 uint8_t field_; 927 }; 928 929 private: 930 // Stream Frame specific: 931 static constexpr uint8_t kFinBit = 0x01; 932 static constexpr uint8_t kDataLengthBit = 0x02; 933 static constexpr uint8_t kOffsetBit = 0x04; 934 935 uint8_t field_; 936 }; 937 938 struct VersionNegotiationPacket { 939 uint8_t packetType; 940 ConnectionId sourceConnectionId; 941 ConnectionId destinationConnectionId; 942 std::vector<QuicVersion> versions; 943 VersionNegotiationPacketVersionNegotiationPacket944 VersionNegotiationPacket( 945 uint8_t packetTypeIn, 946 ConnectionId sourceConnectionIdIn, 947 ConnectionId destinationConnectionIdIn) 948 : packetType(packetTypeIn), 949 sourceConnectionId(sourceConnectionIdIn), 950 destinationConnectionId(destinationConnectionIdIn) {} 951 }; 952 953 /** 954 * Common struct for regular read and write packets. 955 */ 956 struct RegularPacket { 957 PacketHeader header; 958 RegularPacketRegularPacket959 explicit RegularPacket(PacketHeader&& headerIn) 960 : header(std::move(headerIn)) {} 961 }; 962 963 struct RetryPacket { RetryPacketRetryPacket964 RetryPacket( 965 LongHeader&& longHeaderIn, 966 Buf integrityTagIn, 967 uint8_t initialByteIn) 968 : header(std::move(longHeaderIn)), 969 integrityTag(std::move(integrityTagIn)), 970 initialByte(initialByteIn) {} 971 972 LongHeader header; 973 Buf integrityTag; 974 uint8_t initialByte; 975 }; 976 977 /** 978 * A representation of a regular packet that is read from the network. 979 * This could be either Cleartext or Encrypted packets in long or short form. 980 * Cleartext packets include Client Initial, Client Cleartext, Non-Final Server 981 * Cleartext packet or Final Server Cleartext packet. Encrypted packets 982 * include 0-RTT, 1-RTT Phase 0 and 1-RTT Phase 1 packets. 983 */ 984 struct RegularQuicPacket : public RegularPacket { 985 using Vec = SmallVec<QuicFrame, 4, uint16_t>; 986 Vec frames; 987 RegularQuicPacketRegularQuicPacket988 explicit RegularQuicPacket(PacketHeader&& headerIn) 989 : RegularPacket(std::move(headerIn)) {} 990 }; 991 992 /** 993 * A representation of a regular packet that is written to the network. 994 */ 995 struct RegularQuicWritePacket : public RegularPacket { 996 using Vec = SmallVec<QuicWriteFrame, 4, uint16_t>; 997 Vec frames; 998 RegularQuicWritePacketRegularQuicWritePacket999 explicit RegularQuicWritePacket(PacketHeader&& headerIn) 1000 : RegularPacket(std::move(headerIn)) {} 1001 }; 1002 1003 /** 1004 * Returns whether the header is long or short from the initial byte of 1005 * the QUIC packet. 1006 * 1007 * This function is version invariant. 1008 */ 1009 HeaderForm getHeaderForm(uint8_t headerValue); 1010 1011 std::string toString(LongHeader::Types type); 1012 1013 std::string toString(QuicErrorCode code); 1014 1015 inline std::ostream& operator<<( 1016 std::ostream& os, 1017 const LongHeader::Types& type) { 1018 os << toString(type); 1019 return os; 1020 } 1021 1022 inline std::ostream& operator<<(std::ostream& os, const PacketHeader& header) { 1023 auto shortHeader = header.asShort(); 1024 if (shortHeader) { 1025 os << "header=short" 1026 << " protectionType=" << (int)shortHeader->getProtectionType(); 1027 } else { 1028 auto longHeader = header.asLong(); 1029 os << "header=long" 1030 << " protectionType=" << (int)longHeader->getProtectionType() 1031 << " type=" << std::hex << (int)longHeader->getHeaderType(); 1032 } 1033 return os; 1034 } 1035 1036 std::string toString(PacketNumberSpace pnSpace); 1037 1038 std::string toString(FrameType frame); 1039 1040 std::string toString(QuicVersion version); 1041 1042 inline std::ostream& operator<<(std::ostream& os, PacketNumberSpace pnSpace) { 1043 return os << toString(pnSpace); 1044 } 1045 1046 std::string toString(ProtectionType protectionType); 1047 1048 } // namespace quic 1049