diff --git a/frames/ack_frame.go b/frames/ack_frame.go index be721624b..06aafaefb 100644 --- a/frames/ack_frame.go +++ b/frames/ack_frame.go @@ -57,13 +57,13 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, missingSequenceNumberDeltaLen = 1 } - largestAcked, err := utils.LittleEndian.ReadUintN(r, largestAckedLen) + largestAcked, err := utils.GetByteOrder(version).ReadUintN(r, largestAckedLen) if err != nil { return nil, err } frame.LargestAcked = protocol.PacketNumber(largestAcked) - delay, err := utils.LittleEndian.ReadUfloat16(r) + delay, err := utils.GetByteOrder(version).ReadUfloat16(r) if err != nil { return nil, err } @@ -81,7 +81,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, return nil, ErrInvalidAckRanges } - ackBlockLength, err := utils.LittleEndian.ReadUintN(r, missingSequenceNumberDeltaLen) + ackBlockLength, err := utils.GetByteOrder(version).ReadUintN(r, missingSequenceNumberDeltaLen) if err != nil { return nil, err } @@ -109,7 +109,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, return nil, err } - ackBlockLength, err = utils.LittleEndian.ReadUintN(r, missingSequenceNumberDeltaLen) + ackBlockLength, err = utils.GetByteOrder(version).ReadUintN(r, missingSequenceNumberDeltaLen) if err != nil { return nil, err } @@ -167,7 +167,7 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, return nil, err } // First Timestamp - _, err = utils.LittleEndian.ReadUint32(r) + _, err = utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } @@ -180,13 +180,12 @@ func ParseAckFrame(r *bytes.Reader, version protocol.VersionNumber) (*AckFrame, } // Time Since Previous Timestamp - _, err = utils.LittleEndian.ReadUint16(r) + _, err = utils.GetByteOrder(version).ReadUint16(r) if err != nil { return nil, err } } } - return frame, nil } @@ -215,15 +214,15 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error case protocol.PacketNumberLen1: b.WriteByte(uint8(f.LargestAcked)) case protocol.PacketNumberLen2: - utils.LittleEndian.WriteUint16(b, uint16(f.LargestAcked)) + utils.GetByteOrder(version).WriteUint16(b, uint16(f.LargestAcked)) case protocol.PacketNumberLen4: - utils.LittleEndian.WriteUint32(b, uint32(f.LargestAcked)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.LargestAcked)) case protocol.PacketNumberLen6: - utils.LittleEndian.WriteUint48(b, uint64(f.LargestAcked)&(1<<48-1)) + utils.GetByteOrder(version).WriteUint48(b, uint64(f.LargestAcked)&(1<<48-1)) } f.DelayTime = time.Since(f.PacketReceivedTime) - utils.LittleEndian.WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond)) + utils.GetByteOrder(version).WriteUfloat16(b, uint64(f.DelayTime/time.Microsecond)) var numRanges uint64 var numRangesWritten uint64 @@ -253,11 +252,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error case protocol.PacketNumberLen1: b.WriteByte(uint8(firstAckBlockLength)) case protocol.PacketNumberLen2: - utils.LittleEndian.WriteUint16(b, uint16(firstAckBlockLength)) + utils.GetByteOrder(version).WriteUint16(b, uint16(firstAckBlockLength)) case protocol.PacketNumberLen4: - utils.LittleEndian.WriteUint32(b, uint32(firstAckBlockLength)) + utils.GetByteOrder(version).WriteUint32(b, uint32(firstAckBlockLength)) case protocol.PacketNumberLen6: - utils.LittleEndian.WriteUint48(b, uint64(firstAckBlockLength)&(1<<48-1)) + utils.GetByteOrder(version).WriteUint48(b, uint64(firstAckBlockLength)&(1<<48-1)) } for i, ackRange := range f.AckRanges { @@ -279,11 +278,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error case protocol.PacketNumberLen1: b.WriteByte(uint8(length)) case protocol.PacketNumberLen2: - utils.LittleEndian.WriteUint16(b, uint16(length)) + utils.GetByteOrder(version).WriteUint16(b, uint16(length)) case protocol.PacketNumberLen4: - utils.LittleEndian.WriteUint32(b, uint32(length)) + utils.GetByteOrder(version).WriteUint32(b, uint32(length)) case protocol.PacketNumberLen6: - utils.LittleEndian.WriteUint48(b, uint64(length)&(1<<48-1)) + utils.GetByteOrder(version).WriteUint48(b, uint64(length)&(1<<48-1)) } numRangesWritten++ } else { @@ -304,11 +303,11 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error case protocol.PacketNumberLen1: b.WriteByte(uint8(lengthWritten)) case protocol.PacketNumberLen2: - utils.LittleEndian.WriteUint16(b, uint16(lengthWritten)) + utils.GetByteOrder(version).WriteUint16(b, uint16(lengthWritten)) case protocol.PacketNumberLen4: - utils.LittleEndian.WriteUint32(b, uint32(lengthWritten)) + utils.GetByteOrder(version).WriteUint32(b, uint32(lengthWritten)) case protocol.PacketNumberLen6: - utils.LittleEndian.WriteUint48(b, lengthWritten&(1<<48-1)) + utils.GetByteOrder(version).WriteUint48(b, lengthWritten&(1<<48-1)) } numRangesWritten++ @@ -326,7 +325,6 @@ func (f *AckFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error } b.WriteByte(0) // no timestamps - return nil } diff --git a/frames/ack_frame_test.go b/frames/ack_frame_test.go index c992228a6..216aec403 100644 --- a/frames/ack_frame_test.go +++ b/frames/ack_frame_test.go @@ -2,6 +2,8 @@ package frames import ( "bytes" + "fmt" + "io" "time" "github.com/lucas-clemente/quic-go/protocol" @@ -12,25 +14,27 @@ import ( var _ = Describe("AckFrame", func() { Context("when parsing", func() { It("accepts a sample frame", func() { - b := bytes.NewReader([]byte{0x40, 0x1c, 0x8e, 0x0, 0x1c, 0x1, 0x1, 0x6b, 0x26, 0x3, 0x0}) + b := bytes.NewReader([]byte{0x40, + 0x1c, // largest acked + 0x0, 0x0, // delay time + 0x1c, // block length + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x1c))) Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1))) - Expect(frame.DelayTime).To(Equal(142 * time.Microsecond)) Expect(frame.HasMissingRanges()).To(BeFalse()) Expect(b.Len()).To(BeZero()) }) - It("parses a frame without a timestamp", func() { - b := bytes.NewReader([]byte{0x40, 0x3, 0x50, 0x15, 0x3, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(3))) - }) - It("parses a frame where the largest acked is 0", func() { - b := bytes.NewReader([]byte{0x40, 0x0, 0xff, 0xff, 0x0, 0x0}) + b := bytes.NewReader([]byte{0x40, + 0x0, // largest acked + 0x0, 0x0, // delay time + 0x0, // block length + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0))) @@ -39,18 +43,13 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a frame with a 48 bit packet number", func() { - b := bytes.NewReader([]byte{0x4c, 0x37, 0x13, 0xad, 0xfb, 0xca, 0xde, 0x0, 0x0, 0x5, 0x1, 0, 0, 0, 0, 0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdecafbad1337))) - Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0xdecafbad1337 - 5 + 1))) - Expect(frame.HasMissingRanges()).To(BeFalse()) - Expect(b.Len()).To(BeZero()) - }) - It("parses a frame with 1 ACKed packet", func() { - b := bytes.NewReader([]byte{0x40, 0x10, 0x8e, 0x0, 0x1, 0x0}) + b := bytes.NewReader([]byte{0x40, + 0x10, // largest acked + 0x0, 0x0, // delay time + 0x1, // block length + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x10))) @@ -59,17 +58,17 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a frame, when packet 1 was lost", func() { - b := bytes.NewReader([]byte{0x40, 0x9, 0x92, 0x7, 0x8, 0x3, 0x2, 0x69, 0xa3, 0x0, 0x0, 0x1, 0xc9, 0x2, 0x0, 0x46, 0x10}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(9))) - Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(2))) - Expect(b.Len()).To(BeZero()) - }) - It("parses a frame with multiple timestamps", func() { - b := bytes.NewReader([]byte{0x40, 0x10, 0x0, 0x0, 0x10, 0x4, 0x1, 0x6b, 0x26, 0x4, 0x0, 0x3, 0, 0, 0x2, 0, 0, 0x1, 0, 0}) + b := bytes.NewReader([]byte{0x40, + 0x10, // largest acked + 0x0, 0x0, // timestamp + 0x10, // block length + 0x4, // num timestamps + 0x1, 0x6b, 0x26, 0x4, 0x0, // 1st timestamp + 0x3, 0, 0, // 2nd timestamp + 0x2, 0, 0, // 3rd timestamp + 0x1, 0, 0, // 4th timestamp + }) _, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(b.Len()).To(BeZero()) @@ -78,46 +77,261 @@ var _ = Describe("AckFrame", func() { It("errors when the ACK range is too large", func() { // LargestAcked: 0x1c // Length: 0x1d => LowestAcked would be -1 - b := bytes.NewReader([]byte{0x40, 0x1c, 0x8e, 0x0, 0x1d, 0x1, 0x1, 0x6b, 0x26, 0x3, 0x0}) + b := bytes.NewReader([]byte{0x40, + 0x1c, // largest acked + 0x0, 0x0, // delay time + 0x1d, // block length + 0, + }) _, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(ErrInvalidAckRanges)) }) It("errors when the first ACK range is empty", func() { - b := bytes.NewReader([]byte{0x40, 0x9, 0x8e, 0x0, 0x0, 0x1, 0}) + b := bytes.NewReader([]byte{0x40, + 0x9, // largest acked + 0x0, 0x0, // delay time + 0x0, // block length + 0, + }) _, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(ErrInvalidFirstAckRange)) }) + Context("in little endian", func() { + It("parses the delay time", func() { + b := bytes.NewReader([]byte{0x40, + 0x3, // largest acked + 0x8e, 0x0, // delay time + 0x3, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(3))) + Expect(frame.DelayTime).To(Equal(142 * time.Microsecond)) + }) + + It("errors on EOFs", func() { + data := []byte{0x60 ^ 0x4 ^ 0x1, + 0x66, 0x9, // largest acked + 0x23, 0x1, // delay time + 0x7, // num ACk blocks + 0x7, 0x0, // 1st block + 0xff, 0x0, 0x0, // 2nd block + 0xf5, 0x8a, 0x2, // 3rd block + 0xc8, 0xe6, 0x0, // 4th block + 0xff, 0x0, 0x0, // 5th block + 0xff, 0x0, 0x0, // 6th block + 0xff, 0x0, 0x0, // 7th block + 0x23, 0x13, 0x0, // 8th blocks + 0x2, // num timestamps + 0x1, 0x13, 0xae, 0xb, 0x0, // 1st timestamp + 0x0, 0x80, 0x5, // 2nd timestamp + } + _, err := ParseAckFrame(bytes.NewReader(data), versionLittleEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseAckFrame(bytes.NewReader(data[0:i]), versionLittleEndian) + Expect(err).To(MatchError(io.EOF)) + } + }) + + Context("largest acked length", func() { + It("parses a frame with a 2 byte packet number", func() { + b := bytes.NewReader([]byte{0x40 | 0x4, + 0x37, 0x13, // largest acked + 0x0, 0x0, // delay time + 0x9, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x1337))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0x1337 - 0x9 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with a 4 byte packet number", func() { + b := bytes.NewReader([]byte{0x40 | 0x8, + 0xad, 0xfb, 0xca, 0xde, // largest acked + 0x0, 0x0, // timesatmp + 0x5, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdecafbad))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0xdecafbad - 5 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with a 6 byte packet number", func() { + b := bytes.NewReader([]byte{0x4 | 0xc, + 0x37, 0x13, 0xad, 0xfb, 0xca, 0xde, // largest acked + 0x0, 0x0, // delay time + 0x5, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdecafbad1337))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0xdecafbad1337 - 5 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + }) + }) + + Context("in big endian", func() { + It("parses the delay time", func() { + b := bytes.NewReader([]byte{0x40, + 0x3, // largest acked + 0x0, 0x8e, // delay time + 0x3, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(3))) + Expect(frame.DelayTime).To(Equal(142 * time.Microsecond)) + }) + + It("errors on EOFs", func() { + data := []byte{0x60 ^ 0x4 ^ 0x1, + 0x9, 0x66, // largest acked + 0x23, 0x1, // delay time + 0x7, // num ACk blocks + 0x0, 0x7, // 1st block + 0xff, 0x0, 0x0, // 2nd block + 0xf5, 0x2, 0x8a, // 3rd block + 0xc8, 0x0, 0xe6, // 4th block + 0xff, 0x0, 0x0, // 5th block + 0xff, 0x0, 0x0, // 6th block + 0xff, 0x0, 0x0, // 7th block + 0x23, 0x0, 0x13, // 8th blocks + 0x2, // num timestamps + 0x1, 0x13, 0xae, 0xb, 0x0, // 1st timestamp + 0x0, 0x80, 0x5, // 2nd timestamp + } + _, err := ParseAckFrame(bytes.NewReader(data), versionBigEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseAckFrame(bytes.NewReader(data[0:i]), versionBigEndian) + Expect(err).To(MatchError(io.EOF)) + } + }) + + Context("largest acked length", func() { + It("parses a frame with a 2 byte packet number", func() { + b := bytes.NewReader([]byte{0x40 | 0x4, + 0x13, 0x37, // largest acked + 0x0, 0x0, // delay time + 0x9, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x1337))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0x1337 - 0x9 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with a 4 byte packet number", func() { + b := bytes.NewReader([]byte{0x40 | 0x8, + 0xde, 0xca, 0xfb, 0xad, // largest acked + 0x0, 0x0, // timesatmp + 0x5, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdecafbad))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0xdecafbad - 5 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with a 6 byte packet number", func() { + b := bytes.NewReader([]byte{0x4 | 0xc, + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, // largest acked + 0x0, 0x0, // delay time + 0x5, // block length + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe))) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe - 5 + 1))) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(b.Len()).To(BeZero()) + }) + }) + }) + Context("ACK blocks", func() { - It("parses a frame with one ACK block", func() { - b := bytes.NewReader([]byte{0x60, 0x18, 0x94, 0x1, 0x1, 0x3, 0x2, 0x10, 0x2, 0x1, 0x5c, 0xd5, 0x0, 0x0, 0x0, 0x95, 0x0}) + It("parses a frame with two ACK blocks", func() { + b := bytes.NewReader([]byte{0x60, + 0x18, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACK blocks + 0x3, // 1st block + 0x2, 0x10, // 2nd block + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(24))) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x18))) Expect(frame.HasMissingRanges()).To(BeTrue()) Expect(frame.AckRanges).To(HaveLen(2)) - Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 22, LastPacketNumber: 24})) - Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 4, LastPacketNumber: 19})) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 0x18 - 0x3 + 1, LastPacketNumber: 0x18})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: (0x18 - 0x3 + 1) - (0x2 + 1) - (0x10 - 1), LastPacketNumber: (0x18 - 0x3 + 1) - (0x2 + 1)})) Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(4))) Expect(b.Len()).To(BeZero()) }) - It("rejects a frame that says it has ACK blocks in the typeByte, but doesn't have any", func() { - b := bytes.NewReader([]byte{0x63, 0x4, 0xff, 0xff, 0, 2, 0, 0, 0, 0, 0, 0}) + It("rejects a frame with invalid ACK ranges", func() { + // like the test before, but increased the last ACK range, such that the FirstPacketNumber would be negative + b := bytes.NewReader([]byte{0x60, + 0x18, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACK blocks + 0x3, // 1st block + 0x2, 0x15, // 2nd block + 0, + }) _, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(ErrInvalidAckRanges)) }) - It("rejects a frame with invalid ACK ranges", func() { - // like the test before, but increased the last ACK range, such that the FirstPacketNumber would be negative - b := bytes.NewReader([]byte{0x60, 0x18, 0x94, 0x1, 0x1, 0x3, 0x2, 0x15, 0x2, 0x1, 0x5c, 0xd5, 0x0, 0x0, 0x0, 0x95, 0x0}) + It("rejects a frame that says it has ACK blocks in the typeByte, but doesn't have any", func() { + b := bytes.NewReader([]byte{0x60 ^ 0x3, + 0x4, // largest acked + 0x0, 0x0, // delay time + 0, // num ACK blocks + 0, + }) _, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(ErrInvalidAckRanges)) }) It("parses a frame with multiple single packets missing", func() { - b := bytes.NewReader([]byte{0x60, 0x27, 0xda, 0x0, 0x6, 0x9, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x13, 0x2, 0x1, 0x71, 0x12, 0x3, 0x0, 0x0, 0x47, 0x2}) + b := bytes.NewReader([]byte{0x60, + 0x27, // largest acked + 0x0, 0x0, // delay time + 0x6, // num ACK blocks + 0x9, // 1st block + 0x1, 0x1, // 2nd block + 0x1, 0x1, // 3rd block + 0x1, 0x1, // 4th block + 0x1, 0x1, // 5th block + 0x1, 0x1, // 6th block + 0x1, 0x13, // 7th block + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x27))) @@ -134,20 +348,17 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a packet with packet 1 and one more packet lost", func() { - b := bytes.NewReader([]byte{0x60, 0xc, 0x92, 0x0, 0x1, 0x1, 0x1, 0x9, 0x2, 0x2, 0x53, 0x43, 0x1, 0x0, 0x0, 0xa7, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(12))) - Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(2))) - Expect(frame.AckRanges).To(HaveLen(2)) - Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 12, LastPacketNumber: 12})) - Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 2, LastPacketNumber: 10})) - Expect(b.Len()).To(BeZero()) - }) - It("parses a frame with multiple longer ACK blocks", func() { - b := bytes.NewReader([]byte{0x60, 0x52, 0xd1, 0x0, 0x3, 0x17, 0xa, 0x10, 0x4, 0x8, 0x2, 0x12, 0x2, 0x1, 0x6c, 0xc8, 0x2, 0x0, 0x0, 0x7e, 0x1}) + b := bytes.NewReader([]byte{0x60, + 0x52, // largest acked + 0xd1, 0x0, //delay time + 0x3, // num ACK blocks + 0x17, // 1st block + 0xa, 0x10, // 2nd block + 0x4, 0x8, // 3rd block + 0x2, 0x12, // 4th block + 0, + }) frame, err := ParseAckFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x52))) @@ -164,8 +375,15 @@ var _ = Describe("AckFrame", func() { Context("more than 256 lost packets in a row", func() { // 255 missing packets fit into a single ACK block It("parses a frame with a range of 255 missing packets", func() { - b := bytes.NewReader([]byte{0x64, 0x15, 0x1, 0xce, 0x1, 0x1, 0x3, 0xff, 0x13, 0x1, 0x0, 0xb6, 0xc5, 0x0, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) + b := bytes.NewReader([]byte{0x60 ^ 0x4, + 0x15, 0x1, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACK blocks + 0x3, // 1st block + 0xff, 0x13, // 2nd block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x115))) Expect(frame.HasMissingRanges()).To(BeTrue()) @@ -178,8 +396,16 @@ var _ = Describe("AckFrame", func() { // 256 missing packets fit into two ACK blocks It("parses a frame with a range of 256 missing packets", func() { - b := bytes.NewReader([]byte{0x64, 0x14, 0x1, 0x96, 0x0, 0x2, 0x1, 0xff, 0x0, 0x1, 0x13, 0x1, 0x0, 0x92, 0xc0, 0x0, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) + b := bytes.NewReader([]byte{0x60 ^ 0x4, + 0x14, 0x1, // largest acked + 0x0, 0x0, // delay time + 0x2, // num ACK blocks + 0x1, // 1st block + 0xff, 0x0, // 2nd block + 0x1, 0x13, // 3rd block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x114))) Expect(frame.HasMissingRanges()).To(BeTrue()) @@ -194,8 +420,19 @@ var _ = Describe("AckFrame", func() { // this is a modified ACK frame that has 5 instead of originally 6 written ranges // each gap is 300 packets and thus takes 2 ranges // the last range is incomplete, and should be completely ignored - b := bytes.NewReader([]byte{0x64, 0x9b, 0x3, 0xc9, 0x0, 0x5 /*instead of 0x6*/, 0x1, 0xff, 0x0, 0x2d, 0x1, 0xff, 0x0, 0x2d, 0x1, 0xff, 0x0 /*0x2d, 0x14,*/, 0x1, 0x0, 0xf6, 0xbd, 0x0, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) + b := bytes.NewReader([]byte{0x60 ^ 0x4, + 0x9b, 0x3, // largest acked + 0x0, 0x0, // delay time + 0x5, // num ACK blocks, instead of 0x6 + 0x1, // 1st block + 0xff, 0x0, // 2nd block + 0x2d, 0x1, // 3rd block + 0xff, 0x0, // 4th block + 0x2d, 0x1, // 5th block + 0xff, 0x0, /*0x2d, 0x14,*/ // 6th block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x39b))) Expect(frame.HasMissingRanges()).To(BeTrue()) @@ -206,9 +443,18 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a frame with one long range, spanning 2 blocks, of missing packets", func() { // 280 missing packets - b := bytes.NewReader([]byte{0x64, 0x44, 0x1, 0xa7, 0x0, 0x2, 0x19, 0xff, 0x0, 0x19, 0x13, 0x2, 0x1, 0xb, 0x59, 0x2, 0x0, 0x0, 0xb6, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) + It("parses a frame with one long range, spanning 2 blocks, of missing packets", func() { + // 280 missing packets + b := bytes.NewReader([]byte{0x60 ^ 0x4, + 0x44, 0x1, // largest acked + 0x0, 0x0, // delay time + 0x2, // num ACK blocks + 0x19, // 1st block + 0xff, 0x0, // 2nd block + 0x19, 0x13, // 3rd block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x144))) Expect(frame.HasMissingRanges()).To(BeTrue()) @@ -219,9 +465,26 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a frame with one long range, spanning multiple blocks, of missing packets", func() { // 2345 missing packets - b := bytes.NewReader([]byte{0x64, 0x5b, 0x9, 0x66, 0x1, 0xa, 0x1f, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0x32, 0x13, 0x4, 0x3, 0xb4, 0xda, 0x1, 0x0, 0x2, 0xe0, 0x0, 0x1, 0x9a, 0x0, 0x0, 0x81, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) + It("parses a frame with one long range, spanning multiple blocks, of missing packets", func() { + // 2345 missing packets + b := bytes.NewReader([]byte{0x60 ^ 0x4, + 0x5b, 0x9, // largest acked + 0x0, 0x0, // delay time + 0xa, // num ACK blocks + 0x1f, // 1st block + 0xff, 0x0, // 2nd block + 0xff, 0x0, // 3rd block + 0xff, 0x0, // 4th block + 0xff, 0x0, // 5th block + 0xff, 0x0, // 6th block + 0xff, 0x0, // 7th block + 0xff, 0x0, // 8th block + 0xff, 0x0, // 9th block + 0xff, 0x0, // 10th block + 0x32, 0x13, // 11th block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) Expect(err).ToNot(HaveOccurred()) Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x95b))) Expect(frame.HasMissingRanges()).To(BeTrue()) @@ -232,47 +495,139 @@ var _ = Describe("AckFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("parses a frame with multiple long ranges of missing packets", func() { - b := bytes.NewReader([]byte{0x65, 0x66, 0x9, 0x23, 0x1, 0x7, 0x7, 0x0, 0xff, 0x0, 0x0, 0xf5, 0x8a, 0x2, 0xc8, 0xe6, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0x23, 0x13, 0x0, 0x2, 0x1, 0x13, 0xae, 0xb, 0x0, 0x0, 0x80, 0x5}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x966))) - Expect(frame.HasMissingRanges()).To(BeTrue()) - Expect(frame.AckRanges).To(HaveLen(4)) - Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 2400, LastPacketNumber: 0x966})) - Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 1250, LastPacketNumber: 1899})) - Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 820, LastPacketNumber: 1049})) - Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19})) - Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1))) - Expect(b.Len()).To(BeZero()) + Context("in little endian", func() { + It("parses a frame with multiple 2 byte long ranges of missing packets", func() { + b := bytes.NewReader([]byte{0x60 ^ 0x4 ^ 0x1, + 0x66, 0x9, // largest acked + 0x0, 0x0, // delay time + 0x7, // num ACK blocks + 0x7, 0x0, // 1st block + 0xff, 0x0, 0x0, // 2nd block + 0xf5, 0x8a, 0x2, // 3rd block + 0xc8, 0xe6, 0x0, // 4th block + 0xff, 0x0, 0x0, // 5th block + 0xff, 0x0, 0x0, // 6th block + 0xff, 0x0, 0x0, // 7th block + 0x23, 0x13, 0x0, // 8th block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x966))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(4)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 2400, LastPacketNumber: 0x966})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 1250, LastPacketNumber: 1899})) + Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 820, LastPacketNumber: 1049})) + Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19})) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1))) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with with a 4 byte ack block length", func() { + b := bytes.NewReader([]byte{0x60 ^ 0xc ^ 0x2, + 0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACK blocks + 0x37, 0x13, 0, 0, // 1st block + 0x20, 0x78, 0x56, 0x34, 0x12, // 2nd block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(2)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 0xdeadbeefcafe - 0x1337 + 1, LastPacketNumber: 0xdeadbeefcafe})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1) - (0x12345678 - 1), LastPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1)})) + }) + + It("parses a frame with with a 6 byte ack block length", func() { + b := bytes.NewReader([]byte{0x60 ^ 0xc ^ 0x3, + 0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACk blocks + 0x37, 0x13, 0, 0, 0, 0, // 1st block + 0x20, 0x78, 0x56, 0x34, 0x12, 0xab, 0, // 2nd block + 0, + }) + frame, err := ParseAckFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(2)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 0xdeadbeefcafe - 0x1337 + 1, LastPacketNumber: 0xdeadbeefcafe})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1) - (0xab12345678 - 1), LastPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1)})) + }) }) - It("parses a frame with short ranges and one long range", func() { - b := bytes.NewReader([]byte{0x64, 0x8f, 0x3, 0x65, 0x1, 0x5, 0x3d, 0x1, 0x32, 0xff, 0x0, 0xff, 0x0, 0xf0, 0x1c, 0x2, 0x13, 0x3, 0x2, 0x23, 0xaf, 0x2, 0x0, 0x1, 0x3, 0x1, 0x0, 0x8e, 0x0}) - frame, err := ParseAckFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x38f))) - Expect(frame.HasMissingRanges()).To(BeTrue()) - Expect(frame.AckRanges).To(HaveLen(4)) - Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 851, LastPacketNumber: 0x38f})) - Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 800, LastPacketNumber: 849})) - Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 22, LastPacketNumber: 49})) - Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19})) - Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1))) - Expect(b.Len()).To(BeZero()) + Context("in big endian", func() { + It("parses a frame with multiple 2 byte long ranges of missing packets", func() { + b := bytes.NewReader([]byte{0x60 ^ 0x4 ^ 0x1, + 0x9, 0x66, // largest acked + 0x0, 0x0, // delay time + 0x7, // num ACK blocks + 0x0, 0x7, // 1st block + 0xff, 0x0, 0x0, // 2nd block + 0xf5, 0x2, 0x8a, // 3rd block + 0xc8, 0x0, 0xe6, // 4th block + 0xff, 0x0, 0x0, // 5th block + 0xff, 0x0, 0x0, // 6th block + 0xff, 0x0, 0x0, // 7th block + 0x23, 0x0, 0x13, // 8th block + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0x966))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(4)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 2400, LastPacketNumber: 0x966})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: 1250, LastPacketNumber: 1899})) + Expect(frame.AckRanges[2]).To(Equal(AckRange{FirstPacketNumber: 820, LastPacketNumber: 1049})) + Expect(frame.AckRanges[3]).To(Equal(AckRange{FirstPacketNumber: 1, LastPacketNumber: 19})) + Expect(frame.LowestAcked).To(Equal(protocol.PacketNumber(1))) + Expect(b.Len()).To(BeZero()) + }) + + It("parses a frame with with a 4 byte ack block length", func() { + b := bytes.NewReader([]byte{0x60 ^ 0xc ^ 0x2, + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACK blocks + 0, 0, 0x13, 0x37, // 1st block + 0x20, 0x12, 0x34, 0x56, 0x78, // 2nd block + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(2)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 0xdeadbeefcafe - 0x1337 + 1, LastPacketNumber: 0xdeadbeefcafe})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1) - (0x12345678 - 1), LastPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1)})) + }) + + It("parses a frame with with a 6 byte ack block length", func() { + b := bytes.NewReader([]byte{0x60 ^ 0xc ^ 0x3, + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, // largest acked + 0x0, 0x0, // delay time + 0x1, // num ACk blocks + 0, 0, 0, 0, 0x13, 0x37, // 1st block + 0x20, 0x0, 0xab, 0x12, 0x34, 0x56, 0x78, // 2nd block + 0, + }) + frame, err := ParseAckFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(protocol.PacketNumber(0xdeadbeefcafe))) + Expect(frame.HasMissingRanges()).To(BeTrue()) + Expect(frame.AckRanges).To(HaveLen(2)) + Expect(frame.AckRanges[0]).To(Equal(AckRange{FirstPacketNumber: 0xdeadbeefcafe - 0x1337 + 1, LastPacketNumber: 0xdeadbeefcafe})) + Expect(frame.AckRanges[1]).To(Equal(AckRange{FirstPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1) - (0xab12345678 - 1), LastPacketNumber: (0xdeadbeefcafe - 0x1337 + 1) - (0x20 + 1)})) + }) }) }) }) - - It("errors on EOFs", func() { - data := []byte{0x65, 0x66, 0x9, 0x23, 0x1, 0x7, 0x7, 0x0, 0xff, 0x0, 0x0, 0xf5, 0x8a, 0x2, 0xc8, 0xe6, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0xff, 0x0, 0x0, 0x23, 0x13, 0x0, 0x2, 0x1, 0x13, 0xae, 0xb, 0x0, 0x0, 0x80, 0x5} - _, err := ParseAckFrame(bytes.NewReader(data), protocol.VersionWhatever) - Expect(err).NotTo(HaveOccurred()) - for i := range data { - _, err := ParseAckFrame(bytes.NewReader(data[0:i]), protocol.VersionWhatever) - Expect(err).To(MatchError("EOF")) - } - }) }) Context("when writing", func() { @@ -283,383 +638,498 @@ var _ = Describe("AckFrame", func() { }) Context("self-consistency", func() { - It("writes a simple ACK frame", func() { - frameOrig := &AckFrame{ - LargestAcked: 1, - LowestAcked: 1, + for _, v := range []protocol.VersionNumber{versionLittleEndian, versionBigEndian} { + version := v + name := "little endian" + if version == versionBigEndian { + name = "big endian" } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.HasMissingRanges()).To(BeFalse()) - Expect(r.Len()).To(BeZero()) - }) - It("writes the correct block length in a simple ACK frame", func() { - frameOrig := &AckFrame{ - LargestAcked: 20, - LowestAcked: 10, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(frame.HasMissingRanges()).To(BeFalse()) - Expect(r.Len()).To(BeZero()) - }) + Context(fmt.Sprintf("in %s", name), func() { + It("writes a simple ACK frame", func() { + frameOrig := &AckFrame{ + LargestAcked: 1, + LowestAcked: 1, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(r.Len()).To(BeZero()) + }) - It("writes a simple ACK frame with a high packet number", func() { - frameOrig := &AckFrame{ - LargestAcked: 0xDEADBEEFCAFE, - LowestAcked: 0xDEADBEEFCAFE, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.HasMissingRanges()).To(BeFalse()) - Expect(r.Len()).To(BeZero()) - }) + It("writes the correct block length in a simple ACK frame", func() { + frameOrig := &AckFrame{ + LargestAcked: 20, + LowestAcked: 10, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(r.Len()).To(BeZero()) + }) - It("writes an ACK frame with one packet missing", func() { - frameOrig := &AckFrame{ - LargestAcked: 40, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 25, LastPacketNumber: 40}, - {FirstPacketNumber: 1, LastPacketNumber: 23}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - Expect(r.Len()).To(BeZero()) - }) + It("writes a simple ACK frame with a high packet number", func() { + frameOrig := &AckFrame{ + LargestAcked: 0xdeadbeefcafe, + LowestAcked: 0xdeadbeefcafe, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.HasMissingRanges()).To(BeFalse()) + Expect(r.Len()).To(BeZero()) + }) - It("writes an ACK frame with multiple missing packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 25, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 22, LastPacketNumber: 25}, - {FirstPacketNumber: 15, LastPacketNumber: 18}, - {FirstPacketNumber: 13, LastPacketNumber: 13}, - {FirstPacketNumber: 1, LastPacketNumber: 10}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - Expect(r.Len()).To(BeZero()) - }) + It("writes an ACK frame with one packet missing", func() { + frameOrig := &AckFrame{ + LargestAcked: 40, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 25, LastPacketNumber: 40}, + {FirstPacketNumber: 1, LastPacketNumber: 23}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) - It("rejects a frame with incorrect LargestObserved value", func() { - frame := &AckFrame{ - LargestAcked: 26, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 12, LastPacketNumber: 25}, - {FirstPacketNumber: 1, LastPacketNumber: 10}, - }, - } - err := frame.Write(b, protocol.VersionWhatever) - Expect(err).To(MatchError(errInconsistentAckLargestAcked)) - }) + It("writes an ACK frame with multiple missing packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 25, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 22, LastPacketNumber: 25}, + {FirstPacketNumber: 15, LastPacketNumber: 18}, + {FirstPacketNumber: 13, LastPacketNumber: 13}, + {FirstPacketNumber: 1, LastPacketNumber: 10}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) - It("rejects a frame with incorrect LargestObserved value", func() { - frame := &AckFrame{ - LargestAcked: 25, - LowestAcked: 2, - AckRanges: []AckRange{ - {FirstPacketNumber: 12, LastPacketNumber: 25}, - {FirstPacketNumber: 1, LastPacketNumber: 10}, - }, - } - err := frame.Write(b, protocol.VersionWhatever) - Expect(err).To(MatchError(errInconsistentAckLowestAcked)) - }) + It("rejects a frame with incorrect LargestObserved value", func() { + frame := &AckFrame{ + LargestAcked: 26, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 12, LastPacketNumber: 25}, + {FirstPacketNumber: 1, LastPacketNumber: 10}, + }, + } + err := frame.Write(b, version) + Expect(err).To(MatchError(errInconsistentAckLargestAcked)) + }) - Context("longer gaps between ACK blocks", func() { - It("only writes one block for 254 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 300, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 254, LastPacketNumber: 300}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(2))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + It("rejects a frame with incorrect LargestObserved value", func() { + frame := &AckFrame{ + LargestAcked: 25, + LowestAcked: 2, + AckRanges: []AckRange{ + {FirstPacketNumber: 12, LastPacketNumber: 25}, + {FirstPacketNumber: 1, LastPacketNumber: 10}, + }, + } + err := frame.Write(b, version) + Expect(err).To(MatchError(errInconsistentAckLowestAcked)) + }) + + Context("longer gaps between ACK blocks", func() { + It("only writes one block for 254 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 300, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 254, LastPacketNumber: 300}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(2))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("only writes one block for 255 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 300, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 255, LastPacketNumber: 300}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(2))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes two blocks for 256 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 300, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 256, LastPacketNumber: 300}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(3))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes two blocks for 510 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 600, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 510, LastPacketNumber: 600}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(3))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes three blocks for 511 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 600, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 511, LastPacketNumber: 600}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(4))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes three blocks for 512 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 600, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 20 + 512, LastPacketNumber: 600}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(4))) + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes multiple blocks for a lot of lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 3000, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 2900, LastPacketNumber: 3000}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + + It("writes multiple longer blocks for 256 lost packets", func() { + frameOrig := &AckFrame{ + LargestAcked: 3600, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 2900, LastPacketNumber: 3600}, + {FirstPacketNumber: 1000, LastPacketNumber: 2500}, + {FirstPacketNumber: 1, LastPacketNumber: 19}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + }) + }) + + Context("largest acked length", func() { + It("writes a 1 largest acked", func() { + frameOrig := &AckFrame{ + LargestAcked: 200, + LowestAcked: 1, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 2 byte largest acked", func() { + frameOrig := &AckFrame{ + LargestAcked: 0x100, + LowestAcked: 1, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 4 byte largest acked", func() { + frameOrig := &AckFrame{ + LargestAcked: 0x10000, + LowestAcked: 1, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x2))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 6 byte largest acked", func() { + frameOrig := &AckFrame{ + LargestAcked: 0x100000000, + LowestAcked: 1, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x3))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(r.Len()).To(BeZero()) + }) + }) + + Context("ack block length", func() { + It("writes a 1 byte ack block length, if all ACK blocks are short", func() { + frameOrig := &AckFrame{ + LargestAcked: 5001, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 5000, LastPacketNumber: 5001}, + {FirstPacketNumber: 250, LastPacketNumber: 300}, + {FirstPacketNumber: 1, LastPacketNumber: 200}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 2 byte ack block length, for a frame with one ACK block", func() { + frameOrig := &AckFrame{ + LargestAcked: 10000, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 10000}, + {FirstPacketNumber: 1, LastPacketNumber: 9988}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 2 byte ack block length, for a frame with multiple ACK blocks", func() { + frameOrig := &AckFrame{ + LargestAcked: 10000, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 10000}, + {FirstPacketNumber: 1, LastPacketNumber: 256}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 4 byte ack block length, for a frame with single ACK blocks", func() { + frameOrig := &AckFrame{ + LargestAcked: 0xdeadbeef, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 0xdeadbeef}, + {FirstPacketNumber: 1, LastPacketNumber: 9988}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x2))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 4 byte ack block length, for a frame with multiple ACK blocks", func() { + frameOrig := &AckFrame{ + LargestAcked: 0xdeadbeef, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 0xdeadbeef}, + {FirstPacketNumber: 1, LastPacketNumber: 256}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x2))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 6 byte ack block length, for a frame with a single ACK blocks", func() { + frameOrig := &AckFrame{ + LargestAcked: 0xdeadbeefcafe, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 0xdeadbeefcafe}, + {FirstPacketNumber: 1, LastPacketNumber: 9988}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x3))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + + It("writes a 6 byte ack block length, for a frame with multiple ACK blocks", func() { + frameOrig := &AckFrame{ + LargestAcked: 0xdeadbeefcafe, + LowestAcked: 1, + AckRanges: []AckRange{ + {FirstPacketNumber: 9990, LastPacketNumber: 0xdeadbeefcafe}, + {FirstPacketNumber: 1, LastPacketNumber: 256}, + }, + } + err := frameOrig.Write(b, version) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x3))) + r := bytes.NewReader(b.Bytes()) + frame, err := ParseAckFrame(r, version) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) + Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) + Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) + Expect(r.Len()).To(BeZero()) + }) + }) }) - - It("only writes one block for 255 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 300, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 255, LastPacketNumber: 300}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(2))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes two blocks for 256 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 300, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 256, LastPacketNumber: 300}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(3))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - // Expect(b.Bytes()[13+0*(1+6) : 13+1*(1+6)]).To(Equal([]byte{0xFF, 0, 0, 0, 0, 0, 0})) - // Expect(b.Bytes()[13+1*(1+6) : 13+2*(1+6)]).To(Equal([]byte{0x1, 0, 0, 0, 0, 0, 19})) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes two blocks for 510 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 600, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 510, LastPacketNumber: 600}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(3))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes three blocks for 511 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 600, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 511, LastPacketNumber: 600}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(4))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes three blocks for 512 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 600, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 20 + 512, LastPacketNumber: 600}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - Expect(frameOrig.numWritableNackRanges()).To(Equal(uint64(4))) - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes multiple blocks for a lot of lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 3000, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 2900, LastPacketNumber: 3000}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - - It("writes multiple longer blocks for 256 lost packets", func() { - frameOrig := &AckFrame{ - LargestAcked: 3600, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 2900, LastPacketNumber: 3600}, - {FirstPacketNumber: 1000, LastPacketNumber: 2500}, - {FirstPacketNumber: 1, LastPacketNumber: 19}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - }) - }) - - Context("longer ACK blocks", func() { - It("writes a 1 byte Missing Sequence Number Delta", func() { - frameOrig := &AckFrame{ - LargestAcked: 200, - LowestAcked: 1, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(r.Len()).To(BeZero()) - }) - - It("writes a 2 byte Missing Sequence Number Delta", func() { - frameOrig := &AckFrame{ - LargestAcked: 0x100, - LowestAcked: 1, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(r.Len()).To(BeZero()) - }) - - It("writes a 4 byte Missing Sequence Number Delta", func() { - frameOrig := &AckFrame{ - LargestAcked: 0x10000, - LowestAcked: 1, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x2))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(r.Len()).To(BeZero()) - }) - - It("writes a 6 byte Missing Sequence Number Delta", func() { - frameOrig := &AckFrame{ - LargestAcked: 0x100000000, - LowestAcked: 1, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x3))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(r.Len()).To(BeZero()) - }) - - It("writes a 1 byte Missing Sequence Number Delta, if all ACK blocks are short", func() { - frameOrig := &AckFrame{ - LargestAcked: 5001, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 5000, LastPacketNumber: 5001}, - {FirstPacketNumber: 250, LastPacketNumber: 300}, - {FirstPacketNumber: 1, LastPacketNumber: 200}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x0))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - Expect(r.Len()).To(BeZero()) - }) - - It("writes a 2 byte Missing Sequence Number Delta, for a frame with 2 ACK ranges", func() { - frameOrig := &AckFrame{ - LargestAcked: 10000, - LowestAcked: 1, - AckRanges: []AckRange{ - {FirstPacketNumber: 9990, LastPacketNumber: 10000}, - {FirstPacketNumber: 1, LastPacketNumber: 256}, - }, - } - err := frameOrig.Write(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(byte(0x1))) - r := bytes.NewReader(b.Bytes()) - frame, err := ParseAckFrame(r, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LargestAcked).To(Equal(frameOrig.LargestAcked)) - Expect(frame.LowestAcked).To(Equal(frameOrig.LowestAcked)) - Expect(frame.AckRanges).To(Equal(frameOrig.AckRanges)) - Expect(r.Len()).To(BeZero()) - }) - }) + } Context("too many ACK blocks", func() { It("skips the lowest ACK ranges, if there are more than 255 AckRanges", func() { diff --git a/frames/blocked_frame.go b/frames/blocked_frame.go index 73c27afb1..010407a8d 100644 --- a/frames/blocked_frame.go +++ b/frames/blocked_frame.go @@ -15,7 +15,7 @@ type BlockedFrame struct { //Write writes a BlockedFrame frame func (f *BlockedFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { b.WriteByte(0x05) - utils.LittleEndian.WriteUint32(b, uint32(f.StreamID)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.StreamID)) return nil } @@ -29,16 +29,13 @@ func ParseBlockedFrame(r *bytes.Reader, version protocol.VersionNumber) (*Blocke frame := &BlockedFrame{} // read the TypeByte - _, err := r.ReadByte() - if err != nil { + if _, err := r.ReadByte(); err != nil { return nil, err } - - sid, err := utils.LittleEndian.ReadUint32(r) + sid, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.StreamID = protocol.StreamID(sid) - return frame, nil } diff --git a/frames/blocked_frame_test.go b/frames/blocked_frame_test.go index a83491aad..dd990d079 100644 --- a/frames/blocked_frame_test.go +++ b/frames/blocked_frame_test.go @@ -10,15 +10,26 @@ import ( var _ = Describe("BlockedFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{0x05, 0xEF, 0xBE, 0xAD, 0xDE}) - frame, err := ParseBlockedFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.StreamID).To(Equal(protocol.StreamID(0xDEADBEEF))) + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x5, 0xef, 0xbe, 0xad, 0xde}) + frame, err := ParseBlockedFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x5, 0xde, 0xad, 0xbe, 0xef}) + frame, err := ParseBlockedFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + }) }) It("errors on EOFs", func() { - data := []byte{0x05, 0xEF, 0xBE, 0xAD, 0xDE} + data := []byte{0x5, 0xef, 0xbe, 0xad, 0xde} _, err := ParseBlockedFrame(bytes.NewReader(data), protocol.VersionWhatever) Expect(err).NotTo(HaveOccurred()) for i := range data { @@ -29,18 +40,29 @@ var _ = Describe("BlockedFrame", func() { }) Context("when writing", func() { - It("writes a sample frame", func() { - b := &bytes.Buffer{} - frame := BlockedFrame{StreamID: 0x1337} - frame.Write(b, 0) - Expect(b.Bytes()).To(Equal([]byte{0x05, 0x37, 0x13, 0x0, 0x0})) + Context("in little endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := BlockedFrame{StreamID: 0x1337} + frame.Write(b, versionLittleEndian) + Expect(b.Bytes()).To(Equal([]byte{0x5, 0x37, 0x13, 0x0, 0x0})) + }) + }) + + Context("in big endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := BlockedFrame{StreamID: 0x1337} + frame.Write(b, versionBigEndian) + Expect(b.Bytes()).To(Equal([]byte{0x5, 0x0, 0x0, 0x13, 0x37})) + }) }) It("writes a connection-level Blocked", func() { b := &bytes.Buffer{} frame := BlockedFrame{StreamID: 0} frame.Write(b, 0) - Expect(b.Bytes()).To(Equal([]byte{0x05, 0, 0, 0, 0})) + Expect(b.Bytes()).To(Equal([]byte{0x5, 0, 0, 0, 0})) }) It("has the correct min length", func() { diff --git a/frames/connection_close_frame.go b/frames/connection_close_frame.go index f2a5051e3..e70aad75c 100644 --- a/frames/connection_close_frame.go +++ b/frames/connection_close_frame.go @@ -27,13 +27,13 @@ func ParseConnectionCloseFrame(r *bytes.Reader, version protocol.VersionNumber) return nil, err } - errorCode, err := utils.LittleEndian.ReadUint32(r) + errorCode, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.ErrorCode = qerr.ErrorCode(errorCode) - reasonPhraseLen, err := utils.LittleEndian.ReadUint16(r) + reasonPhraseLen, err := utils.GetByteOrder(version).ReadUint16(r) if err != nil { return nil, err } @@ -59,14 +59,14 @@ func (f *ConnectionCloseFrame) MinLength(version protocol.VersionNumber) (protoc // Write writes an CONNECTION_CLOSE frame. func (f *ConnectionCloseFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { b.WriteByte(0x02) - utils.LittleEndian.WriteUint32(b, uint32(f.ErrorCode)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.ErrorCode)) if len(f.ReasonPhrase) > math.MaxUint16 { return errors.New("ConnectionFrame: ReasonPhrase too long") } reasonPhraseLen := uint16(len(f.ReasonPhrase)) - utils.LittleEndian.WriteUint16(b, reasonPhraseLen) + utils.GetByteOrder(version).WriteUint16(b, reasonPhraseLen) b.WriteString(f.ReasonPhrase) return nil diff --git a/frames/connection_close_frame_test.go b/frames/connection_close_frame_test.go index 0ec4567b1..ff788b792 100644 --- a/frames/connection_close_frame_test.go +++ b/frames/connection_close_frame_test.go @@ -12,102 +12,195 @@ import ( var _ = Describe("ConnectionCloseFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{0x40, 0x19, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x4e, 0x6f, 0x20, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e}) - frame, err := ParseConnectionCloseFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.ErrorCode).To(Equal(qerr.ErrorCode(0x19))) - Expect(frame.ReasonPhrase).To(Equal("No recent network activity.")) - Expect(b.Len()).To(Equal(0)) + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x2, + 0x19, 0x0, 0x0, 0x0, // error code + 0x1b, 0x0, // reason phrase length + 'N', 'o', ' ', 'r', 'e', 'c', 'e', 'n', 't', ' ', 'n', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'a', 'c', 't', 'i', 'v', 'i', 't', 'y', '.', + }) + frame, err := ParseConnectionCloseFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.ErrorCode).To(Equal(qerr.ErrorCode(0x19))) + Expect(frame.ReasonPhrase).To(Equal("No recent network activity.")) + Expect(b.Len()).To(BeZero()) + }) + + It("rejects long reason phrases", func() { + b := bytes.NewReader([]byte{0x2, + 0xad, 0xfb, 0xca, 0xde, // error code + 0x0, 0xff, // reason phrase length + }) + _, err := ParseConnectionCloseFrame(b, versionLittleEndian) + Expect(err).To(MatchError(qerr.Error(qerr.InvalidConnectionCloseData, "reason phrase too long"))) + }) + + It("errors on EOFs", func() { + data := []byte{0x2, + 0x19, 0x0, 0x0, 0x0, // error code + 0x1b, 0x0, // reason phrase length + 'N', 'o', ' ', 'r', 'e', 'c', 'e', 'n', 't', ' ', 'n', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'a', 'c', 't', 'i', 'v', 'i', 't', 'y', '.', + } + _, err := ParseConnectionCloseFrame(bytes.NewReader(data), versionLittleEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseConnectionCloseFrame(bytes.NewReader(data[0:i]), versionLittleEndian) + Expect(err).To(HaveOccurred()) + } + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x2, + 0x0, 0x0, 0x0, 0x19, // error code + 0x0, 0x1b, // reason phrase length + 'N', 'o', ' ', 'r', 'e', 'c', 'e', 'n', 't', ' ', 'n', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'a', 'c', 't', 'i', 'v', 'i', 't', 'y', '.', + }) + frame, err := ParseConnectionCloseFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.ErrorCode).To(Equal(qerr.ErrorCode(0x19))) + Expect(frame.ReasonPhrase).To(Equal("No recent network activity.")) + Expect(b.Len()).To(BeZero()) + }) + + It("rejects long reason phrases", func() { + b := bytes.NewReader([]byte{0x2, + 0xad, 0xfb, 0xca, 0xde, // error code + 0xff, 0x0, // reason phrase length + }) + _, err := ParseConnectionCloseFrame(b, versionBigEndian) + Expect(err).To(MatchError(qerr.Error(qerr.InvalidConnectionCloseData, "reason phrase too long"))) + }) + + It("errors on EOFs", func() { + data := []byte{0x40, + 0x19, 0x0, 0x0, 0x0, // error code + 0x0, 0x1b, // reason phrase length + 'N', 'o', ' ', 'r', 'e', 'c', 'e', 'n', 't', ' ', 'n', 'e', 't', 'w', 'o', 'r', 'k', ' ', 'a', 'c', 't', 'i', 'v', 'i', 't', 'y', '.', + } + _, err := ParseConnectionCloseFrame(bytes.NewReader(data), versionBigEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseConnectionCloseFrame(bytes.NewReader(data[0:i]), versionBigEndian) + Expect(err).To(HaveOccurred()) + } + }) }) It("parses a frame without a reason phrase", func() { - b := bytes.NewReader([]byte{0x02, 0xAD, 0xFB, 0xCA, 0xDE, 0x00, 0x00}) + b := bytes.NewReader([]byte{0x2, + 0xad, 0xfb, 0xca, 0xde, // error code + 0x0, 0x0, // reason phrase length + }) frame, err := ParseConnectionCloseFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) - Expect(frame.ErrorCode).To(Equal(qerr.ErrorCode(0xDECAFBAD))) Expect(frame.ReasonPhrase).To(BeEmpty()) - Expect(b.Len()).To(Equal(0)) - }) - - It("rejects long reason phrases", func() { - b := bytes.NewReader([]byte{0x02, 0xAD, 0xFB, 0xCA, 0xDE, 0xff, 0xf}) - _, err := ParseConnectionCloseFrame(b, protocol.VersionWhatever) - Expect(err).To(MatchError(qerr.Error(qerr.InvalidConnectionCloseData, "reason phrase too long"))) - }) - - It("errors on EOFs", func() { - data := []byte{0x40, 0x19, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x4e, 0x6f, 0x20, 0x72, 0x65, 0x63, 0x65, 0x6e, 0x74, 0x20, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x20, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x2e} - _, err := ParseConnectionCloseFrame(bytes.NewReader(data), protocol.VersionWhatever) - Expect(err).NotTo(HaveOccurred()) - for i := range data { - _, err := ParseConnectionCloseFrame(bytes.NewReader(data[0:i]), protocol.VersionWhatever) - Expect(err).To(HaveOccurred()) - } + Expect(b.Len()).To(BeZero()) }) }) Context("when writing", func() { - It("writes a frame without a ReasonPhrase", func() { - b := &bytes.Buffer{} - frame := &ConnectionCloseFrame{ - ErrorCode: 0xDEADBEEF, - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(1 + 2 + 4)) - Expect(b.Bytes()).To(Equal([]byte{0x02, 0xEF, 0xBE, 0xAD, 0xDE, 0x00, 0x00})) + Context("in little endian", func() { + It("writes a frame without a reason phrase", func() { + b := &bytes.Buffer{} + frame := &ConnectionCloseFrame{ + ErrorCode: 0xdeadbeef, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(1 + 2 + 4)) + Expect(b.Bytes()).To(Equal([]byte{0x2, + 0xef, 0xbe, 0xad, 0xde, // error code + 0x0, 0x0, // reason phrase length + })) + }) + + It("writes a frame with a reason phrase", func() { + b := &bytes.Buffer{} + frame := &ConnectionCloseFrame{ + ErrorCode: 0xdeadbeef, + ReasonPhrase: "foobar", + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(1 + 2 + 4 + len(frame.ReasonPhrase))) + Expect(b.Bytes()).To(Equal([]byte{0x2, + 0xef, 0xbe, 0xad, 0xde, // error code + 0x6, 0x0, // reason phrase length + 'f', 'o', 'o', 'b', 'a', 'r', + })) + }) }) - It("writes a frame with a ReasonPhrase", func() { - b := &bytes.Buffer{} - frame := &ConnectionCloseFrame{ - ErrorCode: 0xDEADBEEF, - ReasonPhrase: "foobar", - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(1 + 2 + 4 + len(frame.ReasonPhrase))) - Expect(b.Bytes()[:5]).To(Equal([]byte{0x02, 0xEF, 0xBE, 0xAD, 0xDE})) - Expect(b.Bytes()[5:7]).To(Equal([]byte{0x06, 0x00})) - Expect(b.Bytes()[7:]).To(Equal([]byte{'f', 'o', 'o', 'b', 'a', 'r'})) + Context("in big endian", func() { + It("writes a frame without a ReasonPhrase", func() { + b := &bytes.Buffer{} + frame := &ConnectionCloseFrame{ + ErrorCode: 0xdeadbeef, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(1 + 2 + 4)) + Expect(b.Bytes()).To(Equal([]byte{0x2, + 0xde, 0xad, 0xbe, 0xef, // error code + 0x0, 0x0, // reason phrase length + })) + }) + + It("writes a frame with a ReasonPhrase", func() { + b := &bytes.Buffer{} + frame := &ConnectionCloseFrame{ + ErrorCode: 0xdeadbeef, + ReasonPhrase: "foobar", + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(1 + 2 + 4 + len(frame.ReasonPhrase))) + Expect(b.Bytes()).To(Equal([]byte{0x2, + 0xde, 0xad, 0xbe, 0xef, // error code + 0x0, 0x6, // reason phrase length + 'f', 'o', 'o', 'b', 'a', 'r', + })) + }) }) It("rejects ReasonPhrases that are too long", func() { b := &bytes.Buffer{} - - reasonPhrase := strings.Repeat("a", 0xFFFF+0x11) - + reasonPhrase := strings.Repeat("a", 0xffff+0x11) frame := &ConnectionCloseFrame{ - ErrorCode: 0xDEADBEEF, + ErrorCode: 0xdeadbeef, ReasonPhrase: reasonPhrase, } - err := frame.Write(b, 0) + err := frame.Write(b, protocol.VersionWhatever) Expect(err).To(HaveOccurred()) }) It("has proper min length", func() { b := &bytes.Buffer{} f := &ConnectionCloseFrame{ - ErrorCode: 0xDEADBEEF, + ErrorCode: 0xdeadbeef, ReasonPhrase: "foobar", } - f.Write(b, 0) + err := f.Write(b, protocol.VersionWhatever) + Expect(err).ToNot(HaveOccurred()) Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(b.Len()))) }) }) It("is self-consistent", func() { - b := &bytes.Buffer{} + buf := &bytes.Buffer{} frame := &ConnectionCloseFrame{ - ErrorCode: 0xDEADBEEF, + ErrorCode: 0xdeadbeef, ReasonPhrase: "Lorem ipsum dolor sit amet.", } - err := frame.Write(b, 0) + err := frame.Write(buf, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) - readframe, err := ParseConnectionCloseFrame(bytes.NewReader(b.Bytes()), protocol.VersionWhatever) + b := bytes.NewReader(buf.Bytes()) + readframe, err := ParseConnectionCloseFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(readframe.ErrorCode).To(Equal(frame.ErrorCode)) Expect(readframe.ReasonPhrase).To(Equal(frame.ReasonPhrase)) + Expect(b.Len()).To(BeZero()) }) }) diff --git a/frames/frames_suite_test.go b/frames/frames_suite_test.go index 0cf2be13a..f0e481ee8 100644 --- a/frames/frames_suite_test.go +++ b/frames/frames_suite_test.go @@ -1,6 +1,8 @@ package frames import ( + "github.com/lucas-clemente/quic-go/internal/utils" + "github.com/lucas-clemente/quic-go/protocol" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -11,3 +13,13 @@ func TestCrypto(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Frames Suite") } + +const ( + versionLittleEndian = protocol.Version37 // a QUIC version that uses little endian encoding + versionBigEndian = protocol.Version39 // a QUIC version that uses big endian encoding +) + +var _ = BeforeSuite(func() { + Expect(utils.GetByteOrder(versionLittleEndian)).To(Equal(utils.LittleEndian)) + Expect(utils.GetByteOrder(versionBigEndian)).To(Equal(utils.BigEndian)) +}) diff --git a/frames/goaway_frame.go b/frames/goaway_frame.go index 22d9fa9d4..46a91d4c0 100644 --- a/frames/goaway_frame.go +++ b/frames/goaway_frame.go @@ -20,24 +20,23 @@ type GoawayFrame struct { func ParseGoawayFrame(r *bytes.Reader, version protocol.VersionNumber) (*GoawayFrame, error) { frame := &GoawayFrame{} - _, err := r.ReadByte() - if err != nil { + if _, err := r.ReadByte(); err != nil { return nil, err } - errorCode, err := utils.LittleEndian.ReadUint32(r) + errorCode, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.ErrorCode = qerr.ErrorCode(errorCode) - lastGoodStream, err := utils.LittleEndian.ReadUint32(r) + lastGoodStream, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.LastGoodStream = protocol.StreamID(lastGoodStream) - reasonPhraseLen, err := utils.LittleEndian.ReadUint16(r) + reasonPhraseLen, err := utils.GetByteOrder(version).ReadUint16(r) if err != nil { return nil, err } @@ -51,19 +50,15 @@ func ParseGoawayFrame(r *bytes.Reader, version protocol.VersionNumber) (*GoawayF return nil, err } frame.ReasonPhrase = string(reasonPhrase) - return frame, nil } func (f *GoawayFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { - typeByte := uint8(0x03) - b.WriteByte(typeByte) - - utils.LittleEndian.WriteUint32(b, uint32(f.ErrorCode)) - utils.LittleEndian.WriteUint32(b, uint32(f.LastGoodStream)) - utils.LittleEndian.WriteUint16(b, uint16(len(f.ReasonPhrase))) + b.WriteByte(0x03) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.ErrorCode)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.LastGoodStream)) + utils.GetByteOrder(version).WriteUint16(b, uint16(len(f.ReasonPhrase))) b.WriteString(f.ReasonPhrase) - return nil } diff --git a/frames/goaway_frame_test.go b/frames/goaway_frame_test.go index 2074dd4c7..0b12ad121 100644 --- a/frames/goaway_frame_test.go +++ b/frames/goaway_frame_test.go @@ -12,67 +12,122 @@ import ( var _ = Describe("GoawayFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{ - 0x03, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, - 'f', 'o', 'o', + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x3, + 0x37, 0x13, 0x0, 0x0, // error code + 0x34, 0x12, 0x0, 0x0, // last good stream id + 0x3, 0x0, // reason phrase length + 'f', 'o', 'o', + }) + frame, err := ParseGoawayFrame(b, versionLittleEndian) + Expect(frame).To(Equal(&GoawayFrame{ + ErrorCode: 0x1337, + LastGoodStream: 0x1234, + ReasonPhrase: "foo", + })) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(BeZero()) + }) + + It("errors on EOFs", func() { + data := []byte{0x3, + 0x1, 0x0, 0x0, 0x0, // error code + 0x2, 0x0, 0x0, 0x0, // last good stream id + 0x3, 0x0, // reason phrase length + 'f', 'o', 'o', + } + _, err := ParseGoawayFrame(bytes.NewReader(data), versionLittleEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseGoawayFrame(bytes.NewReader(data[0:i]), versionLittleEndian) + Expect(err).To(HaveOccurred()) + } + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x3, + 0x0, 0x0, 0x13, 0x37, // error code + 0x0, 0x0, 0x12, 0x34, // last good stream id + 0x0, 0x3, // reason phrase length + 'f', 'o', 'o', + }) + frame, err := ParseGoawayFrame(b, versionBigEndian) + Expect(frame).To(Equal(&GoawayFrame{ + ErrorCode: 0x1337, + LastGoodStream: 0x1234, + ReasonPhrase: "foo", + })) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(BeZero()) + }) + + It("errors on EOFs", func() { + data := []byte{0x3, + 0x0, 0x0, 0x0, 0x1, // error code + 0x0, 0x0, 0x0, 0x2, // last good stream id + 0x0, 0x3, // reason phrase length + 'f', 'o', 'o', + } + _, err := ParseGoawayFrame(bytes.NewReader(data), versionBigEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseGoawayFrame(bytes.NewReader(data[0:i]), versionBigEndian) + Expect(err).To(HaveOccurred()) + } }) - frame, err := ParseGoawayFrame(b, protocol.VersionWhatever) - Expect(frame).To(Equal(&GoawayFrame{ - ErrorCode: 1, - LastGoodStream: 2, - ReasonPhrase: "foo", - })) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(0)) }) It("rejects long reason phrases", func() { - b := bytes.NewReader([]byte{ - 0x03, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0xff, 0xff, + b := bytes.NewReader([]byte{0x3, + 0x1, 0x0, 0x0, 0x0, // error code + 0x2, 0x0, 0x0, 0x0, // last good stream id + 0xff, 0xff, // reason phrase length }) _, err := ParseGoawayFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(qerr.Error(qerr.InvalidGoawayData, "reason phrase too long"))) }) - - It("errors on EOFs", func() { - data := []byte{0x03, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, - 'f', 'o', 'o', - } - _, err := ParseGoawayFrame(bytes.NewReader(data), protocol.VersionWhatever) - Expect(err).NotTo(HaveOccurred()) - for i := range data { - _, err := ParseGoawayFrame(bytes.NewReader(data[0:i]), protocol.VersionWhatever) - Expect(err).To(HaveOccurred()) - } - }) }) Context("when writing", func() { - It("writes a sample frame", func() { - b := &bytes.Buffer{} - frame := GoawayFrame{ - ErrorCode: 1, - LastGoodStream: 2, - ReasonPhrase: "foo", - } - frame.Write(b, 0) - Expect(b.Bytes()).To(Equal([]byte{ - 0x03, - 0x01, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, - 0x03, 0x00, - 'f', 'o', 'o', - })) + Context("in little endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := GoawayFrame{ + ErrorCode: 0x1337, + LastGoodStream: 2, + ReasonPhrase: "foo", + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x3, + 0x37, 0x13, 0x0, 0x0, // error code + 0x2, 0x0, 0x0, 0x0, // last good stream + 0x3, 0x0, // reason phrase length + 'f', 'o', 'o', + })) + }) + }) + + Context("in big endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := GoawayFrame{ + ErrorCode: 0x1337, + LastGoodStream: 2, + ReasonPhrase: "foo", + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x3, + 0x0, 0x0, 0x13, 0x37, // reason code + 0x0, 0x0, 0x0, 0x2, // last good stream id + 0x0, 0x3, // reason phrase length + 'f', 'o', 'o', + })) + }) }) It("has the correct min length", func() { diff --git a/frames/ping_frame_test.go b/frames/ping_frame_test.go index 080b926ac..f3e89b250 100644 --- a/frames/ping_frame_test.go +++ b/frames/ping_frame_test.go @@ -14,7 +14,7 @@ var _ = Describe("PingFrame", func() { b := bytes.NewReader([]byte{0x07}) _, err := ParsePingFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(0)) + Expect(b.Len()).To(BeZero()) }) It("errors on EOFs", func() { @@ -27,7 +27,7 @@ var _ = Describe("PingFrame", func() { It("writes a sample frame", func() { b := &bytes.Buffer{} frame := PingFrame{} - frame.Write(b, 0) + frame.Write(b, protocol.VersionWhatever) Expect(b.Bytes()).To(Equal([]byte{0x07})) }) diff --git a/frames/rst_stream_frame.go b/frames/rst_stream_frame.go index ea8d25423..40701d595 100644 --- a/frames/rst_stream_frame.go +++ b/frames/rst_stream_frame.go @@ -17,9 +17,9 @@ type RstStreamFrame struct { //Write writes a RST_STREAM frame func (f *RstStreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { b.WriteByte(0x01) - utils.LittleEndian.WriteUint32(b, uint32(f.StreamID)) - utils.LittleEndian.WriteUint64(b, uint64(f.ByteOffset)) - utils.LittleEndian.WriteUint32(b, f.ErrorCode) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.StreamID)) + utils.GetByteOrder(version).WriteUint64(b, uint64(f.ByteOffset)) + utils.GetByteOrder(version).WriteUint32(b, f.ErrorCode) return nil } @@ -33,27 +33,25 @@ func ParseRstStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*RstS frame := &RstStreamFrame{} // read the TypeByte - _, err := r.ReadByte() - if err != nil { + if _, err := r.ReadByte(); err != nil { return nil, err } - sid, err := utils.LittleEndian.ReadUint32(r) + sid, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.StreamID = protocol.StreamID(sid) - byteOffset, err := utils.LittleEndian.ReadUint64(r) + byteOffset, err := utils.GetByteOrder(version).ReadUint64(r) if err != nil { return nil, err } frame.ByteOffset = protocol.ByteCount(byteOffset) - frame.ErrorCode, err = utils.LittleEndian.ReadUint32(r) + frame.ErrorCode, err = utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } - return frame, nil } diff --git a/frames/rst_stream_frame_test.go b/frames/rst_stream_frame_test.go index 319fe0ad9..97a8abe56 100644 --- a/frames/rst_stream_frame_test.go +++ b/frames/rst_stream_frame_test.go @@ -10,17 +10,42 @@ import ( var _ = Describe("RstStreamFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{0x01, 0xEF, 0xBE, 0xAD, 0xDE, 0x44, 0x33, 0x22, 0x11, 0xAD, 0xFB, 0xCA, 0xDE, 0x34, 0x12, 0x37, 0x13}) - frame, err := ParseRstStreamFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.StreamID).To(Equal(protocol.StreamID(0xDEADBEEF))) - Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0xDECAFBAD11223344))) - Expect(frame.ErrorCode).To(Equal(uint32(0x13371234))) + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x1, + 0xef, 0xbe, 0xad, 0xde, // stream id + 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // byte offset + 0x34, 0x12, 0x37, 0x13, // error code + }) + frame, err := ParseRstStreamFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0x1122334455667788))) + Expect(frame.ErrorCode).To(Equal(uint32(0x13371234))) + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x1, + 0xde, 0xad, 0xbe, 0xef, // stream id + 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, // byte offset + 0x34, 0x12, 0x37, 0x13, // error code + }) + frame, err := ParseRstStreamFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0x8877665544332211))) + Expect(frame.ErrorCode).To(Equal(uint32(0x34123713))) + }) }) It("errors on EOFs", func() { - data := []byte{0x01, 0xEF, 0xBE, 0xAD, 0xDE, 0x44, 0x33, 0x22, 0x11, 0xAD, 0xFB, 0xCA, 0xDE, 0x34, 0x12, 0x37, 0x13} + data := []byte{0x1, + 0xef, 0xbe, 0xad, 0xde, 0x44, // stream id + 0x33, 0x22, 0x11, 0xad, 0xfb, 0xca, 0xde, 0x34, // byte offset + 0x12, 0x37, 0x13, // error code + } _, err := ParseRstStreamFrame(bytes.NewReader(data), protocol.VersionWhatever) Expect(err).NotTo(HaveOccurred()) for i := range data { @@ -31,22 +56,47 @@ var _ = Describe("RstStreamFrame", func() { }) Context("when writing", func() { - It("writes a sample RstStreamFrame", func() { - frame := RstStreamFrame{ - StreamID: 0x1337, - ByteOffset: 0x11223344DECAFBAD, - ErrorCode: 0xDEADBEEF, - } - b := &bytes.Buffer{} - frame.Write(b, 0) - Expect(b.Bytes()).To(Equal([]byte{0x01, 0x37, 0x13, 0, 0, 0xAD, 0xFB, 0xCA, 0xDE, 0x44, 0x33, 0x22, 0x11, 0xEF, 0xBE, 0xAD, 0xDE})) + Context("in little endian", func() { + It("writes a sample RstStreamFrame", func() { + frame := RstStreamFrame{ + StreamID: 0x1337, + ByteOffset: 0x11223344decafbad, + ErrorCode: 0xdeadbeef, + } + b := &bytes.Buffer{} + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x01, + 0x37, 0x13, 0x0, 0x0, // stream id + 0xad, 0xfb, 0xca, 0xde, 0x44, 0x33, 0x22, 0x11, // byte offset + 0xef, 0xbe, 0xad, 0xde, // error code + })) + }) + }) + + Context("in big endian", func() { + It("writes a sample RstStreamFrame", func() { + frame := RstStreamFrame{ + StreamID: 0x1337, + ByteOffset: 0x11223344decafbad, + ErrorCode: 0xdeadbeef, + } + b := &bytes.Buffer{} + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x01, + 0x0, 0x0, 0x13, 0x37, // stream id + 0x11, 0x22, 0x33, 0x44, 0xde, 0xca, 0xfb, 0xad, // byte offset + 0xde, 0xad, 0xbe, 0xef, // error code + })) + }) }) It("has the correct min length", func() { rst := RstStreamFrame{ StreamID: 0x1337, ByteOffset: 0x1000, - ErrorCode: 0xDE, + ErrorCode: 0xde, } Expect(rst.MinLength(0)).To(Equal(protocol.ByteCount(17))) }) diff --git a/frames/stop_waiting_frame.go b/frames/stop_waiting_frame.go index 8b141b72f..60925e5fd 100644 --- a/frames/stop_waiting_frame.go +++ b/frames/stop_waiting_frame.go @@ -13,7 +13,8 @@ import ( type StopWaitingFrame struct { LeastUnacked protocol.PacketNumber PacketNumberLen protocol.PacketNumberLen - PacketNumber protocol.PacketNumber + // PacketNumber is the packet number of the packet that this StopWaitingFrame will be sent with + PacketNumber protocol.PacketNumber } var ( @@ -23,34 +24,28 @@ var ( ) func (f *StopWaitingFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { - // packetNumber is the packet number of the packet that this StopWaitingFrame will be sent with - typeByte := uint8(0x06) - b.WriteByte(typeByte) - // make sure the PacketNumber was set if f.PacketNumber == protocol.PacketNumber(0) { return errPacketNumberNotSet } - if f.LeastUnacked > f.PacketNumber { return errLeastUnackedHigherThanPacketNumber } + b.WriteByte(0x06) leastUnackedDelta := uint64(f.PacketNumber - f.LeastUnacked) - switch f.PacketNumberLen { case protocol.PacketNumberLen1: b.WriteByte(uint8(leastUnackedDelta)) case protocol.PacketNumberLen2: - utils.LittleEndian.WriteUint16(b, uint16(leastUnackedDelta)) + utils.GetByteOrder(version).WriteUint16(b, uint16(leastUnackedDelta)) case protocol.PacketNumberLen4: - utils.LittleEndian.WriteUint32(b, uint32(leastUnackedDelta)) + utils.GetByteOrder(version).WriteUint32(b, uint32(leastUnackedDelta)) case protocol.PacketNumberLen6: - utils.LittleEndian.WriteUint48(b, leastUnackedDelta&(1<<48-1)) + utils.GetByteOrder(version).WriteUint48(b, leastUnackedDelta&(1<<48-1)) default: return errPacketNumberLenNotSet } - return nil } @@ -62,7 +57,6 @@ func (f *StopWaitingFrame) MinLength(version protocol.VersionNumber) (protocol.B return 0, errPacketNumberLenNotSet } minLength += protocol.ByteCount(f.PacketNumberLen) - return minLength, nil } @@ -71,21 +65,17 @@ func ParseStopWaitingFrame(r *bytes.Reader, packetNumber protocol.PacketNumber, frame := &StopWaitingFrame{} // read the TypeByte - _, err := r.ReadByte() - if err != nil { + if _, err := r.ReadByte(); err != nil { return nil, err } - leastUnackedDelta, err := utils.LittleEndian.ReadUintN(r, uint8(packetNumberLen)) + leastUnackedDelta, err := utils.GetByteOrder(version).ReadUintN(r, uint8(packetNumberLen)) if err != nil { return nil, err } - if leastUnackedDelta >= uint64(packetNumber) { return nil, qerr.Error(qerr.InvalidStopWaitingData, "invalid LeastUnackedDelta") } - frame.LeastUnacked = protocol.PacketNumber(uint64(packetNumber) - leastUnackedDelta) - return frame, nil } diff --git a/frames/stop_waiting_frame_test.go b/frames/stop_waiting_frame_test.go index e7a73b65a..5b9de9988 100644 --- a/frames/stop_waiting_frame_test.go +++ b/frames/stop_waiting_frame_test.go @@ -10,12 +10,24 @@ import ( var _ = Describe("StopWaitingFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{0x06, 0x03}) - frame, err := ParseStopWaitingFrame(b, 5, 1, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.LeastUnacked).To(Equal(protocol.PacketNumber(2))) - Expect(b.Len()).To(BeZero()) + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x06, 0x34, 0x12}) + frame, err := ParseStopWaitingFrame(b, 0x1337, 2, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LeastUnacked).To(Equal(protocol.PacketNumber(0x1337 - 0x1234))) + Expect(b.Len()).To(BeZero()) + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x06, 0x12, 0x34}) + frame, err := ParseStopWaitingFrame(b, 0x1337, 2, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.LeastUnacked).To(Equal(protocol.PacketNumber(0x1337 - 0x1234))) + Expect(b.Len()).To(BeZero()) + }) }) It("rejects frames that would have a negative LeastUnacked value", func() { @@ -44,16 +56,34 @@ var _ = Describe("StopWaitingFrame", func() { }) Context("when writing", func() { - It("writes a sample frame", func() { - b := &bytes.Buffer{} - frame := &StopWaitingFrame{ - LeastUnacked: 10, - PacketNumber: 13, - PacketNumberLen: protocol.PacketNumberLen6, - } - frame.Write(b, protocol.VersionWhatever) - Expect(b.Bytes()[0]).To(Equal(uint8(0x06))) - Expect(b.Bytes()[1:7]).To(Equal([]byte{3, 0, 0, 0, 0, 0})) + Context("in little endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 10, + PacketNumber: 13, + PacketNumberLen: protocol.PacketNumberLen6, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0]).To(Equal(uint8(0x06))) + Expect(b.Bytes()[1:7]).To(Equal([]byte{3, 0, 0, 0, 0, 0})) + }) + }) + + Context("in big endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 10, + PacketNumber: 13, + PacketNumberLen: protocol.PacketNumberLen6, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0]).To(Equal(uint8(0x06))) + Expect(b.Bytes()[1:7]).To(Equal([]byte{0, 0, 0, 0, 0, 3})) + }) }) It("errors when PacketNumber was not set", func() { @@ -62,7 +92,7 @@ var _ = Describe("StopWaitingFrame", func() { LeastUnacked: 10, PacketNumberLen: protocol.PacketNumberLen1, } - err := frame.Write(b, 0) + err := frame.Write(b, protocol.VersionWhatever) Expect(err).To(MatchError(errPacketNumberNotSet)) }) @@ -72,7 +102,7 @@ var _ = Describe("StopWaitingFrame", func() { LeastUnacked: 10, PacketNumber: 13, } - err := frame.Write(b, 0) + err := frame.Write(b, protocol.VersionWhatever) Expect(err).To(MatchError(errPacketNumberLenNotSet)) }) @@ -83,61 +113,117 @@ var _ = Describe("StopWaitingFrame", func() { PacketNumber: 5, PacketNumberLen: protocol.PacketNumberLen1, } - err := frame.Write(b, 0) + err := frame.Write(b, protocol.VersionWhatever) Expect(err).To(MatchError(errLeastUnackedHigherThanPacketNumber)) }) Context("LeastUnackedDelta length", func() { - It("writes a 1-byte LeastUnackedDelta", func() { - b := &bytes.Buffer{} - frame := &StopWaitingFrame{ - LeastUnacked: 10, - PacketNumber: 13, - PacketNumberLen: protocol.PacketNumberLen1, - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(2)) - Expect(b.Bytes()[1]).To(Equal(uint8(3))) + Context("in little endian", func() { + It("writes a 1-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 10, + PacketNumber: 13, + PacketNumberLen: protocol.PacketNumberLen1, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(2)) + Expect(b.Bytes()[1]).To(Equal(uint8(3))) + }) + + It("writes a 2-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x10, + PacketNumber: 0x1300, + PacketNumberLen: protocol.PacketNumberLen2, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(3)) + Expect(b.Bytes()[1:3]).To(Equal([]byte{0xf0, 0x12})) + }) + + It("writes a 4-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x1000, + PacketNumber: 0x12345678, + PacketNumberLen: protocol.PacketNumberLen4, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(5)) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0x78, 0x46, 0x34, 0x12})) + }) + + It("writes a 6-byte LeastUnackedDelta, for a delta that fits into 6 bytes", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x10, + PacketNumber: 0x123456789abc, + PacketNumberLen: protocol.PacketNumberLen6, + } + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(7)) + Expect(b.Bytes()[1:7]).To(Equal([]byte{0xbc - 0x10, 0x9a, 0x78, 0x56, 0x34, 0x12})) + }) }) - It("writes a 2-byte LeastUnackedDelta", func() { - b := &bytes.Buffer{} - frame := &StopWaitingFrame{ - LeastUnacked: 0x10, - PacketNumber: 0x1300, - PacketNumberLen: protocol.PacketNumberLen2, - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(3)) - Expect(b.Bytes()[1:3]).To(Equal([]byte{0xF0, 0x12})) - }) + Context("in big endian", func() { + It("writes a 1-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 10, + PacketNumber: 13, + PacketNumberLen: protocol.PacketNumberLen1, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(2)) + Expect(b.Bytes()[1]).To(Equal(uint8(3))) + }) - It("writes a 4-byte LeastUnackedDelta", func() { - b := &bytes.Buffer{} - frame := &StopWaitingFrame{ - LeastUnacked: 0x1000, - PacketNumber: 0x12345678, - PacketNumberLen: protocol.PacketNumberLen4, - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(5)) - Expect(b.Bytes()[1:5]).To(Equal([]byte{0x78, 0x46, 0x34, 0x12})) - }) + It("writes a 2-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x10, + PacketNumber: 0x1300, + PacketNumberLen: protocol.PacketNumberLen2, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(3)) + Expect(b.Bytes()[1:3]).To(Equal([]byte{0x12, 0xf0})) + }) - It("writes a 6-byte LeastUnackedDelta, for a delta that fits into 6 bytes", func() { - b := &bytes.Buffer{} - frame := &StopWaitingFrame{ - LeastUnacked: 0x10, - PacketNumber: 0x123456789ABC, - PacketNumberLen: protocol.PacketNumberLen6, - } - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Len()).To(Equal(7)) - Expect(b.Bytes()[1:7]).To(Equal([]byte{0xAC, 0x9A, 0x78, 0x56, 0x34, 0x12})) + It("writes a 4-byte LeastUnackedDelta", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x1000, + PacketNumber: 0x12345678, + PacketNumberLen: protocol.PacketNumberLen4, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(5)) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0x12, 0x34, 0x46, 0x78})) + }) + + It("writes a 6-byte LeastUnackedDelta, for a delta that fits into 6 bytes", func() { + b := &bytes.Buffer{} + frame := &StopWaitingFrame{ + LeastUnacked: 0x10, + PacketNumber: 0x123456789abc, + PacketNumberLen: protocol.PacketNumberLen6, + } + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Len()).To(Equal(7)) + Expect(b.Bytes()[1:7]).To(Equal([]byte{0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc - 0x10})) + }) }) }) }) @@ -171,7 +257,8 @@ var _ = Describe("StopWaitingFrame", func() { PacketNumberLen: protocol.PacketNumberLen4, } b := &bytes.Buffer{} - frame.Write(b, 0) + err := frame.Write(b, protocol.VersionWhatever) + Expect(err).ToNot(HaveOccurred()) readframe, err := ParseStopWaitingFrame(bytes.NewReader(b.Bytes()), packetNumber, protocol.PacketNumberLen4, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(readframe.LeastUnacked).To(Equal(frame.LeastUnacked)) diff --git a/frames/stream_frame.go b/frames/stream_frame.go index c195e4966..d16b2efdd 100644 --- a/frames/stream_frame.go +++ b/frames/stream_frame.go @@ -35,19 +35,19 @@ func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF frame.FinBit = typeByte&0x40 > 0 frame.DataLenPresent = typeByte&0x20 > 0 - offsetLen := typeByte & 0x1C >> 2 + offsetLen := typeByte & 0x1c >> 2 if offsetLen != 0 { offsetLen++ } - streamIDLen := typeByte&0x03 + 1 + streamIDLen := typeByte&0x3 + 1 - sid, err := utils.LittleEndian.ReadUintN(r, streamIDLen) + sid, err := utils.GetByteOrder(version).ReadUintN(r, streamIDLen) if err != nil { return nil, err } frame.StreamID = protocol.StreamID(sid) - offset, err := utils.LittleEndian.ReadUintN(r, offsetLen) + offset, err := utils.GetByteOrder(version).ReadUintN(r, offsetLen) if err != nil { return nil, err } @@ -55,7 +55,7 @@ func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF var dataLen uint16 if frame.DataLenPresent { - dataLen, err = utils.LittleEndian.ReadUint16(r) + dataLen, err = utils.GetByteOrder(version).ReadUint16(r) if err != nil { return nil, err } @@ -79,11 +79,9 @@ func ParseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF if frame.Offset+frame.DataLen() < frame.Offset { return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset") } - if !frame.FinBit && frame.DataLen() == 0 { return nil, qerr.EmptyStreamFrameNoFin } - return frame, nil } @@ -94,17 +92,14 @@ func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err } typeByte := uint8(0x80) // sets the leftmost bit to 1 - if f.FinBit { typeByte ^= 0x40 } - if f.DataLenPresent { typeByte ^= 0x20 } offsetLength := f.getOffsetLength() - if offsetLength > 0 { typeByte ^= (uint8(offsetLength) - 1) << 2 } @@ -118,11 +113,11 @@ func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err case 1: b.WriteByte(uint8(f.StreamID)) case 2: - utils.LittleEndian.WriteUint16(b, uint16(f.StreamID)) + utils.GetByteOrder(version).WriteUint16(b, uint16(f.StreamID)) case 3: - utils.LittleEndian.WriteUint24(b, uint32(f.StreamID)) + utils.GetByteOrder(version).WriteUint24(b, uint32(f.StreamID)) case 4: - utils.LittleEndian.WriteUint32(b, uint32(f.StreamID)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.StreamID)) default: return errInvalidStreamIDLen } @@ -130,29 +125,28 @@ func (f *StreamFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) err switch offsetLength { case 0: case 2: - utils.LittleEndian.WriteUint16(b, uint16(f.Offset)) + utils.GetByteOrder(version).WriteUint16(b, uint16(f.Offset)) case 3: - utils.LittleEndian.WriteUint24(b, uint32(f.Offset)) + utils.GetByteOrder(version).WriteUint24(b, uint32(f.Offset)) case 4: - utils.LittleEndian.WriteUint32(b, uint32(f.Offset)) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.Offset)) case 5: - utils.LittleEndian.WriteUint40(b, uint64(f.Offset)) + utils.GetByteOrder(version).WriteUint40(b, uint64(f.Offset)) case 6: - utils.LittleEndian.WriteUint48(b, uint64(f.Offset)) + utils.GetByteOrder(version).WriteUint48(b, uint64(f.Offset)) case 7: - utils.LittleEndian.WriteUint56(b, uint64(f.Offset)) + utils.GetByteOrder(version).WriteUint56(b, uint64(f.Offset)) case 8: - utils.LittleEndian.WriteUint64(b, uint64(f.Offset)) + utils.GetByteOrder(version).WriteUint64(b, uint64(f.Offset)) default: return errInvalidOffsetLen } if f.DataLenPresent { - utils.LittleEndian.WriteUint16(b, uint16(len(f.Data))) + utils.GetByteOrder(version).WriteUint16(b, uint16(len(f.Data))) } b.Write(f.Data) - return nil } @@ -199,7 +193,6 @@ func (f *StreamFrame) MinLength(protocol.VersionNumber) (protocol.ByteCount, err if f.DataLenPresent { length += 2 } - return length, nil } diff --git a/frames/stream_frame_test.go b/frames/stream_frame_test.go index fe54b3f16..415fee280 100644 --- a/frames/stream_frame_test.go +++ b/frames/stream_frame_test.go @@ -11,21 +11,115 @@ import ( var _ = Describe("StreamFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - // a STREAM frame, plus 3 additional bytes, not belonging to this frame - b := bytes.NewReader([]byte{0xa0, 0x1, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r' /* additional bytes */, 'f', 'o', 'o'}) - frame, err := ParseStreamFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.FinBit).To(BeFalse()) - Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) - Expect(frame.Offset).To(BeZero()) - Expect(frame.DataLenPresent).To(BeTrue()) - Expect(frame.Data).To(Equal([]byte("foobar"))) - Expect(b.Len()).To(Equal(3)) + Context("in little endian", func() { + It("accepts a sample frame", func() { + // a STREAM frame, plus 3 additional bytes, not belonging to this frame + b := bytes.NewReader([]byte{0x80 ^ 0x20, + 0x1, // stream id + 0x6, 0x0, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + 'f', 'o', 'o', // additional bytes + }) + frame, err := ParseStreamFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.FinBit).To(BeFalse()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) + Expect(frame.Offset).To(BeZero()) + Expect(frame.DataLenPresent).To(BeTrue()) + Expect(frame.Data).To(Equal([]byte("foobar"))) + Expect(b.Len()).To(Equal(3)) + }) + + It("accepts frames with offsets", func() { + b := bytes.NewReader([]byte{0x80 ^ 0x20 /* 2 byte offset */ ^ 0x4, + 0x1, // stream id + 0x42, 0x0, // offset + 0x6, 0x0, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + }) + frame, err := ParseStreamFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.FinBit).To(BeFalse()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) + Expect(frame.Offset).To(Equal(protocol.ByteCount(0x42))) + Expect(frame.DataLenPresent).To(BeTrue()) + Expect(frame.Data).To(Equal([]byte("foobar"))) + Expect(b.Len()).To(BeZero()) + }) + + It("errors on EOFs", func() { + data := []byte{0x80 ^ 0x20 ^ 0x4, + 0x1, // stream id + 0x2a, 0x0, // offset + 0x6, 0x0, // data length, + 'f', 'o', 'o', 'b', 'a', 'r', + } + _, err := ParseStreamFrame(bytes.NewReader(data), versionLittleEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseStreamFrame(bytes.NewReader(data[0:i]), versionLittleEndian) + Expect(err).To(HaveOccurred()) + } + }) + }) + + Context("in big endian", func() { + It("accepts a sample frame", func() { + // a STREAM frame, plus 3 additional bytes, not belonging to this frame + b := bytes.NewReader([]byte{0x80 ^ 0x20, + 0x1, // stream id + 0x0, 0x6, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + 'f', 'o', 'o', // additional bytes + }) + frame, err := ParseStreamFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.FinBit).To(BeFalse()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) + Expect(frame.Offset).To(BeZero()) + Expect(frame.DataLenPresent).To(BeTrue()) + Expect(frame.Data).To(Equal([]byte("foobar"))) + Expect(b.Len()).To(Equal(3)) + }) + + It("accepts frames with offsets", func() { + b := bytes.NewReader([]byte{0x80 ^ 0x20 /* 2 byte offset */ ^ 0x4, + 0x1, // stream id + 0x0, 0x42, // offset + 0x0, 0x6, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + }) + frame, err := ParseStreamFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.FinBit).To(BeFalse()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) + Expect(frame.Offset).To(Equal(protocol.ByteCount(0x42))) + Expect(frame.DataLenPresent).To(BeTrue()) + Expect(frame.Data).To(Equal([]byte("foobar"))) + Expect(b.Len()).To(BeZero()) + }) + + It("errors on EOFs", func() { + data := []byte{0x80 ^ 0x20 ^ 0x4, + 0x1, // stream id + 0x0, 0x2a, // offset + 0x0, 0x6, // data length, + 'f', 'o', 'o', 'b', 'a', 'r', + } + _, err := ParseStreamFrame(bytes.NewReader(data), versionBigEndian) + Expect(err).NotTo(HaveOccurred()) + for i := range data { + _, err := ParseStreamFrame(bytes.NewReader(data[0:i]), versionBigEndian) + Expect(err).To(HaveOccurred()) + } + }) }) It("accepts frame without data length", func() { - b := bytes.NewReader([]byte{0x80, 0x1, 'f', 'o', 'o', 'b', 'a', 'r'}) + b := bytes.NewReader([]byte{0x80, + 0x1, // stream id + 'f', 'o', 'o', 'b', 'a', 'r', + }) frame, err := ParseStreamFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.FinBit).To(BeFalse()) @@ -38,7 +132,11 @@ var _ = Describe("StreamFrame", func() { It("accepts an empty frame with FinBit set, with data length set", func() { // the STREAM frame, plus 3 additional bytes, not belonging to this frame - b := bytes.NewReader([]byte{0x80 ^ 0x40 ^ 0x20, 0x1 /* stream id */, 0, 0, 'f', 'o', 'o'}) + b := bytes.NewReader([]byte{0x80 ^ 0x40 ^ 0x20, + 0x1, // stream id + 0, 0, // data length + 'f', 'o', 'o', // additional bytes + }) frame, err := ParseStreamFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.FinBit).To(BeTrue()) @@ -48,7 +146,10 @@ var _ = Describe("StreamFrame", func() { }) It("accepts an empty frame with the FinBit set", func() { - b := bytes.NewReader([]byte{0x80 ^ 0x40, 0x1 /* stream id */, 'f', 'o', 'o', 'b', 'a', 'r'}) + b := bytes.NewReader([]byte{0x80 ^ 0x40, + 0x1, // stream id + 'f', 'o', 'o', 'b', 'a', 'r', + }) frame, err := ParseStreamFrame(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(frame.FinBit).To(BeTrue()) @@ -57,20 +158,11 @@ var _ = Describe("StreamFrame", func() { Expect(b.Len()).To(BeZero()) }) - It("accepts frames with offsets", func() { - b := bytes.NewReader([]byte{0xa4, 0x1, 0x2a, 0x00, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'}) - frame, err := ParseStreamFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.FinBit).To(BeFalse()) - Expect(frame.StreamID).To(Equal(protocol.StreamID(1))) - Expect(frame.Offset).To(Equal(protocol.ByteCount(42))) - Expect(frame.DataLenPresent).To(BeTrue()) - Expect(frame.Data).To(Equal([]byte("foobar"))) - Expect(b.Len()).To(BeZero()) - }) - It("errors on empty stream frames that don't have the FinBit set", func() { - b := bytes.NewReader([]byte{0x80 ^ 0x20, 0x1, 0, 0}) + b := bytes.NewReader([]byte{0x80 ^ 0x20, + 0x1, // stream id + 0, 0, // data length + }) _, err := ParseStreamFrame(b, protocol.VersionWhatever) Expect(err).To(MatchError(qerr.EmptyStreamFrameNoFin)) }) @@ -89,32 +181,46 @@ var _ = Describe("StreamFrame", func() { Data: []byte{'f'}, } b := &bytes.Buffer{} - f.Write(b, protocol.VersionWhatever) - _, err := ParseStreamFrame(bytes.NewReader(b.Bytes()), protocol.VersionWhatever) + err := f.Write(b, protocol.VersionWhatever) + Expect(err).ToNot(HaveOccurred()) + _, err = ParseStreamFrame(bytes.NewReader(b.Bytes()), protocol.VersionWhatever) Expect(err).To(MatchError(qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset"))) }) - - It("errors on EOFs", func() { - data := []byte{0xa4, 0x1, 0x2a, 0x00, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'} - _, err := ParseStreamFrame(bytes.NewReader(data), protocol.VersionWhatever) - Expect(err).NotTo(HaveOccurred()) - for i := range data { - _, err := ParseStreamFrame(bytes.NewReader(data[0:i]), protocol.VersionWhatever) - Expect(err).To(HaveOccurred()) - } - }) }) Context("when writing", func() { - It("writes sample frame", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - DataLenPresent: true, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()).To(Equal([]byte{0xa0, 0x1, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'})) + Context("in little endian", func() { + It("writes sample frame", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + DataLenPresent: true, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x80 ^ 0x20, + 0x1, // stream id + 0x6, 0x0, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + })) + }) + }) + + Context("in big endian", func() { + It("writes sample frame", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + DataLenPresent: true, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x80 ^ 0x20, + 0x1, // stream id + 0x6, 0x0, // data length + 'f', 'o', 'o', 'b', 'a', 'r', + })) + }) }) It("sets the FinBit", func() { @@ -123,7 +229,7 @@ var _ = Describe("StreamFrame", func() { StreamID: 1, Data: []byte("foobar"), FinBit: true, - }).Write(b, 0) + }).Write(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(b.Bytes()[0] & 0x40).To(Equal(byte(0x40))) }) @@ -132,7 +238,7 @@ var _ = Describe("StreamFrame", func() { b := &bytes.Buffer{} err := (&StreamFrame{ StreamID: 1, - }).Write(b, 0) + }).Write(b, protocol.VersionWhatever) Expect(err).To(MatchError("StreamFrame: attempting to write empty frame without FIN")) }) @@ -144,7 +250,7 @@ var _ = Describe("StreamFrame", func() { Offset: 0, FinBit: true, } - err := f.Write(b, 0) + err := f.Write(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(b.Len()))) }) @@ -152,31 +258,51 @@ var _ = Describe("StreamFrame", func() { It("has proper min length for a long StreamID and a big offset", func() { b := &bytes.Buffer{} f := &StreamFrame{ - StreamID: 0xDECAFBAD, + StreamID: 0xdecafbad, Data: []byte{}, - Offset: 0xDEADBEEFCAFE, + Offset: 0xdeadbeefcafe, FinBit: true, } - err := f.Write(b, 0) + err := f.Write(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(b.Len()))) }) Context("data length field", func() { - It("writes the data length", func() { - dataLen := 0x1337 - b := &bytes.Buffer{} - f := &StreamFrame{ - StreamID: 1, - Data: bytes.Repeat([]byte{'f'}, dataLen), - DataLenPresent: true, - Offset: 0, - } - err := f.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - minLength, _ := f.MinLength(0) - Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0x20))) - Expect(b.Bytes()[minLength-2 : minLength]).To(Equal([]byte{0x37, 0x13})) + Context("in little endian", func() { + It("writes the data length", func() { + dataLen := 0x1337 + b := &bytes.Buffer{} + f := &StreamFrame{ + StreamID: 1, + Data: bytes.Repeat([]byte{'f'}, dataLen), + DataLenPresent: true, + Offset: 0, + } + err := f.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + minLength, _ := f.MinLength(0) + Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0x20))) + Expect(b.Bytes()[minLength-2 : minLength]).To(Equal([]byte{0x37, 0x13})) + }) + }) + + Context("in big endian", func() { + It("writes the data length", func() { + dataLen := 0x1337 + b := &bytes.Buffer{} + f := &StreamFrame{ + StreamID: 1, + Data: bytes.Repeat([]byte{'f'}, dataLen), + DataLenPresent: true, + Offset: 0, + } + err := f.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + minLength, _ := f.MinLength(0) + Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0x20))) + Expect(b.Bytes()[minLength-2 : minLength]).To(Equal([]byte{0x13, 0x37})) + }) }) It("omits the data length field", func() { @@ -188,7 +314,7 @@ var _ = Describe("StreamFrame", func() { DataLenPresent: false, Offset: 0, } - err := f.Write(b, 0) + err := f.Write(b, protocol.VersionWhatever) Expect(err).ToNot(HaveOccurred()) Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0))) Expect(b.Bytes()[1 : b.Len()-dataLen]).ToNot(ContainSubstring(string([]byte{0x37, 0x13}))) @@ -212,157 +338,316 @@ var _ = Describe("StreamFrame", func() { }) Context("offset lengths", func() { - It("does not write an offset if the offset is 0", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x0))) + Context("in little endian", func() { + It("does not write an offset if the offset is 0", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x0))) + }) + + It("writes a 2-byte offset if the offset is larger than 0", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x1337, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x1 << 2))) + Expect(b.Bytes()[2:4]).To(Equal([]byte{0x37, 0x13})) + }) + + It("writes a 3-byte offset if the offset", func() { + b := &bytes.Buffer{} + (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13cafe, + }).Write(b, versionLittleEndian) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x2 << 2))) + Expect(b.Bytes()[2:5]).To(Equal([]byte{0xfe, 0xca, 0x13})) + }) + + It("writes a 4-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0xdeadbeef, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x3 << 2))) + Expect(b.Bytes()[2:6]).To(Equal([]byte{0xef, 0xbe, 0xad, 0xde})) + }) + + It("writes a 5-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13deadbeef, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x4 << 2))) + Expect(b.Bytes()[2:7]).To(Equal([]byte{0xef, 0xbe, 0xad, 0xde, 0x13})) + }) + + It("writes a 6-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0xdeadbeefcafe, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x5 << 2))) + Expect(b.Bytes()[2:8]).To(Equal([]byte{0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde})) + }) + + It("writes a 7-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13deadbeefcafe, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x6 << 2))) + Expect(b.Bytes()[2:9]).To(Equal([]byte{0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde, 0x13})) + }) + + It("writes a 8-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x1337deadbeefcafe, + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x7 << 2))) + Expect(b.Bytes()[2:10]).To(Equal([]byte{0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde, 0x37, 0x13})) + }) }) - It("writes a 2-byte offset if the offset is larger than 0", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0x1337, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x1 << 2))) - Expect(b.Bytes()[2:4]).To(Equal([]byte{0x37, 0x13})) - }) + Context("in big endian", func() { + It("does not write an offset if the offset is 0", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x0))) + }) - It("writes a 3-byte offset if the offset", func() { - b := &bytes.Buffer{} - (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0x13CAFE, - }).Write(b, 0) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x2 << 2))) - Expect(b.Bytes()[2:5]).To(Equal([]byte{0xFE, 0xCA, 0x13})) - }) + It("writes a 2-byte offset if the offset is larger than 0", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x1337, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x1 << 2))) + Expect(b.Bytes()[2:4]).To(Equal([]byte{0x13, 0x37})) + }) - It("writes a 4-byte offset if the offset", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0xDEADBEEF, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x3 << 2))) - Expect(b.Bytes()[2:6]).To(Equal([]byte{0xEF, 0xBE, 0xAD, 0xDE})) - }) + It("writes a 3-byte offset if the offset", func() { + b := &bytes.Buffer{} + (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13cafe, + }).Write(b, versionBigEndian) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x2 << 2))) + Expect(b.Bytes()[2:5]).To(Equal([]byte{0x13, 0xca, 0xfe})) + }) - It("writes a 5-byte offset if the offset", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0x13DEADBEEF, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x4 << 2))) - Expect(b.Bytes()[2:7]).To(Equal([]byte{0xEF, 0xBE, 0xAD, 0xDE, 0x13})) - }) + It("writes a 4-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0xdeadbeef, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x3 << 2))) + Expect(b.Bytes()[2:6]).To(Equal([]byte{0xde, 0xad, 0xbe, 0xef})) + }) - It("writes a 6-byte offset if the offset", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0xDEADBEEFCAFE, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x5 << 2))) - Expect(b.Bytes()[2:8]).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE})) - }) + It("writes a 5-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13deadbeef, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x4 << 2))) + Expect(b.Bytes()[2:7]).To(Equal([]byte{0x13, 0xde, 0xad, 0xbe, 0xef})) + }) - It("writes a 7-byte offset if the offset", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0x13DEADBEEFCAFE, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x6 << 2))) - Expect(b.Bytes()[2:9]).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE, 0x13})) - }) + It("writes a 6-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0xdeadbeefcafe, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x5 << 2))) + Expect(b.Bytes()[2:8]).To(Equal([]byte{0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe})) + }) - It("writes a 8-byte offset if the offset", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 1, - Data: []byte("foobar"), - Offset: 0x1337DEADBEEFCAFE, - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x7 << 2))) - Expect(b.Bytes()[2:10]).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE, 0x37, 0x13})) + It("writes a 7-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x13deadbeefcafe, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x6 << 2))) + Expect(b.Bytes()[2:9]).To(Equal([]byte{0x13, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe})) + }) + + It("writes a 8-byte offset if the offset", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 1, + Data: []byte("foobar"), + Offset: 0x1337deadbeefcafe, + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x1c).To(Equal(uint8(0x7 << 2))) + Expect(b.Bytes()[2:10]).To(Equal([]byte{0x13, 0x37, 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe})) + }) }) }) Context("lengths of StreamIDs", func() { - It("writes a 1 byte StreamID", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 13, - Data: []byte("foobar"), - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x0))) - Expect(b.Bytes()[1]).To(Equal(uint8(13))) + Context("in little endian", func() { + It("writes a 1 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 13, + Data: []byte("foobar"), + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x0))) + Expect(b.Bytes()[1]).To(Equal(uint8(13))) + }) + + It("writes a 2 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0xcafe, + Data: []byte("foobar"), + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x1))) + Expect(b.Bytes()[1:3]).To(Equal([]byte{0xfe, 0xca})) + }) + + It("writes a 3 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0x13beef, + Data: []byte("foobar"), + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x2))) + Expect(b.Bytes()[1:4]).To(Equal([]byte{0xef, 0xbe, 0x13})) + }) + + It("writes a 4 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0xdecafbad, + Data: []byte("foobar"), + }).Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0xad, 0xfb, 0xca, 0xde})) + }) + + It("writes a multiple byte StreamID, after the Stream length was already determined by MinLenght()", func() { + b := &bytes.Buffer{} + frame := &StreamFrame{ + StreamID: 0xdecafbad, + Data: []byte("foobar"), + } + frame.MinLength(0) + err := frame.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0xad, 0xfb, 0xca, 0xde})) + }) }) - It("writes a 2 byte StreamID", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 0xCAFE, - Data: []byte("foobar"), - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x1))) - Expect(b.Bytes()[1:3]).To(Equal([]byte{0xFE, 0xCA})) - }) + Context("in big endian", func() { + It("writes a 1 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 13, + Data: []byte("foobar"), + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x0))) + Expect(b.Bytes()[1]).To(Equal(uint8(13))) + }) - It("writes a 3 byte StreamID", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 0x13BEEF, - Data: []byte("foobar"), - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x2))) - Expect(b.Bytes()[1:4]).To(Equal([]byte{0xEF, 0xBE, 0x13})) - }) + It("writes a 2 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0xcafe, + Data: []byte("foobar"), + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x1))) + Expect(b.Bytes()[1:3]).To(Equal([]byte{0xca, 0xfe})) + }) - It("writes a 4 byte StreamID", func() { - b := &bytes.Buffer{} - err := (&StreamFrame{ - StreamID: 0xDECAFBAD, - Data: []byte("foobar"), - }).Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) - Expect(b.Bytes()[1:5]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE})) - }) + It("writes a 3 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0x13beef, + Data: []byte("foobar"), + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x2))) + Expect(b.Bytes()[1:4]).To(Equal([]byte{0x13, 0xbe, 0xef})) + }) - It("writes a multiple byte StreamID, after the Stream length was already determined by MinLenght()", func() { - b := &bytes.Buffer{} - frame := &StreamFrame{ - StreamID: 0xDECAFBAD, - Data: []byte("foobar"), - } - frame.MinLength(0) - err := frame.Write(b, 0) - Expect(err).ToNot(HaveOccurred()) - Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) - Expect(b.Bytes()[1:5]).To(Equal([]byte{0xAD, 0xFB, 0xCA, 0xDE})) + It("writes a 4 byte StreamID", func() { + b := &bytes.Buffer{} + err := (&StreamFrame{ + StreamID: 0xdecafbad, + Data: []byte("foobar"), + }).Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0xde, 0xca, 0xfb, 0xad})) + }) + + It("writes a multiple byte StreamID, after the Stream length was already determined by MinLenght()", func() { + b := &bytes.Buffer{} + frame := &StreamFrame{ + StreamID: 0xdecafbad, + Data: []byte("foobar"), + } + frame.MinLength(0) + err := frame.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()[0] & 0x3).To(Equal(uint8(0x3))) + Expect(b.Bytes()[1:5]).To(Equal([]byte{0xde, 0xca, 0xfb, 0xad})) + }) }) }) }) diff --git a/frames/window_update_frame.go b/frames/window_update_frame.go index 1097d5851..b91aaf81f 100644 --- a/frames/window_update_frame.go +++ b/frames/window_update_frame.go @@ -15,11 +15,9 @@ type WindowUpdateFrame struct { //Write writes a RST_STREAM frame func (f *WindowUpdateFrame) Write(b *bytes.Buffer, version protocol.VersionNumber) error { - typeByte := uint8(0x04) - b.WriteByte(typeByte) - - utils.LittleEndian.WriteUint32(b, uint32(f.StreamID)) - utils.LittleEndian.WriteUint64(b, uint64(f.ByteOffset)) + b.WriteByte(0x4) + utils.GetByteOrder(version).WriteUint32(b, uint32(f.StreamID)) + utils.GetByteOrder(version).WriteUint64(b, uint64(f.ByteOffset)) return nil } @@ -33,22 +31,20 @@ func ParseWindowUpdateFrame(r *bytes.Reader, version protocol.VersionNumber) (*W frame := &WindowUpdateFrame{} // read the TypeByte - _, err := r.ReadByte() - if err != nil { + if _, err := r.ReadByte(); err != nil { return nil, err } - sid, err := utils.LittleEndian.ReadUint32(r) + sid, err := utils.GetByteOrder(version).ReadUint32(r) if err != nil { return nil, err } frame.StreamID = protocol.StreamID(sid) - byteOffset, err := utils.LittleEndian.ReadUint64(r) + byteOffset, err := utils.GetByteOrder(version).ReadUint64(r) if err != nil { return nil, err } frame.ByteOffset = protocol.ByteCount(byteOffset) - return frame, nil } diff --git a/frames/window_update_frame_test.go b/frames/window_update_frame_test.go index abfccc473..13fc7e713 100644 --- a/frames/window_update_frame_test.go +++ b/frames/window_update_frame_test.go @@ -10,17 +10,39 @@ import ( var _ = Describe("WindowUpdateFrame", func() { Context("when parsing", func() { - It("accepts sample frame", func() { - b := bytes.NewReader([]byte{0x04, 0xEF, 0xBE, 0xAD, 0xDE, 0x44, 0x33, 0x22, 0x11, 0xAD, 0xFB, 0xCA, 0xDE}) - frame, err := ParseWindowUpdateFrame(b, protocol.VersionWhatever) - Expect(err).ToNot(HaveOccurred()) - Expect(frame.StreamID).To(Equal(protocol.StreamID(0xDEADBEEF))) - Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0xDECAFBAD11223344))) - Expect(b.Len()).To(Equal(0)) + Context("in little endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x4, + 0xef, 0xbe, 0xad, 0xde, // stream id + 0x44, 0x33, 0x22, 0x11, 0xad, 0xfb, 0xca, 0xde, // byte offset + }) + frame, err := ParseWindowUpdateFrame(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0xdecafbad11223344))) + Expect(b.Len()).To(BeZero()) + }) + }) + + Context("in big endian", func() { + It("accepts sample frame", func() { + b := bytes.NewReader([]byte{0x4, + 0xde, 0xad, 0xbe, 0xef, // stream id + 0xde, 0xca, 0xfb, 0xad, 0x11, 0x22, 0x33, 0x44, // byte offset + }) + frame, err := ParseWindowUpdateFrame(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(frame.StreamID).To(Equal(protocol.StreamID(0xdeadbeef))) + Expect(frame.ByteOffset).To(Equal(protocol.ByteCount(0xdecafbad11223344))) + Expect(b.Len()).To(BeZero()) + }) }) It("errors on EOFs", func() { - data := []byte{0x04, 0xEF, 0xBE, 0xAD, 0xDE, 0x44, 0x33, 0x22, 0x11, 0xAD, 0xFB, 0xCA, 0xDE} + data := []byte{0x4, + 0xef, 0xbe, 0xad, 0xde, // stream id + 0x44, 0x33, 0x22, 0x11, 0xad, 0xfb, 0xca, 0xde, // byte offset + } _, err := ParseWindowUpdateFrame(bytes.NewReader(data), protocol.VersionWhatever) Expect(err).NotTo(HaveOccurred()) for i := range data { @@ -34,19 +56,41 @@ var _ = Describe("WindowUpdateFrame", func() { It("has proper min length", func() { f := &WindowUpdateFrame{ StreamID: 0x1337, - ByteOffset: 0xDEADBEEF, + ByteOffset: 0xdeadbeef, } Expect(f.MinLength(0)).To(Equal(protocol.ByteCount(13))) }) - It("writes a sample frame", func() { - b := &bytes.Buffer{} - f := &WindowUpdateFrame{ - StreamID: 0xDECAFBAD, - ByteOffset: 0xDEADBEEFCAFE1337, - } - f.Write(b, 0) - Expect(b.Bytes()).To(Equal([]byte{0x04, 0xAD, 0xFB, 0xCA, 0xDE, 0x37, 0x13, 0xFE, 0xCA, 0xEF, 0xBE, 0xAD, 0xDE})) + Context("in little endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + f := &WindowUpdateFrame{ + StreamID: 0xdecafbad, + ByteOffset: 0xdeadbeefcafe1337, + } + err := f.Write(b, versionLittleEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x4, + 0xad, 0xfb, 0xca, 0xde, // stream id + 0x37, 0x13, 0xfe, 0xca, 0xef, 0xbe, 0xad, 0xde, // byte offset + })) + }) + }) + + Context("in big endian", func() { + It("writes a sample frame", func() { + b := &bytes.Buffer{} + f := &WindowUpdateFrame{ + StreamID: 0xdecafbad, + ByteOffset: 0xdeadbeefcafe1337, + } + err := f.Write(b, versionBigEndian) + Expect(err).ToNot(HaveOccurred()) + Expect(b.Bytes()).To(Equal([]byte{0x4, + 0xde, 0xca, 0xfb, 0xad, // stream id + 0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0x13, 0x37, // byte offset + })) + }) }) }) })