github.com/tumi8/quic-go@v0.37.4-tum/noninternal/qerr/errors.go (about) 1 package qerr 2 3 import ( 4 "fmt" 5 "net" 6 7 "github.com/tumi8/quic-go/noninternal/protocol" 8 ) 9 10 var ( 11 ErrHandshakeTimeout = &HandshakeTimeoutError{} 12 ErrIdleTimeout = &IdleTimeoutError{} 13 ) 14 15 type TransportError struct { 16 Remote bool 17 FrameType uint64 18 ErrorCode TransportErrorCode 19 ErrorMessage string 20 } 21 22 var _ error = &TransportError{} 23 24 // NewLocalCryptoError create a new TransportError instance for a crypto error 25 func NewLocalCryptoError(tlsAlert uint8, errorMessage string) *TransportError { 26 return &TransportError{ 27 ErrorCode: 0x100 + TransportErrorCode(tlsAlert), 28 ErrorMessage: errorMessage, 29 } 30 } 31 32 func (e *TransportError) Error() string { 33 str := fmt.Sprintf("%s (%s)", e.ErrorCode.String(), getRole(e.Remote)) 34 if e.FrameType != 0 { 35 str += fmt.Sprintf(" (frame type: %#x)", e.FrameType) 36 } 37 msg := e.ErrorMessage 38 if len(msg) == 0 { 39 msg = e.ErrorCode.Message() 40 } 41 if len(msg) == 0 { 42 return str 43 } 44 return str + ": " + msg 45 } 46 47 func (e *TransportError) Is(target error) bool { 48 return target == net.ErrClosed 49 } 50 51 // An ApplicationErrorCode is an application-defined error code. 52 type ApplicationErrorCode uint64 53 54 func (e *ApplicationError) Is(target error) bool { 55 return target == net.ErrClosed 56 } 57 58 // A StreamErrorCode is an error code used to cancel streams. 59 type StreamErrorCode uint64 60 61 type ApplicationError struct { 62 Remote bool 63 ErrorCode ApplicationErrorCode 64 ErrorMessage string 65 } 66 67 var _ error = &ApplicationError{} 68 69 func (e *ApplicationError) Error() string { 70 if len(e.ErrorMessage) == 0 { 71 return fmt.Sprintf("Application error %#x (%s)", e.ErrorCode, getRole(e.Remote)) 72 } 73 return fmt.Sprintf("Application error %#x (%s): %s", e.ErrorCode, getRole(e.Remote), e.ErrorMessage) 74 } 75 76 type IdleTimeoutError struct{} 77 78 var _ error = &IdleTimeoutError{} 79 80 func (e *IdleTimeoutError) Timeout() bool { return true } 81 func (e *IdleTimeoutError) Temporary() bool { return false } 82 func (e *IdleTimeoutError) Error() string { return "timeout: no recent network activity" } 83 func (e *IdleTimeoutError) Is(target error) bool { return target == net.ErrClosed } 84 85 type HandshakeTimeoutError struct{} 86 87 var _ error = &HandshakeTimeoutError{} 88 89 func (e *HandshakeTimeoutError) Timeout() bool { return true } 90 func (e *HandshakeTimeoutError) Temporary() bool { return false } 91 func (e *HandshakeTimeoutError) Error() string { return "timeout: handshake did not complete in time" } 92 func (e *HandshakeTimeoutError) Is(target error) bool { return target == net.ErrClosed } 93 94 // A VersionNegotiationError occurs when the client and the server can't agree on a QUIC version. 95 type VersionNegotiationError struct { 96 Ours []protocol.VersionNumber 97 Theirs []protocol.VersionNumber 98 } 99 100 func (e *VersionNegotiationError) Error() string { 101 return fmt.Sprintf("no compatible QUIC version found (we support %s, server offered %s)", e.Ours, e.Theirs) 102 } 103 104 func (e *VersionNegotiationError) Is(target error) bool { 105 return target == net.ErrClosed 106 } 107 108 // A StatelessResetError occurs when we receive a stateless reset. 109 type StatelessResetError struct { 110 Token protocol.StatelessResetToken 111 } 112 113 var _ net.Error = &StatelessResetError{} 114 115 func (e *StatelessResetError) Error() string { 116 return fmt.Sprintf("received a stateless reset with token %x", e.Token) 117 } 118 119 func (e *StatelessResetError) Is(target error) bool { 120 return target == net.ErrClosed 121 } 122 123 func (e *StatelessResetError) Timeout() bool { return false } 124 func (e *StatelessResetError) Temporary() bool { return true } 125 126 func getRole(remote bool) string { 127 if remote { 128 return "remote" 129 } 130 return "local" 131 }