File: errors.go

package info (click to toggle)
golang-github-lucas-clemente-quic-go 0.54.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,312 kB
  • sloc: sh: 54; makefile: 7
file content (134 lines) | stat: -rw-r--r-- 3,839 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package qerr

import (
	"fmt"
	"net"

	"github.com/quic-go/quic-go/internal/protocol"
)

var (
	ErrHandshakeTimeout = &HandshakeTimeoutError{}
	ErrIdleTimeout      = &IdleTimeoutError{}
)

type TransportError struct {
	Remote       bool
	FrameType    uint64
	ErrorCode    TransportErrorCode
	ErrorMessage string
	error        error // only set for local errors, sometimes
}

var _ error = &TransportError{}

// NewLocalCryptoError create a new TransportError instance for a crypto error
func NewLocalCryptoError(tlsAlert uint8, err error) *TransportError {
	return &TransportError{
		ErrorCode: 0x100 + TransportErrorCode(tlsAlert),
		error:     err,
	}
}

func (e *TransportError) Error() string {
	str := fmt.Sprintf("%s (%s)", e.ErrorCode.String(), getRole(e.Remote))
	if e.FrameType != 0 {
		str += fmt.Sprintf(" (frame type: %#x)", e.FrameType)
	}
	msg := e.ErrorMessage
	if len(msg) == 0 && e.error != nil {
		msg = e.error.Error()
	}
	if len(msg) == 0 {
		msg = e.ErrorCode.Message()
	}
	if len(msg) == 0 {
		return str
	}
	return str + ": " + msg
}

func (e *TransportError) Unwrap() []error { return []error{net.ErrClosed, e.error} }

func (e *TransportError) Is(target error) bool {
	t, ok := target.(*TransportError)
	return ok && e.ErrorCode == t.ErrorCode && e.FrameType == t.FrameType && e.Remote == t.Remote
}

// An ApplicationErrorCode is an application-defined error code.
type ApplicationErrorCode uint64

// 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 (%s)", e.ErrorCode, getRole(e.Remote))
	}
	return fmt.Sprintf("Application error %#x (%s): %s", e.ErrorCode, getRole(e.Remote), e.ErrorMessage)
}

func (e *ApplicationError) Unwrap() error { return net.ErrClosed }

func (e *ApplicationError) Is(target error) bool {
	t, ok := target.(*ApplicationError)
	return ok && e.ErrorCode == t.ErrorCode && e.Remote == t.Remote
}

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) Unwrap() error   { return 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) Unwrap() error   { return net.ErrClosed }

// A VersionNegotiationError occurs when the client and the server can't agree on a QUIC version.
type VersionNegotiationError struct {
	Ours   []protocol.Version
	Theirs []protocol.Version
}

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) Unwrap() error { return net.ErrClosed }

// A StatelessResetError occurs when we receive a stateless reset.
type StatelessResetError struct{}

var _ net.Error = &StatelessResetError{}

func (e *StatelessResetError) Error() string {
	return "received a stateless reset"
}

func (e *StatelessResetError) Unwrap() error   { return net.ErrClosed }
func (e *StatelessResetError) Timeout() bool   { return false }
func (e *StatelessResetError) Temporary() bool { return true }

func getRole(remote bool) string {
	if remote {
		return "remote"
	}
	return "local"
}