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