mirror of
https://github.com/refraction-networking/uquic.git
synced 2025-04-03 04:07:35 +03:00
expose a StatelessResetError
This commit is contained in:
parent
1ce572228b
commit
93cfef57ca
8 changed files with 53 additions and 24 deletions
|
@ -8,6 +8,7 @@ type (
|
|||
TransportError = qerr.TransportError
|
||||
ApplicationError = qerr.ApplicationError
|
||||
VersionNegotiationError = qerr.VersionNegotiationError
|
||||
StatelessResetError = qerr.StatelessResetError
|
||||
)
|
||||
|
||||
type (
|
||||
|
|
|
@ -99,8 +99,7 @@ var _ = Describe("Stateless Resets", func() {
|
|||
_, serr = str.Read([]byte{0})
|
||||
}
|
||||
Expect(serr).To(HaveOccurred())
|
||||
Expect(serr.Error()).To(ContainSubstring("received a stateless reset"))
|
||||
|
||||
Expect(serr).To(MatchError(&quic.StatelessResetError{}))
|
||||
Expect(ln2.Close()).To(Succeed())
|
||||
Eventually(acceptStopped).Should(BeClosed())
|
||||
})
|
||||
|
|
|
@ -2,6 +2,7 @@ package qerr
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/lucas-clemente/quic-go/internal/protocol"
|
||||
)
|
||||
|
@ -109,3 +110,22 @@ func (e *VersionNegotiationError) Is(target error) bool {
|
|||
_, ok := target.(*VersionNegotiationError)
|
||||
return ok
|
||||
}
|
||||
|
||||
// A StatelessResetError occurs when we receive a stateless reset.
|
||||
type StatelessResetError struct {
|
||||
Token protocol.StatelessResetToken
|
||||
}
|
||||
|
||||
var _ net.Error = &StatelessResetError{}
|
||||
|
||||
func (e *StatelessResetError) Error() string {
|
||||
return fmt.Sprintf("received a stateless reset with token %x", e.Token)
|
||||
}
|
||||
|
||||
func (e *StatelessResetError) Is(target error) bool {
|
||||
_, ok := target.(*StatelessResetError)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (e *StatelessResetError) Timeout() bool { return false }
|
||||
func (e *StatelessResetError) Temporary() bool { return true }
|
||||
|
|
|
@ -115,4 +115,26 @@ var _ = Describe("QUIC Errors", func() {
|
|||
}).Error()).To(Equal("no compatible QUIC version found (we support [0x2 0x3], server offered [0x4 0x5 0x6])"))
|
||||
})
|
||||
})
|
||||
|
||||
Context("Stateless Reset errors", func() {
|
||||
token := protocol.StatelessResetToken{0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}
|
||||
|
||||
It("is a Stateless Reset error", func() {
|
||||
Expect(errors.Is(&StatelessResetError{Token: token}, &StatelessResetError{})).To(BeTrue())
|
||||
})
|
||||
|
||||
It("has a string representation", func() {
|
||||
Expect((&StatelessResetError{Token: token}).Error()).To(Equal("received a stateless reset with token 000102030405060708090a0b0c0d0e0f"))
|
||||
})
|
||||
|
||||
It("is a net.Error", func() {
|
||||
//nolint:gosimple // we need to assign to an interface here
|
||||
var err error
|
||||
err = &StatelessResetError{}
|
||||
nerr, ok := err.(net.Error)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(nerr.Timeout()).To(BeFalse())
|
||||
Expect(nerr.Temporary()).To(BeTrue())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -18,19 +18,6 @@ import (
|
|||
"github.com/lucas-clemente/quic-go/logging"
|
||||
)
|
||||
|
||||
type statelessResetErr struct {
|
||||
token protocol.StatelessResetToken
|
||||
}
|
||||
|
||||
func (e *statelessResetErr) Error() string {
|
||||
return fmt.Sprintf("received a stateless reset with token %x", e.token)
|
||||
}
|
||||
|
||||
func (e *statelessResetErr) Is(target error) bool {
|
||||
_, ok := target.(*statelessResetErr)
|
||||
return ok
|
||||
}
|
||||
|
||||
type zeroRTTQueue struct {
|
||||
queue []*receivedPacket
|
||||
retireTimer *time.Timer
|
||||
|
@ -435,7 +422,7 @@ func (h *packetHandlerMap) maybeHandleStatelessReset(data []byte) bool {
|
|||
copy(token[:], data[len(data)-16:])
|
||||
if sess, ok := h.resetTokens[token]; ok {
|
||||
h.logger.Debugf("Received a stateless reset with token %#x. Closing session.", token)
|
||||
go sess.destroy(&statelessResetErr{token: token})
|
||||
go sess.destroy(&StatelessResetError{Token: token})
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
@ -373,10 +373,10 @@ var _ = Describe("Packet Handler Map", func() {
|
|||
defer GinkgoRecover()
|
||||
defer close(destroyed)
|
||||
Expect(err).To(HaveOccurred())
|
||||
var resetErr *statelessResetErr
|
||||
var resetErr *StatelessResetError
|
||||
Expect(errors.As(err, &resetErr)).To(BeTrue())
|
||||
Expect(err.Error()).To(ContainSubstring("received a stateless reset"))
|
||||
Expect(resetErr.token).To(Equal(token))
|
||||
Expect(resetErr.Token).To(Equal(token))
|
||||
})
|
||||
packetChan <- packetToRead{data: packet}
|
||||
Eventually(destroyed).Should(BeClosed())
|
||||
|
@ -393,10 +393,10 @@ var _ = Describe("Packet Handler Map", func() {
|
|||
packetHandler.EXPECT().destroy(gomock.Any()).Do(func(err error) {
|
||||
defer GinkgoRecover()
|
||||
Expect(err).To(HaveOccurred())
|
||||
var resetErr *statelessResetErr
|
||||
var resetErr *StatelessResetError
|
||||
Expect(errors.As(err, &resetErr)).To(BeTrue())
|
||||
Expect(err.Error()).To(ContainSubstring("received a stateless reset"))
|
||||
Expect(resetErr.token).To(Equal(token))
|
||||
Expect(resetErr.Token).To(Equal(token))
|
||||
close(destroyed)
|
||||
})
|
||||
packetChan <- packetToRead{data: packet}
|
||||
|
|
|
@ -1483,7 +1483,7 @@ func (s *session) handleCloseError(closeErr *closeError) {
|
|||
switch {
|
||||
case errors.Is(e, qerr.ErrIdleTimeout),
|
||||
errors.Is(e, qerr.ErrHandshakeTimeout),
|
||||
errors.Is(e, &statelessResetErr{}),
|
||||
errors.Is(e, &StatelessResetError{}),
|
||||
errors.Is(e, &VersionNegotiationError{}),
|
||||
errors.Is(e, &errCloseForRecreating{}),
|
||||
errors.Is(e, &qerr.ApplicationError{}),
|
||||
|
@ -1503,7 +1503,7 @@ func (s *session) handleCloseError(closeErr *closeError) {
|
|||
|
||||
if s.tracer != nil && !errors.Is(e, &errCloseForRecreating{}) {
|
||||
var (
|
||||
resetErr *statelessResetErr
|
||||
resetErr *StatelessResetError
|
||||
vnErr *VersionNegotiationError
|
||||
transportErr *qerr.TransportError
|
||||
applicationErr *qerr.ApplicationError
|
||||
|
@ -1514,7 +1514,7 @@ func (s *session) handleCloseError(closeErr *closeError) {
|
|||
case errors.Is(e, qerr.ErrHandshakeTimeout):
|
||||
s.tracer.ClosedConnection(logging.NewTimeoutCloseReason(logging.TimeoutReasonHandshake))
|
||||
case errors.As(e, &resetErr):
|
||||
s.tracer.ClosedConnection(logging.NewStatelessResetCloseReason(resetErr.token))
|
||||
s.tracer.ClosedConnection(logging.NewStatelessResetCloseReason(resetErr.Token))
|
||||
case errors.As(e, &vnErr):
|
||||
s.tracer.ClosedConnection(logging.NewVersionNegotiationError(vnErr.Theirs))
|
||||
case errors.As(e, &applicationErr):
|
||||
|
|
|
@ -658,7 +658,7 @@ var _ = Describe("Session", func() {
|
|||
streamManager.EXPECT().CloseWithError(gomock.Any())
|
||||
sessionRunner.EXPECT().Remove(gomock.Any()).AnyTimes()
|
||||
cryptoSetup.EXPECT().Close()
|
||||
sess.destroy(&statelessResetErr{token: token})
|
||||
sess.destroy(&StatelessResetError{Token: token})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue