github.com/metacubex/quic-go@v0.44.1-0.20240520163451-20b689a59136/internal/wire/header_test.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "crypto/rand" 6 "encoding/binary" 7 "io" 8 mrand "math/rand" 9 "testing" 10 "time" 11 12 "github.com/metacubex/quic-go/internal/protocol" 13 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 ) 17 18 var _ = Describe("Header Parsing", func() { 19 Context("Parsing the Connection ID", func() { 20 It("parses the connection ID of a long header packet", func() { 21 b, err := (&ExtendedHeader{ 22 Header: Header{ 23 Type: protocol.PacketTypeHandshake, 24 DestConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}), 25 SrcConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6}), 26 Version: protocol.Version1, 27 }, 28 PacketNumberLen: 2, 29 }).Append(nil, protocol.Version1) 30 Expect(err).ToNot(HaveOccurred()) 31 connID, err := ParseConnectionID(b, 8) 32 Expect(err).ToNot(HaveOccurred()) 33 Expect(connID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad}))) 34 }) 35 36 It("errors on EOF, for long header packets", func() { 37 b, err := (&ExtendedHeader{ 38 Header: Header{ 39 Type: protocol.PacketTypeHandshake, 40 DestConnectionID: protocol.ParseConnectionID([]byte{0xde, 0xca, 0xfb, 0xad, 0x13, 0x37}), 41 SrcConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 8, 9}), 42 Version: protocol.Version1, 43 }, 44 PacketNumberLen: 2, 45 }).Append(nil, protocol.Version1) 46 Expect(err).ToNot(HaveOccurred()) 47 data := b[:len(b)-2] // cut the packet number 48 _, err = ParseConnectionID(data, 8) 49 Expect(err).ToNot(HaveOccurred()) 50 for i := 0; i < 1 /* first byte */ +4 /* version */ +1 /* conn ID lengths */ +6; /* dest conn ID */ i++ { 51 b := make([]byte, i) 52 copy(b, data[:i]) 53 _, err := ParseConnectionID(b, 8) 54 Expect(err).To(MatchError(io.EOF)) 55 } 56 }) 57 58 It("errors when encountering a too long connection ID", func() { 59 b := []byte{0x80, 0, 0, 0, 0} 60 binary.BigEndian.PutUint32(b[1:], uint32(protocol.Version1)) 61 b = append(b, 21) // dest conn id len 62 b = append(b, make([]byte, 21)...) 63 _, err := ParseConnectionID(b, 4) 64 Expect(err).To(MatchError(protocol.ErrInvalidConnectionIDLen)) 65 }) 66 }) 67 68 Context("identifying 0-RTT packets", func() { 69 It("recognizes 0-RTT packets, for QUIC v1", func() { 70 zeroRTTHeader := make([]byte, 5) 71 zeroRTTHeader[0] = 0x80 | 0b01<<4 72 binary.BigEndian.PutUint32(zeroRTTHeader[1:], uint32(protocol.Version1)) 73 74 Expect(Is0RTTPacket(zeroRTTHeader)).To(BeTrue()) 75 Expect(Is0RTTPacket(zeroRTTHeader[:4])).To(BeFalse()) // too short 76 Expect(Is0RTTPacket([]byte{zeroRTTHeader[0], 1, 2, 3, 4})).To(BeFalse()) // unknown version 77 Expect(Is0RTTPacket([]byte{zeroRTTHeader[0] | 0x80, 1, 2, 3, 4})).To(BeFalse()) // short header 78 Expect(Is0RTTPacket(append(zeroRTTHeader, []byte("foobar")...))).To(BeTrue()) 79 }) 80 81 It("recognizes 0-RTT packets, for QUIC v2", func() { 82 zeroRTTHeader := make([]byte, 5) 83 zeroRTTHeader[0] = 0x80 | 0b10<<4 84 binary.BigEndian.PutUint32(zeroRTTHeader[1:], uint32(protocol.Version2)) 85 86 Expect(Is0RTTPacket(zeroRTTHeader)).To(BeTrue()) 87 Expect(Is0RTTPacket(zeroRTTHeader[:4])).To(BeFalse()) // too short 88 Expect(Is0RTTPacket([]byte{zeroRTTHeader[0], 1, 2, 3, 4})).To(BeFalse()) // unknown version 89 Expect(Is0RTTPacket([]byte{zeroRTTHeader[0] | 0x80, 1, 2, 3, 4})).To(BeFalse()) // short header 90 Expect(Is0RTTPacket(append(zeroRTTHeader, []byte("foobar")...))).To(BeTrue()) 91 }) 92 }) 93 Context("parsing the version", func() { 94 It("parses the version", func() { 95 b := []byte{0x80, 0xde, 0xad, 0xbe, 0xef} 96 v, err := ParseVersion(b) 97 Expect(err).ToNot(HaveOccurred()) 98 Expect(v).To(Equal(protocol.Version(0xdeadbeef))) 99 }) 100 101 It("errors with EOF", func() { 102 b := []byte{0x80, 0xde, 0xad, 0xbe, 0xef} 103 _, err := ParseVersion(b) 104 Expect(err).ToNot(HaveOccurred()) 105 for i := range b { 106 _, err := ParseVersion(b[:i]) 107 Expect(err).To(MatchError(io.EOF)) 108 } 109 }) 110 }) 111 112 Context("parsing arbitrary length connection IDs", func() { 113 generateConnID := func(l int) protocol.ArbitraryLenConnectionID { 114 c := make(protocol.ArbitraryLenConnectionID, l) 115 rand.Read(c) 116 return c 117 } 118 119 generatePacket := func(src, dest protocol.ArbitraryLenConnectionID) []byte { 120 b := []byte{0x80, 1, 2, 3, 4} 121 b = append(b, uint8(dest.Len())) 122 b = append(b, dest.Bytes()...) 123 b = append(b, uint8(src.Len())) 124 b = append(b, src.Bytes()...) 125 return b 126 } 127 128 It("parses arbitrary length connection IDs", func() { 129 src := generateConnID(mrand.Intn(255) + 1) 130 dest := generateConnID(mrand.Intn(255) + 1) 131 b := generatePacket(src, dest) 132 l := len(b) 133 b = append(b, []byte("foobar")...) // add some payload 134 135 parsed, d, s, err := ParseArbitraryLenConnectionIDs(b) 136 Expect(parsed).To(Equal(l)) 137 Expect(err).ToNot(HaveOccurred()) 138 Expect(s).To(Equal(src)) 139 Expect(d).To(Equal(dest)) 140 }) 141 142 It("errors on EOF", func() { 143 b := generatePacket(generateConnID(mrand.Intn(255)+1), generateConnID(mrand.Intn(255)+1)) 144 _, _, _, err := ParseArbitraryLenConnectionIDs(b) 145 Expect(err).ToNot(HaveOccurred()) 146 147 for i := range b { 148 _, _, _, err := ParseArbitraryLenConnectionIDs(b[:i]) 149 Expect(err).To(MatchError(io.EOF)) 150 } 151 }) 152 }) 153 154 Context("Identifying Version Negotiation Packets", func() { 155 It("identifies version negotiation packets", func() { 156 Expect(IsVersionNegotiationPacket([]byte{0x80 | 0x56, 0, 0, 0, 0})).To(BeTrue()) 157 Expect(IsVersionNegotiationPacket([]byte{0x56, 0, 0, 0, 0})).To(BeFalse()) 158 Expect(IsVersionNegotiationPacket([]byte{0x80, 1, 0, 0, 0})).To(BeFalse()) 159 Expect(IsVersionNegotiationPacket([]byte{0x80, 0, 1, 0, 0})).To(BeFalse()) 160 Expect(IsVersionNegotiationPacket([]byte{0x80, 0, 0, 1, 0})).To(BeFalse()) 161 Expect(IsVersionNegotiationPacket([]byte{0x80, 0, 0, 0, 1})).To(BeFalse()) 162 }) 163 164 It("returns false on EOF", func() { 165 vnp := []byte{0x80, 0, 0, 0, 0} 166 for i := range vnp { 167 Expect(IsVersionNegotiationPacket(vnp[:i])).To(BeFalse()) 168 } 169 }) 170 }) 171 172 Context("Long Headers", func() { 173 It("parses a Long Header", func() { 174 destConnID := protocol.ParseConnectionID([]byte{9, 8, 7, 6, 5, 4, 3, 2, 1}) 175 srcConnID := protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}) 176 data := []byte{0xc0 ^ 0x3} 177 data = appendVersion(data, protocol.Version1) 178 data = append(data, 0x9) // dest conn id length 179 data = append(data, destConnID.Bytes()...) 180 data = append(data, 0x4) // src conn id length 181 data = append(data, srcConnID.Bytes()...) 182 data = append(data, encodeVarInt(6)...) // token length 183 data = append(data, []byte("foobar")...) // token 184 data = append(data, encodeVarInt(10)...) // length 185 hdrLen := len(data) 186 data = append(data, []byte{0, 0, 0xbe, 0xef}...) // packet number 187 data = append(data, []byte("foobar")...) 188 Expect(IsVersionNegotiationPacket(data)).To(BeFalse()) 189 190 hdr, pdata, rest, err := ParsePacket(data) 191 Expect(err).ToNot(HaveOccurred()) 192 Expect(pdata).To(Equal(data)) 193 Expect(hdr.DestConnectionID).To(Equal(destConnID)) 194 Expect(hdr.SrcConnectionID).To(Equal(srcConnID)) 195 Expect(hdr.Type).To(Equal(protocol.PacketTypeInitial)) 196 Expect(hdr.Token).To(Equal([]byte("foobar"))) 197 Expect(hdr.Length).To(Equal(protocol.ByteCount(10))) 198 Expect(hdr.Version).To(Equal(protocol.Version1)) 199 Expect(rest).To(BeEmpty()) 200 b := bytes.NewReader(data) 201 extHdr, err := hdr.ParseExtended(b, protocol.Version1) 202 Expect(err).ToNot(HaveOccurred()) 203 Expect(extHdr.PacketNumber).To(Equal(protocol.PacketNumber(0xbeef))) 204 Expect(extHdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen4)) 205 Expect(b.Len()).To(Equal(6)) // foobar 206 Expect(hdr.ParsedLen()).To(BeEquivalentTo(hdrLen)) 207 Expect(extHdr.ParsedLen()).To(Equal(hdr.ParsedLen() + 4)) 208 }) 209 210 It("errors if 0x40 is not set", func() { 211 data := []byte{ 212 0x80 | 0x2<<4, 213 0x11, // connection ID lengths 214 0xde, 0xca, 0xfb, 0xad, // dest conn ID 215 0xde, 0xad, 0xbe, 0xef, // src conn ID 216 } 217 _, _, _, err := ParsePacket(data) 218 Expect(err).To(MatchError("not a QUIC packet")) 219 }) 220 221 It("stops parsing when encountering an unsupported version", func() { 222 data := []byte{ 223 0xc0, 224 0xde, 0xad, 0xbe, 0xef, 225 0x8, // dest conn ID len 226 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, // dest conn ID 227 0x8, // src conn ID len 228 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, // src conn ID 229 'f', 'o', 'o', 'b', 'a', 'r', // unspecified bytes 230 } 231 hdr, _, rest, err := ParsePacket(data) 232 Expect(err).To(MatchError(ErrUnsupportedVersion)) 233 Expect(hdr.Version).To(Equal(protocol.Version(0xdeadbeef))) 234 Expect(hdr.DestConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8}))) 235 Expect(hdr.SrcConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1}))) 236 Expect(rest).To(BeEmpty()) 237 }) 238 239 It("parses a Long Header without a destination connection ID", func() { 240 data := []byte{0xc0 ^ 0x1<<4} 241 data = appendVersion(data, protocol.Version1) 242 data = append(data, 0) // dest conn ID len 243 data = append(data, 4) // src conn ID len 244 data = append(data, []byte{0xde, 0xad, 0xbe, 0xef}...) // source connection ID 245 data = append(data, encodeVarInt(0)...) // length 246 data = append(data, []byte{0xde, 0xca, 0xfb, 0xad}...) 247 hdr, _, _, err := ParsePacket(data) 248 Expect(err).ToNot(HaveOccurred()) 249 Expect(hdr.Type).To(Equal(protocol.PacketType0RTT)) 250 Expect(hdr.SrcConnectionID).To(Equal(protocol.ParseConnectionID([]byte{0xde, 0xad, 0xbe, 0xef}))) 251 Expect(hdr.DestConnectionID).To(BeZero()) 252 }) 253 254 It("parses a Long Header without a source connection ID", func() { 255 data := []byte{0xc0 ^ 0x2<<4} 256 data = appendVersion(data, protocol.Version1) 257 data = append(data, 10) // dest conn ID len 258 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}...) // dest connection ID 259 data = append(data, 0) // src conn ID len 260 data = append(data, encodeVarInt(0)...) // length 261 data = append(data, []byte{0xde, 0xca, 0xfb, 0xad}...) 262 hdr, _, _, err := ParsePacket(data) 263 Expect(err).ToNot(HaveOccurred()) 264 Expect(hdr.SrcConnectionID).To(BeZero()) 265 Expect(hdr.DestConnectionID).To(Equal(protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))) 266 }) 267 268 It("parses a Long Header without a too long destination connection ID", func() { 269 data := []byte{0xc0 ^ 0x2<<4} 270 data = appendVersion(data, protocol.Version1) 271 data = append(data, 21) // dest conn ID len 272 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}...) // dest connection ID 273 data = append(data, 0x0) // src conn ID len 274 data = append(data, encodeVarInt(0)...) // length 275 data = append(data, []byte{0xde, 0xca, 0xfb, 0xad}...) 276 _, _, _, err := ParsePacket(data) 277 Expect(err).To(MatchError(protocol.ErrInvalidConnectionIDLen)) 278 }) 279 280 It("parses a Long Header with a 2 byte packet number", func() { 281 data := []byte{0xc0 ^ 0x1} 282 data = appendVersion(data, protocol.Version1) // version number 283 data = append(data, []byte{0x0, 0x0}...) // connection ID lengths 284 data = append(data, encodeVarInt(0)...) // token length 285 data = append(data, encodeVarInt(0)...) // length 286 data = append(data, []byte{0x1, 0x23}...) 287 288 hdr, _, _, err := ParsePacket(data) 289 Expect(err).ToNot(HaveOccurred()) 290 b := bytes.NewReader(data) 291 extHdr, err := hdr.ParseExtended(b, protocol.Version1) 292 Expect(err).ToNot(HaveOccurred()) 293 Expect(extHdr.PacketNumber).To(Equal(protocol.PacketNumber(0x123))) 294 Expect(extHdr.PacketNumberLen).To(Equal(protocol.PacketNumberLen2)) 295 Expect(b.Len()).To(BeZero()) 296 }) 297 298 It("parses a Retry packet, for QUIC v1", func() { 299 data := []byte{0xc0 | 0b11<<4 | (10 - 3) /* connection ID length */} 300 data = appendVersion(data, protocol.Version1) 301 data = append(data, []byte{6}...) // dest conn ID len 302 data = append(data, []byte{6, 5, 4, 3, 2, 1}...) // dest conn ID 303 data = append(data, []byte{10}...) // src conn ID len 304 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}...) // source connection ID 305 data = append(data, []byte{'f', 'o', 'o', 'b', 'a', 'r'}...) // token 306 data = append(data, []byte{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}...) 307 hdr, pdata, rest, err := ParsePacket(data) 308 Expect(err).ToNot(HaveOccurred()) 309 Expect(hdr.Type).To(Equal(protocol.PacketTypeRetry)) 310 Expect(hdr.Version).To(Equal(protocol.Version1)) 311 Expect(hdr.DestConnectionID).To(Equal(protocol.ParseConnectionID([]byte{6, 5, 4, 3, 2, 1}))) 312 Expect(hdr.SrcConnectionID).To(Equal(protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))) 313 Expect(hdr.Token).To(Equal([]byte("foobar"))) 314 Expect(pdata).To(Equal(data)) 315 Expect(rest).To(BeEmpty()) 316 }) 317 318 It("parses a Retry packet, for QUIC v2", func() { 319 data := []byte{0xc0 | 0b00<<4 | (10 - 3) /* connection ID length */} 320 data = appendVersion(data, protocol.Version2) 321 data = append(data, []byte{6}...) // dest conn ID len 322 data = append(data, []byte{6, 5, 4, 3, 2, 1}...) // dest conn ID 323 data = append(data, []byte{10}...) // src conn ID len 324 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}...) // source connection ID 325 data = append(data, []byte{'f', 'o', 'o', 'b', 'a', 'r'}...) // token 326 data = append(data, []byte{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}...) 327 hdr, pdata, rest, err := ParsePacket(data) 328 Expect(err).ToNot(HaveOccurred()) 329 Expect(hdr.Type).To(Equal(protocol.PacketTypeRetry)) 330 Expect(hdr.Version).To(Equal(protocol.Version2)) 331 Expect(hdr.DestConnectionID).To(Equal(protocol.ParseConnectionID([]byte{6, 5, 4, 3, 2, 1}))) 332 Expect(hdr.SrcConnectionID).To(Equal(protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}))) 333 Expect(hdr.Token).To(Equal([]byte("foobar"))) 334 Expect(pdata).To(Equal(data)) 335 Expect(rest).To(BeEmpty()) 336 }) 337 338 It("errors if the Retry packet is too short for the integrity tag", func() { 339 data := []byte{0xc0 | 0x3<<4 | (10 - 3) /* connection ID length */} 340 data = appendVersion(data, protocol.Version1) 341 data = append(data, []byte{0, 0}...) // conn ID lens 342 data = append(data, []byte{'f', 'o', 'o', 'b', 'a', 'r'}...) // token 343 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}...) 344 // this results in a token length of 0 345 _, _, _, err := ParsePacket(data) 346 Expect(err).To(MatchError(io.EOF)) 347 }) 348 349 It("errors if the token length is too large", func() { 350 data := []byte{0xc0 ^ 0x1} 351 data = appendVersion(data, protocol.Version1) 352 data = append(data, 0x0) // connection ID lengths 353 data = append(data, encodeVarInt(4)...) // token length: 4 bytes (1 byte too long) 354 data = append(data, encodeVarInt(0x42)...) // length, 1 byte 355 data = append(data, []byte{0x12, 0x34}...) // packet number 356 357 _, _, _, err := ParsePacket(data) 358 Expect(err).To(MatchError(io.EOF)) 359 }) 360 361 It("errors if the 5th or 6th bit are set", func() { 362 data := []byte{0xc0 | 0x2<<4 | 0x8 /* set the 5th bit */ | 0x1 /* 2 byte packet number */} 363 data = appendVersion(data, protocol.Version1) 364 data = append(data, []byte{0x0, 0x0}...) // connection ID lengths 365 data = append(data, encodeVarInt(2)...) // length 366 data = append(data, []byte{0x12, 0x34}...) // packet number 367 hdr, _, _, err := ParsePacket(data) 368 Expect(err).ToNot(HaveOccurred()) 369 Expect(hdr.Type).To(Equal(protocol.PacketTypeHandshake)) 370 extHdr, err := hdr.ParseExtended(bytes.NewReader(data), protocol.Version1) 371 Expect(err).To(MatchError(ErrInvalidReservedBits)) 372 Expect(extHdr).ToNot(BeNil()) 373 Expect(extHdr.PacketNumber).To(Equal(protocol.PacketNumber(0x1234))) 374 }) 375 376 It("errors on EOF, when parsing the header", func() { 377 data := []byte{0xc0 ^ 0x2<<4} 378 data = appendVersion(data, protocol.Version1) 379 data = append(data, 0x8) // dest conn ID len 380 data = append(data, []byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}...) // dest conn ID 381 data = append(data, 0x8) // src conn ID len 382 data = append(data, []byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37}...) // src conn ID 383 for i := 1; i < len(data); i++ { 384 _, _, _, err := ParsePacket(data[:i]) 385 Expect(err).To(Equal(io.EOF)) 386 } 387 }) 388 389 It("errors on EOF, when parsing the extended header", func() { 390 data := []byte{0xc0 | 0x2<<4 | 0x3} 391 data = appendVersion(data, protocol.Version1) 392 data = append(data, []byte{0x0, 0x0}...) // connection ID lengths 393 data = append(data, encodeVarInt(0)...) // length 394 hdrLen := len(data) 395 data = append(data, []byte{0xde, 0xad, 0xbe, 0xef}...) // packet number 396 for i := hdrLen; i < len(data); i++ { 397 data = data[:i] 398 hdr, _, _, err := ParsePacket(data) 399 Expect(err).ToNot(HaveOccurred()) 400 b := bytes.NewReader(data) 401 _, err = hdr.ParseExtended(b, protocol.Version1) 402 Expect(err).To(Equal(io.EOF)) 403 } 404 }) 405 406 It("errors on EOF, for a Retry packet", func() { 407 data := []byte{0xc0 ^ 0x3<<4} 408 data = appendVersion(data, protocol.Version1) 409 data = append(data, []byte{0x0, 0x0}...) // connection ID lengths 410 data = append(data, 0xa) // Orig Destination Connection ID length 411 data = append(data, []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}...) // source connection ID 412 hdrLen := len(data) 413 for i := hdrLen; i < len(data); i++ { 414 data = data[:i] 415 hdr, _, _, err := ParsePacket(data) 416 Expect(err).ToNot(HaveOccurred()) 417 b := bytes.NewReader(data) 418 _, err = hdr.ParseExtended(b, protocol.Version1) 419 Expect(err).To(Equal(io.EOF)) 420 } 421 }) 422 423 Context("coalesced packets", func() { 424 It("cuts packets", func() { 425 hdr := Header{ 426 Type: protocol.PacketTypeInitial, 427 DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4}), 428 Length: 2 + 6, 429 Version: protocol.Version1, 430 } 431 b, err := (&ExtendedHeader{ 432 Header: hdr, 433 PacketNumber: 0x1337, 434 PacketNumberLen: 2, 435 }).Append(nil, protocol.Version1) 436 Expect(err).ToNot(HaveOccurred()) 437 hdrRaw := append([]byte{}, b...) 438 b = append(b, []byte("foobar")...) // payload of the first packet 439 b = append(b, []byte("raboof")...) // second packet 440 parsedHdr, data, rest, err := ParsePacket(b) 441 Expect(err).ToNot(HaveOccurred()) 442 Expect(parsedHdr.Type).To(Equal(hdr.Type)) 443 Expect(parsedHdr.DestConnectionID).To(Equal(hdr.DestConnectionID)) 444 Expect(data).To(Equal(append(hdrRaw, []byte("foobar")...))) 445 Expect(rest).To(Equal([]byte("raboof"))) 446 }) 447 448 It("errors on packets that are smaller than the length in the packet header, for too small packet number", func() { 449 b, err := (&ExtendedHeader{ 450 Header: Header{ 451 Type: protocol.PacketTypeInitial, 452 DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4}), 453 Length: 3, 454 Version: protocol.Version1, 455 }, 456 PacketNumber: 0x1337, 457 PacketNumberLen: 2, 458 }).Append(nil, protocol.Version1) 459 Expect(err).ToNot(HaveOccurred()) 460 _, _, _, err = ParsePacket(b) 461 Expect(err).To(HaveOccurred()) 462 Expect(err.Error()).To(ContainSubstring("packet length (2 bytes) is smaller than the expected length (3 bytes)")) 463 }) 464 465 It("errors on packets that are smaller than the length in the packet header, for too small payload", func() { 466 b, err := (&ExtendedHeader{ 467 Header: Header{ 468 Type: protocol.PacketTypeInitial, 469 DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4}), 470 Length: 1000, 471 Version: protocol.Version1, 472 }, 473 PacketNumber: 0x1337, 474 PacketNumberLen: 2, 475 }).Append(nil, protocol.Version1) 476 Expect(err).ToNot(HaveOccurred()) 477 b = append(b, make([]byte, 500-2 /* for packet number length */)...) 478 _, _, _, err = ParsePacket(b) 479 Expect(err).To(MatchError("packet length (500 bytes) is smaller than the expected length (1000 bytes)")) 480 }) 481 }) 482 }) 483 484 It("distinguishes long and short header packets", func() { 485 Expect(IsLongHeaderPacket(0x40)).To(BeFalse()) 486 Expect(IsLongHeaderPacket(0x80 ^ 0x40 ^ 0x12)).To(BeTrue()) 487 }) 488 489 It("tells its packet type for logging", func() { 490 Expect((&Header{Type: protocol.PacketTypeInitial}).PacketType()).To(Equal("Initial")) 491 Expect((&Header{Type: protocol.PacketTypeHandshake}).PacketType()).To(Equal("Handshake")) 492 }) 493 }) 494 495 func BenchmarkIs0RTTPacket(b *testing.B) { 496 random := mrand.New(mrand.NewSource(time.Now().UnixNano())) 497 packets := make([][]byte, 1024) 498 for i := 0; i < len(packets); i++ { 499 packets[i] = make([]byte, random.Intn(256)) 500 random.Read(packets[i]) 501 } 502 503 b.ResetTimer() 504 for i := 0; i < b.N; i++ { 505 Is0RTTPacket(packets[i%len(packets)]) 506 } 507 } 508 509 func BenchmarkParseInitial(b *testing.B) { 510 b.Run("without token", func(b *testing.B) { 511 benchmarkInitialPacketParsing(b, nil) 512 }) 513 b.Run("with token", func(b *testing.B) { 514 token := make([]byte, 32) 515 rand.Read(token) 516 benchmarkInitialPacketParsing(b, token) 517 }) 518 } 519 520 func benchmarkInitialPacketParsing(b *testing.B, token []byte) { 521 hdr := Header{ 522 Type: protocol.PacketTypeInitial, 523 DestConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}), 524 SrcConnectionID: protocol.ParseConnectionID([]byte{8, 7, 6, 5, 4, 3, 2, 1}), 525 Length: 1000, 526 Token: token, 527 Version: protocol.Version1, 528 } 529 data, err := (&ExtendedHeader{ 530 Header: hdr, 531 PacketNumber: 0x1337, 532 PacketNumberLen: 4, 533 }).Append(nil, protocol.Version1) 534 if err != nil { 535 b.Fatal(err) 536 } 537 data = append(data, make([]byte, 1000)...) 538 539 b.ResetTimer() 540 b.ReportAllocs() 541 for i := 0; i < b.N; i++ { 542 h, _, _, err := ParsePacket(data) 543 if err != nil { 544 b.Fatal(err) 545 } 546 if h.Type != hdr.Type || h.DestConnectionID != hdr.DestConnectionID || h.SrcConnectionID != hdr.SrcConnectionID || 547 !bytes.Equal(h.Token, hdr.Token) { 548 b.Fatalf("headers don't match: %v vs %v", h, hdr) 549 } 550 } 551 } 552 553 func BenchmarkParseRetry(b *testing.B) { 554 token := make([]byte, 64) 555 rand.Read(token) 556 hdr := &ExtendedHeader{ 557 Header: Header{ 558 Type: protocol.PacketTypeRetry, 559 SrcConnectionID: protocol.ParseConnectionID([]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}), 560 DestConnectionID: protocol.ParseConnectionID([]byte{8, 7, 6, 5, 4, 3, 2, 1}), 561 Token: token, 562 Version: protocol.Version1, 563 }, 564 } 565 data, err := hdr.Append(nil, hdr.Version) 566 if err != nil { 567 b.Fatal(err) 568 } 569 570 b.ResetTimer() 571 b.ReportAllocs() 572 for i := 0; i < b.N; i++ { 573 h, _, _, err := ParsePacket(data) 574 if err != nil { 575 b.Fatal(err) 576 } 577 if h.Type != hdr.Type || h.DestConnectionID != hdr.DestConnectionID || h.SrcConnectionID != hdr.SrcConnectionID || 578 !bytes.Equal(h.Token, hdr.Token[:len(hdr.Token)-16]) { 579 b.Fatalf("headers don't match: %#v vs %#v", h, hdr) 580 } 581 } 582 }