forked from quic-go/quic-go
@@ -77,8 +77,25 @@ func (f *StreamFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber,
|
||||
typeByte ^= 0x40
|
||||
}
|
||||
typeByte ^= 0x20 // dataLenPresent
|
||||
if f.Offset != 0 {
|
||||
typeByte ^= 0x1c // TODO: Send shorter offset if possible
|
||||
|
||||
offsetLength := f.getOffsetLength()
|
||||
switch offsetLength {
|
||||
case 0:
|
||||
typeByte ^= 0x0
|
||||
case 2:
|
||||
typeByte ^= 0x1 << 2
|
||||
case 3:
|
||||
typeByte ^= 0x2 << 2
|
||||
case 4:
|
||||
typeByte ^= 0x3 << 2
|
||||
case 5:
|
||||
typeByte ^= 0x4 << 2
|
||||
case 6:
|
||||
typeByte ^= 0x5 << 2
|
||||
case 7:
|
||||
typeByte ^= 0x6 << 2
|
||||
case 8:
|
||||
typeByte ^= 0x7 << 2
|
||||
}
|
||||
|
||||
if f.streamIDLen == 0 {
|
||||
@@ -109,9 +126,24 @@ func (f *StreamFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber,
|
||||
utils.WriteUint32(b, uint32(f.StreamID))
|
||||
}
|
||||
|
||||
if f.Offset != 0 {
|
||||
switch offsetLength {
|
||||
case 0:
|
||||
case 2:
|
||||
utils.WriteUint16(b, uint16(f.Offset))
|
||||
case 3:
|
||||
utils.WriteUint24(b, uint32(f.Offset))
|
||||
case 4:
|
||||
utils.WriteUint32(b, uint32(f.Offset))
|
||||
case 5:
|
||||
utils.WriteUint40(b, uint64(f.Offset))
|
||||
case 6:
|
||||
utils.WriteUint48(b, uint64(f.Offset))
|
||||
case 7:
|
||||
utils.WriteUint56(b, uint64(f.Offset))
|
||||
case 8:
|
||||
utils.WriteUint64(b, uint64(f.Offset))
|
||||
}
|
||||
|
||||
utils.WriteUint16(b, uint16(len(f.Data)))
|
||||
b.Write(f.Data)
|
||||
return nil
|
||||
@@ -129,13 +161,38 @@ func (f *StreamFrame) calculateStreamIDLength() {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *StreamFrame) getOffsetLength() protocol.ByteCount {
|
||||
if f.Offset == 0 {
|
||||
return 0
|
||||
}
|
||||
if f.Offset < (1 << 16) {
|
||||
return 2
|
||||
}
|
||||
if f.Offset < (1 << 24) {
|
||||
return 3
|
||||
}
|
||||
if f.Offset < (1 << 32) {
|
||||
return 4
|
||||
}
|
||||
if f.Offset < (1 << 40) {
|
||||
return 5
|
||||
}
|
||||
if f.Offset < (1 << 48) {
|
||||
return 6
|
||||
}
|
||||
if f.Offset < (1 << 56) {
|
||||
return 7
|
||||
}
|
||||
return 8
|
||||
}
|
||||
|
||||
// MinLength of a written frame
|
||||
func (f *StreamFrame) MinLength() protocol.ByteCount {
|
||||
if f.streamIDLen == 0 {
|
||||
f.calculateStreamIDLength()
|
||||
}
|
||||
|
||||
return 1 + f.streamIDLen + 8 + 2 + 1
|
||||
return 1 + f.streamIDLen + f.getOffsetLength() + 2 + 1
|
||||
}
|
||||
|
||||
// MaybeSplitOffFrame removes the first n bytes and returns them as a separate frame. If n >= len(n), nil is returned and nothing is modified.
|
||||
|
||||
@@ -41,27 +41,117 @@ var _ = Describe("StreamFrame", func() {
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xa0, 0x1, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'}))
|
||||
})
|
||||
|
||||
It("writes offsets", func() {
|
||||
b := &bytes.Buffer{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Offset: 16,
|
||||
Data: []byte("foobar"),
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xbc, 0x1, 0x10, 0, 0, 0, 0, 0, 0, 0, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'}))
|
||||
})
|
||||
|
||||
It("has proper min length", func() {
|
||||
It("has proper min length for a short StreamID and a short offset", func() {
|
||||
b := &bytes.Buffer{}
|
||||
f := &StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("f"),
|
||||
Offset: 1,
|
||||
Offset: 0,
|
||||
}
|
||||
f.Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
Expect(f.MinLength()).To(Equal(protocol.ByteCount(b.Len())))
|
||||
})
|
||||
|
||||
It("has proper min length for a long StreamID and a big offset", func() {
|
||||
b := &bytes.Buffer{}
|
||||
f := &StreamFrame{
|
||||
StreamID: 0xDECAFBAD,
|
||||
Data: []byte("f"),
|
||||
Offset: 0xDEADBEEFCAFE,
|
||||
}
|
||||
f.Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
Expect(f.MinLength()).To(Equal(protocol.ByteCount(b.Len())))
|
||||
})
|
||||
|
||||
Context("offset lengths", func() {
|
||||
It("does not write an offset if the offset is 0", func() {
|
||||
b := &bytes.Buffer{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0x1337,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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, 1, protocol.PacketNumberLen6, 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 4-byte offset if the offset", func() {
|
||||
b := &bytes.Buffer{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0xDEADBEEF,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0x13DEADBEEF,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0xDEADBEEFCAFE,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0x13DEADBEEFCAFE,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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{}
|
||||
(&StreamFrame{
|
||||
StreamID: 1,
|
||||
Data: []byte("foobar"),
|
||||
Offset: 0x1337DEADBEEFCAFE,
|
||||
}).Write(b, 1, protocol.PacketNumberLen6, 0)
|
||||
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}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("lengths of StreamIDs", func() {
|
||||
It("writes a 2 byte StreamID", func() {
|
||||
b := &bytes.Buffer{}
|
||||
@@ -131,6 +221,53 @@ var _ = Describe("StreamFrame", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("shortening of Offsets", func() {
|
||||
It("determines length 0 of offset 0", func() {
|
||||
f := &StreamFrame{Offset: 0}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(0)))
|
||||
})
|
||||
|
||||
It("determines the length of a 2 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(2)))
|
||||
})
|
||||
|
||||
It("determines the length of a 2 byte offset, even if it would fit into 1 byte", func() {
|
||||
f := &StreamFrame{Offset: 0x1}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(2)))
|
||||
})
|
||||
|
||||
It("determines the length of a 3 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(3)))
|
||||
})
|
||||
|
||||
It("determines the length of a 4 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(4)))
|
||||
})
|
||||
|
||||
It("determines the length of a 5 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(5)))
|
||||
})
|
||||
|
||||
It("determines the length of a 6 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFFFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(6)))
|
||||
})
|
||||
|
||||
It("determines the length of a 7 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFFFFFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(7)))
|
||||
})
|
||||
|
||||
It("determines the length of an 8 byte offset", func() {
|
||||
f := &StreamFrame{Offset: 0xFFFFFFFFFFFFFFFF}
|
||||
Expect(f.getOffsetLength()).To(Equal(protocol.ByteCount(8)))
|
||||
})
|
||||
})
|
||||
|
||||
Context("splitting off earlier stream frames", func() {
|
||||
It("splits off nothing", func() {
|
||||
f := &StreamFrame{
|
||||
|
||||
@@ -238,9 +238,9 @@ var _ = Describe("Packet packer", func() {
|
||||
It("packs a packet that has the maximum packet size when given a large enough stream frame", func() {
|
||||
publicHeaderLength := protocol.ByteCount(3)
|
||||
f := frames.StreamFrame{
|
||||
Data: bytes.Repeat([]byte{'f'}, int(protocol.MaxFrameAndPublicHeaderSize-publicHeaderLength-(1+4+8+2))),
|
||||
Offset: 1,
|
||||
}
|
||||
f.Data = bytes.Repeat([]byte{'f'}, int(protocol.MaxFrameAndPublicHeaderSize-publicHeaderLength-f.MinLength()+1)) // + 1 since MinceLength is 1 bigger than the actual StreamFrame header
|
||||
packer.AddStreamFrame(f)
|
||||
p, err := packer.PackPacket(nil, []frames.Frame{}, true)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
@@ -109,6 +109,17 @@ func WriteUint64(b *bytes.Buffer, i uint64) {
|
||||
b.WriteByte(uint8(i >> 56))
|
||||
}
|
||||
|
||||
// WriteUint56 writes 56 bit of a uint64
|
||||
func WriteUint56(b *bytes.Buffer, i uint64) {
|
||||
b.WriteByte(uint8(i & 0xff))
|
||||
b.WriteByte(uint8((i >> 8) & 0xff))
|
||||
b.WriteByte(uint8((i >> 16) & 0xff))
|
||||
b.WriteByte(uint8((i >> 24) & 0xff))
|
||||
b.WriteByte(uint8((i >> 32) & 0xff))
|
||||
b.WriteByte(uint8((i >> 40) & 0xff))
|
||||
b.WriteByte(uint8((i >> 48)))
|
||||
}
|
||||
|
||||
// WriteUint48 writes 48 bit of a uint64
|
||||
func WriteUint48(b *bytes.Buffer, i uint64) {
|
||||
b.WriteByte(uint8(i & 0xff))
|
||||
@@ -119,6 +130,15 @@ func WriteUint48(b *bytes.Buffer, i uint64) {
|
||||
b.WriteByte(uint8((i >> 40)))
|
||||
}
|
||||
|
||||
// WriteUint40 writes 40 bit of a uint64
|
||||
func WriteUint40(b *bytes.Buffer, i uint64) {
|
||||
b.WriteByte(uint8(i & 0xff))
|
||||
b.WriteByte(uint8((i >> 8) & 0xff))
|
||||
b.WriteByte(uint8((i >> 16) & 0xff))
|
||||
b.WriteByte(uint8((i >> 24) & 0xff))
|
||||
b.WriteByte(uint8((i >> 32)))
|
||||
}
|
||||
|
||||
// WriteUint32 writes a uint32
|
||||
func WriteUint32(b *bytes.Buffer, i uint32) {
|
||||
b.WriteByte(uint8(i & 0xff))
|
||||
|
||||
@@ -99,6 +99,21 @@ var _ = Describe("Utils", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("WriteUint40", func() {
|
||||
It("outputs 5 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteUint40(b, uint64(1))
|
||||
Expect(b.Len()).To(Equal(5))
|
||||
})
|
||||
|
||||
It("outputs a little endian", func() {
|
||||
num := uint64(0xDEADBEEFCAFE)
|
||||
b := &bytes.Buffer{}
|
||||
WriteUint40(b, num)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0xFE, 0xCA, 0xEF, 0xBE, 0xAD}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("WriteUint48", func() {
|
||||
It("outputs 6 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
@@ -122,6 +137,21 @@ var _ = Describe("Utils", func() {
|
||||
})
|
||||
})
|
||||
|
||||
Context("WriteUint56", func() {
|
||||
It("outputs 7 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
WriteUint56(b, uint64(1))
|
||||
Expect(b.Len()).To(Equal(7))
|
||||
})
|
||||
|
||||
It("outputs a little endian", func() {
|
||||
num := uint64(0xFFEEDDCCBBAA9988)
|
||||
b := &bytes.Buffer{}
|
||||
WriteUint56(b, num)
|
||||
Expect(b.Bytes()).To(Equal([]byte{0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE}))
|
||||
})
|
||||
})
|
||||
|
||||
Context("WriteUint64", func() {
|
||||
It("outputs 8 bytes", func() {
|
||||
b := &bytes.Buffer{}
|
||||
|
||||
Reference in New Issue
Block a user