golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/quic/packet.go (about) 1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build go1.21 6 7 package quic 8 9 import ( 10 "encoding/binary" 11 "fmt" 12 ) 13 14 // packetType is a QUIC packet type. 15 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17 16 type packetType byte 17 18 const ( 19 packetTypeInvalid = packetType(iota) 20 packetTypeInitial 21 packetType0RTT 22 packetTypeHandshake 23 packetTypeRetry 24 packetType1RTT 25 packetTypeVersionNegotiation 26 ) 27 28 func (p packetType) String() string { 29 switch p { 30 case packetTypeInitial: 31 return "Initial" 32 case packetType0RTT: 33 return "0-RTT" 34 case packetTypeHandshake: 35 return "Handshake" 36 case packetTypeRetry: 37 return "Retry" 38 case packetType1RTT: 39 return "1-RTT" 40 } 41 return fmt.Sprintf("unknown packet type %v", byte(p)) 42 } 43 44 func (p packetType) qlogString() string { 45 switch p { 46 case packetTypeInitial: 47 return "initial" 48 case packetType0RTT: 49 return "0RTT" 50 case packetTypeHandshake: 51 return "handshake" 52 case packetTypeRetry: 53 return "retry" 54 case packetType1RTT: 55 return "1RTT" 56 } 57 return "unknown" 58 } 59 60 // Bits set in the first byte of a packet. 61 const ( 62 headerFormLong = 0x80 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.2.1 63 headerFormShort = 0x00 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.3.1-4.2.1 64 fixedBit = 0x40 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.4.1 65 reservedLongBits = 0x0c // https://www.rfc-editor.org/rfc/rfc9000#section-17.2-8.2.1 66 reserved1RTTBits = 0x18 // https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.8.1 67 keyPhaseBit = 0x04 // https://www.rfc-editor.org/rfc/rfc9000#section-17.3.1-4.10.1 68 ) 69 70 // Long Packet Type bits. 71 // https://www.rfc-editor.org/rfc/rfc9000.html#section-17.2-3.6.1 72 const ( 73 longPacketTypeInitial = 0 << 4 74 longPacketType0RTT = 1 << 4 75 longPacketTypeHandshake = 2 << 4 76 longPacketTypeRetry = 3 << 4 77 ) 78 79 // Frame types. 80 // https://www.rfc-editor.org/rfc/rfc9000.html#section-19 81 const ( 82 frameTypePadding = 0x00 83 frameTypePing = 0x01 84 frameTypeAck = 0x02 85 frameTypeAckECN = 0x03 86 frameTypeResetStream = 0x04 87 frameTypeStopSending = 0x05 88 frameTypeCrypto = 0x06 89 frameTypeNewToken = 0x07 90 frameTypeStreamBase = 0x08 // low three bits carry stream flags 91 frameTypeMaxData = 0x10 92 frameTypeMaxStreamData = 0x11 93 frameTypeMaxStreamsBidi = 0x12 94 frameTypeMaxStreamsUni = 0x13 95 frameTypeDataBlocked = 0x14 96 frameTypeStreamDataBlocked = 0x15 97 frameTypeStreamsBlockedBidi = 0x16 98 frameTypeStreamsBlockedUni = 0x17 99 frameTypeNewConnectionID = 0x18 100 frameTypeRetireConnectionID = 0x19 101 frameTypePathChallenge = 0x1a 102 frameTypePathResponse = 0x1b 103 frameTypeConnectionCloseTransport = 0x1c 104 frameTypeConnectionCloseApplication = 0x1d 105 frameTypeHandshakeDone = 0x1e 106 ) 107 108 // The low three bits of STREAM frames. 109 // https://www.rfc-editor.org/rfc/rfc9000.html#section-19.8 110 const ( 111 streamOffBit = 0x04 112 streamLenBit = 0x02 113 streamFinBit = 0x01 114 ) 115 116 // Maximum length of a connection ID. 117 const maxConnIDLen = 20 118 119 // isLongHeader returns true if b is the first byte of a long header. 120 func isLongHeader(b byte) bool { 121 return b&headerFormLong == headerFormLong 122 } 123 124 // getPacketType returns the type of a packet. 125 func getPacketType(b []byte) packetType { 126 if len(b) == 0 { 127 return packetTypeInvalid 128 } 129 if !isLongHeader(b[0]) { 130 if b[0]&fixedBit != fixedBit { 131 return packetTypeInvalid 132 } 133 return packetType1RTT 134 } 135 if len(b) < 5 { 136 return packetTypeInvalid 137 } 138 if b[1] == 0 && b[2] == 0 && b[3] == 0 && b[4] == 0 { 139 // Version Negotiation packets don't necessarily set the fixed bit. 140 return packetTypeVersionNegotiation 141 } 142 if b[0]&fixedBit != fixedBit { 143 return packetTypeInvalid 144 } 145 switch b[0] & 0x30 { 146 case longPacketTypeInitial: 147 return packetTypeInitial 148 case longPacketType0RTT: 149 return packetType0RTT 150 case longPacketTypeHandshake: 151 return packetTypeHandshake 152 case longPacketTypeRetry: 153 return packetTypeRetry 154 } 155 return packetTypeInvalid 156 } 157 158 // dstConnIDForDatagram returns the destination connection ID field of the 159 // first QUIC packet in a datagram. 160 func dstConnIDForDatagram(pkt []byte) (id []byte, ok bool) { 161 if len(pkt) < 1 { 162 return nil, false 163 } 164 var n int 165 var b []byte 166 if isLongHeader(pkt[0]) { 167 if len(pkt) < 6 { 168 return nil, false 169 } 170 n = int(pkt[5]) 171 b = pkt[6:] 172 } else { 173 n = connIDLen 174 b = pkt[1:] 175 } 176 if len(b) < n { 177 return nil, false 178 } 179 return b[:n], true 180 } 181 182 // parseVersionNegotiation parses a Version Negotiation packet. 183 // The returned versions is a slice of big-endian uint32s. 184 // It returns (nil, nil, nil) for an invalid packet. 185 func parseVersionNegotiation(pkt []byte) (dstConnID, srcConnID, versions []byte) { 186 p, ok := parseGenericLongHeaderPacket(pkt) 187 if !ok { 188 return nil, nil, nil 189 } 190 if len(p.data)%4 != 0 { 191 return nil, nil, nil 192 } 193 return p.dstConnID, p.srcConnID, p.data 194 } 195 196 // appendVersionNegotiation appends a Version Negotiation packet to pkt, 197 // returning the result. 198 func appendVersionNegotiation(pkt, dstConnID, srcConnID []byte, versions ...uint32) []byte { 199 pkt = append(pkt, headerFormLong|fixedBit) // header byte 200 pkt = append(pkt, 0, 0, 0, 0) // Version (0 for Version Negotiation) 201 pkt = appendUint8Bytes(pkt, dstConnID) // Destination Connection ID 202 pkt = appendUint8Bytes(pkt, srcConnID) // Source Connection ID 203 for _, v := range versions { 204 pkt = binary.BigEndian.AppendUint32(pkt, v) // Supported Version 205 } 206 return pkt 207 } 208 209 // A longPacket is a long header packet. 210 type longPacket struct { 211 ptype packetType 212 version uint32 213 num packetNumber 214 dstConnID []byte 215 srcConnID []byte 216 payload []byte 217 218 // The extra data depends on the packet type: 219 // Initial: Token. 220 // Retry: Retry token and integrity tag. 221 extra []byte 222 } 223 224 // A shortPacket is a short header (1-RTT) packet. 225 type shortPacket struct { 226 num packetNumber 227 payload []byte 228 } 229 230 // A genericLongPacket is a long header packet of an arbitrary QUIC version. 231 // https://www.rfc-editor.org/rfc/rfc8999#section-5.1 232 type genericLongPacket struct { 233 version uint32 234 dstConnID []byte 235 srcConnID []byte 236 data []byte 237 } 238 239 func parseGenericLongHeaderPacket(b []byte) (p genericLongPacket, ok bool) { 240 if len(b) < 5 || !isLongHeader(b[0]) { 241 return genericLongPacket{}, false 242 } 243 b = b[1:] 244 // Version (32), 245 var n int 246 p.version, n = consumeUint32(b) 247 if n < 0 { 248 return genericLongPacket{}, false 249 } 250 b = b[n:] 251 // Destination Connection ID Length (8), 252 // Destination Connection ID (0..2048), 253 p.dstConnID, n = consumeUint8Bytes(b) 254 if n < 0 || len(p.dstConnID) > 2048/8 { 255 return genericLongPacket{}, false 256 } 257 b = b[n:] 258 // Source Connection ID Length (8), 259 // Source Connection ID (0..2048), 260 p.srcConnID, n = consumeUint8Bytes(b) 261 if n < 0 || len(p.dstConnID) > 2048/8 { 262 return genericLongPacket{}, false 263 } 264 b = b[n:] 265 p.data = b 266 return p, true 267 }