github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/internal/wire/ack_frame_test.go (about) 1 package wire 2 3 import ( 4 "bytes" 5 "io" 6 "math" 7 "time" 8 9 "github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol" 10 "github.com/danielpfeifer02/quic-go-prio-packs/quicvarint" 11 12 . "github.com/onsi/ginkgo/v2" 13 . "github.com/onsi/gomega" 14 ) 15 16 var _ = Describe("ACK Frame (for IETF QUIC)", func() { 17 Context("parsing", func() { 18 It("parses an ACK frame without any ranges", func() { 19 data := encodeVarInt(100) // largest acked 20 data = append(data, encodeVarInt(0)...) // delay 21 data = append(data, encodeVarInt(0)...) // num blocks 22 data = append(data, encodeVarInt(10)...) // first ack block 23 b := bytes.NewReader(data) 24 var frame AckFrame 25 Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 26 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100))) 27 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90))) 28 Expect(frame.HasMissingRanges()).To(BeFalse()) 29 Expect(b.Len()).To(BeZero()) 30 }) 31 32 It("parses an ACK frame that only acks a single packet", func() { 33 data := encodeVarInt(55) // largest acked 34 data = append(data, encodeVarInt(0)...) // delay 35 data = append(data, encodeVarInt(0)...) // num blocks 36 data = append(data, encodeVarInt(0)...) // first ack block 37 b := bytes.NewReader(data) 38 var frame AckFrame 39 Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 40 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(55))) 41 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(55))) 42 Expect(frame.HasMissingRanges()).To(BeFalse()) 43 Expect(b.Len()).To(BeZero()) 44 }) 45 46 It("accepts an ACK frame that acks all packets from 0 to largest", func() { 47 data := encodeVarInt(20) // largest acked 48 data = append(data, encodeVarInt(0)...) // delay 49 data = append(data, encodeVarInt(0)...) // num blocks 50 data = append(data, encodeVarInt(20)...) // first ack block 51 b := bytes.NewReader(data) 52 var frame AckFrame 53 Expect(parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 54 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(20))) 55 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(0))) 56 Expect(frame.HasMissingRanges()).To(BeFalse()) 57 Expect(b.Len()).To(BeZero()) 58 }) 59 60 It("rejects an ACK frame that has a first ACK block which is larger than LargestAcked", func() { 61 data := encodeVarInt(20) // largest acked 62 data = append(data, encodeVarInt(0)...) // delay 63 data = append(data, encodeVarInt(0)...) // num blocks 64 data = append(data, encodeVarInt(21)...) // first ack block 65 var frame AckFrame 66 Expect(parseAckFrame(&frame, bytes.NewReader(data), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError("invalid first ACK range")) 67 }) 68 69 It("parses an ACK frame that has a single block", func() { 70 data := encodeVarInt(1000) // largest acked 71 data = append(data, encodeVarInt(0)...) // delay 72 data = append(data, encodeVarInt(1)...) // num blocks 73 data = append(data, encodeVarInt(100)...) // first ack block 74 data = append(data, encodeVarInt(98)...) // gap 75 data = append(data, encodeVarInt(50)...) // ack block 76 b := bytes.NewReader(data) 77 var frame AckFrame 78 err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1) 79 Expect(err).ToNot(HaveOccurred()) 80 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(1000))) 81 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(750))) 82 Expect(frame.HasMissingRanges()).To(BeTrue()) 83 Expect(frame.AckRanges).To(Equal([]AckRange{ 84 {Largest: 1000, Smallest: 900}, 85 {Largest: 800, Smallest: 750}, 86 })) 87 Expect(b.Len()).To(BeZero()) 88 }) 89 90 It("parses an ACK frame that has a multiple blocks", func() { 91 data := encodeVarInt(100) // largest acked 92 data = append(data, encodeVarInt(0)...) // delay 93 data = append(data, encodeVarInt(2)...) // num blocks 94 data = append(data, encodeVarInt(0)...) // first ack block 95 data = append(data, encodeVarInt(0)...) // gap 96 data = append(data, encodeVarInt(0)...) // ack block 97 data = append(data, encodeVarInt(1)...) // gap 98 data = append(data, encodeVarInt(1)...) // ack block 99 b := bytes.NewReader(data) 100 var frame AckFrame 101 err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1) 102 Expect(err).ToNot(HaveOccurred()) 103 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100))) 104 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(94))) 105 Expect(frame.HasMissingRanges()).To(BeTrue()) 106 Expect(frame.AckRanges).To(Equal([]AckRange{ 107 {Largest: 100, Smallest: 100}, 108 {Largest: 98, Smallest: 98}, 109 {Largest: 95, Smallest: 94}, 110 })) 111 Expect(b.Len()).To(BeZero()) 112 }) 113 114 It("uses the ack delay exponent", func() { 115 const delayTime = 1 << 10 * time.Millisecond 116 f := &AckFrame{ 117 AckRanges: []AckRange{{Smallest: 1, Largest: 1}}, 118 DelayTime: delayTime, 119 } 120 b, err := f.Append(nil, protocol.Version1) 121 Expect(err).ToNot(HaveOccurred()) 122 for i := uint8(0); i < 8; i++ { 123 r := bytes.NewReader(b) 124 typ, err := quicvarint.Read(r) 125 Expect(err).ToNot(HaveOccurred()) 126 var frame AckFrame 127 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent+i, protocol.Version1)).To(Succeed()) 128 Expect(frame.DelayTime).To(Equal(delayTime * (1 << i))) 129 } 130 }) 131 132 It("gracefully handles overflows of the delay time", func() { 133 data := encodeVarInt(100) // largest acked 134 data = append(data, encodeVarInt(math.MaxUint64/5)...) // delay 135 data = append(data, encodeVarInt(0)...) // num blocks 136 data = append(data, encodeVarInt(0)...) // first ack block 137 b := bytes.NewReader(data) 138 var frame AckFrame 139 err := parseAckFrame(&frame, b, ackFrameType, protocol.AckDelayExponent, protocol.Version1) 140 Expect(err).ToNot(HaveOccurred()) 141 Expect(frame.DelayTime).To(BeNumerically(">", 0)) 142 // The maximum encodable duration is ~292 years. 143 Expect(frame.DelayTime.Hours()).To(BeNumerically("~", 292*365*24, 365*24)) 144 }) 145 146 It("errors on EOF", func() { 147 data := encodeVarInt(1000) // largest acked 148 data = append(data, encodeVarInt(0)...) // delay 149 data = append(data, encodeVarInt(1)...) // num blocks 150 data = append(data, encodeVarInt(100)...) // first ack block 151 data = append(data, encodeVarInt(98)...) // gap 152 data = append(data, encodeVarInt(50)...) // ack block 153 var frame AckFrame 154 Expect(parseAckFrame(&frame, bytes.NewReader(data), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 155 for i := range data { 156 var frame AckFrame 157 Expect(parseAckFrame(&frame, bytes.NewReader(data[:i]), ackFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError(io.EOF)) 158 } 159 }) 160 161 Context("ACK_ECN", func() { 162 It("parses", func() { 163 data := encodeVarInt(100) // largest acked 164 data = append(data, encodeVarInt(0)...) // delay 165 data = append(data, encodeVarInt(0)...) // num blocks 166 data = append(data, encodeVarInt(10)...) // first ack block 167 data = append(data, encodeVarInt(0x42)...) // ECT(0) 168 data = append(data, encodeVarInt(0x12345)...) // ECT(1) 169 data = append(data, encodeVarInt(0x12345678)...) // ECN-CE 170 b := bytes.NewReader(data) 171 var frame AckFrame 172 err := parseAckFrame(&frame, b, ackECNFrameType, protocol.AckDelayExponent, protocol.Version1) 173 Expect(err).ToNot(HaveOccurred()) 174 Expect(frame.LargestAcked()).To(Equal(protocol.PacketNumber(100))) 175 Expect(frame.LowestAcked()).To(Equal(protocol.PacketNumber(90))) 176 Expect(frame.HasMissingRanges()).To(BeFalse()) 177 Expect(frame.ECT0).To(BeEquivalentTo(0x42)) 178 Expect(frame.ECT1).To(BeEquivalentTo(0x12345)) 179 Expect(frame.ECNCE).To(BeEquivalentTo(0x12345678)) 180 Expect(b.Len()).To(BeZero()) 181 }) 182 183 It("errors on EOF", func() { 184 data := encodeVarInt(1000) // largest acked 185 data = append(data, encodeVarInt(0)...) // delay 186 data = append(data, encodeVarInt(1)...) // num blocks 187 data = append(data, encodeVarInt(100)...) // first ack block 188 data = append(data, encodeVarInt(98)...) // gap 189 data = append(data, encodeVarInt(50)...) // ack block 190 data = append(data, encodeVarInt(0x42)...) // ECT(0) 191 data = append(data, encodeVarInt(0x12345)...) // ECT(1) 192 data = append(data, encodeVarInt(0x12345678)...) // ECN-CE 193 var frame AckFrame 194 Expect(parseAckFrame(&frame, bytes.NewReader(data), ackECNFrameType, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 195 for i := range data { 196 var frame AckFrame 197 Expect(parseAckFrame(&frame, bytes.NewReader(data[:i]), ackECNFrameType, protocol.AckDelayExponent, protocol.Version1)).To(MatchError(io.EOF)) 198 } 199 }) 200 }) 201 }) 202 203 Context("when writing", func() { 204 It("writes a simple frame", func() { 205 f := &AckFrame{ 206 AckRanges: []AckRange{{Smallest: 100, Largest: 1337}}, 207 } 208 b, err := f.Append(nil, protocol.Version1) 209 Expect(err).ToNot(HaveOccurred()) 210 expected := []byte{ackFrameType} 211 expected = append(expected, encodeVarInt(1337)...) // largest acked 212 expected = append(expected, 0) // delay 213 expected = append(expected, encodeVarInt(0)...) // num ranges 214 expected = append(expected, encodeVarInt(1337-100)...) 215 Expect(b).To(Equal(expected)) 216 }) 217 218 It("writes an ACK-ECN frame", func() { 219 f := &AckFrame{ 220 AckRanges: []AckRange{{Smallest: 10, Largest: 2000}}, 221 ECT0: 13, 222 ECT1: 37, 223 ECNCE: 12345, 224 } 225 b, err := f.Append(nil, protocol.Version1) 226 Expect(err).ToNot(HaveOccurred()) 227 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 228 expected := []byte{ackECNFrameType} 229 expected = append(expected, encodeVarInt(2000)...) // largest acked 230 expected = append(expected, 0) // delay 231 expected = append(expected, encodeVarInt(0)...) // num ranges 232 expected = append(expected, encodeVarInt(2000-10)...) 233 expected = append(expected, encodeVarInt(13)...) 234 expected = append(expected, encodeVarInt(37)...) 235 expected = append(expected, encodeVarInt(12345)...) 236 Expect(b).To(Equal(expected)) 237 }) 238 239 It("writes a frame that acks a single packet", func() { 240 f := &AckFrame{ 241 AckRanges: []AckRange{{Smallest: 0x2eadbeef, Largest: 0x2eadbeef}}, 242 DelayTime: 18 * time.Millisecond, 243 } 244 b, err := f.Append(nil, protocol.Version1) 245 Expect(err).ToNot(HaveOccurred()) 246 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 247 r := bytes.NewReader(b) 248 typ, err := quicvarint.Read(r) 249 Expect(err).ToNot(HaveOccurred()) 250 var frame AckFrame 251 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 252 Expect(&frame).To(Equal(f)) 253 Expect(frame.HasMissingRanges()).To(BeFalse()) 254 Expect(frame.DelayTime).To(Equal(f.DelayTime)) 255 Expect(r.Len()).To(BeZero()) 256 }) 257 258 It("writes a frame that acks many packets", func() { 259 f := &AckFrame{ 260 AckRanges: []AckRange{{Smallest: 0x1337, Largest: 0x2eadbeef}}, 261 } 262 b, err := f.Append(nil, protocol.Version1) 263 Expect(err).ToNot(HaveOccurred()) 264 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 265 r := bytes.NewReader(b) 266 typ, err := quicvarint.Read(r) 267 Expect(err).ToNot(HaveOccurred()) 268 var frame AckFrame 269 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 270 Expect(&frame).To(Equal(f)) 271 Expect(frame.HasMissingRanges()).To(BeFalse()) 272 Expect(r.Len()).To(BeZero()) 273 }) 274 275 It("writes a frame with a a single gap", func() { 276 f := &AckFrame{ 277 AckRanges: []AckRange{ 278 {Smallest: 400, Largest: 1000}, 279 {Smallest: 100, Largest: 200}, 280 }, 281 } 282 Expect(f.validateAckRanges()).To(BeTrue()) 283 b, err := f.Append(nil, protocol.Version1) 284 Expect(err).ToNot(HaveOccurred()) 285 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 286 r := bytes.NewReader(b) 287 typ, err := quicvarint.Read(r) 288 Expect(err).ToNot(HaveOccurred()) 289 var frame AckFrame 290 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 291 Expect(&frame).To(Equal(f)) 292 Expect(frame.HasMissingRanges()).To(BeTrue()) 293 Expect(r.Len()).To(BeZero()) 294 }) 295 296 It("writes a frame with multiple ranges", func() { 297 f := &AckFrame{ 298 AckRanges: []AckRange{ 299 {Smallest: 10, Largest: 10}, 300 {Smallest: 8, Largest: 8}, 301 {Smallest: 5, Largest: 6}, 302 {Smallest: 1, Largest: 3}, 303 }, 304 } 305 Expect(f.validateAckRanges()).To(BeTrue()) 306 b, err := f.Append(nil, protocol.Version1) 307 Expect(err).ToNot(HaveOccurred()) 308 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 309 r := bytes.NewReader(b) 310 typ, err := quicvarint.Read(r) 311 Expect(err).ToNot(HaveOccurred()) 312 var frame AckFrame 313 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 314 Expect(&frame).To(Equal(f)) 315 Expect(frame.HasMissingRanges()).To(BeTrue()) 316 Expect(r.Len()).To(BeZero()) 317 }) 318 319 It("limits the maximum size of the ACK frame", func() { 320 const numRanges = 1000 321 ackRanges := make([]AckRange, numRanges) 322 for i := protocol.PacketNumber(1); i <= numRanges; i++ { 323 ackRanges[numRanges-i] = AckRange{Smallest: 2 * i, Largest: 2 * i} 324 } 325 f := &AckFrame{AckRanges: ackRanges} 326 Expect(f.validateAckRanges()).To(BeTrue()) 327 b, err := f.Append(nil, protocol.Version1) 328 Expect(err).ToNot(HaveOccurred()) 329 Expect(b).To(HaveLen(int(f.Length(protocol.Version1)))) 330 // make sure the ACK frame is *a little bit* smaller than the MaxAckFrameSize 331 Expect(len(b)).To(BeNumerically(">", protocol.MaxAckFrameSize-5)) 332 Expect(len(b)).To(BeNumerically("<=", protocol.MaxAckFrameSize)) 333 r := bytes.NewReader(b) 334 typ, err := quicvarint.Read(r) 335 Expect(err).ToNot(HaveOccurred()) 336 var frame AckFrame 337 Expect(parseAckFrame(&frame, r, typ, protocol.AckDelayExponent, protocol.Version1)).To(Succeed()) 338 Expect(frame.HasMissingRanges()).To(BeTrue()) 339 Expect(r.Len()).To(BeZero()) 340 Expect(len(frame.AckRanges)).To(BeNumerically("<", numRanges)) // make sure we dropped some ranges 341 }) 342 }) 343 344 Context("ACK range validator", func() { 345 It("rejects ACKs without ranges", func() { 346 Expect((&AckFrame{}).validateAckRanges()).To(BeFalse()) 347 }) 348 349 It("accepts an ACK without NACK Ranges", func() { 350 ack := AckFrame{ 351 AckRanges: []AckRange{{Smallest: 1, Largest: 7}}, 352 } 353 Expect(ack.validateAckRanges()).To(BeTrue()) 354 }) 355 356 It("rejects ACK ranges with Smallest greater than Largest", func() { 357 ack := AckFrame{ 358 AckRanges: []AckRange{ 359 {Smallest: 8, Largest: 10}, 360 {Smallest: 4, Largest: 3}, 361 }, 362 } 363 Expect(ack.validateAckRanges()).To(BeFalse()) 364 }) 365 366 It("rejects ACK ranges in the wrong order", func() { 367 ack := AckFrame{ 368 AckRanges: []AckRange{ 369 {Smallest: 2, Largest: 2}, 370 {Smallest: 6, Largest: 7}, 371 }, 372 } 373 Expect(ack.validateAckRanges()).To(BeFalse()) 374 }) 375 376 It("rejects with overlapping ACK ranges", func() { 377 ack := AckFrame{ 378 AckRanges: []AckRange{ 379 {Smallest: 5, Largest: 7}, 380 {Smallest: 2, Largest: 5}, 381 }, 382 } 383 Expect(ack.validateAckRanges()).To(BeFalse()) 384 }) 385 386 It("rejects ACK ranges that are part of a larger ACK range", func() { 387 ack := AckFrame{ 388 AckRanges: []AckRange{ 389 {Smallest: 4, Largest: 7}, 390 {Smallest: 5, Largest: 6}, 391 }, 392 } 393 Expect(ack.validateAckRanges()).To(BeFalse()) 394 }) 395 396 It("rejects with directly adjacent ACK ranges", func() { 397 ack := AckFrame{ 398 AckRanges: []AckRange{ 399 {Smallest: 5, Largest: 7}, 400 {Smallest: 2, Largest: 4}, 401 }, 402 } 403 Expect(ack.validateAckRanges()).To(BeFalse()) 404 }) 405 406 It("accepts an ACK with one lost packet", func() { 407 ack := AckFrame{ 408 AckRanges: []AckRange{ 409 {Smallest: 5, Largest: 10}, 410 {Smallest: 1, Largest: 3}, 411 }, 412 } 413 Expect(ack.validateAckRanges()).To(BeTrue()) 414 }) 415 416 It("accepts an ACK with multiple lost packets", func() { 417 ack := AckFrame{ 418 AckRanges: []AckRange{ 419 {Smallest: 15, Largest: 20}, 420 {Smallest: 10, Largest: 12}, 421 {Smallest: 1, Largest: 3}, 422 }, 423 } 424 Expect(ack.validateAckRanges()).To(BeTrue()) 425 }) 426 }) 427 428 Context("check if ACK frame acks a certain packet", func() { 429 It("works with an ACK without any ranges", func() { 430 f := AckFrame{ 431 AckRanges: []AckRange{{Smallest: 5, Largest: 10}}, 432 } 433 Expect(f.AcksPacket(1)).To(BeFalse()) 434 Expect(f.AcksPacket(4)).To(BeFalse()) 435 Expect(f.AcksPacket(5)).To(BeTrue()) 436 Expect(f.AcksPacket(8)).To(BeTrue()) 437 Expect(f.AcksPacket(10)).To(BeTrue()) 438 Expect(f.AcksPacket(11)).To(BeFalse()) 439 Expect(f.AcksPacket(20)).To(BeFalse()) 440 }) 441 442 It("works with an ACK with multiple ACK ranges", func() { 443 f := AckFrame{ 444 AckRanges: []AckRange{ 445 {Smallest: 15, Largest: 20}, 446 {Smallest: 5, Largest: 8}, 447 }, 448 } 449 Expect(f.AcksPacket(4)).To(BeFalse()) 450 Expect(f.AcksPacket(5)).To(BeTrue()) 451 Expect(f.AcksPacket(6)).To(BeTrue()) 452 Expect(f.AcksPacket(7)).To(BeTrue()) 453 Expect(f.AcksPacket(8)).To(BeTrue()) 454 Expect(f.AcksPacket(9)).To(BeFalse()) 455 Expect(f.AcksPacket(14)).To(BeFalse()) 456 Expect(f.AcksPacket(15)).To(BeTrue()) 457 Expect(f.AcksPacket(18)).To(BeTrue()) 458 Expect(f.AcksPacket(19)).To(BeTrue()) 459 Expect(f.AcksPacket(20)).To(BeTrue()) 460 Expect(f.AcksPacket(21)).To(BeFalse()) 461 }) 462 }) 463 464 It("resets", func() { 465 f := &AckFrame{ 466 DelayTime: time.Second, 467 AckRanges: []AckRange{{Smallest: 1, Largest: 3}}, 468 ECT0: 1, 469 ECT1: 2, 470 ECNCE: 3, 471 } 472 f.Reset() 473 Expect(f.AckRanges).To(BeEmpty()) 474 Expect(f.AckRanges).To(HaveCap(1)) 475 Expect(f.DelayTime).To(BeZero()) 476 Expect(f.ECT0).To(BeZero()) 477 Expect(f.ECT1).To(BeZero()) 478 Expect(f.ECNCE).To(BeZero()) 479 }) 480 })