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