github.com/apernet/quic-go@v0.43.1-0.20240515053213-5e9e635fd9f0/internal/qerr/errors.go (about)

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