1use std::fmt;
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
22pub enum ProxyMode {
23 #[default]
25 Off,
26 Required {
28 versions: ProxyVersions,
30 },
31}
32
33#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub enum ProxyVersions {
40 V1,
42 V2,
44 Both,
46}
47
48#[derive(Clone, Copy)]
55pub struct ProxyFacts {
56 alpn: [u8; 32],
57 alpn_len: u8,
58 authority: [u8; 255],
59 authority_len: u8,
60 unique_id: [u8; 128],
61 unique_id_len: u8,
62 ssl_client: Option<u8>,
63}
64
65impl Default for ProxyFacts {
66 fn default() -> ProxyFacts {
67 ProxyFacts {
68 alpn: [0; 32],
69 alpn_len: 0,
70 authority: [0; 255],
71 authority_len: 0,
72 unique_id: [0; 128],
73 unique_id_len: 0,
74 ssl_client: None,
75 }
76 }
77}
78
79impl ProxyFacts {
80 #[cfg_attr(not(feature = "proxy"), allow(dead_code))]
82 pub(crate) fn from_parts(
83 alpn: Option<&[u8]>,
84 authority: Option<&str>,
85 unique_id: Option<&[u8]>,
86 ssl_client: Option<u8>,
87 ) -> ProxyFacts {
88 let mut f = ProxyFacts {
89 ssl_client,
90 ..ProxyFacts::default()
91 };
92 if let Some(a) = alpn.filter(|a| a.len() <= f.alpn.len()) {
93 f.alpn[..a.len()].copy_from_slice(a);
94 f.alpn_len = a.len() as u8;
95 }
96 if let Some(a) = authority.filter(|a| a.len() <= f.authority.len()) {
97 f.authority[..a.len()].copy_from_slice(a.as_bytes());
98 f.authority_len = a.len() as u8;
99 }
100 if let Some(u) = unique_id.filter(|u| u.len() <= f.unique_id.len()) {
101 f.unique_id[..u.len()].copy_from_slice(u);
102 f.unique_id_len = u.len() as u8;
103 }
104 f
105 }
106
107 #[must_use]
109 pub fn alpn(&self) -> Option<&[u8]> {
110 (self.alpn_len > 0).then(|| &self.alpn[..usize::from(self.alpn_len)])
111 }
112
113 #[must_use]
115 pub fn authority(&self) -> Option<&str> {
116 if self.authority_len == 0 {
117 return None;
118 }
119 std::str::from_utf8(&self.authority[..usize::from(self.authority_len)]).ok()
120 }
121
122 #[must_use]
124 pub fn unique_id(&self) -> Option<&[u8]> {
125 (self.unique_id_len > 0).then(|| &self.unique_id[..usize::from(self.unique_id_len)])
126 }
127
128 #[must_use]
130 pub fn ssl_client(&self) -> Option<u8> {
131 self.ssl_client
132 }
133}
134
135impl fmt::Debug for ProxyFacts {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 f.debug_struct("ProxyFacts")
138 .field("alpn", &self.alpn().map(String::from_utf8_lossy))
139 .field("authority", &self.authority())
140 .field("unique_id_len", &self.unique_id_len)
141 .field("ssl_client", &self.ssl_client)
142 .finish()
143 }
144}
145
146#[non_exhaustive]
152#[derive(Clone, Copy, Debug, PartialEq, Eq)]
153pub enum ProxyError {
154 OutputTooSmall {
156 need: usize,
158 },
159 NotProxy,
161 V1TooLong,
163 V1Syntax {
165 at: u8,
167 },
168 V1BadAddress,
170 V1BadPort,
172 V2BadVersion,
174 V2BadCommand,
176 V2BadFamily,
178 V2LengthTooLarge {
180 declared: u16,
182 max: u16,
184 },
185 V2AddressTooShort,
187 V2TlvOverrun,
189 V2CrcMismatch,
191 V2UniqueIdTooLong,
193 V2SslMalformed,
195 FamilyMismatch,
197}
198
199impl fmt::Display for ProxyError {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 match self {
202 ProxyError::OutputTooSmall { need } => {
203 write!(f, "output buffer too small ({need} bytes needed)")
204 }
205 ProxyError::NotProxy => f.write_str("the connection did not start with a PROXY header"),
206 ProxyError::V1TooLong => f.write_str("v1 header longer than 107 bytes"),
207 ProxyError::V1Syntax { at } => write!(f, "v1 header syntax error at byte {at}"),
208 ProxyError::V1BadAddress => f.write_str("v1 header with an invalid address"),
209 ProxyError::V1BadPort => f.write_str("v1 header with an invalid port"),
210 ProxyError::V2BadVersion => f.write_str("v2 header with an unknown version"),
211 ProxyError::V2BadCommand => f.write_str("v2 header with an unknown command"),
212 ProxyError::V2BadFamily => f.write_str("v2 header with an unknown address family"),
213 ProxyError::V2LengthTooLarge { declared, max } => {
214 write!(
215 f,
216 "v2 header declares {declared} bytes, above the maximum of {max}"
217 )
218 }
219 ProxyError::V2AddressTooShort => {
220 f.write_str("v2 address block too short for its family")
221 }
222 ProxyError::V2TlvOverrun => f.write_str("v2 TLV runs past the declared length"),
223 ProxyError::V2CrcMismatch => f.write_str("v2 header checksum does not match"),
224 ProxyError::V2UniqueIdTooLong => f.write_str("v2 unique id longer than 128 bytes"),
225 ProxyError::V2SslMalformed => f.write_str("v2 SSL TLV is malformed"),
226 ProxyError::FamilyMismatch => f.write_str("addresses do not match the declared family"),
227 }
228 }
229}
230
231impl std::error::Error for ProxyError {}