use std::mem::offset_of;
use std::{borrow::Cow, fmt, io::Cursor, marker::PhantomData};
use std::io::Read;
use byteorder::{BigEndian, ReadBytesExt};
use crc32fast::Hasher;
use crate::common::map_io_err;
use crate::{common, error::{HaProxErr, HaProxRes}, map_error, return_error};
use super::
{
protocol::
{
HdrV2Command,
PP2TlvClient,
PP2Tlvs,
ProtocolVersion,
ProxyTransportFam,
ProxyV2Addr,
ProxyV2AddrType
},
protocol_raw,
PP2TlvRestore
};
pub struct ProxyV2Parser<'t, EXT: PP2TlvRestore = ProxyV2Dummy>
{
buffer: &'t [u8],
_p: PhantomData<EXT>
}
impl<'t> ProxyV2Parser<'t>
{
pub
fn try_from_slice(value: &'t [u8]) -> HaProxRes<Self>
{
let pkt_size = Self::new_from(value)?;
let tmp = Self{ buffer: &value[0..pkt_size], _p: PhantomData };
tmp.post_check()?;
return Ok(tmp);
}
}
impl<'t, EXT: PP2TlvRestore> ProxyV2Parser<'t, EXT>
{
pub
fn try_from_slice_custom(value: &'t [u8]) -> HaProxRes<Self>
{
let pkt_size = Self::new_from(value)?;
let tmp = Self{ buffer: &value[0..pkt_size], _p: PhantomData };
tmp.post_check()?;
return Ok(tmp);
}
}
impl<'t, EXT: PP2TlvRestore> ProxyV2Parser<'t, EXT>
{
fn post_check(&self) -> HaProxRes<()>
{
let _ = self.get_address_family()?;
let _ = self.get_transport()?;
return Ok(());
}
fn new_from(value: &[u8]) -> HaProxRes<usize>
{
if value.len() <= protocol_raw::HEADER_MAGIC_V1.len()
{
return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown",
value);
}
else if &value[0..protocol_raw::HEADER_MAGIC_V1.len()] == protocol_raw::HEADER_MAGIC_V1
{
return_error!(ProtocolNotSuported, "V1 protocol is not supported");
}
else if value.len() < size_of::<protocol_raw::ProxyHdrV2>()
{
return_error!(ProtocolMsgIncomplete, "protocol with footprint '{:02X?}' unknown",
value);
}
else if &value[0..protocol_raw::HEADER_MAGIC_V2.len()] != protocol_raw::HEADER_MAGIC_V2
{
return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown",
value);
}
else if value[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)] & protocol_raw::ProxyHdrV2::VERSION_MASK !=
protocol_raw::ProxyHdrV2::VERSION_RAW
{
return_error!(MalformedData, "protocol version '{:02X?}' incorrect",
value[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
}
let payload_len =
[
value[offset_of!(protocol_raw::ProxyHdrV2, len)],
value[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
];
let full_size = u16::from_be_bytes(payload_len) + protocol_raw::ProxyHdrV2::HEADER_LEN as u16;
if value.len() < full_size as usize
{
return_error!(ProtocolMsgIncomplete, "fragmented pkt received, declared len + header: {}, received len: {}",
full_size, value.len());
}
return Ok(full_size as usize);
}
pub
fn get_proto_version(&self) -> ProtocolVersion
{
return ProtocolVersion::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
}
pub
fn get_proto_command(&self) -> HdrV2Command
{
return HdrV2Command::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
}
pub
fn get_transport(&self) -> HaProxRes<ProxyTransportFam>
{
return ProxyTransportFam::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, fam)]);
}
pub
fn get_address_family(&self) -> HaProxRes<ProxyV2AddrType>
{
return ProxyV2AddrType::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, fam)]);
}
pub
fn get_palyload_len(&self) -> u16
{
let hi =
[
self
.buffer[offset_of!(protocol_raw::ProxyHdrV2, len)],
self
.buffer[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
];
return u16::from_be_bytes(hi);
}
pub
fn get_full_len(&self) -> u16
{
let hi =
[
self
.buffer[offset_of!(protocol_raw::ProxyHdrV2, len)],
self
.buffer[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
];
return u16::from_be_bytes(hi) + protocol_raw::ProxyHdrV2::HEADER_LEN as u16;
}
pub
fn get_address(&self) -> HaProxRes<Option<ProxyV2Addr>>
{
let addr_fam = self.get_address_family()?;
let Some(addr_len) = addr_fam.get_size_by_addr_family()
else { return Ok(None) };
let buf_len = self.buffer.len() - size_of::<protocol_raw::ProxyHdrV2>();
if buf_len < addr_len as usize
{
return_error!(ProtocolMsgIncomplete, "cannot read address, msg len: '{}', addr len: '{}'",
buf_len, addr_len);
}
let mut cur = Cursor::new(&self.buffer.as_ref()[offset_of!(protocol_raw::ProxyHdrV2, address)..]);
return ProxyV2Addr::read(addr_fam, &mut cur);
}
pub
fn get_tlvs_iter(&self) -> Option<ProxyV2TlvIter<'_, EXT>>
{
let addr_fam = self.get_address_family().ok()?.get_size_by_addr_family()?;
if self.get_palyload_len() - addr_fam == 0
{
return None;
}
let addr_size = self.get_address_family().ok()?.get_size_by_addr_family()? as usize;
let tlv_offset_start =
offset_of!(protocol_raw::ProxyHdrV2, address) + addr_size;
let itr =
ProxyV2TlvIter
{
curs:
vec![
ProxyV2TlvIterTlv
{
cur: Cursor::new(&self.buffer.as_ref()[tlv_offset_start..]),
parent_tlv_idx: None,
},
],
_p: PhantomData
};
return Some(itr);
}
pub
fn check_crc(&self) -> HaProxRes<bool>
{
let mut crc32: Option<u32> = None;
let mut hasher = Hasher::new();
let addr_fam_len =
self
.get_address_family()?
.get_size_by_addr_family()
.ok_or_else(||
map_error!(ArgumentEinval, "unknown address family")
)? as usize;
let full_hdr_len = addr_fam_len + protocol_raw::ProxyHdrV2::HEADER_LEN;
hasher.update(&self.buffer[0..full_hdr_len]);
let payload_len = self.get_palyload_len() as usize - addr_fam_len;
let mut cur = Cursor::new(&self.buffer[full_hdr_len..]);
while cur.position() < payload_len as u64
{
let s = cur.position() as usize;
let op = cur.read_u8().map_err(map_io_err)?;
let len = cur.read_u16::<BigEndian>().map_err(map_io_err)?;
if op == PP2Tlvs::TYPE_CRC32C
{
crc32 = Some(cur.read_u32::<BigEndian>().map_err(map_io_err)?);
hasher.update(&[op]);
hasher.update(len.to_be_bytes().as_slice());
hasher.update(&[0]);
}
else
{
let last = s+2+len as usize;
hasher.update(&self.buffer[s..last]);
cur.set_position(last as u64);
}
}
if let Some(cr) = crc32
{
return Ok(cr == hasher.finalize());
}
else
{
return_error!(ArgumentEinval, "no CRC TLV found!");
}
}
}
#[derive(Clone, Debug)]
pub enum ProxyV2Dummy {}
impl fmt::Display for ProxyV2Dummy
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "DUMMY external reader")
}
}
impl PP2TlvRestore for ProxyV2Dummy
{
fn restore(_tlv_type: u8, _cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized
{
return_error!(ArgumentEinval, "assertion trap, DUMMY external decoder");
}
fn is_in_range(_tlv_type: u8, _tlv_parent_type: Option<u8>) -> bool
{
return false;
}
fn contains_subtype(&self) -> bool
{
return false;
}
}
impl PP2TlvRestore for PP2Tlvs
{
fn contains_subtype(&self) -> bool
{
return self.contains_subtype();
}
fn is_in_range(tlv_type: u8, tlv_parent_type: Option<u8>) -> bool
{
if let Some(p_tlv) = tlv_parent_type
{
if p_tlv == Self::TYPE_SSL
{
return Self::TLV_TYPE_SSL_SUB_RANGE.iter().any(|tlv| tlv.contains(&tlv_type));
}
else
{
return false;
}
}
return Self::TLV_TYPE_MAIN_RANGES.iter().any(|tlv| tlv.contains(&tlv_type));
}
fn restore(tlv_type: u8, cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized
{
let tlv_len = cur.get_ref().len();
match tlv_type
{
Self::TYPE_ALPN =>
{
let mut alpns: Vec<Vec<u8>> = Vec::with_capacity(2);
while let Some(alpn_len) = cur.read_u16::<BigEndian>().ok()
{
let mut alpn: Vec<u8> = vec![0_u8; alpn_len as usize];
cur.read_exact(&mut alpn).map_err(common::map_io_err)?;
alpns.push(alpn);
}
return Ok(Self::TypeAlpn(alpns));
},
Self::TYPE_AUTHORITY =>
{
let mut authority: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut authority).map_err(common::map_io_err)?;
return Ok(
Self::TypeAuthority(
String::from_utf8(authority)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_AUTHORITY restore error: '{}'", e)
)?
)
);
},
Self::TYPE_CRC32C =>
{
let crc = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
return Ok(Self::TypeCrc32c(crc));
},
Self::TYPE_NOOP =>
{
return Ok(Self::TypeNoop);
},
Self::TYPE_UNIQID =>
{
let mut authority: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut authority).map_err(common::map_io_err)?;
return Ok(
Self::TypeUniqId(authority)
);
},
Self::TYPE_SSL =>
{
let client_bits = cur.read_u8().map_err(common::map_io_err)?;
let client =
PP2TlvClient::from_bits(client_bits)
.ok_or_else(|| map_error!(ProtocolUnknownData, "TLV TYPE_SSL unknown client bits: {}", client_bits))?;
let verify = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
return Ok(
Self::TypeSsl{ client: client, verify: verify }
);
},
Self::TYPE_SUBTYPE_SSL_VERSION =>
{
let mut ssl_version: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut ssl_version).map_err(common::map_io_err)?;
let ssl_version_str =
String::from_utf8(ssl_version)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeSubtypeSslVersion(Cow::Owned(ssl_version_str))
);
},
Self::TYPE_SUBTYPE_SSL_CN =>
{
let mut ssl_cn: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut ssl_cn).map_err(common::map_io_err)?;
let ssl_cn =
String::from_utf8(ssl_cn)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeSubtypeSslCn(Cow::Owned(ssl_cn))
);
},
Self::TYPE_SUBTYPE_SSL_CIPHER =>
{
let mut ssl_cipher: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut ssl_cipher).map_err(common::map_io_err)?;
let ssl_cipher =
String::from_utf8(ssl_cipher)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeSubtypeSslCipher(Cow::Owned(ssl_cipher))
);
},
Self::TYPE_SUBTYPE_SSL_SIGALG =>
{
let mut ssl_sigalg: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut ssl_sigalg).map_err(common::map_io_err)?;
let ssl_sigalg =
String::from_utf8(ssl_sigalg)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeSubtypeSslSigAlg(Cow::Owned(ssl_sigalg))
);
},
Self::TYPE_SUBTYPE_SSL_KEYALG =>
{
let mut ssl_keyalg: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut ssl_keyalg).map_err(common::map_io_err)?;
let ssl_keyalg =
String::from_utf8(ssl_keyalg)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeSubtypeSslKeyAlg(Cow::Owned(ssl_keyalg))
);
},
Self::TYPE_NETNS =>
{
let mut netns: Vec<u8> = vec![0_u8; tlv_len];
cur.read_exact(&mut netns).map_err(common::map_io_err)?;
let netns =
String::from_utf8(netns)
.map_err(|e|
map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
)?;
return Ok(
Self::TypeNetNs(netns)
);
},
_ =>
return_error!(ProtocolUnknownData, "unknown TLV type: {}", tlv_type)
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ProxyV2TlvSource<EXT: PP2TlvRestore>
{
Internal(PP2Tlvs),
External(EXT),
Error(HaProxErr),
}
impl<EXT: PP2TlvRestore> ProxyV2TlvSource<EXT>
{
fn new_internal(pp2: HaProxRes<PP2Tlvs>) -> Self
{
return
pp2.map_or_else(|e| Self::Error(e), |f| Self::Internal(f));
}
fn new_external(pp2: HaProxRes<EXT>) -> Self
{
return
pp2.map_or_else(|e| Self::Error(e), |f| Self::External(f));
}
fn new_error(err: HaProxErr) -> Self
{
return Self::Error(err);
}
fn new_io_error(err: std::io::Error) -> Self
{
return Self::Error(map_error!(IoError, "while reading TLV, error: {}", err));
}
pub
fn take_internal(self) -> Option<PP2Tlvs>
{
let Self::Internal(s) = self else {return None};
return Some(s);
}
pub
fn take_external(self) -> Option<EXT>
{
let Self::External(s) = self else {return None};
return Some(s);
}
pub
fn contains_subtype(&self) -> bool
{
match self
{
Self::Internal(i) =>
return i.contains_subtype(),
Self::External(e) =>
return e.contains_subtype(),
_ =>
return false
}
}
}
#[derive(Debug)]
struct ProxyV2TlvIterTlv<'iter>
{
cur: Cursor<&'iter [u8]>,
parent_tlv_idx: Option<u8>,
}
#[derive(Debug)]
pub struct ProxyV2TlvIter<'iter, EXT>
{
curs: Vec<ProxyV2TlvIterTlv<'iter>>,
_p: PhantomData<EXT>
}
impl<'iter, EXT: PP2TlvRestore> ProxyV2TlvIter<'iter, EXT>
{
fn get_last_cur(&self) -> &Cursor<&'iter [u8]>
{
return &self.curs.last().unwrap().cur;
}
fn get_last_mut_cur(&mut self) -> &mut Cursor<&'iter [u8]>
{
return &mut self.curs.last_mut().unwrap().cur;
}
fn get_parent_tlv(&self) -> Option<u8>
{
return self.curs.last().unwrap().parent_tlv_idx;
}
}
impl<'iter, EXT: PP2TlvRestore> Iterator for ProxyV2TlvIter<'iter, EXT>
{
type Item = ProxyV2TlvSource<EXT>;
fn next(&mut self) -> Option<Self::Item>
{
if self.get_last_cur().get_ref().len() <= self.get_last_cur().position() as usize
{
if self.curs.len() == 1
{
return None;
}
else
{
let _ = self.curs.pop();
return self.next();
}
}
let tlv_type =
match self.get_last_mut_cur().read_u8()
{
Ok(r) => r,
Err(e) =>
return Some(ProxyV2TlvSource::new_io_error(e)),
};
let tlv_len =
match self.get_last_mut_cur().read_u16::<BigEndian>()
{
Ok(r) => r,
Err(e) =>
return Some(ProxyV2TlvSource::new_io_error(e)),
};
let tlv_range =
self.get_last_cur().position() as usize .. (self.get_last_cur().position()+ tlv_len as u64) as usize;
let mut cur =
Cursor::new(&self.get_last_cur().get_ref()[tlv_range]);
let next_item =
if PP2Tlvs::is_in_range(tlv_type, self.get_parent_tlv()) == true
{
ProxyV2TlvSource::new_internal(
PP2Tlvs::restore(tlv_type, &mut cur)
)
}
else if EXT::is_in_range(tlv_type, self.get_parent_tlv()) == true
{
ProxyV2TlvSource::new_external(
EXT::restore(tlv_type, &mut cur)
)
}
else
{
ProxyV2TlvSource::new_error(
map_error!(ProtocolUnknownData, "TLV tpye: '{}' out of int/ext ranges", tlv_type)
)
};
let new_pos = self.get_last_cur().position()+ tlv_len as u64;
self.get_last_mut_cur().set_position(new_pos);
if next_item.contains_subtype() == true
{
self.curs.push(
ProxyV2TlvIterTlv
{
cur: cur,
parent_tlv_idx: Some(tlv_type),
}
);
}
return Some(next_item);
}
}
#[cfg(test)]
mod tests
{
use std::{fmt, io::Cursor};
use byteorder::{BigEndian, ReadBytesExt};
use crate::{common, error::HaProxRes, protocol::{protocol::{HdrV2Command, PP2TlvClient, PP2Tlvs, ProtocolVersion, ProxyTransportFam, ProxyV2Addr, ProxyV2AddrType, PP2_TYPE_MIN_CUSTOM}, protocol_raw, PP2TlvDump, PP2TlvRestore}, return_error};
use super::ProxyV2Parser;
#[test]
fn test_0()
{
let pkt_ssl =
b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x2a\
\x7f\x00\x00\x01\x7f\x00\x00\x43\x9d\xd2\x2e\x6b\x20\x00\x1b\x07\
\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\x22\x00\
\x09\x6d\x71\x74\x74\x75\x73\x65\x72\x31";
let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
assert_eq!(dec.get_transport().is_ok(), true);
assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
assert_eq!(dec.get_address_family().is_ok(), true);
assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
let addr = dec.get_address().unwrap();
assert_eq!(addr.is_some(), true);
let addr = addr.unwrap();
let maddr = ProxyV2Addr::try_from(("127.0.0.1:40402", "127.0.0.67:11883")).unwrap();
assert_eq!(addr, maddr);
let tlv_iter = dec.get_tlvs_iter();
assert_eq!(tlv_iter.is_some(), true);
let mut tlv_iter = tlv_iter.unwrap();
let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
assert_eq!(client, PP2TlvClient::all());
assert_eq!(verify, 0);
let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
assert_eq!(ssl_version, "TLSv1.2");
let type_ssl_cn = tlv_iter.next().unwrap().take_internal().unwrap();
assert_eq!(type_ssl_cn.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_CN);
let PP2Tlvs::TypeSubtypeSslCn(ssl_cn) = type_ssl_cn else { panic!("wrong") };
assert_eq!(ssl_cn, "mqttuser1");
}
#[test]
fn test_1()
{
#[derive(Clone, Debug)]
pub enum ProxyV2Dummy2
{
SomeTlvName(u32, u32),
OtherTlv,
}
impl fmt::Display for ProxyV2Dummy2
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
write!(f, "DUMMY external reader")
}
}
impl PP2TlvRestore for ProxyV2Dummy2
{
fn restore(tlv_type: u8, cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized
{
match tlv_type
{
0xE0 =>
{
let arg0 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
let arg1 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
return Ok(Self::SomeTlvName(arg0, arg1));
},
_ =>
return_error!(ProtocolUnknownData, "unknown tlv_type: {}", tlv_type)
}
}
fn is_in_range(tlv_type: u8, _tlv_parent_type: Option<u8>) -> bool
{
return tlv_type == PP2_TYPE_MIN_CUSTOM;
}
fn contains_subtype(&self) -> bool
{
return false;
}
}
impl PP2TlvDump for ProxyV2Dummy2
{
fn get_type(&self) -> u8
{
let Self::SomeTlvName(..) = self else { panic!("wrong") };
return 0xE0;
}
fn dump(&self, _cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()>
{
todo!()
}
}
let pkt_ssl =
b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x29\
\x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\xE0\x00\
\x08\x01\x02\x03\x04\x05\x06\x07\x08";
let dec = ProxyV2Parser::<ProxyV2Dummy2>::try_from_slice_custom(pkt_ssl.as_slice()).unwrap();
assert_eq!(dec.get_transport().is_ok(), true);
assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
assert_eq!(dec.get_address_family().is_ok(), true);
assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
let addr = dec.get_address().unwrap();
assert_eq!(addr.is_some(), true);
let addr = addr.unwrap();
let maddr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
assert_eq!(addr, maddr);
let tlv_iter = dec.get_tlvs_iter();
assert_eq!(tlv_iter.is_some(), true);
let mut tlv_iter = tlv_iter.unwrap();
let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
assert_eq!(client, PP2TlvClient::PP2_CLIENT_SSL);
assert_eq!(verify, 0);
let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
assert_eq!(ssl_version, "TLSv1.2");
let ext_type_e0 = tlv_iter.next().unwrap().take_external().unwrap();
assert_eq!(ext_type_e0.get_type(), 0xE0);
let ProxyV2Dummy2::SomeTlvName(arg0, arg1) = ext_type_e0 else {panic!("wrong")};
assert_eq!(arg0, 0x01020304);
assert_eq!(arg1, 0x05060708);
}
#[test]
fn test_3()
{
let pkt_ssl =
b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x0c\
\x7f\x00\x00\x01\x7f\x00\x00\x01\x8c\x76\x00\x50";
let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
assert_eq!(dec.get_transport().is_ok(), true);
assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
assert_eq!(dec.get_address_family().is_ok(), true);
assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
let addr = dec.get_address().unwrap();
assert_eq!(addr.is_some(), true);
let addr = addr.unwrap();
let maddr = ProxyV2Addr::try_from(("127.0.0.1:35958", "127.0.0.1:80")).unwrap();
assert_eq!(addr, maddr);
let tlv_iter = dec.get_tlvs_iter();
assert_eq!(tlv_iter.is_some(), false);
}
}