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 #include <quic/codec/Decode.h>
10 
11 #include <folly/String.h>
12 #include <quic/QuicException.h>
13 #include <quic/codec/PacketNumber.h>
14 #include <quic/codec/QuicInteger.h>
15 
16 namespace {
17 
nextAckedPacketGap(quic::PacketNum packetNum,uint64_t gap)18 quic::PacketNum nextAckedPacketGap(quic::PacketNum packetNum, uint64_t gap) {
19   // Gap cannot overflow because of the definition of quic integer encoding, so
20   // we can just add to gap.
21   uint64_t adjustedGap = gap + 2;
22   if (packetNum < adjustedGap) {
23     throw quic::QuicTransportException(
24         "Bad gap",
25         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
26         quic::FrameType::ACK);
27   }
28   return packetNum - adjustedGap;
29 }
30 
nextAckedPacketLen(quic::PacketNum packetNum,uint64_t ackBlockLen)31 quic::PacketNum nextAckedPacketLen(
32     quic::PacketNum packetNum,
33     uint64_t ackBlockLen) {
34   // Going to allow 0 as a valid value.
35   if (packetNum < ackBlockLen) {
36     throw quic::QuicTransportException(
37         "Bad block len",
38         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
39         quic::FrameType::ACK);
40   }
41   return packetNum - ackBlockLen;
42 }
43 
44 } // namespace
45 
46 namespace quic {
47 
decodePaddingFrame(folly::io::Cursor & cursor)48 PaddingFrame decodePaddingFrame(folly::io::Cursor& cursor) {
49   // we might have multiple padding frames in sequence in the common case.
50   // Let's consume all the padding and return 1 padding frame for everything.
51   static_assert(
52       static_cast<int>(FrameType::PADDING) == 0, "Padding value is 0");
53   folly::ByteRange paddingBytes = cursor.peekBytes();
54   if (paddingBytes.size() == 0) {
55     return PaddingFrame();
56   }
57   uint8_t firstByte = paddingBytes.data()[0];
58   // While type can be variable length, since PADDING frame is always a 0
59   // byte frame, the length of the type should be 1 byte.
60   if (static_cast<FrameType>(firstByte) != FrameType::PADDING) {
61     return PaddingFrame();
62   }
63   int ret = memcmp(
64       paddingBytes.data(), paddingBytes.data() + 1, paddingBytes.size() - 1);
65   if (ret == 0) {
66     cursor.skip(paddingBytes.size());
67   }
68   return PaddingFrame();
69 }
70 
decodePingFrame(folly::io::Cursor &)71 PingFrame decodePingFrame(folly::io::Cursor&) {
72   return PingFrame();
73 }
74 
decodeKnobFrame(folly::io::Cursor & cursor)75 KnobFrame decodeKnobFrame(folly::io::Cursor& cursor) {
76   auto knobSpace = decodeQuicInteger(cursor);
77   if (!knobSpace) {
78     throw QuicTransportException(
79         "Bad knob space",
80         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
81         quic::FrameType::KNOB);
82   }
83   auto knobId = decodeQuicInteger(cursor);
84   if (!knobId) {
85     throw QuicTransportException(
86         "Bad knob id",
87         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
88         quic::FrameType::KNOB);
89   }
90   auto knobLen = decodeQuicInteger(cursor);
91   if (!knobLen) {
92     throw QuicTransportException(
93         "Bad knob len",
94         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
95         quic::FrameType::KNOB);
96   }
97   Buf knobBlob;
98   cursor.cloneAtMost(knobBlob, knobLen->first);
99   return KnobFrame(knobSpace->first, knobId->first, std::move(knobBlob));
100 }
101 
decodeAckFrequencyFrame(folly::io::Cursor & cursor)102 AckFrequencyFrame decodeAckFrequencyFrame(folly::io::Cursor& cursor) {
103   auto sequenceNumber = decodeQuicInteger(cursor);
104   if (!sequenceNumber) {
105     throw QuicTransportException(
106         "Bad sequence number",
107         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
108         quic::FrameType::ACK_FREQUENCY);
109   }
110   auto packetTolerance = decodeQuicInteger(cursor);
111   if (!packetTolerance) {
112     throw QuicTransportException(
113         "Bad packet tolerance",
114         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
115         quic::FrameType::ACK_FREQUENCY);
116   }
117   auto updateMaxAckDelay = decodeQuicInteger(cursor);
118   if (!updateMaxAckDelay) {
119     throw QuicTransportException(
120         "Bad update max ack delay",
121         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
122         quic::FrameType::ACK_FREQUENCY);
123   }
124   if (cursor.isAtEnd()) {
125     throw QuicTransportException(
126         "Bad ignore order",
127         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
128         quic::FrameType::ACK_FREQUENCY);
129   }
130   auto ignoreOrder = cursor.readBE<uint8_t>();
131 
132   AckFrequencyFrame frame;
133   frame.sequenceNumber = sequenceNumber->first;
134   frame.packetTolerance = packetTolerance->first;
135   frame.updateMaxAckDelay = updateMaxAckDelay->first;
136   frame.ignoreOrder = ignoreOrder;
137   return frame;
138 }
139 
decodeAckFrame(folly::io::Cursor & cursor,const PacketHeader & header,const CodecParameters & params)140 ReadAckFrame decodeAckFrame(
141     folly::io::Cursor& cursor,
142     const PacketHeader& header,
143     const CodecParameters& params) {
144   ReadAckFrame frame;
145   auto largestAckedInt = decodeQuicInteger(cursor);
146   if (!largestAckedInt) {
147     throw QuicTransportException(
148         "Bad largest acked",
149         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
150         quic::FrameType::ACK);
151   }
152   auto largestAcked = folly::to<PacketNum>(largestAckedInt->first);
153   auto ackDelay = decodeQuicInteger(cursor);
154   if (!ackDelay) {
155     throw QuicTransportException(
156         "Bad ack delay",
157         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
158         quic::FrameType::ACK);
159   }
160   auto additionalAckBlocks = decodeQuicInteger(cursor);
161   if (!additionalAckBlocks) {
162     throw QuicTransportException(
163         "Bad ack block count",
164         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
165         quic::FrameType::ACK);
166   }
167   auto firstAckBlockLen = decodeQuicInteger(cursor);
168   if (!firstAckBlockLen) {
169     throw QuicTransportException(
170         "Bad first block",
171         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
172         quic::FrameType::ACK);
173   }
174   // Using default ack delay for long header packets. Before negotiating
175   // and ack delay, the sender has to use something, so they use the default
176   // ack delay. To keep it consistent the protocol specifies using the same
177   // ack delay for all the long header packets.
178   uint8_t ackDelayExponentToUse = (header.getHeaderForm() == HeaderForm::Long)
179       ? kDefaultAckDelayExponent
180       : params.peerAckDelayExponent;
181   DCHECK_LT(ackDelayExponentToUse, sizeof(ackDelay->first) * 8);
182   // ackDelayExponentToUse is guaranteed to be less than the size of uint64_t
183   uint64_t delayOverflowMask = 0xFFFFFFFFFFFFFFFF;
184   uint8_t leftShift = (sizeof(ackDelay->first) * 8 - ackDelayExponentToUse);
185   DCHECK_LT(leftShift, sizeof(delayOverflowMask) * 8);
186   delayOverflowMask = delayOverflowMask << leftShift;
187   if ((ackDelay->first & delayOverflowMask) != 0) {
188     throw QuicTransportException(
189         "Decoded ack delay overflows",
190         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
191         quic::FrameType::ACK);
192   }
193   uint64_t adjustedAckDelay = ackDelay->first << ackDelayExponentToUse;
194   if (adjustedAckDelay >
195       static_cast<uint64_t>(
196           std::numeric_limits<std::chrono::microseconds::rep>::max())) {
197     throw QuicTransportException(
198         "Bad ack delay",
199         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
200         quic::FrameType::ACK);
201   } else if (UNLIKELY(adjustedAckDelay > 1000 * 1000 * 1000 /* 1000s */)) {
202     LOG(ERROR) << "Quic recvd long ack delay=" << adjustedAckDelay;
203     adjustedAckDelay = 0;
204   }
205   PacketNum currentPacketNum =
206       nextAckedPacketLen(largestAcked, firstAckBlockLen->first);
207   frame.largestAcked = largestAcked;
208   frame.ackDelay = std::chrono::microseconds(adjustedAckDelay);
209   frame.ackBlocks.emplace_back(currentPacketNum, largestAcked);
210   for (uint64_t numBlocks = 0; numBlocks < additionalAckBlocks->first;
211        ++numBlocks) {
212     auto currentGap = decodeQuicInteger(cursor);
213     if (!currentGap) {
214       throw QuicTransportException(
215           "Bad gap",
216           quic::TransportErrorCode::FRAME_ENCODING_ERROR,
217           quic::FrameType::ACK);
218     }
219     auto blockLen = decodeQuicInteger(cursor);
220     if (!blockLen) {
221       throw QuicTransportException(
222           "Bad block len",
223           quic::TransportErrorCode::FRAME_ENCODING_ERROR,
224           quic::FrameType::ACK);
225     }
226     PacketNum nextEndPacket =
227         nextAckedPacketGap(currentPacketNum, currentGap->first);
228     currentPacketNum = nextAckedPacketLen(nextEndPacket, blockLen->first);
229     // We don't need to add the entry when the block length is zero since we
230     // already would have processed it in the previous iteration.
231     frame.ackBlocks.emplace_back(currentPacketNum, nextEndPacket);
232   }
233   return frame;
234 }
235 
decodeAckFrameWithECN(folly::io::Cursor & cursor,const PacketHeader & header,const CodecParameters & params)236 ReadAckFrame decodeAckFrameWithECN(
237     folly::io::Cursor& cursor,
238     const PacketHeader& header,
239     const CodecParameters& params) {
240   // TODO this is incomplete
241   auto readAckFrame = decodeAckFrame(cursor, header, params);
242   // TODO we simply ignore ECN blocks in ACK-ECN frames for now.
243   auto ect_0 = decodeQuicInteger(cursor);
244   if (!ect_0) {
245     throw QuicTransportException(
246         "Bad ECT(0) value",
247         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
248         quic::FrameType::ACK_ECN);
249   }
250   auto ect_1 = decodeQuicInteger(cursor);
251   if (!ect_1) {
252     throw QuicTransportException(
253         "Bad ECT(1) value",
254         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
255         quic::FrameType::ACK_ECN);
256   }
257   auto ect_ce = decodeQuicInteger(cursor);
258   if (!ect_ce) {
259     throw QuicTransportException(
260         "Bad ECT-CE value",
261         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
262         quic::FrameType::ACK_ECN);
263   }
264   return readAckFrame;
265 }
266 
decodeRstStreamFrame(folly::io::Cursor & cursor)267 RstStreamFrame decodeRstStreamFrame(folly::io::Cursor& cursor) {
268   auto streamId = decodeQuicInteger(cursor);
269   if (!streamId) {
270     throw QuicTransportException(
271         "Bad streamId",
272         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
273         quic::FrameType::RST_STREAM);
274   }
275   ApplicationErrorCode errorCode;
276   auto varCode = decodeQuicInteger(cursor);
277   if (varCode) {
278     errorCode = static_cast<ApplicationErrorCode>(varCode->first);
279   } else {
280     throw QuicTransportException(
281         "Cannot decode error code",
282         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
283         quic::FrameType::RST_STREAM);
284   }
285   auto offset = decodeQuicInteger(cursor);
286   if (!offset) {
287     throw QuicTransportException(
288         "Bad offset",
289         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
290         quic::FrameType::RST_STREAM);
291   }
292   return RstStreamFrame(
293       folly::to<StreamId>(streamId->first), errorCode, offset->first);
294 }
295 
decodeStopSendingFrame(folly::io::Cursor & cursor)296 StopSendingFrame decodeStopSendingFrame(folly::io::Cursor& cursor) {
297   auto streamId = decodeQuicInteger(cursor);
298   if (!streamId) {
299     throw QuicTransportException(
300         "Bad streamId",
301         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
302         quic::FrameType::STOP_SENDING);
303   }
304   ApplicationErrorCode errorCode;
305   auto varCode = decodeQuicInteger(cursor);
306   if (varCode) {
307     errorCode = static_cast<ApplicationErrorCode>(varCode->first);
308   } else {
309     throw QuicTransportException(
310         "Cannot decode error code",
311         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
312         quic::FrameType::STOP_SENDING);
313   }
314   return StopSendingFrame(folly::to<StreamId>(streamId->first), errorCode);
315 }
316 
decodeCryptoFrame(folly::io::Cursor & cursor)317 ReadCryptoFrame decodeCryptoFrame(folly::io::Cursor& cursor) {
318   auto optionalOffset = decodeQuicInteger(cursor);
319   if (!optionalOffset) {
320     throw QuicTransportException(
321         "Invalid offset",
322         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
323         quic::FrameType::CRYPTO_FRAME);
324   }
325   uint64_t offset = optionalOffset->first;
326 
327   auto dataLength = decodeQuicInteger(cursor);
328   if (!dataLength) {
329     throw QuicTransportException(
330         "Invalid length",
331         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
332         quic::FrameType::CRYPTO_FRAME);
333   }
334   Buf data;
335   if (cursor.totalLength() < dataLength->first) {
336     throw QuicTransportException(
337         "Length mismatch",
338         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
339         quic::FrameType::CRYPTO_FRAME);
340   }
341   // If dataLength > data's actual length then the cursor will throw.
342   cursor.clone(data, dataLength->first);
343   return ReadCryptoFrame(offset, std::move(data));
344 }
345 
decodeNewTokenFrame(folly::io::Cursor & cursor)346 ReadNewTokenFrame decodeNewTokenFrame(folly::io::Cursor& cursor) {
347   auto tokenLength = decodeQuicInteger(cursor);
348   if (!tokenLength) {
349     throw QuicTransportException(
350         "Invalid length",
351         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
352         quic::FrameType::NEW_TOKEN);
353   }
354   Buf token;
355   if (cursor.totalLength() < tokenLength->first) {
356     throw QuicTransportException(
357         "Length mismatch",
358         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
359         quic::FrameType::NEW_TOKEN);
360   }
361   // If tokenLength > token's actual length then the cursor will throw.
362   cursor.clone(token, tokenLength->first);
363   return ReadNewTokenFrame(std::move(token));
364 }
365 
decodeStreamFrame(BufQueue & queue,StreamTypeField frameTypeField)366 ReadStreamFrame decodeStreamFrame(
367     BufQueue& queue,
368     StreamTypeField frameTypeField) {
369   folly::io::Cursor cursor(queue.front());
370   auto streamId = decodeQuicInteger(cursor);
371   if (!streamId) {
372     throw QuicTransportException(
373         "Invalid stream id",
374         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
375         quic::FrameType::STREAM);
376   }
377   uint64_t offset = 0;
378   if (frameTypeField.hasOffset()) {
379     auto optionalOffset = decodeQuicInteger(cursor);
380     if (!optionalOffset) {
381       throw QuicTransportException(
382           "Invalid offset",
383           quic::TransportErrorCode::FRAME_ENCODING_ERROR,
384           quic::FrameType::STREAM);
385     }
386     offset = optionalOffset->first;
387   }
388   auto fin = frameTypeField.hasFin();
389   folly::Optional<std::pair<uint64_t, size_t>> dataLength;
390   if (frameTypeField.hasDataLength()) {
391     dataLength = decodeQuicInteger(cursor);
392     if (!dataLength) {
393       throw QuicTransportException(
394           "Invalid length",
395           quic::TransportErrorCode::FRAME_ENCODING_ERROR,
396           quic::FrameType::STREAM);
397     }
398   }
399   Buf data;
400   if (dataLength.has_value()) {
401     if (cursor.totalLength() < dataLength->first) {
402       throw QuicTransportException(
403           "Length mismatch",
404           quic::TransportErrorCode::FRAME_ENCODING_ERROR,
405           quic::FrameType::STREAM);
406     }
407     // If dataLength > data's actual length then the cursor will throw.
408     queue.trimStart(cursor - queue.front());
409     data = queue.splitAtMost(dataLength->first);
410   } else {
411     // Missing Data Length field doesn't mean no data. It means the rest of the
412     // frame are all data.
413     queue.trimStart(cursor - queue.front());
414     data = queue.move();
415   }
416   return ReadStreamFrame(
417       folly::to<StreamId>(streamId->first), offset, std::move(data), fin);
418 }
419 
decodeMaxDataFrame(folly::io::Cursor & cursor)420 MaxDataFrame decodeMaxDataFrame(folly::io::Cursor& cursor) {
421   auto maximumData = decodeQuicInteger(cursor);
422   if (!maximumData) {
423     throw QuicTransportException(
424         "Bad Max Data",
425         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
426         quic::FrameType::MAX_DATA);
427   }
428   return MaxDataFrame(maximumData->first);
429 }
430 
decodeMaxStreamDataFrame(folly::io::Cursor & cursor)431 MaxStreamDataFrame decodeMaxStreamDataFrame(folly::io::Cursor& cursor) {
432   auto streamId = decodeQuicInteger(cursor);
433   if (!streamId) {
434     throw QuicTransportException(
435         "Invalid streamId",
436         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
437         quic::FrameType::MAX_STREAM_DATA);
438   }
439   auto offset = decodeQuicInteger(cursor);
440   if (!offset) {
441     throw QuicTransportException(
442         "Invalid offset",
443         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
444         quic::FrameType::MAX_STREAM_DATA);
445   }
446   return MaxStreamDataFrame(
447       folly::to<StreamId>(streamId->first), offset->first);
448 }
449 
decodeBiDiMaxStreamsFrame(folly::io::Cursor & cursor)450 MaxStreamsFrame decodeBiDiMaxStreamsFrame(folly::io::Cursor& cursor) {
451   auto streamCount = decodeQuicInteger(cursor);
452   if (!streamCount || streamCount->first > kMaxMaxStreams) {
453     throw QuicTransportException(
454         "Invalid Bi-directional streamId",
455         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
456         quic::FrameType::MAX_STREAMS_BIDI);
457   }
458   return MaxStreamsFrame(streamCount->first, true /* isBidirectional*/);
459 }
460 
decodeUniMaxStreamsFrame(folly::io::Cursor & cursor)461 MaxStreamsFrame decodeUniMaxStreamsFrame(folly::io::Cursor& cursor) {
462   auto streamCount = decodeQuicInteger(cursor);
463   if (!streamCount || streamCount->first > kMaxMaxStreams) {
464     throw QuicTransportException(
465         "Invalid Uni-directional streamId",
466         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
467         quic::FrameType::MAX_STREAMS_UNI);
468   }
469   return MaxStreamsFrame(streamCount->first, false /* isUnidirectional */);
470 }
471 
decodeDataBlockedFrame(folly::io::Cursor & cursor)472 DataBlockedFrame decodeDataBlockedFrame(folly::io::Cursor& cursor) {
473   auto dataLimit = decodeQuicInteger(cursor);
474   if (!dataLimit) {
475     throw QuicTransportException(
476         "Bad offset",
477         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
478         quic::FrameType::DATA_BLOCKED);
479   }
480   return DataBlockedFrame(dataLimit->first);
481 }
482 
decodeStreamDataBlockedFrame(folly::io::Cursor & cursor)483 StreamDataBlockedFrame decodeStreamDataBlockedFrame(folly::io::Cursor& cursor) {
484   auto streamId = decodeQuicInteger(cursor);
485   if (!streamId) {
486     throw QuicTransportException(
487         "Bad streamId",
488         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
489         quic::FrameType::STREAM_DATA_BLOCKED);
490   }
491   auto dataLimit = decodeQuicInteger(cursor);
492   if (!dataLimit) {
493     throw QuicTransportException(
494         "Bad offset",
495         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
496         quic::FrameType::STREAM_DATA_BLOCKED);
497   }
498   return StreamDataBlockedFrame(
499       folly::to<StreamId>(streamId->first), dataLimit->first);
500 }
501 
decodeBiDiStreamsBlockedFrame(folly::io::Cursor & cursor)502 StreamsBlockedFrame decodeBiDiStreamsBlockedFrame(folly::io::Cursor& cursor) {
503   auto streamId = decodeQuicInteger(cursor);
504   if (!streamId) {
505     throw QuicTransportException(
506         "Bad Bi-Directional streamId",
507         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
508         quic::FrameType::STREAMS_BLOCKED_BIDI);
509   }
510   return StreamsBlockedFrame(
511       folly::to<StreamId>(streamId->first), true /* isBidirectional */);
512 }
513 
decodeUniStreamsBlockedFrame(folly::io::Cursor & cursor)514 StreamsBlockedFrame decodeUniStreamsBlockedFrame(folly::io::Cursor& cursor) {
515   auto streamId = decodeQuicInteger(cursor);
516   if (!streamId) {
517     throw QuicTransportException(
518         "Bad Uni-direcitonal streamId",
519         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
520         quic::FrameType::STREAMS_BLOCKED_UNI);
521   }
522   return StreamsBlockedFrame(
523       folly::to<StreamId>(streamId->first), false /* isBidirectional */);
524 }
525 
decodeNewConnectionIdFrame(folly::io::Cursor & cursor)526 NewConnectionIdFrame decodeNewConnectionIdFrame(folly::io::Cursor& cursor) {
527   auto sequenceNumber = decodeQuicInteger(cursor);
528   if (!sequenceNumber) {
529     throw QuicTransportException(
530         "Bad sequence",
531         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
532         quic::FrameType::NEW_CONNECTION_ID);
533   }
534   auto retirePriorTo = decodeQuicInteger(cursor);
535   if (!retirePriorTo) {
536     throw QuicTransportException(
537         "Bad retire prior to",
538         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
539         quic::FrameType::NEW_CONNECTION_ID);
540   }
541   if (!cursor.canAdvance(sizeof(uint8_t))) {
542     throw QuicTransportException(
543         "Not enough input bytes to read Dest. ConnectionId",
544         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
545         quic::FrameType::NEW_CONNECTION_ID);
546   }
547   auto connIdLen = cursor.readBE<uint8_t>();
548   if (cursor.totalLength() < connIdLen) {
549     throw QuicTransportException(
550         "Bad connid",
551         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
552         quic::FrameType::NEW_CONNECTION_ID);
553   }
554   if (connIdLen > kMaxConnectionIdSize) {
555     throw QuicTransportException(
556         "ConnectionId invalid length",
557         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
558         quic::FrameType::NEW_CONNECTION_ID);
559   }
560   ConnectionId connId(cursor, connIdLen);
561   StatelessResetToken statelessResetToken;
562   cursor.pull(statelessResetToken.data(), statelessResetToken.size());
563   return NewConnectionIdFrame(
564       sequenceNumber->first,
565       retirePriorTo->first,
566       std::move(connId),
567       std::move(statelessResetToken));
568 }
569 
decodeRetireConnectionIdFrame(folly::io::Cursor & cursor)570 RetireConnectionIdFrame decodeRetireConnectionIdFrame(
571     folly::io::Cursor& cursor) {
572   auto sequenceNum = decodeQuicInteger(cursor);
573   if (!sequenceNum) {
574     throw QuicTransportException(
575         // TODO change the error code
576         "Bad sequence num",
577         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
578         quic::FrameType::RETIRE_CONNECTION_ID);
579   }
580   return RetireConnectionIdFrame(sequenceNum->first);
581 }
582 
decodePathChallengeFrame(folly::io::Cursor & cursor)583 PathChallengeFrame decodePathChallengeFrame(folly::io::Cursor& cursor) {
584   // just parse and ignore expected data
585   // A PATH_CHALLENGE frame contains 8 bytes
586   if (!cursor.canAdvance(sizeof(uint64_t))) {
587     throw QuicTransportException(
588         "Not enough input bytes to read path challenge frame.",
589         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
590         quic::FrameType::PATH_CHALLENGE);
591   }
592   auto pathData = cursor.readBE<uint64_t>();
593   return PathChallengeFrame(pathData);
594 }
595 
decodePathResponseFrame(folly::io::Cursor & cursor)596 PathResponseFrame decodePathResponseFrame(folly::io::Cursor& cursor) {
597   // just parse and ignore expected data
598   // Its format is identical to the PATH_CHALLENGE frame
599   if (!cursor.canAdvance(sizeof(uint64_t))) {
600     throw QuicTransportException(
601         "Not enough input bytes to read path response frame.",
602         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
603         quic::FrameType::PATH_RESPONSE);
604   }
605   auto pathData = cursor.readBE<uint64_t>();
606   return PathResponseFrame(pathData);
607 }
608 
decodeConnectionCloseFrame(folly::io::Cursor & cursor)609 ConnectionCloseFrame decodeConnectionCloseFrame(folly::io::Cursor& cursor) {
610   TransportErrorCode errorCode{};
611   auto varCode = decodeQuicInteger(cursor);
612   if (varCode) {
613     errorCode = static_cast<TransportErrorCode>(varCode->first);
614   } else {
615     throw QuicTransportException(
616         "Failed to parse error code.",
617         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
618         quic::FrameType::CONNECTION_CLOSE);
619   }
620   auto frameTypeField = decodeQuicInteger(cursor);
621   if (!frameTypeField || frameTypeField->second != sizeof(uint8_t)) {
622     throw QuicTransportException(
623         "Bad connection close triggering frame type value",
624         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
625         quic::FrameType::CONNECTION_CLOSE);
626   }
627   FrameType triggeringFrameType = static_cast<FrameType>(frameTypeField->first);
628   auto reasonPhraseLength = decodeQuicInteger(cursor);
629   if (!reasonPhraseLength ||
630       reasonPhraseLength->first > kMaxReasonPhraseLength) {
631     throw QuicTransportException(
632         "Bad reason phrase length",
633         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
634         quic::FrameType::CONNECTION_CLOSE);
635   }
636   auto reasonPhrase =
637       cursor.readFixedString(folly::to<size_t>(reasonPhraseLength->first));
638   return ConnectionCloseFrame(
639       QuicErrorCode(errorCode), std::move(reasonPhrase), triggeringFrameType);
640 }
641 
decodeApplicationClose(folly::io::Cursor & cursor)642 ConnectionCloseFrame decodeApplicationClose(folly::io::Cursor& cursor) {
643   ApplicationErrorCode errorCode{};
644   auto varCode = decodeQuicInteger(cursor);
645   if (varCode) {
646     errorCode = static_cast<ApplicationErrorCode>(varCode->first);
647   } else {
648     throw QuicTransportException(
649         "Failed to parse error code.",
650         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
651         quic::FrameType::CONNECTION_CLOSE_APP_ERR);
652   }
653 
654   auto reasonPhraseLength = decodeQuicInteger(cursor);
655   if (!reasonPhraseLength ||
656       reasonPhraseLength->first > kMaxReasonPhraseLength) {
657     throw QuicTransportException(
658         "Bad reason phrase length",
659         quic::TransportErrorCode::FRAME_ENCODING_ERROR,
660         quic::FrameType::CONNECTION_CLOSE_APP_ERR);
661   }
662 
663   auto reasonPhrase =
664       cursor.readFixedString(folly::to<size_t>(reasonPhraseLength->first));
665   return ConnectionCloseFrame(
666       QuicErrorCode(errorCode), std::move(reasonPhrase));
667 }
668 
decodeHandshakeDoneFrame(folly::io::Cursor &)669 HandshakeDoneFrame decodeHandshakeDoneFrame(folly::io::Cursor& /*cursor*/) {
670   return HandshakeDoneFrame();
671 }
672 
parsePlaintextRetryToken(folly::io::Cursor & cursor)673 folly::Expected<RetryToken, TransportErrorCode> parsePlaintextRetryToken(
674     folly::io::Cursor& cursor) {
675   // Read in the length of the odcid.
676   if (!cursor.canAdvance(sizeof(uint8_t))) {
677     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
678   }
679   auto odcidLen = cursor.readBE<uint8_t>();
680 
681   // Read in the odcid.
682   if (!cursor.canAdvance(odcidLen)) {
683     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
684   }
685   ConnectionId connId(cursor, odcidLen);
686 
687   // Read in the port.
688   if (!cursor.canAdvance(sizeof(uint16_t))) {
689     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
690   }
691   auto clientPort = cursor.readBE<uint16_t>();
692 
693   // Read in the length of the client ip address.
694   if (!cursor.canAdvance(sizeof(uint8_t))) {
695     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
696   }
697   uint16_t ipAddrLen = cursor.readBE<uint8_t>();
698 
699   if (!cursor.canAdvance(ipAddrLen)) {
700     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
701   }
702 
703   // Read in the ip address.
704   std::string ipAddressStr = cursor.readFixedString(ipAddrLen);
705   auto ipAddress = folly::IPAddress::tryFromString(ipAddressStr);
706   if (!ipAddress.hasValue()) {
707     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
708   }
709 
710   // Read in the timestamp
711   if (!cursor.canAdvance(sizeof(uint64_t))) {
712     return folly::makeUnexpected(TransportErrorCode::INVALID_TOKEN);
713   }
714   auto timestampInMs = cursor.readBE<uint64_t>();
715 
716   return RetryToken(connId, *ipAddress, clientPort, timestampInMs);
717 }
718 
decodeDatagramFrame(BufQueue & queue,bool hasLen)719 DatagramFrame decodeDatagramFrame(BufQueue& queue, bool hasLen) {
720   folly::io::Cursor cursor(queue.front());
721   size_t length = cursor.length();
722   if (hasLen) {
723     auto decodeLength = decodeQuicInteger(cursor);
724     if (!decodeLength) {
725       throw QuicTransportException(
726           "Invalid datagram len",
727           TransportErrorCode::FRAME_ENCODING_ERROR,
728           FrameType::DATAGRAM_LEN);
729     }
730     length = decodeLength->first;
731     if (cursor.length() < length) {
732       throw QuicTransportException(
733           "Invalid datagram frame",
734           TransportErrorCode::FRAME_ENCODING_ERROR,
735           FrameType::DATAGRAM_LEN);
736     }
737     queue.trimStart(decodeLength->second);
738   }
739   return DatagramFrame(length, queue.splitAtMost(length));
740 }
741 
parseFrame(BufQueue & queue,const PacketHeader & header,const CodecParameters & params)742 QuicFrame parseFrame(
743     BufQueue& queue,
744     const PacketHeader& header,
745     const CodecParameters& params) {
746   folly::io::Cursor cursor(queue.front());
747   auto frameTypeInt = decodeQuicInteger(cursor);
748   if (!frameTypeInt) {
749     throw QuicTransportException(
750         "Invalid frame-type field", TransportErrorCode::FRAME_ENCODING_ERROR);
751   }
752   queue.trimStart(cursor - queue.front());
753   bool consumedQueue = false;
754   bool error = false;
755   SCOPE_EXIT {
756     if (consumedQueue || error) {
757       return;
758     }
759     queue.trimStart(cursor - queue.front());
760   };
761   cursor.reset(queue.front());
762   FrameType frameType = static_cast<FrameType>(frameTypeInt->first);
763   try {
764     switch (frameType) {
765       case FrameType::PADDING:
766         return QuicFrame(decodePaddingFrame(cursor));
767       case FrameType::PING:
768         return QuicFrame(decodePingFrame(cursor));
769       case FrameType::ACK:
770         return QuicFrame(decodeAckFrame(cursor, header, params));
771       case FrameType::ACK_ECN:
772         return QuicFrame(decodeAckFrameWithECN(cursor, header, params));
773       case FrameType::RST_STREAM:
774         return QuicFrame(decodeRstStreamFrame(cursor));
775       case FrameType::STOP_SENDING:
776         return QuicFrame(decodeStopSendingFrame(cursor));
777       case FrameType::CRYPTO_FRAME:
778         return QuicFrame(decodeCryptoFrame(cursor));
779       case FrameType::NEW_TOKEN:
780         return QuicFrame(decodeNewTokenFrame(cursor));
781       case FrameType::STREAM:
782       case FrameType::STREAM_FIN:
783       case FrameType::STREAM_LEN:
784       case FrameType::STREAM_LEN_FIN:
785       case FrameType::STREAM_OFF:
786       case FrameType::STREAM_OFF_FIN:
787       case FrameType::STREAM_OFF_LEN:
788       case FrameType::STREAM_OFF_LEN_FIN:
789         consumedQueue = true;
790         return QuicFrame(
791             decodeStreamFrame(queue, StreamTypeField(frameTypeInt->first)));
792       case FrameType::MAX_DATA:
793         return QuicFrame(decodeMaxDataFrame(cursor));
794       case FrameType::MAX_STREAM_DATA:
795         return QuicFrame(decodeMaxStreamDataFrame(cursor));
796       case FrameType::MAX_STREAMS_BIDI:
797         return QuicFrame(decodeBiDiMaxStreamsFrame(cursor));
798       case FrameType::MAX_STREAMS_UNI:
799         return QuicFrame(decodeUniMaxStreamsFrame(cursor));
800       case FrameType::DATA_BLOCKED:
801         return QuicFrame(decodeDataBlockedFrame(cursor));
802       case FrameType::STREAM_DATA_BLOCKED:
803         return QuicFrame(decodeStreamDataBlockedFrame(cursor));
804       case FrameType::STREAMS_BLOCKED_BIDI:
805         return QuicFrame(decodeBiDiStreamsBlockedFrame(cursor));
806       case FrameType::STREAMS_BLOCKED_UNI:
807         return QuicFrame(decodeUniStreamsBlockedFrame(cursor));
808       case FrameType::NEW_CONNECTION_ID:
809         return QuicFrame(decodeNewConnectionIdFrame(cursor));
810       case FrameType::RETIRE_CONNECTION_ID:
811         return QuicFrame(decodeRetireConnectionIdFrame(cursor));
812       case FrameType::PATH_CHALLENGE:
813         return QuicFrame(decodePathChallengeFrame(cursor));
814       case FrameType::PATH_RESPONSE:
815         return QuicFrame(decodePathResponseFrame(cursor));
816       case FrameType::CONNECTION_CLOSE:
817         return QuicFrame(decodeConnectionCloseFrame(cursor));
818       case FrameType::CONNECTION_CLOSE_APP_ERR:
819         return QuicFrame(decodeApplicationClose(cursor));
820       case FrameType::HANDSHAKE_DONE:
821         return QuicFrame(decodeHandshakeDoneFrame(cursor));
822       case FrameType::DATAGRAM: {
823         consumedQueue = true;
824         return QuicFrame(decodeDatagramFrame(queue, false /* hasLen */));
825       }
826       case FrameType::DATAGRAM_LEN: {
827         consumedQueue = true;
828         return QuicFrame(decodeDatagramFrame(queue, true /* hasLen */));
829       }
830       case FrameType::KNOB:
831         return QuicFrame(decodeKnobFrame(cursor));
832       case FrameType::ACK_FREQUENCY:
833         return QuicFrame(decodeAckFrequencyFrame(cursor));
834     }
835   } catch (const std::exception&) {
836     error = true;
837     throw QuicTransportException(
838         folly::to<std::string>(
839             "Frame format invalid, type=", frameTypeInt->first),
840         TransportErrorCode::FRAME_ENCODING_ERROR,
841         frameType);
842   }
843   error = true;
844   throw QuicTransportException(
845       folly::to<std::string>("Unknown frame, type=", frameTypeInt->first),
846       TransportErrorCode::FRAME_ENCODING_ERROR,
847       frameType);
848 }
849 
850 // Parse packet
851 
decodeRegularPacket(PacketHeader && header,const CodecParameters & params,std::unique_ptr<folly::IOBuf> packetData)852 RegularQuicPacket decodeRegularPacket(
853     PacketHeader&& header,
854     const CodecParameters& params,
855     std::unique_ptr<folly::IOBuf> packetData) {
856   RegularQuicPacket packet(std::move(header));
857   BufQueue queue;
858   queue.append(std::move(packetData));
859   while (queue.chainLength() > 0) {
860     packet.frames.push_back(parseFrame(queue, packet.header, params));
861   }
862   return packet;
863 }
864 
decodeVersionNegotiation(const ParsedLongHeaderInvariant & longHeaderInvariant,folly::io::Cursor & cursor)865 folly::Optional<VersionNegotiationPacket> decodeVersionNegotiation(
866     const ParsedLongHeaderInvariant& longHeaderInvariant,
867     folly::io::Cursor& cursor) {
868   auto cursorLength = cursor.totalLength();
869 
870   if (cursorLength < sizeof(QuicVersionType) ||
871       cursorLength % sizeof(QuicVersionType)) {
872     VLOG(4) << "Version negotiation packet invalid";
873     return folly::none;
874   }
875 
876   VersionNegotiationPacket packet(
877       longHeaderInvariant.initialByte,
878       longHeaderInvariant.invariant.srcConnId,
879       longHeaderInvariant.invariant.dstConnId);
880 
881   while (!cursor.isAtEnd()) {
882     packet.versions.push_back(
883         static_cast<QuicVersion>(cursor.readBE<QuicVersionType>()));
884   }
885 
886   return packet;
887 }
888 
ParsedLongHeaderResult(bool isVersionNegotiationIn,folly::Optional<ParsedLongHeader> parsedLongHeaderIn)889 ParsedLongHeaderResult::ParsedLongHeaderResult(
890     bool isVersionNegotiationIn,
891     folly::Optional<ParsedLongHeader> parsedLongHeaderIn)
892     : isVersionNegotiation(isVersionNegotiationIn),
893       parsedLongHeader(std::move(parsedLongHeaderIn)) {
894   CHECK(isVersionNegotiation || parsedLongHeader);
895 }
896 
ParsedLongHeaderInvariant(uint8_t initialByteIn,LongHeaderInvariant headerInvariant,size_t length)897 ParsedLongHeaderInvariant::ParsedLongHeaderInvariant(
898     uint8_t initialByteIn,
899     LongHeaderInvariant headerInvariant,
900     size_t length)
901     : initialByte(initialByteIn),
902       invariant(std::move(headerInvariant)),
903       invariantLength(length) {}
904 
905 folly::Expected<ParsedLongHeaderInvariant, TransportErrorCode>
parseLongHeaderInvariant(uint8_t initialByte,folly::io::Cursor & cursor)906 parseLongHeaderInvariant(uint8_t initialByte, folly::io::Cursor& cursor) {
907   size_t initialLength = cursor.totalLength();
908   if (!cursor.canAdvance(sizeof(QuicVersionType))) {
909     VLOG(5) << "Not enough input bytes to read Version or connection-id";
910     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
911   }
912   auto version = static_cast<QuicVersion>(cursor.readBE<QuicVersionType>());
913   if (!cursor.canAdvance(1)) {
914     VLOG(5) << "Not enough input bytes to read Dest. ConnectionId length";
915     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
916   }
917   uint8_t destConnIdLen = cursor.readBE<uint8_t>();
918   if (destConnIdLen > kMaxConnectionIdSize) {
919     VLOG(5) << "destConnIdLen > kMaxConnectionIdSize: " << destConnIdLen;
920     return folly::makeUnexpected(TransportErrorCode::PROTOCOL_VIOLATION);
921   }
922   if (!cursor.canAdvance(destConnIdLen)) {
923     VLOG(5) << "Not enough input bytes to read Dest. ConnectionId";
924     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
925   }
926   ConnectionId destConnId(cursor, destConnIdLen);
927   if (!cursor.canAdvance(1)) {
928     VLOG(5) << "Not enough input bytes to read Source ConnectionId length";
929     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
930   }
931   uint8_t srcConnIdLen = cursor.readBE<uint8_t>();
932   if (srcConnIdLen > kMaxConnectionIdSize) {
933     VLOG(5) << "srcConnIdLen > kMaxConnectionIdSize: " << srcConnIdLen;
934     return folly::makeUnexpected(TransportErrorCode::PROTOCOL_VIOLATION);
935   }
936   if (!cursor.canAdvance(srcConnIdLen)) {
937     VLOG(5) << "Not enough input bytes to read Source ConnectionId";
938     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
939   }
940   ConnectionId srcConnId(cursor, srcConnIdLen);
941   size_t currentLength = cursor.totalLength();
942   size_t bytesRead = initialLength - currentLength;
943   return ParsedLongHeaderInvariant(
944       initialByte,
945       LongHeaderInvariant(version, std::move(srcConnId), std::move(destConnId)),
946       bytesRead);
947 }
948 
parseLongHeaderType(uint8_t initialByte)949 LongHeader::Types parseLongHeaderType(uint8_t initialByte) {
950   return static_cast<LongHeader::Types>(
951       (initialByte & LongHeader::kPacketTypeMask) >> LongHeader::kTypeShift);
952 }
953 
parsePacketNumberLength(uint8_t initialByte)954 size_t parsePacketNumberLength(uint8_t initialByte) {
955   static_assert(
956       LongHeader::kPacketNumLenMask == ShortHeader::kPacketNumLenMask,
957       "Expected both pn masks are the same");
958   return (initialByte & LongHeader::kPacketNumLenMask) + 1;
959 }
960 
961 /**
962  * Returns the packet number and the length of the packet number
963  */
parsePacketNumber(uint8_t initialByte,folly::ByteRange packetNumberRange,PacketNum expectedNextPacketNum)964 std::pair<PacketNum, size_t> parsePacketNumber(
965     uint8_t initialByte,
966     folly::ByteRange packetNumberRange,
967     PacketNum expectedNextPacketNum) {
968   size_t packetNumLen = parsePacketNumberLength(initialByte);
969   uint32_t encodedPacketNum = 0;
970   memcpy(
971       reinterpret_cast<char*>(&encodedPacketNum) + sizeof(uint32_t) -
972           packetNumLen,
973       packetNumberRange.data(),
974       packetNumLen);
975   uint32_t bigEncodedPacketNum = folly::Endian::big(encodedPacketNum);
976   return std::make_pair(
977       decodePacketNumber(
978           bigEncodedPacketNum, packetNumLen, expectedNextPacketNum),
979       packetNumLen);
980 }
981 
parseLongHeader(uint8_t initialByte,folly::io::Cursor & cursor)982 folly::Expected<ParsedLongHeaderResult, TransportErrorCode> parseLongHeader(
983     uint8_t initialByte,
984     folly::io::Cursor& cursor) {
985   if (getHeaderForm(initialByte) != HeaderForm::Long) {
986     VLOG(5) << "Bad header form bit";
987     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
988   }
989   LongHeader::Types type = parseLongHeaderType(initialByte);
990   switch (type) {
991     case LongHeader::Types::Initial:
992     case LongHeader::Types::Retry:
993     case LongHeader::Types::Handshake:
994     case LongHeader::Types::ZeroRtt:
995       break;
996     default:
997       return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
998   }
999 
1000   auto parsedLongHeaderInvariant =
1001       parseLongHeaderInvariant(initialByte, cursor);
1002   if (!parsedLongHeaderInvariant) {
1003     VLOG(5) << "Bad invariants fields in long header";
1004     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1005   }
1006 
1007   auto version = parsedLongHeaderInvariant->invariant.version;
1008   if (version == QuicVersion::VERSION_NEGOTIATION) {
1009     return ParsedLongHeaderResult(true, folly::none);
1010   }
1011   auto parsedHeader = parseLongHeaderVariants(
1012       type, std::move(*parsedLongHeaderInvariant), cursor);
1013   if (!parsedHeader) {
1014     return folly::makeUnexpected(parsedHeader.error());
1015   }
1016   return ParsedLongHeaderResult(false, std::move(*parsedHeader));
1017 }
1018 
parseLongHeaderVariants(LongHeader::Types type,ParsedLongHeaderInvariant parsedLongHeaderInvariant,folly::io::Cursor & cursor,QuicNodeType nodeType)1019 folly::Expected<ParsedLongHeader, TransportErrorCode> parseLongHeaderVariants(
1020     LongHeader::Types type,
1021     ParsedLongHeaderInvariant parsedLongHeaderInvariant,
1022     folly::io::Cursor& cursor,
1023     QuicNodeType nodeType) {
1024   if (type == LongHeader::Types::Retry) {
1025     // The integrity tag is kRetryIntegrityTagLen bytes in length, and the
1026     // token must be at least one byte, so the remaining length must
1027     // be > kRetryIntegrityTagLen.
1028     if (cursor.totalLength() <= kRetryIntegrityTagLen) {
1029       VLOG(5) << "Not enough bytes for retry token";
1030       return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1031     }
1032 
1033     Buf token;
1034     cursor.clone(token, cursor.totalLength() - kRetryIntegrityTagLen);
1035 
1036     return ParsedLongHeader(
1037         LongHeader(
1038             type,
1039             std::move(parsedLongHeaderInvariant.invariant),
1040             token ? token->moveToFbString().toStdString() : std::string()),
1041         PacketLength(0, 0));
1042   }
1043 
1044   // TODO Checking kMinInitialDestinationConnIdLength isn't necessary
1045   // if this packet is in response to a retry.
1046   if (type == LongHeader::Types::Initial && nodeType == QuicNodeType::Server &&
1047       parsedLongHeaderInvariant.invariant.dstConnId.size() <
1048           kMinInitialDestinationConnIdLength) {
1049     VLOG(5)
1050         << "Dest Conn-Id length in client initial packet must be >= 8 bytes.";
1051     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1052   }
1053 
1054   Buf token;
1055   if (type == LongHeader::Types::Initial) {
1056     auto tokenLen = decodeQuicInteger(cursor);
1057     if (!tokenLen) {
1058       VLOG(5) << "Token len not found in Long header";
1059       return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1060     }
1061     if (!cursor.canAdvance(tokenLen->first)) {
1062       VLOG(5) << "Not enough input bytes to read input token";
1063       return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1064     }
1065 
1066     if (tokenLen->first > 0) {
1067       Buf tokenBuf;
1068       // If tokenLen > token's actual length then the cursor will throw.
1069       cursor.clone(tokenBuf, tokenLen->first);
1070       token = std::move(tokenBuf);
1071     }
1072   }
1073   auto pktLen = decodeQuicInteger(cursor);
1074   if (!pktLen) {
1075     VLOG(5) << "Packet len not found in Long header";
1076     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1077   }
1078   if (!cursor.canAdvance(pktLen->first)) {
1079     VLOG(5) << "Not enough input bytes to read packet number";
1080     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1081   }
1082   size_t packetNumLen =
1083       parsePacketNumberLength(parsedLongHeaderInvariant.initialByte);
1084   if (!cursor.canAdvance(packetNumLen)) {
1085     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1086   }
1087   if (packetNumLen > kMaxPacketNumEncodingSize) {
1088     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1089   }
1090   return ParsedLongHeader(
1091       LongHeader(
1092           type,
1093           std::move(parsedLongHeaderInvariant.invariant),
1094           token ? token->moveToFbString().toStdString() : std::string()),
1095       PacketLength(pktLen->first, pktLen->second));
1096 }
1097 
1098 folly::Expected<ShortHeaderInvariant, TransportErrorCode>
parseShortHeaderInvariants(uint8_t initialByte,folly::io::Cursor & cursor,size_t dstConnIdSize)1099 parseShortHeaderInvariants(
1100     uint8_t initialByte,
1101     folly::io::Cursor& cursor,
1102     size_t dstConnIdSize) {
1103   if (getHeaderForm(initialByte) != HeaderForm::Short) {
1104     VLOG(5) << "Bad header form bit";
1105     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1106   }
1107   // TODO(t39154014, yangchi): read the length from the connection state in
1108   // draft-17
1109   if (dstConnIdSize > kMaxConnectionIdSize) {
1110     VLOG(5) << "dstConnIdSize > kMaxConnectionIdSize: " << dstConnIdSize;
1111     return folly::makeUnexpected(TransportErrorCode::PROTOCOL_VIOLATION);
1112   }
1113   if (!cursor.canAdvance(dstConnIdSize)) {
1114     VLOG(5) << "Not enough input bytes for ConnectionId";
1115     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1116   }
1117   ConnectionId connId(cursor, dstConnIdSize);
1118   return ShortHeaderInvariant(std::move(connId));
1119 }
1120 
parseShortHeader(uint8_t initialByte,folly::io::Cursor & cursor,size_t dstConnIdSize)1121 folly::Expected<ShortHeader, TransportErrorCode> parseShortHeader(
1122     uint8_t initialByte,
1123     folly::io::Cursor& cursor,
1124     size_t dstConnIdSize) {
1125   if (getHeaderForm(initialByte) != HeaderForm::Short) {
1126     VLOG(5) << "Bad header form bit";
1127     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1128   }
1129   if (!(initialByte & ShortHeader::kFixedBitMask)) {
1130     VLOG(5) << "Fixed bit in ShortHeader is 0";
1131     // Specs doesn't say which error code to use
1132     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1133   }
1134   if (initialByte & ShortHeader::kReservedBitsMask) {
1135     VLOG(5) << "Non-zero reserved bits in ShortHeader";
1136     // Specs asks this to be PROTOCOL_VIOLATION
1137     return folly::makeUnexpected(TransportErrorCode::PROTOCOL_VIOLATION);
1138   }
1139   auto invariant =
1140       parseShortHeaderInvariants(initialByte, cursor, dstConnIdSize);
1141   if (!invariant) {
1142     VLOG(5) << "Error parsing short header invariant";
1143     return folly::makeUnexpected(TransportErrorCode::FRAME_ENCODING_ERROR);
1144   }
1145   auto protectionType = initialByte & ShortHeader::kKeyPhaseMask
1146       ? ProtectionType::KeyPhaseOne
1147       : ProtectionType::KeyPhaseZero;
1148   return ShortHeader(protectionType, std::move(invariant->destinationConnId));
1149 }
1150 
1151 } // namespace quic
1152