use crate::{HaProxRes, HapProtoV1, common, map_error, protocol_raw, return_error};
#[derive(Debug)]
pub struct ProxyV1Parser;
impl ProxyV1Parser
{
pub
fn try_from_str(value: &str, skip_strict_size_check: bool) -> HaProxRes<HapProtoV1>
{
if value.starts_with(protocol_raw::HEADER_MAGIC_V1_STR) == false
{
return_error!(IncorrectBanner, "unknown proto identifier '{:02X?}'",
&value[0..protocol_raw::HEADER_MAGIC_V1.len()]);
}
else if skip_strict_size_check == false && value.as_bytes().len() >= protocol_raw::HEADER_V1_MAX_LEN
{
return_error!(IncorrectBanner, "size of the messagge: '{}' larger '{}' for '{:02X?}'",
value.len(), protocol_raw::HEADER_V1_MAX_LEN, value);
}
let Some(res_value) = common::check_printable_ascii_single_wp(value, "HEADER")?
else
{
return_error!(ProtocolMsgIncomplete, "protocol message is incomplite '{}'", value);
};
return Self::parse(res_value);
}
pub
fn try_from_slice(value: &[u8], skip_strict_size_check: bool) -> HaProxRes<HapProtoV1>
{
let pre_parsed_msg = Self::new_from(value, skip_strict_size_check)?;
return Self::parse(pre_parsed_msg);
}
fn new_from(value: &[u8], skip_strict_size_check: bool) -> HaProxRes<&str>
{
if value.len() <= protocol_raw::HEADER_MAGIC_V1.len()
{
return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown",
value);
}
else if skip_strict_size_check == false && value.len() >= protocol_raw::HEADER_V1_MAX_LEN
{
return_error!(IncorrectBanner, "size of the messagge: '{}' larger '{}' for '{:02X?}'",
value.len(), protocol_raw::HEADER_V1_MAX_LEN, value);
}
else if &value[0..protocol_raw::HEADER_MAGIC_V1.len()] != protocol_raw::HEADER_MAGIC_V1
{
return_error!(IncorrectBanner, "unknown proto identifier '{:02X?}'",
&value[0..protocol_raw::HEADER_MAGIC_V1.len()]);
}
let str_val =
str::from_utf8(value)
.map_err(|e|
map_error!(MalformedData, "UTF8 decode error {}", e)
)?;
let Some(res_value) = common::check_printable_ascii_single_wp(str_val, "HEADER")?
else
{
return_error!(ProtocolMsgIncomplete, "protocol message is incomplite '{}'",
str_val);
};
return Ok(res_value);
}
fn parse(pre_parsed_msg: &str) -> HaProxRes<HapProtoV1>
{
let mut parsed_iter = pre_parsed_msg.split(protocol_raw::HEADER_V1_WSPACE);
let _ =
parsed_iter.next().ok_or_else(||
map_error!(MalformedData, "no INET exists in '{}'", pre_parsed_msg)
)?;
let inet =
parsed_iter
.next()
.ok_or_else(||
map_error!(MalformedData, "no INET exists in '{}'", pre_parsed_msg)
)?;
let src_ip= parsed_iter.next();
let dst_ip = parsed_iter.next();
let src_port = parsed_iter.next();
let dst_port = parsed_iter.next();
return HapProtoV1::from_raw(inet, src_ip, dst_ip, src_port, dst_port);
}
}
#[cfg(test)]
mod tests_parser
{
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use crate::{ProtocolV1Inet, ProxyV1Parser};
#[test]
fn test_v1_parser_0()
{
let pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 192.168.2.1 10.8.0.1 4567 1234\r\n", false)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp4);
assert_eq!(pv1.get_src_addr(), Some("192.168.2.1".parse().unwrap()));
assert_eq!(pv1.get_src_port(), Some(4567));
assert_eq!(pv1.get_dst_addr(), Some("10.8.0.1".parse().unwrap()));
assert_eq!(pv1.get_dst_port(), Some(1234));
}
#[test]
fn test_v1_parser_1()
{
let pv1 =
ProxyV1Parser
::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)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp6);
assert_eq!(pv1.get_src_addr(), Some(IpAddr::V6("0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f".parse::<Ipv6Addr>().unwrap())));
assert_eq!(pv1.get_src_port(), Some(23456));
assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V6("4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse::<Ipv6Addr>().unwrap())));
assert_eq!(pv1.get_dst_port(), Some(12345));
}
#[test]
fn test_v1_parser_2()
{
let pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY UNKNOWN\r\n", false)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::None);
assert_eq!(pv1.get_src_addr(), None);
assert_eq!(pv1.get_src_port(), None);
assert_eq!(pv1.get_dst_addr(), None);
assert_eq!(pv1.get_dst_port(), None);
}
#[test]
fn test_v1_parser_3()
{
let pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY UNKNOWN 255.255.255.255 255.255.255.255 65535 65535\r\n", false)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::None);
assert_eq!(pv1.get_src_addr(), None);
assert_eq!(pv1.get_src_port(), None);
assert_eq!(pv1.get_dst_addr(), None);
assert_eq!(pv1.get_dst_port(), None);
}
#[should_panic]
#[test]
fn test_v1_parser_4()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_5()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP5 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_6()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_7()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP6 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_8()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 349.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_9()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 \0149.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_10()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 149.168.1.1 10.8.0.1 6787765 12345\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_11()
{
let _pv1 =
ProxyV1Parser
::try_from_slice(b"PROXY TCP4 149.168.1.1 10.8.0.1 1 12345\r", false)
.unwrap();
}
#[test]
fn test_v1_parser_0_str()
{
let pv1 =
ProxyV1Parser
::try_from_str("PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n", false)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp4);
assert_eq!(pv1.get_src_addr(), Some(IpAddr::V4("192.168.1.1".parse::<Ipv4Addr>().unwrap())));
assert_eq!(pv1.get_src_port(), Some(23456));
assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V4("10.8.0.1".parse::<Ipv4Addr>().unwrap())));
assert_eq!(pv1.get_dst_port(), Some(12345));
}
#[test]
fn test_v1_parser_1_str()
{
let pv1 =
ProxyV1Parser
::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)
.unwrap();
assert_eq!(pv1.get_inet(), ProtocolV1Inet::Tcp6);
assert_eq!(pv1.get_src_addr(), Some(IpAddr::V6("0acf:5d35:b4c4:731c:2442:2f17:c6f9:5b7f".parse::<Ipv6Addr>().unwrap())));
assert_eq!(pv1.get_src_port(), Some(23456));
assert_eq!(pv1.get_dst_addr(), Some(IpAddr::V6("4d7f:8980:38d6:e0c3:7301:70e9:f8ef:e393".parse::<Ipv6Addr>().unwrap())));
assert_eq!(pv1.get_dst_port(), Some(12345));
}
#[should_panic]
#[test]
fn test_v1_parser_2_str()
{
let _pv1 =
ProxyV1Parser
::try_from_str("PROXY TCP4 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
.unwrap();
}
#[should_panic]
#[test]
fn test_v1_parser_3_str()
{
let _pv1 =
ProxyV1Parser
::try_from_str("PROXY TCP4\0 192.168.1.1 10.8.0.1 23456 12345\r\n\r\n", false)
.unwrap();
}
}