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