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