125 lines
3.3 KiB
Go
125 lines
3.3 KiB
Go
package qerr
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
|
|
"github.com/lucas-clemente/quic-go/internal/protocol"
|
|
)
|
|
|
|
var (
|
|
ErrHandshakeTimeout = &HandshakeTimeoutError{}
|
|
ErrIdleTimeout = &IdleTimeoutError{}
|
|
)
|
|
|
|
type TransportError struct {
|
|
Remote bool
|
|
FrameType uint64
|
|
ErrorCode TransportErrorCode
|
|
ErrorMessage string
|
|
}
|
|
|
|
var _ error = &TransportError{}
|
|
|
|
// NewCryptoError create a new TransportError instance for a crypto error
|
|
func NewCryptoError(tlsAlert uint8, errorMessage string) *TransportError {
|
|
return &TransportError{
|
|
ErrorCode: 0x100 + TransportErrorCode(tlsAlert),
|
|
ErrorMessage: errorMessage,
|
|
}
|
|
}
|
|
|
|
func (e *TransportError) Error() string {
|
|
str := e.ErrorCode.String()
|
|
if e.FrameType != 0 {
|
|
str += fmt.Sprintf(" (frame type: %#x)", e.FrameType)
|
|
}
|
|
msg := e.ErrorMessage
|
|
if len(msg) == 0 {
|
|
msg = e.ErrorCode.Message()
|
|
}
|
|
if len(msg) == 0 {
|
|
return str
|
|
}
|
|
return str + ": " + msg
|
|
}
|
|
|
|
func (e *TransportError) Is(target error) bool {
|
|
return target == net.ErrClosed
|
|
}
|
|
|
|
// An ApplicationErrorCode is an application-defined error code.
|
|
type ApplicationErrorCode uint64
|
|
|
|
func (e *ApplicationError) Is(target error) bool {
|
|
return target == net.ErrClosed
|
|
}
|
|
|
|
// A StreamErrorCode is an error code used to cancel streams.
|
|
type StreamErrorCode uint64
|
|
|
|
type ApplicationError struct {
|
|
Remote bool
|
|
ErrorCode ApplicationErrorCode
|
|
ErrorMessage string
|
|
}
|
|
|
|
var _ error = &ApplicationError{}
|
|
|
|
func (e *ApplicationError) Error() string {
|
|
if len(e.ErrorMessage) == 0 {
|
|
return fmt.Sprintf("Application error %#x", e.ErrorCode)
|
|
}
|
|
return fmt.Sprintf("Application error %#x: %s", e.ErrorCode, e.ErrorMessage)
|
|
}
|
|
|
|
type IdleTimeoutError struct{}
|
|
|
|
var _ error = &IdleTimeoutError{}
|
|
|
|
func (e *IdleTimeoutError) Timeout() bool { return true }
|
|
func (e *IdleTimeoutError) Temporary() bool { return false }
|
|
func (e *IdleTimeoutError) Error() string { return "timeout: no recent network activity" }
|
|
func (e *IdleTimeoutError) Is(target error) bool { return target == net.ErrClosed }
|
|
|
|
type HandshakeTimeoutError struct{}
|
|
|
|
var _ error = &HandshakeTimeoutError{}
|
|
|
|
func (e *HandshakeTimeoutError) Timeout() bool { return true }
|
|
func (e *HandshakeTimeoutError) Temporary() bool { return false }
|
|
func (e *HandshakeTimeoutError) Error() string { return "timeout: handshake did not complete in time" }
|
|
func (e *HandshakeTimeoutError) Is(target error) bool { return target == net.ErrClosed }
|
|
|
|
// A VersionNegotiationError occurs when the client and the server can't agree on a QUIC version.
|
|
type VersionNegotiationError struct {
|
|
Ours []protocol.VersionNumber
|
|
Theirs []protocol.VersionNumber
|
|
}
|
|
|
|
func (e *VersionNegotiationError) Error() string {
|
|
return fmt.Sprintf("no compatible QUIC version found (we support %s, server offered %s)", e.Ours, e.Theirs)
|
|
}
|
|
|
|
func (e *VersionNegotiationError) Is(target error) bool {
|
|
return target == net.ErrClosed
|
|
}
|
|
|
|
// 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 {
|
|
return target == net.ErrClosed
|
|
}
|
|
|
|
func (e *StatelessResetError) Timeout() bool { return false }
|
|
func (e *StatelessResetError) Temporary() bool { return true }
|