allow empty STREAM frames at arbitrary offsets

This commit is contained in:
Marten Seemann 2018-05-11 11:08:08 +09:00
parent 240896a4dd
commit 5f5bb1f700
5 changed files with 10 additions and 29 deletions

View file

@ -76,10 +76,6 @@ func parseStreamFrame(r *bytes.Reader, version protocol.VersionNumber) (*StreamF
if frame.Offset+frame.DataLen() > protocol.MaxByteCount { if frame.Offset+frame.DataLen() > protocol.MaxByteCount {
return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset") return nil, qerr.Error(qerr.InvalidStreamData, "data overflows maximum offset")
} }
// empty frames are only allowed if they have offset 0 or the FIN bit set
if frame.DataLen() == 0 && !frame.FinBit && frame.Offset != 0 {
return nil, qerr.EmptyStreamFrameNoFin
}
return frame, nil return frame, nil
} }

View file

@ -56,27 +56,19 @@ var _ = Describe("STREAM frame (for IETF QUIC)", func() {
Expect(r.Len()).To(BeZero()) Expect(r.Len()).To(BeZero())
}) })
It("allows empty frames at offset 0", func() { It("allows empty frames", func() {
data := []byte{0x10} data := []byte{0x10 ^ 0x4}
data = append(data, encodeVarInt(0x1337)...) // stream ID data = append(data, encodeVarInt(0x1337)...) // stream ID
data = append(data, encodeVarInt(0x12345)...) // offset
r := bytes.NewReader(data) r := bytes.NewReader(data)
f, err := parseStreamFrame(r, versionIETFFrames) f, err := parseStreamFrame(r, versionIETFFrames)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(f.StreamID).To(Equal(protocol.StreamID(0x1337))) Expect(f.StreamID).To(Equal(protocol.StreamID(0x1337)))
Expect(f.Offset).To(Equal(protocol.ByteCount(0x12345)))
Expect(f.Data).To(BeEmpty()) Expect(f.Data).To(BeEmpty())
Expect(f.Offset).To(BeZero())
Expect(f.FinBit).To(BeFalse()) Expect(f.FinBit).To(BeFalse())
}) })
It("rejects empty frames than don't have the FIN bit set", func() {
data := []byte{0x10 ^ 0x4}
data = append(data, encodeVarInt(0x1337)...) // stream ID
data = append(data, encodeVarInt(0xdecafbad)...) // offset
r := bytes.NewReader(data)
_, err := parseStreamFrame(r, versionIETFFrames)
Expect(err).To(MatchError(qerr.EmptyStreamFrameNoFin))
})
It("rejects frames that overflow the maximum offset", func() { It("rejects frames that overflow the maximum offset", func() {
data := []byte{0x10 ^ 0x4} data := []byte{0x10 ^ 0x4}
data = append(data, encodeVarInt(0x12345)...) // stream ID data = append(data, encodeVarInt(0x12345)...) // stream ID

View file

@ -224,12 +224,6 @@ var _ = Describe("Receive Stream", func() {
Expect(b).To(Equal([]byte("foobar"))) Expect(b).To(Equal([]byte("foobar")))
}) })
It("passes on errors from the streamFrameSorter", func() {
mockFC.EXPECT().UpdateHighestReceived(protocol.ByteCount(0), false)
err := str.handleStreamFrame(&wire.StreamFrame{StreamID: streamID}) // STREAM frame without data
Expect(err).To(MatchError(errEmptyStreamData))
})
Context("deadlines", func() { Context("deadlines", func() {
It("the deadline error has the right net.Error properties", func() { It("the deadline error has the right net.Error properties", func() {
Expect(errDeadline.Temporary()).To(BeTrue()) Expect(errDeadline.Temporary()).To(BeTrue())

View file

@ -17,7 +17,6 @@ type streamFrameSorter struct {
var ( var (
errTooManyGapsInReceivedStreamData = errors.New("Too many gaps in received StreamFrame data") errTooManyGapsInReceivedStreamData = errors.New("Too many gaps in received StreamFrame data")
errDuplicateStreamData = errors.New("Duplicate Stream Data") errDuplicateStreamData = errors.New("Duplicate Stream Data")
errEmptyStreamData = errors.New("Stream Data empty")
) )
func newStreamFrameSorter() *streamFrameSorter { func newStreamFrameSorter() *streamFrameSorter {
@ -33,9 +32,8 @@ func (s *streamFrameSorter) Push(frame *wire.StreamFrame) error {
if frame.DataLen() == 0 { if frame.DataLen() == 0 {
if frame.FinBit { if frame.FinBit {
s.queuedFrames[frame.Offset] = frame s.queuedFrames[frame.Offset] = frame
return nil
} }
return errEmptyStreamData return nil
} }
var wasCut bool var wasCut bool

View file

@ -10,7 +10,7 @@ import (
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
) )
var _ = Describe("StreamFrame sorter", func() { var _ = Describe("STREAM frame sorter", func() {
var s *streamFrameSorter var s *streamFrameSorter
checkGaps := func(expectedGaps []utils.ByteInterval) { checkGaps := func(expectedGaps []utils.ByteInterval) {
@ -61,10 +61,11 @@ var _ = Describe("StreamFrame sorter", func() {
Expect(s.Head()).To(BeNil()) Expect(s.Head()).To(BeNil())
}) })
It("rejects empty frames", func() { It("ignores empty frames", func() {
f := &wire.StreamFrame{} f := &wire.StreamFrame{}
err := s.Push(f) err := s.Push(f)
Expect(err).To(MatchError(errEmptyStreamData)) Expect(err).ToNot(HaveOccurred())
Expect(s.Pop()).To(BeNil())
}) })
Context("FinBit handling", func() { Context("FinBit handling", func() {