rama_haproxy/protocol/v1/
error.rs

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
//! Errors for the text proxy protocol.

use std::fmt;

/// An error in parsing a text PROXY protocol header.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseError {
    /// Header must start with 'PROXY'.
    InvalidPrefix,
    /// Header is only partially present.
    Partial,
    /// Header is empty.
    MissingPrefix,
    /// Header does not end with the string '\r\n'.
    MissingNewLine,
    /// Header missing protocol.
    MissingProtocol,
    /// Header missing source address.
    MissingSourceAddress,
    /// Header missing destination address.
    MissingDestinationAddress,
    /// Header missing source port.
    MissingSourcePort,
    /// Header missing destination port.
    MissingDestinationPort,
    /// Header does not fit within the expected buffer size of 107 bytes (plus 1 byte for null-terminated strings).
    HeaderTooLong,
    /// Header has an invalid protocol.
    InvalidProtocol,
    /// Header must end in '\r\n'.
    InvalidSuffix,
    /// Header contains invalid IP address for the source.
    InvalidSourceAddress(std::net::AddrParseError),
    /// Header contains invalid IP address for the destination.
    InvalidDestinationAddress(std::net::AddrParseError),
    /// Header contains invalid TCP port for the source.
    InvalidSourcePort(Option<std::num::ParseIntError>),
    /// Header contains invalid TCP port for the destination.]
    InvalidDestinationPort(Option<std::num::ParseIntError>),
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::InvalidPrefix => write!(f, "Header must start with 'PROXY'."),
            Self::Partial => write!(f, "Header is only partially present."),
            Self::MissingPrefix => write!(f, "Header is empty."),
            Self::MissingNewLine => write!(f, "Header does not end with the string '\\r\\n'."),
            Self::MissingProtocol => write!(f, "Header missing protocol."),
            Self::MissingSourceAddress => write!(f, "Header missing source address."),
            Self::MissingDestinationAddress => write!(f, "Header missing destination address."),
            Self::MissingSourcePort => write!(f, "Header missing source port."),
            Self::MissingDestinationPort => write!(f, "Header missing destination port."),
            Self::HeaderTooLong => write!(f, "Header does not fit within the expected buffer size of 107 bytes (plus 1 byte for null-terminated strings)."),
            Self::InvalidProtocol => write!(f, "Header has an invalid protocol."),
            Self::InvalidSuffix => write!(f, "Header must end in '\r\n'."),
            Self::InvalidSourceAddress(source) => write!(f, "Header contains invalid IP address for the source: {}", source),
            Self::InvalidDestinationAddress(destination) => write!(f, "Header contains invalid IP address for the destination: {}", destination),
            Self::InvalidSourcePort(port) => write!(f, "Header contains invalid TCP port for the source: {}", port.as_ref().map(|e| e.to_string()).unwrap_or_default()),
            Self::InvalidDestinationPort(port) => write!(f, "Header contains invalid TCP port for the destination: {}", port.as_ref().map(|e| e.to_string()).unwrap_or_default()),
        }
    }
}

impl std::error::Error for ParseError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::InvalidSourceAddress(source) => Some(source),
            Self::InvalidDestinationAddress(destination) => Some(destination),
            Self::InvalidSourcePort(port) => port.as_ref().map(|e| e as &dyn std::error::Error),
            Self::InvalidDestinationPort(port) => {
                port.as_ref().map(|e| e as &dyn std::error::Error)
            }
            _ => None,
        }
    }
}

/// An error in parsing a text PROXY protocol header that is represented as a byte slice.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum BinaryParseError {
    /// An error in parsing a binary PROXY protocol header.
    Parse(ParseError),
    /// Header is not valid UTF-8.
    InvalidUtf8(std::str::Utf8Error),
}

impl From<ParseError> for BinaryParseError {
    fn from(error: ParseError) -> Self {
        Self::Parse(error)
    }
}

impl From<std::str::Utf8Error> for BinaryParseError {
    fn from(error: std::str::Utf8Error) -> Self {
        Self::InvalidUtf8(error)
    }
}

impl fmt::Display for BinaryParseError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Self::Parse(error) => write!(f, "{}", error),
            Self::InvalidUtf8(error) => write!(f, "Header is not valid UTF-8: {}", error),
        }
    }
}

impl std::error::Error for BinaryParseError {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Self::Parse(error) => Some(error),
            Self::InvalidUtf8(error) => Some(error),
        }
    }
}