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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use std::fmt;
/// The enum represents an error code that are used in `RST_STREAM` and `GOAWAY` frames.
/// These are defined in [Section 7](http://http2.github.io/http2-spec/#ErrorCodes) of the HTTP/2
/// spec.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorCode {
/// The associated condition is not a result of an error. For example, a GOAWAY might include
/// this code to indicate graceful shutdown of a connection.
NoError = 0x0,
/// The endpoint detected an unspecific protocol error. This error is for use when a more
/// specific error code is not available.
ProtocolError = 0x1,
/// The endpoint encountered an unexpected internal error.
InternalError = 0x2,
/// The endpoint detected that its peer violated the flow-control protocol.
FlowControlError = 0x3,
/// The endpoint sent a SETTINGS frame but did not receive a response in a timely manner. See
/// Section 6.5.3 ("Settings Synchronization").
SettingsTimeout = 0x4,
/// The endpoint received a frame after a stream was half-closed.
StreamClosed = 0x5,
/// The endpoint received a frame with an invalid size.
FrameSizeError = 0x6,
/// The endpoint refused the stream prior to performing any application processing (see Section
/// 8.1.4 for details).
RefusedStream = 0x7,
/// Used by the endpoint to indicate that the stream is no longer needed.
Cancel = 0x8,
/// The endpoint is unable to maintain the header compression context for the connection.
CompressionError = 0x9,
/// The connection established in response to a CONNECT request (Section 8.3) was reset or
/// abnormally closed.
ConnectError = 0xa,
/// The endpoint detected that its peer is exhibiting a behavior that might be generating
/// excessive load.
EnhanceYourCalm = 0xb,
/// The underlying transport has properties that do not meet minimum security requirements (see
/// Section 9.2).
InadequateSecurity = 0xc,
/// The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
Http11Required = 0xd,
}
impl ErrorCode {
fn try_from(error_code: u32) -> Result<ErrorCode, u32> {
Ok(match error_code {
0x0 => ErrorCode::NoError,
0x1 => ErrorCode::ProtocolError,
0x2 => ErrorCode::InternalError,
0x3 => ErrorCode::FlowControlError,
0x4 => ErrorCode::SettingsTimeout,
0x5 => ErrorCode::StreamClosed,
0x6 => ErrorCode::FrameSizeError,
0x7 => ErrorCode::RefusedStream,
0x8 => ErrorCode::Cancel,
0x9 => ErrorCode::CompressionError,
0xa => ErrorCode::ConnectError,
0xb => ErrorCode::EnhanceYourCalm,
0xc => ErrorCode::InadequateSecurity,
0xd => ErrorCode::Http11Required,
// According to the spec, unknown error codes MAY be treated as equivalent to
// INTERNAL_ERROR.
_ => return Err(error_code),
})
}
}
impl From<u32> for ErrorCode {
/// Converts the given `u32` number to the appropriate `ErrorCode` variant.
fn from(code: u32) -> ErrorCode {
match code {
0x0 => ErrorCode::NoError,
0x1 => ErrorCode::ProtocolError,
0x2 => ErrorCode::InternalError,
0x3 => ErrorCode::FlowControlError,
0x4 => ErrorCode::SettingsTimeout,
0x5 => ErrorCode::StreamClosed,
0x6 => ErrorCode::FrameSizeError,
0x7 => ErrorCode::RefusedStream,
0x8 => ErrorCode::Cancel,
0x9 => ErrorCode::CompressionError,
0xa => ErrorCode::ConnectError,
0xb => ErrorCode::EnhanceYourCalm,
0xc => ErrorCode::InadequateSecurity,
0xd => ErrorCode::Http11Required,
// According to the spec, unknown error codes MAY be treated as equivalent to
// INTERNAL_ERROR.
_ => ErrorCode::InternalError,
}
}
}
impl From<ErrorCodeOrUnknown> for ErrorCode {
fn from(e: ErrorCodeOrUnknown) -> Self {
ErrorCode::from(e.0)
}
}
impl AsRef<str> for ErrorCode {
fn as_ref(&self) -> &str {
match *self {
ErrorCode::NoError => "NoError",
ErrorCode::ProtocolError => "ProtocolError",
ErrorCode::InternalError => "InternalError",
ErrorCode::FlowControlError => "FlowControlError",
ErrorCode::SettingsTimeout => "SettingsTimeout",
ErrorCode::StreamClosed => "StreamClosed",
ErrorCode::FrameSizeError => "FrameSizeError",
ErrorCode::RefusedStream => "RefusedStream",
ErrorCode::Cancel => "Cancel",
ErrorCode::CompressionError => "CompressionError",
ErrorCode::ConnectError => "ConnectError",
ErrorCode::EnhanceYourCalm => "EnhanceYourCalm",
ErrorCode::InadequateSecurity => "InadequateSecurity",
ErrorCode::Http11Required => "Http11Required",
}
}
}
impl Into<u32> for ErrorCode {
#[inline]
fn into(self) -> u32 {
self as u32
}
}
/// Unknown error codes are valid in HTTP/2,
/// this struct represents error code when it is unknown
#[derive(Copy, Clone, Eq, PartialEq)]
pub(crate) struct ErrorCodeOrUnknown(pub(crate) u32);
impl ErrorCodeOrUnknown {
pub fn _to_error_code(&self) -> ErrorCode {
ErrorCode::from(self.0)
}
}
impl fmt::Debug for ErrorCodeOrUnknown {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match ErrorCode::try_from(self.0) {
Ok(error_code) => fmt::Debug::fmt(&error_code, f),
Err(error_code) => fmt::Debug::fmt(&error_code, f),
}
}
}
impl From<ErrorCode> for ErrorCodeOrUnknown {
fn from(e: ErrorCode) -> Self {
ErrorCodeOrUnknown(e.into())
}
}