rama_haproxy/protocol/v1/
error.rs

1//! Errors for the text proxy protocol.
2
3use std::fmt;
4
5/// An error in parsing a text PROXY protocol header.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum ParseError {
8    /// Header must start with 'PROXY'.
9    InvalidPrefix,
10    /// Header is only partially present.
11    Partial,
12    /// Header is empty.
13    MissingPrefix,
14    /// Header does not end with the string '\r\n'.
15    MissingNewLine,
16    /// Header missing protocol.
17    MissingProtocol,
18    /// Header missing source address.
19    MissingSourceAddress,
20    /// Header missing destination address.
21    MissingDestinationAddress,
22    /// Header missing source port.
23    MissingSourcePort,
24    /// Header missing destination port.
25    MissingDestinationPort,
26    /// Header does not fit within the expected buffer size of 107 bytes (plus 1 byte for null-terminated strings).
27    HeaderTooLong,
28    /// Header has an invalid protocol.
29    InvalidProtocol,
30    /// Header must end in '\r\n'.
31    InvalidSuffix,
32    /// Header contains invalid IP address for the source.
33    InvalidSourceAddress(std::net::AddrParseError),
34    /// Header contains invalid IP address for the destination.
35    InvalidDestinationAddress(std::net::AddrParseError),
36    /// Header contains invalid TCP port for the source.
37    InvalidSourcePort(Option<std::num::ParseIntError>),
38    /// Header contains invalid TCP port for the destination.]
39    InvalidDestinationPort(Option<std::num::ParseIntError>),
40}
41
42impl fmt::Display for ParseError {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        match self {
45            Self::InvalidPrefix => write!(f, "Header must start with 'PROXY'."),
46            Self::Partial => write!(f, "Header is only partially present."),
47            Self::MissingPrefix => write!(f, "Header is empty."),
48            Self::MissingNewLine => write!(f, "Header does not end with the string '\\r\\n'."),
49            Self::MissingProtocol => write!(f, "Header missing protocol."),
50            Self::MissingSourceAddress => write!(f, "Header missing source address."),
51            Self::MissingDestinationAddress => write!(f, "Header missing destination address."),
52            Self::MissingSourcePort => write!(f, "Header missing source port."),
53            Self::MissingDestinationPort => write!(f, "Header missing destination port."),
54            Self::HeaderTooLong => write!(
55                f,
56                "Header does not fit within the expected buffer size of 107 bytes (plus 1 byte for null-terminated strings)."
57            ),
58            Self::InvalidProtocol => write!(f, "Header has an invalid protocol."),
59            Self::InvalidSuffix => write!(f, "Header must end in '\r\n'."),
60            Self::InvalidSourceAddress(source) => write!(
61                f,
62                "Header contains invalid IP address for the source: {}",
63                source
64            ),
65            Self::InvalidDestinationAddress(destination) => write!(
66                f,
67                "Header contains invalid IP address for the destination: {}",
68                destination
69            ),
70            Self::InvalidSourcePort(port) => write!(
71                f,
72                "Header contains invalid TCP port for the source: {}",
73                port.as_ref().map(|e| e.to_string()).unwrap_or_default()
74            ),
75            Self::InvalidDestinationPort(port) => write!(
76                f,
77                "Header contains invalid TCP port for the destination: {}",
78                port.as_ref().map(|e| e.to_string()).unwrap_or_default()
79            ),
80        }
81    }
82}
83
84impl std::error::Error for ParseError {
85    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
86        match self {
87            Self::InvalidSourceAddress(source) => Some(source),
88            Self::InvalidDestinationAddress(destination) => Some(destination),
89            Self::InvalidSourcePort(port) => port.as_ref().map(|e| e as &dyn std::error::Error),
90            Self::InvalidDestinationPort(port) => {
91                port.as_ref().map(|e| e as &dyn std::error::Error)
92            }
93            _ => None,
94        }
95    }
96}
97
98/// An error in parsing a text PROXY protocol header that is represented as a byte slice.
99#[derive(Debug, Clone, PartialEq, Eq)]
100pub enum BinaryParseError {
101    /// An error in parsing a binary PROXY protocol header.
102    Parse(ParseError),
103    /// Header is not valid UTF-8.
104    InvalidUtf8(std::str::Utf8Error),
105}
106
107impl From<ParseError> for BinaryParseError {
108    fn from(error: ParseError) -> Self {
109        Self::Parse(error)
110    }
111}
112
113impl From<std::str::Utf8Error> for BinaryParseError {
114    fn from(error: std::str::Utf8Error) -> Self {
115        Self::InvalidUtf8(error)
116    }
117}
118
119impl fmt::Display for BinaryParseError {
120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121        match self {
122            Self::Parse(error) => write!(f, "{}", error),
123            Self::InvalidUtf8(error) => write!(f, "Header is not valid UTF-8: {}", error),
124        }
125    }
126}
127
128impl std::error::Error for BinaryParseError {
129    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
130        match self {
131            Self::Parse(error) => Some(error),
132            Self::InvalidUtf8(error) => Some(error),
133        }
134    }
135}