1use crate::{HaProxRes, HapProtoV1, common, map_error, protocol_raw, return_error};
16
17
18#[derive(Debug)]
53pub struct ProxyV1Parser;
54
55impl ProxyV1Parser
56{
57 pub
81 fn try_from_str(value: &str, skip_strict_size_check: bool) -> HaProxRes<HapProtoV1>
82 {
83 if value.starts_with(protocol_raw::HEADER_MAGIC_V1_STR) == false
84 {
85 return_error!(IncorrectBanner, "unknown proto identifier '{:02X?}'",
86 &value[0..protocol_raw::HEADER_MAGIC_V1.len()]);
87 }
88 else if skip_strict_size_check == false && value.as_bytes().len() >= protocol_raw::HEADER_V1_MAX_LEN
89 {
90 return_error!(IncorrectBanner, "size of the messagge: '{}' larger '{}' for '{:02X?}'",
91 value.len(), protocol_raw::HEADER_V1_MAX_LEN, value);
92 }
93
94 let Some(res_value) = common::check_printable_ascii_single_wp(value, "HEADER")?
96 else
97 {
98 return_error!(ProtocolMsgIncomplete, "protocol message is incomplite '{}'", value);
100 };
101
102 return Self::parse(res_value);
103 }
104
105 pub
135 fn try_from_slice(value: &[u8], skip_strict_size_check: bool) -> HaProxRes<HapProtoV1>
136 {
137 let pre_parsed_msg = Self::new_from(value, skip_strict_size_check)?;
138
139 return Self::parse(pre_parsed_msg);
140 }
141
142 fn new_from(value: &[u8], skip_strict_size_check: bool) -> HaProxRes<&str>
153 {
154 if value.len() <= protocol_raw::HEADER_MAGIC_V1.len()
155 {
156 return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown",
157 value);
158 }
159 else if skip_strict_size_check == false && value.len() >= protocol_raw::HEADER_V1_MAX_LEN
160 {
161 return_error!(IncorrectBanner, "size of the messagge: '{}' larger '{}' for '{:02X?}'",
162 value.len(), protocol_raw::HEADER_V1_MAX_LEN, value);
163 }
164 else if &value[0..protocol_raw::HEADER_MAGIC_V1.len()] != protocol_raw::HEADER_MAGIC_V1
165 {
166 return_error!(IncorrectBanner, "unknown proto identifier '{:02X?}'",
167 &value[0..protocol_raw::HEADER_MAGIC_V1.len()]);
168 }
169
170 let str_val =
172 str::from_utf8(value)
173 .map_err(|e|
174 map_error!(MalformedData, "UTF8 decode error {}", e)
175 )?;
176
177 let Some(res_value) = common::check_printable_ascii_single_wp(str_val, "HEADER")?
179 else
180 {
181 return_error!(ProtocolMsgIncomplete, "protocol message is incomplite '{}'",
183 str_val);
184 };
185
186 return Ok(res_value);
187 }
188
189 fn parse(pre_parsed_msg: &str) -> HaProxRes<HapProtoV1>
190 {
191 let mut parsed_iter = pre_parsed_msg.split(protocol_raw::HEADER_V1_WSPACE);
192
193 let _ =
195 parsed_iter.next().ok_or_else(||
196 map_error!(MalformedData, "no INET exists in '{}'", pre_parsed_msg)
197 )?;
198
199 let inet =
201 parsed_iter
202 .next()
203 .ok_or_else(||
204 map_error!(MalformedData, "no INET exists in '{}'", pre_parsed_msg)
205 )?;
206
207 let src_ip= parsed_iter.next();
209 let dst_ip = parsed_iter.next();
210 let src_port = parsed_iter.next();
211 let dst_port = parsed_iter.next();
212
213 return HapProtoV1::from_raw(inet, src_ip, dst_ip, src_port, dst_port);
214 }
215}
216
217#[cfg(test)]
218mod tests_parser
219{
220 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
221
222 use crate::{ProtocolV1Inet, ProxyV1Parser};
223
224 #[test]
225 fn test_v1_parser_0()
226 {
227 let pv1 =
228 ProxyV1Parser
229 ::try_from_slice(b"PROXY TCP4 192.168.2.1 10.8.0.1 4567 1234\r\n", false)
230 .unwrap();
231
232 assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp4);
233 assert_eq!(pv1.get_src_addr(), Some("192.168.2.1".parse().unwrap()));
234 assert_eq!(pv1.get_src_port(), Some(4567));
235 assert_eq!(pv1.get_dst_addr(), Some("10.8.0.1".parse().unwrap()));
236 assert_eq!(pv1.get_dst_port(), Some(1234));
237 }
238
239 #[test]
240 fn test_v1_parser_1()
241 {
242 let pv1 =
243 ProxyV1Parser
244 ::try_from_slice(b"PROXY TCP6 0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f 4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393 23456 12345\r\n", false)
245 .unwrap();
246
247 assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp6);
248 assert_eq!(pv1.get_src_addr(), Some(IpAddr::V6("0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f".parse::<Ipv6Addr>().unwrap())));
249 assert_eq!(pv1.get_src_port(), Some(23456));
250 assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V6("4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse::<Ipv6Addr>().unwrap())));
251 assert_eq!(pv1.get_dst_port(), Some(12345));
252 }
253
254 #[test]
255 fn test_v1_parser_2()
256 {
257 let pv1 =
258 ProxyV1Parser
259 ::try_from_slice(b"PROXY UNKNOWN\r\n", false)
260 .unwrap();
261
262 assert_eq!(pv1.get_inet(), ProtocolV1Inet::None);
263 assert_eq!(pv1.get_src_addr(), None);
264 assert_eq!(pv1.get_src_port(), None);
265 assert_eq!(pv1.get_dst_addr(), None);
266 assert_eq!(pv1.get_dst_port(), None);
267 }
268
269 #[test]
270 fn test_v1_parser_3()
271 {
272 let pv1 =
273 ProxyV1Parser
274 ::try_from_slice(b"PROXY UNKNOWN 255.255.255.255 255.255.255.255 65535 65535\r\n", false)
275 .unwrap();
276
277 assert_eq!(pv1.get_inet(), ProtocolV1Inet::None);
278 assert_eq!(pv1.get_src_addr(), None);
279 assert_eq!(pv1.get_src_port(), None);
280 assert_eq!(pv1.get_dst_addr(), None);
281 assert_eq!(pv1.get_dst_port(), None);
282 }
283
284 #[should_panic]
285 #[test]
286 fn test_v1_parser_4()
287 {
288 let _pv1 =
289 ProxyV1Parser
290 ::try_from_slice(b"PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
291 .unwrap();
292 }
293
294 #[should_panic]
295 #[test]
296 fn test_v1_parser_5()
297 {
298 let _pv1 =
299 ProxyV1Parser
300 ::try_from_slice(b"PROXY TCP5 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
301 .unwrap();
302 }
303
304 #[should_panic]
305 #[test]
306 fn test_v1_parser_6()
307 {
308 let _pv1 =
309 ProxyV1Parser
310 ::try_from_slice(b"PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
311 .unwrap();
312 }
313
314 #[should_panic]
315 #[test]
316 fn test_v1_parser_7()
317 {
318 let _pv1 =
319 ProxyV1Parser
320 ::try_from_slice(b"PROXY TCP6 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
321 .unwrap();
322 }
323
324 #[should_panic]
325 #[test]
326 fn test_v1_parser_8()
327 {
328 let _pv1 =
329 ProxyV1Parser
330 ::try_from_slice(b"PROXY TCP4 349.168.1.1 10.8.0.1 23456 12345\r\n", false)
331 .unwrap();
332 }
333
334 #[should_panic]
335 #[test]
336 fn test_v1_parser_9()
337 {
338 let _pv1 =
339 ProxyV1Parser
340 ::try_from_slice(b"PROXY TCP4 \0149.168.1.1 10.8.0.1 23456 12345\r\n", false)
341 .unwrap();
342 }
343
344 #[should_panic]
345 #[test]
346 fn test_v1_parser_10()
347 {
348 let _pv1 =
349 ProxyV1Parser
350 ::try_from_slice(b"PROXY TCP4 149.168.1.1 10.8.0.1 6787765 12345\r\n", false)
351 .unwrap();
352 }
353
354 #[should_panic]
355 #[test]
356 fn test_v1_parser_11()
357 {
358 let _pv1 =
359 ProxyV1Parser
360 ::try_from_slice(b"PROXY TCP4 149.168.1.1 10.8.0.1 1 12345\r", false)
361 .unwrap();
362 }
363
364 #[test]
365 fn test_v1_parser_0_str()
366 {
367 let pv1 =
368 ProxyV1Parser
369 ::try_from_str("PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
370 .unwrap();
371
372 assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp4);
373 assert_eq!(pv1.get_src_addr(), Some(IpAddr::V4("192.168.1.1".parse::<Ipv4Addr>().unwrap())));
374 assert_eq!(pv1.get_src_port(), Some(23456));
375 assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V4("10.8.0.1".parse::<Ipv4Addr>().unwrap())));
376 assert_eq!(pv1.get_dst_port(), Some(12345));
377 }
378
379 #[test]
380 fn test_v1_parser_1_str()
381 {
382 let pv1 =
383 ProxyV1Parser
384 ::try_from_str("PROXY TCP6 0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f 4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393 23456 12345\r\n", false)
385 .unwrap();
386
387 assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp6);
388 assert_eq!(pv1.get_src_addr(), Some(IpAddr::V6("0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f".parse::<Ipv6Addr>().unwrap())));
389 assert_eq!(pv1.get_src_port(), Some(23456));
390 assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V6("4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse::<Ipv6Addr>().unwrap())));
391 assert_eq!(pv1.get_dst_port(), Some(12345));
392 }
393
394 #[should_panic]
395 #[test]
396 fn test_v1_parser_2_str()
397 {
398 let _pv1 =
399 ProxyV1Parser
400 ::try_from_str("PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
401 .unwrap();
402 }
403
404 #[should_panic]
405 #[test]
406 fn test_v1_parser_3_str()
407 {
408 let _pv1 =
409 ProxyV1Parser
410 ::try_from_str("PROXY TCP4\0 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
411 .unwrap();
412 }
413}