1pub mod protocol_parser;
16pub mod protocol_composer;
17
18use core::fmt;
19use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
20
21use crate::{HaProxRes, map_error, protocol_raw, return_error};
22
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq)]
25pub enum ProtocolV1Inet
26{
27 Tcp4, Tcp6, None
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq)]
31pub enum HapProtoV1
32{
33 TCP4
34 {
35 src_addr: Ipv4Addr,
36 dst_addr: Ipv4Addr,
37 src_port: u16,
38 dst_port: u16,
39 },
40 TCP6
41 {
42 src_addr: Ipv6Addr,
43 dst_addr: Ipv6Addr,
44 src_port: u16,
45 dst_port: u16,
46 },
47 UNKNOWN,
48}
49
50impl fmt::Display for HapProtoV1
51{
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
53 {
54 let s: String = self.into();
55
56 write!(f, "{}", s)
57 }
58}
59
60impl From<&HapProtoV1> for String
61{
62 fn from(value: &HapProtoV1) -> Self
63 {
64 match value
65 {
66 HapProtoV1::TCP4{ src_addr, dst_addr, src_port, dst_port } =>
67 {
68 let out =
69 [
70 protocol_raw::HEADER_MAGIC_V1_STR, protocol_raw::HEADER_V1_WSPACE,
71 protocol_raw::HEADER_V1_INET_TCP4, protocol_raw::HEADER_V1_WSPACE,
72 src_addr.to_string().as_str(), protocol_raw::HEADER_V1_WSPACE,
73 dst_addr.to_string().as_str(), protocol_raw::HEADER_V1_WSPACE,
74 src_port.to_string().as_str(), protocol_raw::HEADER_V1_WSPACE,
75 dst_port.to_string().as_str(), protocol_raw::HEADER_V1_EOM
76 ]
77 .concat();
78
79 return out;
80 },
81 HapProtoV1::TCP6{ src_addr, dst_addr, src_port, dst_port } =>
82 {
83 let out =
84 [
85 protocol_raw::HEADER_MAGIC_V1_STR, protocol_raw::HEADER_V1_WSPACE,
86 protocol_raw::HEADER_V1_INET_TCP6, protocol_raw::HEADER_V1_WSPACE,
87 src_addr.segments().iter().map(|v| format!("{:04x}", v)).collect::<Vec<String>>().join(":").as_str(), protocol_raw::HEADER_V1_WSPACE,
88 dst_addr.segments().iter().map(|v| format!("{:04x}", v)).collect::<Vec<String>>().join(":").as_str(), protocol_raw::HEADER_V1_WSPACE,
89 src_port.to_string().as_str(), protocol_raw::HEADER_V1_WSPACE,
90 dst_port.to_string().as_str(), protocol_raw::HEADER_V1_EOM
91 ]
92 .concat();
93
94 return out;
95 },
96 HapProtoV1::UNKNOWN =>
97 {
98 let out =
99 [
100 protocol_raw::HEADER_MAGIC_V1_STR, protocol_raw::HEADER_V1_WSPACE,
101 protocol_raw::HEADER_V1_INET_UNKNWON, protocol_raw::HEADER_V1_EOM
102 ]
103 .concat();
104
105 return out;
106 }
107 }
108
109 }
110}
111
112
113impl From<HapProtoV1> for String
114{
115 fn from(value: HapProtoV1) -> Self
116 {
117 return (&value).into();
118 }
119}
120
121impl HapProtoV1
122{
123 pub(super)
124 fn unknown() -> Self
125 {
126 return Self::UNKNOWN;
127 }
128
129 pub(super)
130 fn from_ip_port(
131 src_ip: IpAddr,
132 dst_ip: IpAddr,
133 src_port: u16,
134 dst_port: u16
135 ) -> HaProxRes<Self>
136 {
137
138 if src_ip.is_ipv4() == true
139 {
140 let IpAddr::V4(dst_addr) = dst_ip
141 else
142 {
143 return_error!(ArgumentEinval, "dst_addr is not IPv4");
144 };
145
146 let IpAddr::V4(src_addr) = src_ip
147 else
148 {
149 return_error!(ArgumentEinval, "src_addr is not IPv4");
150 };
151
152 return Ok(
153 Self::TCP4{ src_addr, dst_addr, src_port, dst_port }
154 )
155 }
156 else
157 {
158 let IpAddr::V6(src_addr) = src_ip
159 else
160 {
161 return_error!(ArgumentEinval, "src_addr is not IPv6");
162 };
163
164 let IpAddr::V6(dst_addr) = dst_ip
165 else
166 {
167 return_error!(ArgumentEinval, "dst_addr is not IPv6");
168 };
169
170 return Ok(
171 Self::TCP6{ src_addr, dst_addr, src_port, dst_port }
172 )
173 }
174 }
175
176 pub
177 fn from_raw(
178 inet: &str,
179 src_ip: Option<&str>,
180 dst_ip: Option<&str>,
181 src_port: Option<&str>,
182 dst_port: Option<&str>
183 ) -> HaProxRes<Self>
184 {
185 if inet == protocol_raw::HEADER_V1_INET_UNKNWON
186 {
187 return Ok(Self::UNKNOWN);
188 }
189
190 if src_ip.is_none() == true || dst_ip.is_none() == true ||
191 src_port.is_none() == true || dst_port.is_none() == true
192 {
193 return_error!(MalformedData, "missing field/s '{:?}' '{:?}' '{:?}' '{:?}'",
194 src_ip, dst_ip, src_port, dst_port);
195 }
196
197 if inet == protocol_raw::HEADER_V1_INET_TCP4
198 {
199 return Ok(
200 Self::TCP4
201 {
202 src_addr:
203 src_ip.as_ref().unwrap().parse().map_err(|e|
204 map_error!(MalformedData, "cannot parse src_addr '{}' err: '{}", src_ip.unwrap(), e)
205 )?,
206 dst_addr:
207 dst_ip.as_ref().unwrap().parse().map_err(|e|
208 map_error!(MalformedData, "cannot parse dst_addr '{}' err: '{}", dst_ip.unwrap(), e)
209 )?,
210 src_port:
211 src_port.as_ref().unwrap().parse().map_err(|e|
212 map_error!(MalformedData, "cannot parse src_port '{}' err: '{}", src_port.unwrap(), e)
213 )?,
214 dst_port:
215 dst_port.as_ref().unwrap().parse().map_err(|e|
216 map_error!(MalformedData, "cannot parse dst_port '{}' err: '{}", dst_port.unwrap(), e)
217 )?
218 }
219 );
220 }
221 else if inet == protocol_raw::HEADER_V1_INET_TCP6
222 {
223 return Ok(
224 Self::TCP6
225 {
226 src_addr:
227 src_ip.as_ref().unwrap().parse().map_err(|e|
228 map_error!(MalformedData, "cannot parse src_addr '{}' err: '{}", src_ip.unwrap(), e)
229 )?,
230 dst_addr:
231 dst_ip.as_ref().unwrap().parse().map_err(|e|
232 map_error!(MalformedData, "cannot parse dst_addr '{}' err: '{}", dst_ip.unwrap(), e)
233 )?,
234 src_port:
235 src_port.as_ref().unwrap().parse().map_err(|e|
236 map_error!(MalformedData, "cannot parse src_port '{}' err: '{}", src_port.unwrap(), e)
237 )?,
238 dst_port:
239 dst_port.as_ref().unwrap().parse().map_err(|e|
240 map_error!(MalformedData, "cannot parse dst_port '{}' err: '{}", dst_port.unwrap(), e)
241 )?
242 }
243 );
244 }
245 else
246 {
247 return_error!(MalformedData, "unknown INET: '{}'", inet);
248 }
249 }
250
251 pub
252 fn get_src_addr(&self) -> Option<IpAddr>
253 {
254 match self
255 {
256 Self::TCP4 { src_addr, .. } =>
257 return Some(IpAddr::V4(*src_addr)),
258 Self::TCP6 { src_addr, .. } =>
259 return Some(IpAddr::V6(*src_addr)),
260 Self::UNKNOWN =>
261 return None,
262 }
263 }
264
265 pub
266 fn get_dst_addr(&self) -> Option<IpAddr>
267 {
268 match self
269 {
270 Self::TCP4 { dst_addr, .. } =>
271 return Some(IpAddr::V4(*dst_addr)),
272 Self::TCP6 { dst_addr, .. } =>
273 return Some(IpAddr::V6(*dst_addr)),
274 Self::UNKNOWN =>
275 return None,
276 }
277 }
278
279 pub
280 fn get_src_port(&self) -> Option<u16>
281 {
282 match self
283 {
284 Self::TCP4 { src_port, .. } =>
285 return Some(*src_port),
286 Self::TCP6 { src_port, .. } =>
287 return Some(*src_port),
288 Self::UNKNOWN =>
289 return None,
290 }
291 }
292
293 pub
294 fn get_dst_port(&self) -> Option<u16>
295 {
296 match self
297 {
298 Self::TCP4 { dst_port, .. } =>
299 return Some(*dst_port),
300 Self::TCP6 { dst_port, .. } =>
301 return Some(*dst_port),
302 Self::UNKNOWN =>
303 return None,
304 }
305 }
306
307 pub
308 fn get_inet(&self) -> ProtocolV1Inet
309 {
310 match self
311 {
312 Self::TCP4{ .. } =>
313 return ProtocolV1Inet::Tcp4,
314 Self::TCP6 { .. } =>
315 return ProtocolV1Inet::Tcp6,
316 Self::UNKNOWN =>
317 return ProtocolV1Inet::None
318 }
319 }
320}
321
322#[cfg(test)]
323mod tests_proto
324{
325 use crate::HapProtoV1;
326
327 #[test]
328 fn simple_test1()
329 {
330 let s: String =
331 HapProtoV1::TCP4
332 {
333 src_addr: "255.255.255.255".parse().unwrap(),
334 dst_addr: "255.255.255.255".parse().unwrap(),
335 src_port: 65535,
336 dst_port: 65535
337 }
338 .into();
339
340 assert_eq!(s.as_str(), "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n");
341 }
342
343 #[test]
344 fn simple_test2()
345 {
346 let s: String =
347 HapProtoV1::TCP4
348 {
349 src_addr: "192.168.1.1".parse().unwrap(),
350 dst_addr: "10.8.0.1".parse().unwrap(),
351 src_port: 23456,
352 dst_port: 12345
353 }
354 .into();
355
356 assert_eq!(s.as_str(), "PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n");
357 }
358
359 #[test]
360 fn simple_test3()
361 {
362 let s: String =
363 HapProtoV1::TCP6
364 {
365 src_addr: "0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f".parse().unwrap(),
366 dst_addr: "4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse().unwrap(),
367 src_port: 23456,
368 dst_port: 12345
369 }
370 .into();
371
372 assert_eq!(s.as_str(), "PROXY TCP6 0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f 4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393 23456 12345\r\n");
373 }
374
375 #[test]
376 fn simple_test4()
377 {
378 let s: String =
379 HapProtoV1::TCP6
380 {
381 src_addr: "0acf:5d35:b4c4:0000:2442:2f17:c6f9:5b7f".parse().unwrap(),
382 dst_addr: "4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse().unwrap(),
383 src_port: 23456,
384 dst_port: 12345
385 }
386 .into();
387
388 assert_eq!(s.as_str(), "PROXY TCP6 0acf:5d35:b4c4:0000:2442:2f17:c6f9:5b7f 4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393 23456 12345\r\n");
389 }
390
391 #[test]
392 fn simple_test5()
393 {
394 let s: String =
395 HapProtoV1::UNKNOWN.into();
396
397 assert_eq!(s.as_str(), "PROXY UNKNOWN\r\n");
398 }
399}