1use std::fmt;
23/// HTTP/2 error codes.
4///
5/// Error codes are used in `RST_STREAM` and `GOAWAY` frames to convey the
6/// reasons for the stream or connection error. For example,
7/// [`SendStream::send_reset`] takes a `Reason` argument. Also, the `Error` type
8/// may contain a `Reason`.
9///
10/// Error codes share a common code space. Some error codes apply only to
11/// streams, others apply only to connections, and others may apply to either.
12/// See [RFC 7540] for more information.
13///
14/// See [Error Codes in the spec][spec].
15///
16/// [spec]: http://httpwg.org/specs/rfc7540.html#ErrorCodes
17/// [`SendStream::send_reset`]: struct.SendStream.html#method.send_reset
18#[derive(PartialEq, Eq, Clone, Copy)]
19pub struct Reason(u32);
2021impl Reason {
22/// The associated condition is not a result of an error.
23 ///
24 /// For example, a GOAWAY might include this code to indicate graceful
25 /// shutdown of a connection.
26pub const NO_ERROR: Reason = Reason(0);
27/// The endpoint detected an unspecific protocol error.
28 ///
29 /// This error is for use when a more specific error code is not available.
30pub const PROTOCOL_ERROR: Reason = Reason(1);
31/// The endpoint encountered an unexpected internal error.
32pub const INTERNAL_ERROR: Reason = Reason(2);
33/// The endpoint detected that its peer violated the flow-control protocol.
34pub const FLOW_CONTROL_ERROR: Reason = Reason(3);
35/// The endpoint sent a SETTINGS frame but did not receive a response in
36 /// a timely manner.
37pub const SETTINGS_TIMEOUT: Reason = Reason(4);
38/// The endpoint received a frame after a stream was half-closed.
39pub const STREAM_CLOSED: Reason = Reason(5);
40/// The endpoint received a frame with an invalid size.
41pub const FRAME_SIZE_ERROR: Reason = Reason(6);
42/// The endpoint refused the stream prior to performing any application
43 /// processing.
44pub const REFUSED_STREAM: Reason = Reason(7);
45/// Used by the endpoint to indicate that the stream is no longer needed.
46pub const CANCEL: Reason = Reason(8);
47/// The endpoint is unable to maintain the header compression context for
48 /// the connection.
49pub const COMPRESSION_ERROR: Reason = Reason(9);
50/// The connection established in response to a CONNECT request was reset
51 /// or abnormally closed.
52pub const CONNECT_ERROR: Reason = Reason(10);
53/// The endpoint detected that its peer is exhibiting a behavior that might
54 /// be generating excessive load.
55pub const ENHANCE_YOUR_CALM: Reason = Reason(11);
56/// The underlying transport has properties that do not meet minimum
57 /// security requirements.
58pub const INADEQUATE_SECURITY: Reason = Reason(12);
59/// The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
60pub const HTTP_1_1_REQUIRED: Reason = Reason(13);
6162/// Get a string description of the error code.
63pub fn description(&self) -> &str {
64match self.0 {
650 => "not a result of an error",
661 => "unspecific protocol error detected",
672 => "unexpected internal error encountered",
683 => "flow-control protocol violated",
694 => "settings ACK not received in timely manner",
705 => "received frame when stream half-closed",
716 => "frame with invalid size",
727 => "refused stream before processing any application logic",
738 => "stream no longer needed",
749 => "unable to maintain the header compression context",
7510 => {
76"connection established in response to a CONNECT request was reset or abnormally \
77 closed"
78}
7911 => "detected excessive load generating behavior",
8012 => "security properties do not meet minimum requirements",
8113 => "endpoint requires HTTP/1.1",
82_ => "unknown reason",
83 }
84 }
85}
8687impl From<u32> for Reason {
88fn from(src: u32) -> Reason {
89 Reason(src)
90 }
91}
9293impl From<Reason> for u32 {
94fn from(src: Reason) -> u32 {
95 src.0
96}
97}
9899impl fmt::Debug for Reason {
100fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101let name = match self.0 {
1020 => "NO_ERROR",
1031 => "PROTOCOL_ERROR",
1042 => "INTERNAL_ERROR",
1053 => "FLOW_CONTROL_ERROR",
1064 => "SETTINGS_TIMEOUT",
1075 => "STREAM_CLOSED",
1086 => "FRAME_SIZE_ERROR",
1097 => "REFUSED_STREAM",
1108 => "CANCEL",
1119 => "COMPRESSION_ERROR",
11210 => "CONNECT_ERROR",
11311 => "ENHANCE_YOUR_CALM",
11412 => "INADEQUATE_SECURITY",
11513 => "HTTP_1_1_REQUIRED",
116 other => return f.debug_tuple("Reason").field(&Hex(other)).finish(),
117 };
118 f.write_str(name)
119 }
120}
121122struct Hex(u32);
123124impl fmt::Debug for Hex {
125fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126 fmt::LowerHex::fmt(&self.0, f)
127 }
128}
129130impl fmt::Display for Reason {
131fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
132write!(fmt, "{}", self.description())
133 }
134}