From 99d22b0908a690678bba9d75047e10b250fe58d2 Mon Sep 17 00:00:00 2001 From: Marten Seemann Date: Mon, 25 Jul 2016 16:37:27 +0700 Subject: [PATCH] open new stream when receiving a WindowUpdate for an unknown stream fixes #203 --- session.go | 9 ++++++++- session_test.go | 7 ++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/session.go b/session.go index 05439394..1682956c 100644 --- a/session.go +++ b/session.go @@ -349,9 +349,16 @@ func (s *Session) handleWindowUpdateFrame(frame *frames.WindowUpdateFrame) error s.streamsMutex.RLock() defer s.streamsMutex.RUnlock() if frame.StreamID != 0 { - if s, ok := s.streams[frame.StreamID]; ok && s == nil { + stream, ok := s.streams[frame.StreamID] + if ok && stream == nil { return errWindowUpdateOnClosedStream } + + // open new stream when receiving a WindowUpdate for a non-existing stream + // this can occur if the client immediately sends a WindowUpdate for a newly opened stream, and packet reordering occurs such that the packet opening the new stream arrives after the WindowUpdate + if !ok { + s.newStreamImpl(frame.StreamID) + } } _, err := s.flowControlManager.UpdateWindow(frame.StreamID, frame.ByteOffset) return err diff --git a/session_test.go b/session_test.go index fd0a5af1..358bfe1b 100644 --- a/session_test.go +++ b/session_test.go @@ -316,13 +316,14 @@ var _ = Describe("Session", func() { Expect(err).ToNot(HaveOccurred()) }) - It("errors when the stream is not known", func() { - // See https://github.com/lucas-clemente/quic-go/issues/203 + It("opens a new stream when receiving a WINDOW_UPDATE for an unknown stream", func() { err := session.handleWindowUpdateFrame(&frames.WindowUpdateFrame{ StreamID: 5, ByteOffset: 1337, }) - Expect(err).To(HaveOccurred()) + Expect(err).ToNot(HaveOccurred()) + Expect(session.streams).To(HaveKey(protocol.StreamID(5))) + Expect(session.streams[5]).ToNot(BeNil()) }) It("errors when receiving a WindowUpdateFrame for a closed stream", func() {