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/io/Cursor.h>
12 #include <quic/codec/PacketNumber.h>
13 #include <quic/codec/Types.h>
14 
15 namespace quic {
16 
17 /**
18  * Connection level parameters needed by the codec to decode the packet
19  * successfully.
20  */
21 struct CodecParameters {
22   // This must not be set to zero.
23   uint8_t peerAckDelayExponent{kDefaultAckDelayExponent};
24   QuicVersion version{QuicVersion::MVFST};
25 
26   CodecParameters() = default;
27 
CodecParametersCodecParameters28   CodecParameters(uint8_t peerAckDelayExponentIn, QuicVersion versionIn)
29       : peerAckDelayExponent(peerAckDelayExponentIn), version(versionIn) {}
30 };
31 
32 struct ParsedLongHeaderInvariant {
33   uint8_t initialByte;
34   LongHeaderInvariant invariant;
35   size_t invariantLength;
36 
37   ParsedLongHeaderInvariant(
38       uint8_t initialByteIn,
39       LongHeaderInvariant headerInvariant,
40       size_t length);
41 };
42 
43 /**
44  * Decodes a version negotiation packet. Returns a folly::none, if it cannot
45  * decode the packet.
46  */
47 folly::Optional<VersionNegotiationPacket> decodeVersionNegotiation(
48     const ParsedLongHeaderInvariant& longHeaderInvariant,
49     folly::io::Cursor& cursor);
50 
51 /**
52  * Decodes a single regular QUIC packet from the cursor.
53  * PacketData represents data from 1 QUIC packet.
54  * Throws with a QuicException if the data in the cursor is not a complete QUIC
55  * packet or the packet could not be decoded correctly.
56  */
57 RegularQuicPacket decodeRegularPacket(
58     PacketHeader&& header,
59     const CodecParameters& params,
60     std::unique_ptr<folly::IOBuf> packetData);
61 
62 /**
63  * Parses a single frame from the queue. Throws a QuicException if the frame
64  * could not be parsed.
65  */
66 QuicFrame parseFrame(
67     BufQueue& queue,
68     const PacketHeader& header,
69     const CodecParameters& params);
70 
71 /**
72  * The following functions decode frames. They throw an QuicException when error
73  * occurs.
74  */
75 PaddingFrame decodePaddingFrame(folly::io::Cursor&);
76 
77 RstStreamFrame decodeRstStreamFrame(folly::io::Cursor& cursor);
78 
79 ConnectionCloseFrame decodeConnectionCloseFrame(folly::io::Cursor& cursor);
80 
81 ConnectionCloseFrame decodeApplicationClose(folly::io::Cursor& cursor);
82 
83 MaxDataFrame decodeMaxDataFrame(folly::io::Cursor& cursor);
84 
85 MaxStreamDataFrame decodeMaxStreamDataFrame(folly::io::Cursor& cursor);
86 
87 MaxStreamsFrame decodeBiDiMaxStreamsFrame(folly::io::Cursor& cursor);
88 
89 MaxStreamsFrame decodeUniMaxStreamsFrame(folly::io::Cursor& cursor);
90 
91 PingFrame decodePingFrame(folly::io::Cursor& cursor);
92 
93 KnobFrame decodeKnobFrame(folly::io::Cursor& cursor);
94 
95 AckFrequencyFrame decodeAckFrequencyFrame(folly::io::Cursor& cursor);
96 
97 DataBlockedFrame decodeDataBlockedFrame(folly::io::Cursor& cursor);
98 
99 StreamDataBlockedFrame decodeStreamDataBlockedFrame(folly::io::Cursor& cursor);
100 
101 StreamsBlockedFrame decodeBiDiStreamsBlockedFrame(folly::io::Cursor& cursor);
102 
103 StreamsBlockedFrame decodeUniStreamsBlockedFrame(folly::io::Cursor& cursor);
104 
105 NewConnectionIdFrame decodeNewConnectionIdFrame(folly::io::Cursor& cursor);
106 
107 RetireConnectionIdFrame decodeRetireConnectionIdFrame(
108     folly::io::Cursor& cursor);
109 
110 StopSendingFrame decodeStopSendingFrame(folly::io::Cursor& cursor);
111 
112 PathChallengeFrame decodePathChallengeFrame(folly::io::Cursor& cursor);
113 
114 PathResponseFrame decodePathResponseFrame(folly::io::Cursor& cursor);
115 
116 ReadAckFrame decodeAckFrame(
117     folly::io::Cursor& cursor,
118     const PacketHeader& header,
119     const CodecParameters& params);
120 
121 ReadAckFrame decodeAckFrameWithECN(
122     folly::io::Cursor& cursor,
123     const PacketHeader& header,
124     const CodecParameters& params);
125 
126 ReadStreamFrame decodeStreamFrame(
127     BufQueue& queue,
128     StreamTypeField frameTypeField);
129 
130 ReadCryptoFrame decodeCryptoFrame(folly::io::Cursor& cursor);
131 
132 ReadNewTokenFrame decodeNewTokenFrame(folly::io::Cursor& cursor);
133 
134 HandshakeDoneFrame decodeHandshakeDoneFrame(folly::io::Cursor& cursor);
135 
136 folly::Expected<RetryToken, TransportErrorCode> parsePlaintextRetryToken(
137     folly::io::Cursor& cursor);
138 
139 DatagramFrame decodeDatagramFrame(BufQueue& queue, bool hasLen);
140 
141 /**
142  * Parse the Invariant fields in Long Header.
143  *
144  * cursor: points to the byte just past initialByte. After parsing, cursor will
145  *         be moved to the byte right after Source Connection ID.
146  */
147 folly::Expected<ParsedLongHeaderInvariant, TransportErrorCode>
148 parseLongHeaderInvariant(uint8_t initalByte, folly::io::Cursor& cursor);
149 
150 struct PacketLength {
151   // The length of the packet payload (inlcuding packet number)
152   uint64_t packetLength;
153   // Length of the length field.
154   size_t lengthLength;
155 
PacketLengthPacketLength156   PacketLength(uint64_t packetLengthIn, size_t lengthLengthIn)
157       : packetLength(packetLengthIn), lengthLength(lengthLengthIn) {}
158 };
159 
160 struct ParsedLongHeader {
161   LongHeader header;
162   PacketLength packetLength;
163 
ParsedLongHeaderParsedLongHeader164   ParsedLongHeader(LongHeader headerIn, PacketLength packetLengthIn)
165       : header(std::move(headerIn)), packetLength(packetLengthIn) {}
166 };
167 
168 struct ParsedLongHeaderResult {
169   bool isVersionNegotiation;
170   folly::Optional<ParsedLongHeader> parsedLongHeader;
171 
172   ParsedLongHeaderResult(
173       bool isVersionNegotiationIn,
174       folly::Optional<ParsedLongHeader> parsedLongHeaderIn);
175 };
176 
177 // Functions that operate on the initial byte
178 
179 LongHeader::Types parseLongHeaderType(uint8_t initialByte);
180 
181 size_t parsePacketNumberLength(uint8_t initialByte);
182 
183 /**
184  * Returns the packet number and the length of the packet number.
185  * packetNumberRange should be kMaxPacketNumEncodingSize size.
186  */
187 std::pair<PacketNum, size_t> parsePacketNumber(
188     uint8_t initialByte,
189     folly::ByteRange packetNumberRange,
190     PacketNum expectedNextPacketNum);
191 
192 // cursor: has to be point to the byte just past initialByte
193 folly::Expected<ParsedLongHeaderResult, TransportErrorCode> parseLongHeader(
194     uint8_t initialByte,
195     folly::io::Cursor& cursor);
196 
197 // nodeType: Determine if we allow 0-len dst connection ids.
198 folly::Expected<ParsedLongHeader, TransportErrorCode> parseLongHeaderVariants(
199     LongHeader::Types type,
200     ParsedLongHeaderInvariant longHeaderInvariant,
201     folly::io::Cursor& cursor,
202     QuicNodeType nodeType = QuicNodeType::Server);
203 
204 folly::Expected<ShortHeaderInvariant, TransportErrorCode>
205 parseShortHeaderInvariants(
206     uint8_t initialByte,
207     folly::io::Cursor& cursor,
208     size_t dstConnIdSize = kDefaultConnectionIdSize);
209 
210 folly::Expected<ShortHeader, TransportErrorCode> parseShortHeader(
211     uint8_t initialByte,
212     folly::io::Cursor& cursor,
213     size_t dstConnIdSize = kDefaultConnectionIdSize);
214 } // namespace quic
215