introduce a quic.StreamError type and use it for stream cancelations

This commit is contained in:
Marten Seemann
2021-04-26 16:26:05 +07:00
parent 93cfef57ca
commit 90727cb41a
26 changed files with 128 additions and 114 deletions

View File

@@ -93,6 +93,6 @@ func (r *body) requestDone() {
func (r *body) Close() error {
r.requestDone()
// If the EOF was read, CancelRead() is a no-op.
r.str.CancelRead(quic.ApplicationErrorCode(errorRequestCanceled))
r.str.CancelRead(quic.StreamErrorCode(errorRequestCanceled))
return nil
}

View File

@@ -173,12 +173,12 @@ var _ = Describe("Body", func() {
})
It("closes responses", func() {
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled))
str.EXPECT().CancelRead(quic.StreamErrorCode(errorRequestCanceled))
Expect(rb.Close()).To(Succeed())
})
It("allows multiple calls to Close", func() {
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)).MaxTimes(2)
str.EXPECT().CancelRead(quic.StreamErrorCode(errorRequestCanceled)).MaxTimes(2)
Expect(rb.Close()).To(Succeed())
Expect(reqDone).To(BeClosed())
Expect(rb.Close()).To(Succeed())

View File

@@ -165,7 +165,7 @@ func (c *client) handleUnidirectionalStreams() {
c.session.CloseWithError(quic.ApplicationErrorCode(errorIDError), "")
return
default:
str.CancelRead(quic.ApplicationErrorCode(errorStreamCreationError))
str.CancelRead(quic.StreamErrorCode(errorStreamCreationError))
return
}
f, err := parseNextFrame(str)
@@ -243,8 +243,8 @@ func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
go func() {
select {
case <-req.Context().Done():
str.CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled))
str.CancelRead(quic.ApplicationErrorCode(errorRequestCanceled))
str.CancelWrite(quic.StreamErrorCode(errorRequestCanceled))
str.CancelRead(quic.StreamErrorCode(errorRequestCanceled))
case <-reqDone:
}
}()
@@ -253,7 +253,7 @@ func (c *client) RoundTrip(req *http.Request) (*http.Response, error) {
if rerr.err != nil { // if any error occurred
close(reqDone)
if rerr.streamErr != 0 { // if it was a stream error
str.CancelWrite(quic.ApplicationErrorCode(rerr.streamErr))
str.CancelWrite(quic.StreamErrorCode(rerr.streamErr))
}
if rerr.connErr != 0 { // if it was a connection error
var reason string

View File

@@ -267,7 +267,7 @@ var _ = Describe("Client", func() {
str := mockquic.NewMockStream(mockCtrl)
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
done := make(chan struct{})
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)).Do(func(code quic.ApplicationErrorCode) {
str.EXPECT().CancelRead(quic.StreamErrorCode(errorStreamCreationError)).Do(func(code quic.StreamErrorCode) {
close(done)
})
@@ -546,7 +546,7 @@ var _ = Describe("Client", func() {
request.Body.(*mockBody).readErr = errors.New("testErr")
done := make(chan struct{})
gomock.InOrder(
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) {
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestCanceled)).Do(func(quic.StreamErrorCode) {
close(done)
}),
str.EXPECT().CancelWrite(gomock.Any()),
@@ -596,7 +596,7 @@ var _ = Describe("Client", func() {
It("cancels the stream when the HEADERS frame is too large", func() {
buf := &bytes.Buffer{}
(&headersFrame{Length: 1338}).Write(buf)
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorFrameError))
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorFrameError))
closed := make(chan struct{})
str.EXPECT().Close().Do(func() { close(closed) })
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
@@ -635,8 +635,8 @@ var _ = Describe("Client", func() {
done := make(chan struct{})
canceled := make(chan struct{})
gomock.InOrder(
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) { close(canceled) }),
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) { close(done) }),
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestCanceled)).Do(func(quic.StreamErrorCode) { close(canceled) }),
str.EXPECT().CancelRead(quic.StreamErrorCode(errorRequestCanceled)).Do(func(quic.StreamErrorCode) { close(done) }),
)
str.EXPECT().CancelWrite(gomock.Any()).MaxTimes(1)
str.EXPECT().Read(gomock.Any()).DoAndReturn(func([]byte) (int, error) {
@@ -663,8 +663,8 @@ var _ = Describe("Client", func() {
done := make(chan struct{})
str.EXPECT().Write(gomock.Any()).DoAndReturn(buf.Write)
str.EXPECT().Read(gomock.Any()).DoAndReturn(rspBuf.Read).AnyTimes()
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled))
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) { close(done) })
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestCanceled))
str.EXPECT().CancelRead(quic.StreamErrorCode(errorRequestCanceled)).Do(func(quic.StreamErrorCode) { close(done) })
_, err := client.RoundTrip(req)
Expect(err).ToNot(HaveOccurred())
cancel()

View File

@@ -79,7 +79,7 @@ func (w *requestWriter) WriteRequest(str quic.Stream, req *http.Request, gzip bo
if rerr == io.EOF {
break
}
str.CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled))
str.CancelWrite(quic.StreamErrorCode(errorRequestCanceled))
w.logger.Errorf("Error writing request: %s", rerr)
return
}

View File

@@ -263,7 +263,7 @@ func (s *Server) handleConn(sess quic.EarlySession) {
if rerr.err != nil || rerr.streamErr != 0 || rerr.connErr != 0 {
s.logger.Debugf("Handling request failed: %s", err)
if rerr.streamErr != 0 {
str.CancelWrite(quic.ApplicationErrorCode(rerr.streamErr))
str.CancelWrite(quic.StreamErrorCode(rerr.streamErr))
}
if rerr.connErr != 0 {
var reason string
@@ -304,7 +304,7 @@ func (s *Server) handleUnidirectionalStreams(sess quic.EarlySession) {
sess.CloseWithError(quic.ApplicationErrorCode(errorStreamCreationError), "")
return
default:
str.CancelRead(quic.ApplicationErrorCode(errorStreamCreationError))
str.CancelRead(quic.StreamErrorCode(errorStreamCreationError))
return
}
f, err := parseNextFrame(str)
@@ -410,7 +410,7 @@ func (s *Server) handleRequest(sess quic.Session, str quic.Stream, decoder *qpac
r.WriteHeader(200)
}
// If the EOF was read by the handler, CancelRead() is a no-op.
str.CancelRead(quic.ApplicationErrorCode(errorNoError))
str.CancelRead(quic.StreamErrorCode(errorNoError))
}
return requestError{}
}

View File

@@ -257,7 +257,7 @@ var _ = Describe("Server", func() {
str := mockquic.NewMockStream(mockCtrl)
str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes()
done := make(chan struct{})
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)).Do(func(code quic.ApplicationErrorCode) {
str.EXPECT().CancelRead(quic.StreamErrorCode(errorStreamCreationError)).Do(func(code quic.StreamErrorCode) {
close(done)
})
@@ -408,7 +408,7 @@ var _ = Describe("Server", func() {
done := make(chan struct{})
str.EXPECT().Context().Return(reqContext)
str.EXPECT().Write(gomock.Any()).DoAndReturn(responseBuf.Write).AnyTimes()
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorNoError))
str.EXPECT().CancelRead(quic.StreamErrorCode(errorNoError))
str.EXPECT().Close().Do(func() { close(done) })
s.handleConn(sess)
@@ -431,7 +431,7 @@ var _ = Describe("Server", func() {
setRequest(append(requestData, buf.Bytes()...))
done := make(chan struct{})
str.EXPECT().Write(gomock.Any()).DoAndReturn(responseBuf.Write).AnyTimes()
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorFrameError)).Do(func(quic.ApplicationErrorCode) { close(done) })
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorFrameError)).Do(func(quic.StreamErrorCode) { close(done) })
s.handleConn(sess)
Eventually(done).Should(BeClosed())
@@ -446,7 +446,7 @@ var _ = Describe("Server", func() {
testErr := errors.New("stream reset")
done := make(chan struct{})
str.EXPECT().Read(gomock.Any()).Return(0, testErr)
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestIncomplete)).Do(func(quic.ApplicationErrorCode) { close(done) })
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorRequestIncomplete)).Do(func(quic.StreamErrorCode) { close(done) })
s.handleConn(sess)
Consistently(handlerCalled).ShouldNot(BeClosed())
@@ -491,7 +491,7 @@ var _ = Describe("Server", func() {
return len(p), nil
}).AnyTimes()
done := make(chan struct{})
str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorFrameError)).Do(func(quic.ApplicationErrorCode) { close(done) })
str.EXPECT().CancelWrite(quic.StreamErrorCode(errorFrameError)).Do(func(quic.StreamErrorCode) { close(done) })
s.handleConn(sess)
Eventually(done).Should(BeClosed())
@@ -513,7 +513,7 @@ var _ = Describe("Server", func() {
str.EXPECT().Write(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
return len(p), nil
}).AnyTimes()
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorNoError))
str.EXPECT().CancelRead(quic.StreamErrorCode(errorNoError))
serr := s.handleRequest(sess, str, qpackDecoder, nil)
Expect(serr.err).ToNot(HaveOccurred())
@@ -536,7 +536,7 @@ var _ = Describe("Server", func() {
str.EXPECT().Write(gomock.Any()).DoAndReturn(func(p []byte) (int, error) {
return len(p), nil
}).AnyTimes()
str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorNoError))
str.EXPECT().CancelRead(quic.StreamErrorCode(errorNoError))
serr := s.handleRequest(sess, str, qpackDecoder, nil)
Expect(serr.err).ToNot(HaveOccurred())