• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::fmt;
2 
3 /// 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)]
19 pub struct Reason(u32);
20 
21 impl 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.
26     pub 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.
30     pub const PROTOCOL_ERROR: Reason = Reason(1);
31     /// The endpoint encountered an unexpected internal error.
32     pub const INTERNAL_ERROR: Reason = Reason(2);
33     /// The endpoint detected that its peer violated the flow-control protocol.
34     pub 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.
37     pub const SETTINGS_TIMEOUT: Reason = Reason(4);
38     /// The endpoint received a frame after a stream was half-closed.
39     pub const STREAM_CLOSED: Reason = Reason(5);
40     /// The endpoint received a frame with an invalid size.
41     pub const FRAME_SIZE_ERROR: Reason = Reason(6);
42     /// The endpoint refused the stream prior to performing any application
43     /// processing.
44     pub const REFUSED_STREAM: Reason = Reason(7);
45     /// Used by the endpoint to indicate that the stream is no longer needed.
46     pub const CANCEL: Reason = Reason(8);
47     /// The endpoint is unable to maintain the header compression context for
48     /// the connection.
49     pub const COMPRESSION_ERROR: Reason = Reason(9);
50     /// The connection established in response to a CONNECT request was reset
51     /// or abnormally closed.
52     pub const CONNECT_ERROR: Reason = Reason(10);
53     /// The endpoint detected that its peer is exhibiting a behavior that might
54     /// be generating excessive load.
55     pub const ENHANCE_YOUR_CALM: Reason = Reason(11);
56     /// The underlying transport has properties that do not meet minimum
57     /// security requirements.
58     pub const INADEQUATE_SECURITY: Reason = Reason(12);
59     /// The endpoint requires that HTTP/1.1 be used instead of HTTP/2.
60     pub const HTTP_1_1_REQUIRED: Reason = Reason(13);
61 
62     /// Get a string description of the error code.
description(&self) -> &str63     pub fn description(&self) -> &str {
64         match self.0 {
65             0 => "not a result of an error",
66             1 => "unspecific protocol error detected",
67             2 => "unexpected internal error encountered",
68             3 => "flow-control protocol violated",
69             4 => "settings ACK not received in timely manner",
70             5 => "received frame when stream half-closed",
71             6 => "frame with invalid size",
72             7 => "refused stream before processing any application logic",
73             8 => "stream no longer needed",
74             9 => "unable to maintain the header compression context",
75             10 => {
76                 "connection established in response to a CONNECT request was reset or abnormally \
77                  closed"
78             }
79             11 => "detected excessive load generating behavior",
80             12 => "security properties do not meet minimum requirements",
81             13 => "endpoint requires HTTP/1.1",
82             _ => "unknown reason",
83         }
84     }
85 }
86 
87 impl From<u32> for Reason {
from(src: u32) -> Reason88     fn from(src: u32) -> Reason {
89         Reason(src)
90     }
91 }
92 
93 impl From<Reason> for u32 {
from(src: Reason) -> u3294     fn from(src: Reason) -> u32 {
95         src.0
96     }
97 }
98 
99 impl fmt::Debug for Reason {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result100     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
101         let name = match self.0 {
102             0 => "NO_ERROR",
103             1 => "PROTOCOL_ERROR",
104             2 => "INTERNAL_ERROR",
105             3 => "FLOW_CONTROL_ERROR",
106             4 => "SETTINGS_TIMEOUT",
107             5 => "STREAM_CLOSED",
108             6 => "FRAME_SIZE_ERROR",
109             7 => "REFUSED_STREAM",
110             8 => "CANCEL",
111             9 => "COMPRESSION_ERROR",
112             10 => "CONNECT_ERROR",
113             11 => "ENHANCE_YOUR_CALM",
114             12 => "INADEQUATE_SECURITY",
115             13 => "HTTP_1_1_REQUIRED",
116             other => return f.debug_tuple("Reason").field(&Hex(other)).finish(),
117         };
118         f.write_str(name)
119     }
120 }
121 
122 struct Hex(u32);
123 
124 impl fmt::Debug for Hex {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result125     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
126         fmt::LowerHex::fmt(&self.0, f)
127     }
128 }
129 
130 impl fmt::Display for Reason {
fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result131     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
132         write!(fmt, "{}", self.description())
133     }
134 }
135