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  }