reject push streams initiated by the client

This commit is contained in:
Marten Seemann 2020-12-21 15:31:36 +07:00
parent bf54ffe0df
commit 04eebb7f6a
2 changed files with 31 additions and 1 deletions

View file

@ -40,6 +40,7 @@ const (
nextProtoH3Draft29 = "h3-29"
nextProtoH3Draft32 = "h3-32"
streamTypeControlStream = 0
streamTypePushStream = 1
)
func versionToALPN(v protocol.VersionNumber) string {
@ -272,7 +273,13 @@ func (s *Server) handleUnidirectionalStreams(sess quic.EarlySession) {
s.logger.Debugf("reading stream type on stream %d failed: %s", str.StreamID(), err)
return
}
if streamType != streamTypeControlStream {
// We're only interested in the control stream here.
switch streamType {
case streamTypeControlStream:
case streamTypePushStream: // only the server can push
sess.CloseWithError(quic.ErrorCode(errorStreamCreationError), "")
return
default:
return
}
f, err := parseNextFrame(str)

View file

@ -287,6 +287,29 @@ var _ = Describe("Server", func() {
s.handleConn(sess)
Eventually(done).Should(BeClosed())
})
It("errors when the client opens a push stream", func() {
buf := &bytes.Buffer{}
utils.WriteVarInt(buf, streamTypePushStream)
(&dataFrame{}).Write(buf)
controlStr := mockquic.NewMockStream(mockCtrl)
controlStr.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
sess.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
return controlStr, nil
})
sess.EXPECT().AcceptUniStream(gomock.Any()).DoAndReturn(func(context.Context) (quic.ReceiveStream, error) {
<-testDone
return nil, errors.New("test done")
})
done := make(chan struct{})
sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) {
defer GinkgoRecover()
Expect(code).To(BeEquivalentTo(errorStreamCreationError))
close(done)
})
s.handleConn(sess)
Eventually(done).Should(BeClosed())
})
})
Context("stream- and connection-level errors", func() {