1package qerr
2
3import (
4	"fmt"
5
6	"github.com/lucas-clemente/quic-go/internal/qtls"
7)
8
9// ErrorCode can be used as a normal error without reason.
10type ErrorCode uint64
11
12// The error codes defined by QUIC
13const (
14	NoError                 ErrorCode = 0x0
15	InternalError           ErrorCode = 0x1
16	ConnectionRefused       ErrorCode = 0x2
17	FlowControlError        ErrorCode = 0x3
18	StreamLimitError        ErrorCode = 0x4
19	StreamStateError        ErrorCode = 0x5
20	FinalSizeError          ErrorCode = 0x6
21	FrameEncodingError      ErrorCode = 0x7
22	TransportParameterError ErrorCode = 0x8
23	ConnectionIDLimitError  ErrorCode = 0x9
24	ProtocolViolation       ErrorCode = 0xa
25	InvalidToken            ErrorCode = 0xb
26	ApplicationError        ErrorCode = 0xc
27	CryptoBufferExceeded    ErrorCode = 0xd
28	KeyUpdateError          ErrorCode = 0xe
29	AEADLimitReached        ErrorCode = 0xf
30	NoViablePathError       ErrorCode = 0x10
31)
32
33func (e ErrorCode) isCryptoError() bool {
34	return e >= 0x100 && e < 0x200
35}
36
37func (e ErrorCode) Error() string {
38	if e.isCryptoError() {
39		return fmt.Sprintf("%s: %s", e.String(), e.Message())
40	}
41	return e.String()
42}
43
44// Message is a description of the error.
45// It only returns a non-empty string for crypto errors.
46func (e ErrorCode) Message() string {
47	if !e.isCryptoError() {
48		return ""
49	}
50	return qtls.Alert(e - 0x100).Error()
51}
52
53func (e ErrorCode) String() string {
54	switch e {
55	case NoError:
56		return "NO_ERROR"
57	case InternalError:
58		return "INTERNAL_ERROR"
59	case ConnectionRefused:
60		return "CONNECTION_REFUSED"
61	case FlowControlError:
62		return "FLOW_CONTROL_ERROR"
63	case StreamLimitError:
64		return "STREAM_LIMIT_ERROR"
65	case StreamStateError:
66		return "STREAM_STATE_ERROR"
67	case FinalSizeError:
68		return "FINAL_SIZE_ERROR"
69	case FrameEncodingError:
70		return "FRAME_ENCODING_ERROR"
71	case TransportParameterError:
72		return "TRANSPORT_PARAMETER_ERROR"
73	case ConnectionIDLimitError:
74		return "CONNECTION_ID_LIMIT_ERROR"
75	case ProtocolViolation:
76		return "PROTOCOL_VIOLATION"
77	case InvalidToken:
78		return "INVALID_TOKEN"
79	case ApplicationError:
80		return "APPLICATION_ERROR"
81	case CryptoBufferExceeded:
82		return "CRYPTO_BUFFER_EXCEEDED"
83	case KeyUpdateError:
84		return "KEY_UPDATE_ERROR"
85	case AEADLimitReached:
86		return "AEAD_LIMIT_REACHED"
87	case NoViablePathError:
88		return "NO_VIABLE_PATH"
89	default:
90		if e.isCryptoError() {
91			return fmt.Sprintf("CRYPTO_ERROR (%#x)", uint16(e))
92		}
93		return fmt.Sprintf("unknown error code: %#x", uint16(e))
94	}
95}
96