add option to write StreamFrames without Data length field

work towards #77
This commit is contained in:
Marten Seemann
2016-05-11 10:31:04 +07:00
parent bdf53744ac
commit 41fa096480
3 changed files with 77 additions and 14 deletions

View File

@@ -11,11 +11,12 @@ import (
// A StreamFrame of QUIC
type StreamFrame struct {
FinBit bool
StreamID protocol.StreamID
streamIDLen protocol.ByteCount
Offset protocol.ByteCount
Data []byte
FinBit bool
StreamID protocol.StreamID
streamIDLen protocol.ByteCount
Offset protocol.ByteCount
Data []byte
DataLenPresent bool
}
var (
@@ -33,7 +34,7 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
}
frame.FinBit = typeByte&0x40 > 0
dataLenPresent := typeByte&0x20 > 0
frame.DataLenPresent = typeByte&0x20 > 0
offsetLen := typeByte & 0x1C >> 2
if offsetLen != 0 {
offsetLen++
@@ -53,7 +54,7 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
frame.Offset = protocol.ByteCount(offset)
var dataLen uint16
if dataLenPresent {
if frame.DataLenPresent {
dataLen, err = utils.ReadUint16(r)
if err != nil {
return nil, err
@@ -79,10 +80,14 @@ func ParseStreamFrame(r *bytes.Reader) (*StreamFrame, error) {
// WriteStreamFrame writes a stream frame.
func (f *StreamFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber, packetNumberLen protocol.PacketNumberLen, version protocol.VersionNumber) error {
typeByte := uint8(0x80) // sets the leftmost bit to 1
if f.FinBit {
typeByte ^= 0x40
}
typeByte ^= 0x20 // dataLenPresent
if f.DataLenPresent {
typeByte ^= 0x20
}
offsetLength := f.getOffsetLength()
@@ -130,8 +135,12 @@ func (f *StreamFrame) Write(b *bytes.Buffer, packetNumber protocol.PacketNumber,
return errInvalidOffsetLen
}
utils.WriteUint16(b, uint16(len(f.Data)))
if f.DataLenPresent {
utils.WriteUint16(b, uint16(len(f.Data)))
}
b.Write(f.Data)
return nil
}
@@ -178,7 +187,12 @@ func (f *StreamFrame) MinLength() protocol.ByteCount {
f.calculateStreamIDLength()
}
return 1 + f.streamIDLen + f.getOffsetLength() + 2 + 1
length := protocol.ByteCount(1) + f.streamIDLen + f.getOffsetLength()
if f.DataLenPresent {
length += 2
}
return length + 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.

View File

@@ -17,16 +17,18 @@ var _ = Describe("StreamFrame", func() {
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")))
})
It("accepts frame without datalength", func() {
It("accepts frame without data length", func() {
b := bytes.NewReader([]byte{0x80, 0x1, 'f', 'o', 'o', 'b', 'a', 'r'})
frame, err := ParseStreamFrame(b)
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(BeFalse())
Expect(frame.Data).To(Equal([]byte("foobar")))
})
})
@@ -35,8 +37,9 @@ var _ = Describe("StreamFrame", func() {
It("writes sample frame", func() {
b := &bytes.Buffer{}
(&StreamFrame{
StreamID: 1,
Data: []byte("foobar"),
StreamID: 1,
Data: []byte("foobar"),
DataLenPresent: true,
}).Write(b, 1, protocol.PacketNumberLen6, 0)
Expect(b.Bytes()).To(Equal([]byte{0xa0, 0x1, 0x06, 0x00, 'f', 'o', 'o', 'b', 'a', 'r'}))
})
@@ -63,6 +66,52 @@ var _ = Describe("StreamFrame", func() {
Expect(f.MinLength()).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,
}
f.Write(b, 1, protocol.PacketNumberLen6, 0)
headerLength := f.MinLength() - 1
Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0x20)))
Expect(b.Bytes()[headerLength-2 : headerLength]).To(Equal([]byte{0x37, 0x13}))
})
It("omits the data length field", func() {
dataLen := 0x1337
b := &bytes.Buffer{}
f := &StreamFrame{
StreamID: 1,
Data: bytes.Repeat([]byte{'f'}, dataLen),
DataLenPresent: false,
Offset: 0,
}
f.Write(b, 1, protocol.PacketNumberLen6, 0)
Expect(b.Bytes()[0] & 0x20).To(Equal(uint8(0)))
Expect(b.Bytes()[1 : b.Len()-dataLen]).ToNot(ContainSubstring(string([]byte{0x37, 0x13})))
minLength := f.MinLength()
f.DataLenPresent = true
Expect(minLength).To(Equal(f.MinLength() - 2))
})
It("calculates the correcct min-length", func() {
f := &StreamFrame{
StreamID: 0xCAFE,
Data: []byte("foobar"),
DataLenPresent: false,
Offset: 0xDEADBEEF,
}
minLengthWithoutDataLen := f.MinLength()
f.DataLenPresent = true
Expect(f.MinLength()).To(Equal(minLengthWithoutDataLen + 2))
})
})
Context("offset lengths", func() {
It("does not write an offset if the offset is 0", func() {
b := &bytes.Buffer{}