diff --git a/errors.go b/errors.go new file mode 100644 index 00000000..0145c8dd --- /dev/null +++ b/errors.go @@ -0,0 +1,30 @@ +package quic + +import "github.com/lucas-clemente/quic-go/internal/qerr" + +type ( + TransportError = qerr.TransportError + ApplicationError = qerr.ApplicationError + TransportErrorCode = qerr.TransportErrorCode + ApplicationErrorCode = qerr.ApplicationErrorCode +) + +const ( + NoError = qerr.NoError + InternalError = qerr.InternalError + ConnectionRefused = qerr.ConnectionRefused + FlowControlError = qerr.FlowControlError + StreamLimitError = qerr.StreamLimitError + StreamStateError = qerr.StreamStateError + FinalSizeError = qerr.FinalSizeError + FrameEncodingError = qerr.FrameEncodingError + TransportParameterError = qerr.TransportParameterError + ConnectionIDLimitError = qerr.ConnectionIDLimitError + ProtocolViolation = qerr.ProtocolViolation + InvalidToken = qerr.InvalidToken + ApplicationErrorErrorCode = qerr.ApplicationErrorErrorCode + CryptoBufferExceeded = qerr.CryptoBufferExceeded + KeyUpdateError = qerr.KeyUpdateError + AEADLimitReached = qerr.AEADLimitReached + NoViablePathError = qerr.NoViablePathError +) diff --git a/fuzzing/frames/cmd/corpus.go b/fuzzing/frames/cmd/corpus.go index 9773995f..308d320d 100644 --- a/fuzzing/frames/cmd/corpus.go +++ b/fuzzing/frames/cmd/corpus.go @@ -124,17 +124,17 @@ func getFrames() []wire.Frame { &wire.PingFrame{}, &wire.ResetStreamFrame{ StreamID: protocol.StreamID(getRandomNumber()), - ErrorCode: quic.ErrorCode(getRandomNumber()), + ErrorCode: quic.ApplicationErrorCode(getRandomNumber()), FinalSize: protocol.ByteCount(getRandomNumber()), }, &wire.ResetStreamFrame{ // at maximum offset StreamID: protocol.StreamID(getRandomNumber()), - ErrorCode: quic.ErrorCode(getRandomNumber()), + ErrorCode: quic.ApplicationErrorCode(getRandomNumber()), FinalSize: protocol.MaxByteCount, }, &wire.StopSendingFrame{ StreamID: protocol.StreamID(getRandomNumber()), - ErrorCode: quic.ErrorCode(getRandomNumber()), + ErrorCode: quic.ApplicationErrorCode(getRandomNumber()), }, &wire.CryptoFrame{ Data: getRandomData(100), diff --git a/http3/body.go b/http3/body.go index 761d0783..4433fef8 100644 --- a/http3/body.go +++ b/http3/body.go @@ -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.ErrorCode(errorRequestCanceled)) + r.str.CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)) return nil } diff --git a/http3/body_test.go b/http3/body_test.go index af731bd3..e63c52be 100644 --- a/http3/body_test.go +++ b/http3/body_test.go @@ -173,12 +173,12 @@ var _ = Describe("Body", func() { }) It("closes responses", func() { - str.EXPECT().CancelRead(quic.ErrorCode(errorRequestCanceled)) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)) Expect(rb.Close()).To(Succeed()) }) It("allows multiple calls to Close", func() { - str.EXPECT().CancelRead(quic.ErrorCode(errorRequestCanceled)).MaxTimes(2) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)).MaxTimes(2) Expect(rb.Close()).To(Succeed()) Expect(reqDone).To(BeClosed()) Expect(rb.Close()).To(Succeed()) diff --git a/http3/client.go b/http3/client.go index 7c59bc74..2af59da9 100644 --- a/http3/client.go +++ b/http3/client.go @@ -117,7 +117,7 @@ func (c *client) dial() error { go func() { if err := c.setupSession(); err != nil { c.logger.Debugf("Setting up session failed: %s", err) - c.session.CloseWithError(quic.ErrorCode(errorInternalError), "") + c.session.CloseWithError(quic.ApplicationErrorCode(errorInternalError), "") } }() @@ -162,20 +162,20 @@ func (c *client) handleUnidirectionalStreams() { return case streamTypePushStream: // We never increased the Push ID, so we don't expect any push streams. - c.session.CloseWithError(quic.ErrorCode(errorIDError), "") + c.session.CloseWithError(quic.ApplicationErrorCode(errorIDError), "") return default: - str.CancelRead(quic.ErrorCode(errorStreamCreationError)) + str.CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)) return } f, err := parseNextFrame(str) if err != nil { - c.session.CloseWithError(quic.ErrorCode(errorFrameError), "") + c.session.CloseWithError(quic.ApplicationErrorCode(errorFrameError), "") return } sf, ok := f.(*settingsFrame) if !ok { - c.session.CloseWithError(quic.ErrorCode(errorMissingSettings), "") + c.session.CloseWithError(quic.ApplicationErrorCode(errorMissingSettings), "") return } if !sf.Datagram { @@ -185,7 +185,7 @@ func (c *client) handleUnidirectionalStreams() { // we can expect it to have been negotiated both on the transport and on the HTTP/3 layer. // Note: ConnectionState() will block until the handshake is complete (relevant when using 0-RTT). if c.opts.EnableDatagram && !c.session.ConnectionState().SupportsDatagrams { - c.session.CloseWithError(quic.ErrorCode(errorSettingsError), "missing QUIC Datagram support") + c.session.CloseWithError(quic.ApplicationErrorCode(errorSettingsError), "missing QUIC Datagram support") } }() } @@ -195,7 +195,7 @@ func (c *client) Close() error { if c.session == nil { return nil } - return c.session.CloseWithError(quic.ErrorCode(errorNoError), "") + return c.session.CloseWithError(quic.ApplicationErrorCode(errorNoError), "") } func (c *client) maxHeaderBytes() uint64 { @@ -243,8 +243,8 @@ func (c *client) RoundTrip(req *http.Request) (*http.Response, error) { go func() { select { case <-req.Context().Done(): - str.CancelWrite(quic.ErrorCode(errorRequestCanceled)) - str.CancelRead(quic.ErrorCode(errorRequestCanceled)) + str.CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)) + str.CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)) case <-reqDone: } }() @@ -253,14 +253,14 @@ 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.ErrorCode(rerr.streamErr)) + str.CancelWrite(quic.ApplicationErrorCode(rerr.streamErr)) } if rerr.connErr != 0 { // if it was a connection error var reason string if rerr.err != nil { reason = rerr.err.Error() } - c.session.CloseWithError(quic.ErrorCode(rerr.connErr), reason) + c.session.CloseWithError(quic.ApplicationErrorCode(rerr.connErr), reason) } } return rsp, rerr.err @@ -321,7 +321,7 @@ func (c *client) doRequest( } } respBody := newResponseBody(str, reqDone, func() { - c.session.CloseWithError(quic.ErrorCode(errorFrameUnexpected), "") + c.session.CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), "") }) // Rules for when to set Content-Length are defined in https://tools.ietf.org/html/rfc7230#section-3.3.2. diff --git a/http3/client_test.go b/http3/client_test.go index 8dd79601..28ca29bc 100644 --- a/http3/client_test.go +++ b/http3/client_test.go @@ -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.ErrorCode(errorStreamCreationError)).Do(func(code quic.ErrorCode) { + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)).Do(func(code quic.ApplicationErrorCode) { close(done) }) @@ -297,7 +297,7 @@ var _ = Describe("Client", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorMissingSettings)) close(done) @@ -323,7 +323,7 @@ var _ = Describe("Client", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorFrameError)) close(done) @@ -346,7 +346,7 @@ var _ = Describe("Client", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorIDError)) close(done) @@ -372,7 +372,7 @@ var _ = Describe("Client", func() { }) sess.EXPECT().ConnectionState().Return(quic.ConnectionState{SupportsDatagrams: false}) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, reason string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, reason string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorSettingsError)) Expect(reason).To(Equal("missing QUIC Datagram support")) @@ -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.ErrorCode(errorRequestCanceled)).Do(func(quic.ErrorCode) { + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) { close(done) }), str.EXPECT().CancelWrite(gomock.Any()), @@ -584,7 +584,7 @@ var _ = Describe("Client", func() { It("closes the connection when the first frame is not a HEADERS frame", func() { buf := &bytes.Buffer{} (&dataFrame{Length: 0x42}).Write(buf) - sess.EXPECT().CloseWithError(quic.ErrorCode(errorFrameUnexpected), gomock.Any()) + sess.EXPECT().CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), gomock.Any()) closed := make(chan struct{}) str.EXPECT().Close().Do(func() { close(closed) }) str.EXPECT().Read(gomock.Any()).DoAndReturn(buf.Read).AnyTimes() @@ -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.ErrorCode(errorFrameError)) + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(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.ErrorCode(errorRequestCanceled)).Do(func(quic.ErrorCode) { close(canceled) }), - str.EXPECT().CancelRead(quic.ErrorCode(errorRequestCanceled)).Do(func(quic.ErrorCode) { close(done) }), + 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(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.ErrorCode(errorRequestCanceled)) - str.EXPECT().CancelRead(quic.ErrorCode(errorRequestCanceled)).Do(func(quic.ErrorCode) { close(done) }) + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorRequestCanceled)).Do(func(quic.ApplicationErrorCode) { close(done) }) _, err := client.RoundTrip(req) Expect(err).ToNot(HaveOccurred()) cancel() diff --git a/http3/error_codes.go b/http3/error_codes.go index ee8b8a0f..dfde76d4 100644 --- a/http3/error_codes.go +++ b/http3/error_codes.go @@ -3,10 +3,10 @@ package http3 import ( "fmt" - quic "github.com/lucas-clemente/quic-go" + "github.com/lucas-clemente/quic-go" ) -type errorCode quic.ErrorCode +type errorCode quic.ApplicationErrorCode const ( errorNoError errorCode = 0x100 diff --git a/http3/request_writer.go b/http3/request_writer.go index 6720ff52..2382e948 100644 --- a/http3/request_writer.go +++ b/http3/request_writer.go @@ -79,7 +79,7 @@ func (w *requestWriter) WriteRequest(str quic.Stream, req *http.Request, gzip bo if rerr == io.EOF { break } - str.CancelWrite(quic.ErrorCode(errorRequestCanceled)) + str.CancelWrite(quic.ApplicationErrorCode(errorRequestCanceled)) w.logger.Errorf("Error writing request: %s", rerr) return } diff --git a/http3/roundtrip_test.go b/http3/roundtrip_test.go index cb07ab3e..184889f1 100644 --- a/http3/roundtrip_test.go +++ b/http3/roundtrip_test.go @@ -10,7 +10,7 @@ import ( "time" "github.com/golang/mock/gomock" - quic "github.com/lucas-clemente/quic-go" + "github.com/lucas-clemente/quic-go" mockquic "github.com/lucas-clemente/quic-go/internal/mocks/quic" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -105,7 +105,7 @@ var _ = Describe("RoundTripper", func() { <-closed return nil, errors.New("test done") }).MaxTimes(1) - session.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(quic.ErrorCode, string) { close(closed) }) + session.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(quic.ApplicationErrorCode, string) { close(closed) }) _, err = rt.RoundTrip(req) Expect(err).To(MatchError(testErr)) Expect(rt.clients).To(HaveLen(1)) @@ -147,7 +147,7 @@ var _ = Describe("RoundTripper", func() { <-closed return nil, errors.New("test done") }).MaxTimes(1) - session.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(quic.ErrorCode, string) { close(closed) }) + session.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(quic.ApplicationErrorCode, string) { close(closed) }) req, err := http.NewRequest("GET", "https://quic.clemente.io/file1.html", nil) Expect(err).ToNot(HaveOccurred()) _, err = rt.RoundTrip(req) diff --git a/http3/server.go b/http3/server.go index d49c64f4..69ae74f3 100644 --- a/http3/server.go +++ b/http3/server.go @@ -258,19 +258,19 @@ func (s *Server) handleConn(sess quic.EarlySession) { } go func() { rerr := s.handleRequest(sess, str, decoder, func() { - sess.CloseWithError(quic.ErrorCode(errorFrameUnexpected), "") + sess.CloseWithError(quic.ApplicationErrorCode(errorFrameUnexpected), "") }) 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.ErrorCode(rerr.streamErr)) + str.CancelWrite(quic.ApplicationErrorCode(rerr.streamErr)) } if rerr.connErr != 0 { var reason string if rerr.err != nil { reason = rerr.err.Error() } - sess.CloseWithError(quic.ErrorCode(rerr.connErr), reason) + sess.CloseWithError(quic.ApplicationErrorCode(rerr.connErr), reason) } return } @@ -301,20 +301,20 @@ func (s *Server) handleUnidirectionalStreams(sess quic.EarlySession) { // TODO: check that only one stream of each type is opened. return case streamTypePushStream: // only the server can push - sess.CloseWithError(quic.ErrorCode(errorStreamCreationError), "") + sess.CloseWithError(quic.ApplicationErrorCode(errorStreamCreationError), "") return default: - str.CancelRead(quic.ErrorCode(errorStreamCreationError)) + str.CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)) return } f, err := parseNextFrame(str) if err != nil { - sess.CloseWithError(quic.ErrorCode(errorFrameError), "") + sess.CloseWithError(quic.ApplicationErrorCode(errorFrameError), "") return } sf, ok := f.(*settingsFrame) if !ok { - sess.CloseWithError(quic.ErrorCode(errorMissingSettings), "") + sess.CloseWithError(quic.ApplicationErrorCode(errorMissingSettings), "") return } if !sf.Datagram { @@ -324,7 +324,7 @@ func (s *Server) handleUnidirectionalStreams(sess quic.EarlySession) { // we can expect it to have been negotiated both on the transport and on the HTTP/3 layer. // Note: ConnectionState() will block until the handshake is complete (relevant when using 0-RTT). if s.EnableDatagrams && !sess.ConnectionState().SupportsDatagrams { - sess.CloseWithError(quic.ErrorCode(errorSettingsError), "missing QUIC Datagram support") + sess.CloseWithError(quic.ApplicationErrorCode(errorSettingsError), "missing QUIC Datagram support") } }(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.ErrorCode(errorNoError)) + str.CancelRead(quic.ApplicationErrorCode(errorNoError)) } return requestError{} } diff --git a/http3/server_test.go b/http3/server_test.go index 2a009120..431e806b 100644 --- a/http3/server_test.go +++ b/http3/server_test.go @@ -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.ErrorCode(errorStreamCreationError)).Do(func(code quic.ErrorCode) { + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorStreamCreationError)).Do(func(code quic.ApplicationErrorCode) { close(done) }) @@ -286,7 +286,7 @@ var _ = Describe("Server", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorMissingSettings)) close(done) @@ -311,7 +311,7 @@ var _ = Describe("Server", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorFrameError)) close(done) @@ -334,7 +334,7 @@ var _ = Describe("Server", func() { return nil, errors.New("test done") }) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorStreamCreationError)) close(done) @@ -359,7 +359,7 @@ var _ = Describe("Server", func() { }) sess.EXPECT().ConnectionState().Return(quic.ConnectionState{SupportsDatagrams: false}) done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, reason string) { + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, reason string) { defer GinkgoRecover() Expect(code).To(BeEquivalentTo(errorSettingsError)) Expect(reason).To(Equal("missing QUIC Datagram support")) @@ -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.ErrorCode(errorNoError)) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(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.ErrorCode(errorFrameError)).Do(func(quic.ErrorCode) { close(done) }) + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorFrameError)).Do(func(quic.ApplicationErrorCode) { 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.ErrorCode(errorRequestIncomplete)).Do(func(quic.ErrorCode) { close(done) }) + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorRequestIncomplete)).Do(func(quic.ApplicationErrorCode) { close(done) }) s.handleConn(sess) Consistently(handlerCalled).ShouldNot(BeClosed()) @@ -466,8 +466,8 @@ var _ = Describe("Server", func() { }).AnyTimes() done := make(chan struct{}) - sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ErrorCode, _ string) { - Expect(code).To(Equal(quic.ErrorCode(errorFrameUnexpected))) + sess.EXPECT().CloseWithError(gomock.Any(), gomock.Any()).Do(func(code quic.ApplicationErrorCode, _ string) { + Expect(code).To(Equal(quic.ApplicationErrorCode(errorFrameUnexpected))) close(done) }) s.handleConn(sess) @@ -491,7 +491,7 @@ var _ = Describe("Server", func() { return len(p), nil }).AnyTimes() done := make(chan struct{}) - str.EXPECT().CancelWrite(quic.ErrorCode(errorFrameError)).Do(func(quic.ErrorCode) { close(done) }) + str.EXPECT().CancelWrite(quic.ApplicationErrorCode(errorFrameError)).Do(func(quic.ApplicationErrorCode) { 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.ErrorCode(errorNoError)) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(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.ErrorCode(errorNoError)) + str.EXPECT().CancelRead(quic.ApplicationErrorCode(errorNoError)) serr := s.handleRequest(sess, str, qpackDecoder, nil) Expect(serr.err).ToNot(HaveOccurred()) diff --git a/integrationtests/self/cancelation_test.go b/integrationtests/self/cancelation_test.go index a069243f..aa97a149 100644 --- a/integrationtests/self/cancelation_test.go +++ b/integrationtests/self/cancelation_test.go @@ -11,7 +11,7 @@ import ( "sync/atomic" "time" - quic "github.com/lucas-clemente/quic-go" + "github.com/lucas-clemente/quic-go" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -87,7 +87,7 @@ var _ = Describe("Stream Cancelations", func() { // cancel around 2/3 of the streams if rand.Int31()%3 != 0 { atomic.AddInt32(&canceledCounter, 1) - str.CancelRead(quic.ErrorCode(str.StreamID())) + str.CancelRead(quic.ApplicationErrorCode(str.StreamID())) return } data, err := ioutil.ReadAll(str) @@ -133,7 +133,7 @@ var _ = Describe("Stream Cancelations", func() { length := int(rand.Int31n(int32(len(PRData) - 1))) data, err := ioutil.ReadAll(io.LimitReader(str, int64(length))) Expect(err).ToNot(HaveOccurred()) - str.CancelRead(quic.ErrorCode(str.StreamID())) + str.CancelRead(quic.ApplicationErrorCode(str.StreamID())) Expect(data).To(Equal(PRData[:length])) atomic.AddInt32(&canceledCounter, 1) return @@ -212,7 +212,7 @@ var _ = Describe("Stream Cancelations", func() { Expect(err).ToNot(HaveOccurred()) // cancel about 2/3 of the streams if rand.Int31()%3 != 0 { - str.CancelWrite(quic.ErrorCode(str.StreamID())) + str.CancelWrite(quic.ApplicationErrorCode(str.StreamID())) atomic.AddInt32(&canceledCounter, 1) return } @@ -246,7 +246,7 @@ var _ = Describe("Stream Cancelations", func() { length := int(rand.Int31n(int32(len(PRData) - 1))) _, err = str.Write(PRData[:length]) Expect(err).ToNot(HaveOccurred()) - str.CancelWrite(quic.ErrorCode(str.StreamID())) + str.CancelWrite(quic.ApplicationErrorCode(str.StreamID())) atomic.AddInt32(&canceledCounter, 1) return } @@ -282,7 +282,7 @@ var _ = Describe("Stream Cancelations", func() { Expect(err).ToNot(HaveOccurred()) // cancel about half of the streams if rand.Int31()%2 == 0 { - str.CancelWrite(quic.ErrorCode(str.StreamID())) + str.CancelWrite(quic.ApplicationErrorCode(str.StreamID())) return } if _, err = str.Write(PRData); err != nil { @@ -317,7 +317,7 @@ var _ = Describe("Stream Cancelations", func() { Expect(err).ToNot(HaveOccurred()) // cancel around half of the streams if rand.Int31()%2 == 0 { - str.CancelRead(quic.ErrorCode(str.StreamID())) + str.CancelRead(quic.ApplicationErrorCode(str.StreamID())) return } data, err := ioutil.ReadAll(str) @@ -368,7 +368,7 @@ var _ = Describe("Stream Cancelations", func() { return } if length < len(PRData) { - str.CancelWrite(quic.ErrorCode(str.StreamID())) + str.CancelWrite(quic.ApplicationErrorCode(str.StreamID())) } else if err := str.Close(); err != nil { Expect(err).To(MatchError(fmt.Sprintf("close called for canceled stream %d", str.StreamID()))) return @@ -410,7 +410,7 @@ var _ = Describe("Stream Cancelations", func() { } Expect(data).To(Equal(PRData[:length])) if length < len(PRData) { - str.CancelRead(quic.ErrorCode(str.StreamID())) + str.CancelRead(quic.ApplicationErrorCode(str.StreamID())) return } diff --git a/integrationtests/self/handshake_rtt_test.go b/integrationtests/self/handshake_rtt_test.go index 1f0725c6..df092086 100644 --- a/integrationtests/self/handshake_rtt_test.go +++ b/integrationtests/self/handshake_rtt_test.go @@ -7,7 +7,7 @@ import ( "net" "time" - quic "github.com/lucas-clemente/quic-go" + "github.com/lucas-clemente/quic-go" quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy" "github.com/lucas-clemente/quic-go/internal/protocol" @@ -86,7 +86,6 @@ var _ = Describe("Handshake RTT tests", func() { clientConfig, ) Expect(err).To(HaveOccurred()) - // Expect(err.(qerr.ErrorCode)).To(Equal(qerr.InvalidVersion)) expectDurationInRTTs(1) }) diff --git a/integrationtests/self/handshake_test.go b/integrationtests/self/handshake_test.go index c48d3b10..951825e3 100644 --- a/integrationtests/self/handshake_test.go +++ b/integrationtests/self/handshake_test.go @@ -12,8 +12,8 @@ import ( "github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go/integrationtests/tools/israce" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/logging" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -269,7 +269,7 @@ var _ = Describe("Handshake tests", func() { clientConfig, ) Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) Expect(transportErr.ErrorCode.IsCryptoError()).To(BeTrue()) Expect(transportErr.Error()).To(ContainSubstring("x509: certificate is valid for localhost, not foo.bar")) @@ -298,7 +298,7 @@ var _ = Describe("Handshake tests", func() { Eventually(errChan).Should(Receive(&err)) } Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) Expect(transportErr.ErrorCode.IsCryptoError()).To(BeTrue()) Expect(transportErr.Error()).To(ContainSubstring("tls: bad certificate")) @@ -314,7 +314,7 @@ var _ = Describe("Handshake tests", func() { clientConfig, ) Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) Expect(transportErr.ErrorCode.IsCryptoError()).To(BeTrue()) Expect(transportErr.Error()).To(ContainSubstring("x509: certificate is valid for localhost, not foo.bar")) @@ -376,9 +376,9 @@ var _ = Describe("Handshake tests", func() { _, err := dial() Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.ConnectionRefused)) + Expect(transportErr.ErrorCode).To(Equal(quic.ConnectionRefused)) // now accept one session, freeing one spot in the queue _, err = server.Accept(context.Background()) @@ -392,7 +392,7 @@ var _ = Describe("Handshake tests", func() { _, err = dial() Expect(err).To(HaveOccurred()) Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.ConnectionRefused)) + Expect(transportErr.ErrorCode).To(Equal(quic.ConnectionRefused)) }) It("removes closed connections from the accept queue", func() { @@ -408,9 +408,9 @@ var _ = Describe("Handshake tests", func() { _, err = dial() Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.ConnectionRefused)) + Expect(transportErr.ErrorCode).To(Equal(quic.ConnectionRefused)) // Now close the one of the session that are waiting to be accepted. // This should free one spot in the queue. @@ -426,7 +426,7 @@ var _ = Describe("Handshake tests", func() { _, err = dial() Expect(err).To(HaveOccurred()) Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.ConnectionRefused)) + Expect(transportErr.ErrorCode).To(Equal(quic.ConnectionRefused)) }) }) @@ -469,7 +469,7 @@ var _ = Describe("Handshake tests", func() { nil, ) Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) Expect(transportErr.ErrorCode.IsCryptoError()).To(BeTrue()) Expect(transportErr.Error()).To(ContainSubstring("no application protocol")) @@ -550,9 +550,9 @@ var _ = Describe("Handshake tests", func() { nil, ) Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.InvalidToken)) + Expect(transportErr.ErrorCode).To(Equal(quic.InvalidToken)) // Receiving a Retry might lead the client to measure a very small RTT. // Then, it sometimes would retransmit the ClientHello before receiving the ServerHello. Expect(len(tokenChan)).To(BeNumerically(">=", 2)) diff --git a/integrationtests/self/http_test.go b/integrationtests/self/http_test.go index bf557991..a8817da3 100644 --- a/integrationtests/self/http_test.go +++ b/integrationtests/self/http_test.go @@ -17,7 +17,6 @@ import ( "github.com/lucas-clemente/quic-go" "github.com/lucas-clemente/quic-go/http3" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/internal/testdata" . "github.com/onsi/ginkgo" @@ -27,7 +26,7 @@ import ( type streamCancelError interface { Canceled() bool - ErrorCode() qerr.ApplicationErrorCode + ErrorCode() quic.ApplicationErrorCode } var _ = Describe("HTTP tests", func() { diff --git a/integrationtests/self/mitm_test.go b/integrationtests/self/mitm_test.go index 03f027a0..16a5cec4 100644 --- a/integrationtests/self/mitm_test.go +++ b/integrationtests/self/mitm_test.go @@ -15,7 +15,6 @@ import ( "github.com/lucas-clemente/quic-go" quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/internal/testutils" "github.com/lucas-clemente/quic-go/internal/wire" . "github.com/onsi/ginkgo" @@ -441,9 +440,9 @@ var _ = Describe("MITM test", func() { } err := runTest(delayCb) Expect(err).To(HaveOccurred()) - var transportErr *qerr.TransportError + var transportErr *quic.TransportError Expect(errors.As(err, &transportErr)).To(BeTrue()) - Expect(transportErr.ErrorCode).To(Equal(qerr.ProtocolViolation)) + Expect(transportErr.ErrorCode).To(Equal(quic.ProtocolViolation)) Expect(transportErr.ErrorMessage).To(ContainSubstring("received ACK for an unsent packet")) }) }) diff --git a/integrationtests/self/timeout_test.go b/integrationtests/self/timeout_test.go index 4dd81efb..de619b8a 100644 --- a/integrationtests/self/timeout_test.go +++ b/integrationtests/self/timeout_test.go @@ -3,7 +3,6 @@ package self_test import ( "bytes" "context" - "errors" "fmt" "io" "io/ioutil" @@ -14,12 +13,11 @@ import ( "sync/atomic" "time" - "github.com/lucas-clemente/quic-go/internal/qerr" - "github.com/lucas-clemente/quic-go" quicproxy "github.com/lucas-clemente/quic-go/integrationtests/tools/proxy" "github.com/lucas-clemente/quic-go/internal/utils" "github.com/lucas-clemente/quic-go/logging" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/interface.go b/interface.go index b8fa4368..c57af432 100644 --- a/interface.go +++ b/interface.go @@ -9,7 +9,6 @@ import ( "github.com/lucas-clemente/quic-go/internal/handshake" "github.com/lucas-clemente/quic-go/internal/protocol" - "github.com/lucas-clemente/quic-go/internal/qerr" "github.com/lucas-clemente/quic-go/logging" ) @@ -65,10 +64,6 @@ type TokenStore interface { Put(key string, token *ClientToken) } -// An ErrorCode is an application-defined error code. -// Valid values range between 0 and MAX_UINT62. -type ErrorCode = qerr.ApplicationErrorCode - // Err0RTTRejected is the returned from: // * Open{Uni}Stream{Sync} // * Accept{Uni}Stream @@ -109,7 +104,7 @@ type ReceiveStream interface { // It will ask the peer to stop transmitting stream data. // Read will unblock immediately, and future Read calls will fail. // When called multiple times or after reading the io.EOF it is a no-op. - CancelRead(ErrorCode) + CancelRead(ApplicationErrorCode) // SetReadDeadline sets the deadline for future Read calls and // any currently-blocked Read call. // A zero value for t means Read will not time out. @@ -138,7 +133,7 @@ type SendStream interface { // Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably. // Write will unblock immediately, and future calls to Write will fail. // When called multiple times or after closing the stream it is a no-op. - CancelWrite(ErrorCode) + CancelWrite(ApplicationErrorCode) // The context is canceled as soon as the write-side of the stream is closed. // This happens when Close() or CancelWrite() is called, or when the peer // cancels the read-side of their stream. @@ -156,7 +151,7 @@ type SendStream interface { type StreamError interface { error Canceled() bool - ErrorCode() ErrorCode + ErrorCode() ApplicationErrorCode } // A Session is a QUIC connection between two peers. @@ -195,9 +190,9 @@ type Session interface { LocalAddr() net.Addr // RemoteAddr returns the address of the peer. RemoteAddr() net.Addr - // Close the connection with an error. + // CloseWithError closes the connection with an error. // The error string will be sent to the peer. - CloseWithError(ErrorCode, string) error + CloseWithError(ApplicationErrorCode, string) error // The context is cancelled when the session is closed. // Warning: This API should not be considered stable and might change soon. Context() context.Context diff --git a/mock_quic_session_test.go b/mock_quic_session_test.go index e91d0c3b..08c03c30 100644 --- a/mock_quic_session_test.go +++ b/mock_quic_session_test.go @@ -67,7 +67,7 @@ func (mr *MockQuicSessionMockRecorder) AcceptUniStream(arg0 interface{}) *gomock } // CloseWithError mocks base method. -func (m *MockQuicSession) CloseWithError(arg0 ErrorCode, arg1 string) error { +func (m *MockQuicSession) CloseWithError(arg0 ApplicationErrorCode, arg1 string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "CloseWithError", arg0, arg1) ret0, _ := ret[0].(error) diff --git a/mock_receive_stream_internal_test.go b/mock_receive_stream_internal_test.go index bdf02aaa..0bddae4f 100644 --- a/mock_receive_stream_internal_test.go +++ b/mock_receive_stream_internal_test.go @@ -37,7 +37,7 @@ func (m *MockReceiveStreamI) EXPECT() *MockReceiveStreamIMockRecorder { } // CancelRead mocks base method. -func (m *MockReceiveStreamI) CancelRead(arg0 ErrorCode) { +func (m *MockReceiveStreamI) CancelRead(arg0 ApplicationErrorCode) { m.ctrl.T.Helper() m.ctrl.Call(m, "CancelRead", arg0) } diff --git a/mock_send_stream_internal_test.go b/mock_send_stream_internal_test.go index 0a561aa7..07de6e25 100644 --- a/mock_send_stream_internal_test.go +++ b/mock_send_stream_internal_test.go @@ -39,7 +39,7 @@ func (m *MockSendStreamI) EXPECT() *MockSendStreamIMockRecorder { } // CancelWrite mocks base method. -func (m *MockSendStreamI) CancelWrite(arg0 ErrorCode) { +func (m *MockSendStreamI) CancelWrite(arg0 ApplicationErrorCode) { m.ctrl.T.Helper() m.ctrl.Call(m, "CancelWrite", arg0) } diff --git a/mock_stream_internal_test.go b/mock_stream_internal_test.go index 1fa35c75..a89aef4b 100644 --- a/mock_stream_internal_test.go +++ b/mock_stream_internal_test.go @@ -39,7 +39,7 @@ func (m *MockStreamI) EXPECT() *MockStreamIMockRecorder { } // CancelRead mocks base method. -func (m *MockStreamI) CancelRead(arg0 ErrorCode) { +func (m *MockStreamI) CancelRead(arg0 ApplicationErrorCode) { m.ctrl.T.Helper() m.ctrl.Call(m, "CancelRead", arg0) } @@ -51,7 +51,7 @@ func (mr *MockStreamIMockRecorder) CancelRead(arg0 interface{}) *gomock.Call { } // CancelWrite mocks base method. -func (m *MockStreamI) CancelWrite(arg0 ErrorCode) { +func (m *MockStreamI) CancelWrite(arg0 ApplicationErrorCode) { m.ctrl.T.Helper() m.ctrl.Call(m, "CancelWrite", arg0) } diff --git a/session.go b/session.go index 15515387..13820917 100644 --- a/session.go +++ b/session.go @@ -1475,7 +1475,7 @@ func (s *session) shutdown() { <-s.ctx.Done() } -func (s *session) CloseWithError(code ErrorCode, desc string) error { +func (s *session) CloseWithError(code ApplicationErrorCode, desc string) error { s.closeLocal(&qerr.ApplicationError{ ErrorCode: code, ErrorMessage: desc,