1use std::borrow::Cow;
14use std::ffi::CStr;
15use std::fmt;
16use std::io::{Cursor, Read, Write};
17use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
18use std::ops::RangeInclusive;
19use std::os::unix::ffi::OsStrExt;
20use std::os::unix::net;
21use std::str::FromStr;
22
23use bitflags::bitflags;
24use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
25
26use crate::{common, map_error, return_error};
27use crate::error::{HaProxErr, HaProxRes};
28
29use super::protocol_raw::{self, HEADER_UNIX_ADDR_LEN};
30
31pub const PP2_TYPE_MIN_CUSTOM: u8 = 0xE0;
39
40pub const PP2_TYPE_MAX_CUSTOM: u8 = 0xEF;
43
44pub const PP2_TYPE_MIN_EXPERIMENT: u8 = 0xF0;
51
52pub const PP2_TYPE_MAX_EXPERIMENT: u8 = 0xF7;
55
56pub const PP2_TYPE_MIN_FUTURE: u8 = 0xF8;
62
63pub const PP2_TYPE_MAX_FUTURE: u8 = 0xFF;
65
66
67pub const MAX_UNIQ_ID_LEN_BYTES: u16 = 128;
70
71pub const TLV_HEADER_LEN: u16 = 3;
73
74
75
76#[repr(u8)]
81#[derive(Clone, Copy, PartialEq, Eq, Debug)]
82pub enum HdrV2Command
83{
84 LOCAL = 0,
85 PROXY = 1,
86 UNKNOWN,
87}
88
89impl From<HdrV2Command> for u8
90{
91 fn from(value: HdrV2Command) -> Self
92 {
93 if value == HdrV2Command::UNKNOWN
94 {
95 panic!("can not encode the unknown command");
96 }
97
98 return value as u8;
99 }
100}
101
102impl HdrV2Command
103{
104 pub(crate)
105 fn decode(raw: u8) -> Self
106 {
107 match raw & protocol_raw::ProxyHdrV2::COMMAND_MASK
108 {
109 r if r == HdrV2Command::LOCAL.into() => return Self::LOCAL,
110 r if r == HdrV2Command::PROXY.into() => return Self::PROXY,
111 _ => return Self::UNKNOWN,
112 }
113 }
114}
115
116#[repr(u8)]
118#[derive(Clone, Copy, PartialEq, Eq, Debug)]
119pub enum ProtocolVersion
120{
121 V1 = 1,
122 V2 = 2,
123 UNKNOWN,
124}
125
126impl From<ProtocolVersion> for u8
127{
128 fn from(value: ProtocolVersion) -> Self
129 {
130 if value == ProtocolVersion::UNKNOWN
131 {
132 panic!("can not encode the unknown version");
133 }
134
135 return (value as u8) << 4;
136 }
137}
138
139impl ProtocolVersion
140{
141 pub(crate)
142 fn decode(raw: u8) -> Self
143 {
144 match raw >> 4
145 {
146 1 => return Self::V1,
147 2 => return Self::V2,
148 _ => return Self::UNKNOWN,
149 }
150 }
151}
152
153bitflags! {
154 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
156 pub struct PP2TlvClient: u8
157 {
158 const PP2_CLIENT_SSL = 0x01;
160
161 const PP2_CLIENT_CERT_CONN = 0x02;
163
164 const PP2_CLIENT_CERT_SESS = 0x04;
167 }
168}
169
170#[derive(Clone, Debug, PartialEq, Eq)]
172pub struct PP2TlvsTypeSsl
173{
174 pub(crate) client: PP2TlvClient,
176
177 pub(crate) verify: u32,
180
181 pub(crate) sub_tlv: Vec<PP2Tlvs>
183}
184
185impl fmt::Display for PP2TlvsTypeSsl
186{
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
188 {
189 write!(f, "CLIENT: {:?}, VERIFY: {}, TLVs: {}",
190 self.client, self.verify,
191 self.sub_tlv.iter().map(|t| t.to_string()).collect::<Vec<String>>().join(", "))
192 }
193}
194
195#[repr(u8)]
206#[derive(Clone, Debug, PartialEq, Eq)]
207pub enum PP2Tlvs
208{
209 TypeAlpn(Vec<Vec<u8>>) = Self::TYPE_ALPN,
211
212 TypeAuthority(String) = Self::TYPE_AUTHORITY,
215
216 TypeCrc32c(u32) = Self::TYPE_CRC32C,
218
219 TypeNoop = Self::TYPE_NOOP,
223
224 TypeUniqId(Vec<u8>) = Self::TYPE_UNIQID,
227
228 TypeSsl
230 {
231 client: PP2TlvClient,
232 verify: u32,
233 } = Self::TYPE_SSL,
234
235 TypeSubtypeSslVersion(Cow<'static, str>) = Self::TYPE_SUBTYPE_SSL_VERSION,
237
238 TypeSubtypeSslCn(Cow<'static, str>) = Self::TYPE_SUBTYPE_SSL_CN,
242
243 TypeSubtypeSslCipher(Cow<'static, str>) = Self::TYPE_SUBTYPE_SSL_CIPHER,
245
246 TypeSubtypeSslSigAlg(Cow<'static, str>) = Self::TYPE_SUBTYPE_SSL_SIGALG,
250
251 TypeSubtypeSslKeyAlg(Cow<'static, str>) = Self::TYPE_SUBTYPE_SSL_KEYALG,
255
256 TypeNetNs(String) = Self::TYPE_NETNS,
258}
259
260impl fmt::Display for PP2Tlvs
261{
262 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
263 {
264 let id : u8= self.into();
265
266 match self
267 {
268 PP2Tlvs::TypeAlpn(alpns) =>
269 {
270 let alpns_dec =
271 alpns
272 .iter()
273 .map(
274 |a|
275 std
276 ::str
277 ::from_utf8(a)
278 .map_err(|e| map_error!(MalformedData, "{}", e))
279 )
280 .collect::<HaProxRes<Vec<&str>>>()
281 .map_err(|_e| fmt::Error)?
282 .join(",");
283
284 write!(f, "ALPNS({:02X}): {}", id, alpns_dec)
285 },
286 PP2Tlvs::TypeAuthority(sni) =>
287 write!(f, "SNI({:02X}): {}", id, sni),
288 PP2Tlvs::TypeCrc32c(crc) =>
289 write!(f, "CRC({:02X}): {}", id, crc),
290 PP2Tlvs::TypeNoop =>
291 write!(f, "NOOP({:02X})", id),
292 PP2Tlvs::TypeUniqId(items) =>
293 write!(f, "UNIQID({:02X}): {:02X?}", id, items),
294 PP2Tlvs::TypeSsl{client, verify} =>
295 write!(f, "SSL({:02X}): client: {:?}, verify: {}", id, client, verify),
296 PP2Tlvs::TypeSubtypeSslVersion(ver) =>
297 write!(f, "SSL VERSION({:02X}): {}", id, ver),
298 PP2Tlvs::TypeSubtypeSslCn(cn) =>
299 write!(f, "SSL CN({:02X}): {}", id, cn),
300 PP2Tlvs::TypeSubtypeSslCipher(c) =>
301 write!(f, "SSL CIPHER({:02X}): {}", id, c),
302 PP2Tlvs::TypeSubtypeSslSigAlg(sa) =>
303 write!(f, "SSL SIGALG({:02X}): {}", id, sa),
304 PP2Tlvs::TypeSubtypeSslKeyAlg(ka) =>
305 write!(f, "SSL KEYALG({:02X}): {}", id, ka),
306 PP2Tlvs::TypeNetNs(ns) =>
307 write!(f, "NETNS({:02X}): {}", id, ns),
308 }
309 }
310}
311
312impl From<PP2Tlvs> for u8
313{
314 fn from(value: PP2Tlvs) -> Self
315 {
316 return (&value).into();
317 }
318}
319
320impl From<&PP2Tlvs> for u8
321{
322 fn from(value: &PP2Tlvs) -> Self
323 {
324 return unsafe { *<*const _>::from(value).cast::<Self>() };
325 }
326}
327
328
329
330impl PP2Tlvs
331{
332 pub const TLV_TYPE_MAIN_RANGES: &'static [RangeInclusive<u8>] =
334 &[
335 Self::TYPE_ALPN..=Self::TYPE_SSL,
336 Self::TYPE_NETNS ..= Self::TYPE_NETNS
337 ];
338
339 pub const TLV_TYPE_SSL_SUB_RANGE: &'static [RangeInclusive<u8>] =
341 &[Self::TYPE_SUBTYPE_SSL_VERSION ..= Self::TYPE_SUBTYPE_SSL_KEYALG];
342
343 pub const TYPE_ALPN: u8 = 0x01;
344
345 pub const TYPE_AUTHORITY: u8 = 0x02;
346
347 pub const TYPE_CRC32C: u8 = 0x03;
348
349 pub const TYPE_NOOP: u8 = 0x04;
350
351 pub const TYPE_UNIQID: u8 = 0x05;
352
353 pub const TYPE_SSL: u8 = 0x20;
354
355 pub const TYPE_SUBTYPE_SSL_VERSION: u8 = 0x21;
356
357 pub const TYPE_SUBTYPE_SSL_CN: u8 = 0x22;
358
359 pub const TYPE_SUBTYPE_SSL_CIPHER: u8 = 0x23;
360
361 pub const TYPE_SUBTYPE_SSL_SIGALG: u8 = 0x24;
362
363 pub const TYPE_SUBTYPE_SSL_KEYALG: u8 = 0x25;
364
365 pub const TYPE_NETNS: u8 = 0x30;
366
367 pub
368 fn contains_subtype(&self) -> bool
369 {
370 let Self::TypeSsl{ .. } = self else { return false };
371
372 return true;
373 }
374
375 pub
376 fn conntains_subtype_discr(discr: u8) -> bool
377 {
378 return discr == Self::TYPE_SSL;
379 }
380}
381
382#[repr(u8)]
386#[derive(Clone, Copy, Debug, PartialEq, Eq)]
387pub enum ProxyV2AddrType
388{
389 AfUnspec = 0x00,
396
397 AfInet = 0x01,
402
403 AfInet6 = 0x02,
408
409 AfUnix = 0x03,
413}
414
415impl From<ProxyV2AddrType> for u8
416{
417 fn from(value: ProxyV2AddrType) -> Self
418 {
419 return value as u8;
420 }
421}
422
423impl ProxyV2AddrType
424{
425 pub const DEF_IPV4_ADDR_LEN: u16 = 12;
426 pub const DEF_IPV6_ADDR_LEN: u16 = 36;
427 pub const DEF_UNIX_ADDR_LEN: u16 = 216;
428
429 pub(crate)
430 fn decode(raw: u8) -> HaProxRes<Self>
431 {
432 match raw >> 4
433 {
434 r if r == ProxyV2AddrType::AfUnspec.into() =>
435 return Ok(Self::AfUnspec),
436 r if r == ProxyV2AddrType::AfInet.into() =>
437 return Ok(Self::AfInet),
438 r if r == ProxyV2AddrType::AfInet6.into() =>
439 return Ok(Self::AfInet6),
440 r if r == ProxyV2AddrType::AfUnix.into() =>
441 return Ok(Self::AfUnix),
442 r =>
443 return_error!(ProtocolUnknownData, "can not decode address type: '{:02X}'", r),
444 }
445 }
446
447 pub
448 fn get_size_by_addr_family(&self) -> Option<u16>
449 {
450 match self
451 {
452 Self::AfUnspec =>
453 return None,
454 Self::AfInet =>
455 return Some(Self::DEF_IPV4_ADDR_LEN),
456 Self::AfInet6 =>
457 return Some(Self::DEF_IPV6_ADDR_LEN),
458 Self::AfUnix =>
459 return Some(Self::DEF_UNIX_ADDR_LEN),
460 }
461 }
462}
463
464
465#[derive(Clone, Debug)]
475pub enum ProxyV2Addr
476{
477 Ip
479 {
480 src: SocketAddr,
481 dst: SocketAddr,
482 },
483
484 Unix
486 {
487 src: net::SocketAddr,
488 dst: net::SocketAddr,
489 }
490}
491
492impl Eq for ProxyV2Addr {}
493
494impl PartialEq for ProxyV2Addr
495{
496 fn eq(&self, other: &Self) -> bool
497 {
498 match (self, other)
499 {
500 (
501 Self::Ip { src: l_src, dst: l_dst },
502 Self::Ip { src: r_src, dst: r_dst }
503 ) =>
504 l_src == r_src && l_dst == r_dst,
505
506 (
507 Self::Unix { src: l_src, dst: l_dst },
508 Self::Unix { src: r_src, dst: r_dst }
509 ) =>
510 l_src.as_pathname() == r_src.as_pathname() && l_dst.as_pathname() == r_dst.as_pathname(),
511 _ => false,
512 }
513 }
514}
515
516impl fmt::Display for ProxyV2Addr
517{
518 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
519 {
520 match self
521 {
522 ProxyV2Addr::Ip{ src, dst } =>
523 write!(f, "SRC: {}, DST: {}", src, dst),
524 ProxyV2Addr::Unix{ src, dst } =>
525 write!(f, "SRC: {:?}, DST: {:?}", src, dst)
526 }
527 }
528}
529
530impl TryFrom<(IpAddr, u16, IpAddr, u16)> for ProxyV2Addr
531{
532 type Error = HaProxErr;
533
534 fn try_from(value: (IpAddr, u16, IpAddr, u16)) -> Result<Self, Self::Error>
544 {
545 let src = SocketAddr::new(value.0, value.1);
546 let dst = SocketAddr::new(value.2, value.3);
547
548 return Ok(Self::Ip{ src: src, dst: dst });
549 }
550}
551
552impl TryFrom<(SocketAddr, SocketAddr)> for ProxyV2Addr
553{
554 type Error = HaProxErr;
555
556 fn try_from(value: (SocketAddr, SocketAddr)) -> Result<Self, Self::Error>
562 {
563 return Ok(Self::Ip{ src: value.0, dst: value.1 });
564 }
565}
566
567impl TryFrom<(net::SocketAddr, net::SocketAddr)> for ProxyV2Addr
569{
570 type Error = HaProxErr;
571
572 fn try_from(value: (net::SocketAddr, net::SocketAddr)) -> Result<Self, Self::Error>
578 {
579 return Ok(Self::Unix{ src: value.0, dst: value.1 });
580 }
581}
582
583impl TryFrom<(&str, &str)> for ProxyV2Addr
585{
586 type Error = HaProxErr;
587
588 fn try_from(value: (&str, &str)) -> Result<Self, Self::Error>
594 {
595 if let Ok(src) = SocketAddr::from_str(value.0)
596 {
597 let Ok(dst) = SocketAddr::from_str(value.1)
598 else
599 {
600 return_error!(ArgumentEinval, "can not convert '{}' to SocketAddr",
601 common::sanitize_str_unicode(value.1));
602 };
603
604 return Ok(Self::Ip{ src: src, dst: dst });
605 }
606 else if let Ok(src) = net::SocketAddr::from_pathname(value.0)
607 {
608 let Ok(dst) = net::SocketAddr::from_pathname(value.1)
609 else
610 {
611 return_error!(ArgumentEinval, "can not convert '{}' to net::SocketAddr",
612 common::sanitize_str_unicode(value.1));
613 };
614
615 return Ok(Self::Unix{ src: src, dst: dst });
616 }
617 else
618 {
619 return_error!(ArgumentEinval, "can not convert '{}' to either SocketAddr or net::SocketAddr",
620 common::sanitize_str_unicode(value.0));
621 }
622 }
623}
624
625impl ProxyV2Addr
626{
627 #[inline]
630 pub
631 fn get_len(&self) -> u16
632 {
633 return self.as_addr_family().get_size_by_addr_family().unwrap();
634 }
635
636 #[inline]
638 pub
639 fn as_addr_family(&self) -> ProxyV2AddrType
640 {
641 match self
642 {
643 ProxyV2Addr::Ip{ src, .. } =>
644 {
645 if src.is_ipv4() == true
646 {
647 return ProxyV2AddrType::AfInet;
648 }
649 else
650 {
651 return ProxyV2AddrType::AfInet6;
652 }
653 }
654 ProxyV2Addr::Unix{ .. } =>
655 return ProxyV2AddrType::AfUnix
656 }
657 }
658
659 pub
668 fn read(addr_fam: ProxyV2AddrType, cur: &mut Cursor<&[u8]>) -> HaProxRes<Option<Self>>
669 {
670 match addr_fam
671 {
672 ProxyV2AddrType::AfUnspec => Ok(None),
673 ProxyV2AddrType::AfInet =>
674 {
675 let src = IpAddr::from(Ipv4Addr::from_bits(cur.read_u32::<BigEndian>().map_err(common::map_io_err)?));
676 let dst = IpAddr::from(Ipv4Addr::from_bits(cur.read_u32::<BigEndian>().map_err(common::map_io_err)?));
677 let src_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
678 let dst_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
679
680 return Ok(Some(Self::try_from((src, src_port, dst, dst_port))?));
681 },
682 ProxyV2AddrType::AfInet6 =>
683 {
684 let src = IpAddr::from(Ipv6Addr::from_bits(cur.read_u128::<BigEndian>().map_err(common::map_io_err)?));
685 let dst = IpAddr::from(Ipv6Addr::from_bits(cur.read_u128::<BigEndian>().map_err(common::map_io_err)?));
686 let src_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
687 let dst_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
688
689 return Ok(Some(Self::try_from((src, src_port, dst, dst_port))?));
690 },
691 ProxyV2AddrType::AfUnix =>
692 {
693 let mut n_src: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
694 cur.read(&mut n_src).map_err(common::map_io_err)?;
695
696 let mut n_dst: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
697 cur.read(&mut n_dst).map_err(common::map_io_err)?;
698
699 let src_s =
700 net::SocketAddr::from_pathname(
701 CStr::from_bytes_until_nul(&n_src)
702 .map_err(|e|
703 map_error!(MalformedData, "cannot read unix path, error: {}", e)
704 )?
705 .to_str()
706 .map_err(|e|
707 map_error!(MalformedData, "cannot read unix path, error: {}", e)
708 )?
709 )
710 .map_err(|e|
711 map_error!(MalformedData, "cannot read unix path, error: {}", e)
712 )?;
713
714 let dst_s =
715 net::SocketAddr::from_pathname(
716 CStr::from_bytes_until_nul(&n_dst)
717 .map_err(|e|
718 map_error!(MalformedData, "cannot read unix path, error: {}", e)
719 )?
720 .to_str()
721 .map_err(|e|
722 map_error!(MalformedData, "cannot read unix path, error: {}", e)
723 )?
724 )
725 .map_err(|e|
726 map_error!(MalformedData, "cannot read unix path, error: {}", e)
727 )?;
728
729 return Ok(Some(Self::try_from((src_s, dst_s))?));
730 },
731 }
732 }
733
734 pub
738 fn write(&self, cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()>
739 {
740 match self
741 {
742 ProxyV2Addr::Ip{ src, dst } =>
743 {
744 match src.ip()
745 {
746 IpAddr::V4(ipv4_addr) =>
747 cur.write_u32::<BigEndian>(ipv4_addr.to_bits()).map_err(common::map_io_err)?,
748 IpAddr::V6(ipv6_addr) =>
749 cur.write_u128::<BigEndian>(ipv6_addr.to_bits()).map_err(common::map_io_err)?,
750 }
751
752 match dst.ip()
753 {
754 IpAddr::V4(ipv4_addr) =>
755 cur.write_u32::<BigEndian>(ipv4_addr.to_bits()).map_err(common::map_io_err)?,
756 IpAddr::V6(ipv6_addr) =>
757 cur.write_u128::<BigEndian>(ipv6_addr.to_bits()).map_err(common::map_io_err)?,
758 }
759
760 cur.write_u16::<BigEndian>(src.port()).map_err(common::map_io_err)?;
761 cur.write_u16::<BigEndian>(dst.port()).map_err(common::map_io_err)?;
762 },
763 ProxyV2Addr::Unix { src, dst } =>
764 {
765 let src_p =
766 src.as_pathname().ok_or_else(|| map_error!(ArgumentEinval, "UNIX src socket addr is not path"))?;
767 let dst_p =
768 dst.as_pathname().ok_or_else(|| map_error!(ArgumentEinval, "UNIX src socket addr is not path"))?;
769
770 let src_b = src_p.as_os_str().as_bytes();
771 let dst_b = dst_p.as_os_str().as_bytes();
772
773 if src_b.len() > HEADER_UNIX_ADDR_LEN
774 {
775 return_error!(ArgumentEinval, "socket path: '{}' longer than: '{}'",
776 src_p.display(), HEADER_UNIX_ADDR_LEN);
777 }
778 else if dst_b.len() > HEADER_UNIX_ADDR_LEN
779 {
780 return_error!(ArgumentEinval, "socket path: '{}' longer than: '{}'",
781 dst_p.display(), HEADER_UNIX_ADDR_LEN);
782 }
783
784
785 let mut n_src: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
786 n_src[0..src_b.len()].copy_from_slice(src_b);
787
788 cur.write_all(&n_src).map_err(common::map_io_err)?;
789
790 let mut n_dst: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
791 n_dst[0..dst_b.len()].copy_from_slice(dst_b);
792
793 cur.write_all(&n_dst).map_err(common::map_io_err)?;
794 }
795 }
796
797 return Ok(());
798 }
799}
800
801#[repr(u8)]
805#[derive(Clone, Debug, PartialEq, Eq)]
806pub enum ProxyTransportFam
807{
808 UNSPEC = 0x00,
814
815 STREAM,
820
821 DGRAM,
826}
827
828impl fmt::Display for ProxyTransportFam
829{
830 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
831 {
832 match self
833 {
834 Self::UNSPEC => write!(f, "UNSPEC"),
835 Self::STREAM => write!(f, "STREAM"),
836 Self::DGRAM => write!(f, "DGRAM"),
837 }
838 }
839}
840
841impl From<ProxyTransportFam> for u8
842{
843 fn from(value: ProxyTransportFam) -> Self
844 {
845 return value as u8;
846 }
847}
848
849impl From<&ProxyTransportFam> for u8
850{
851 fn from(value: &ProxyTransportFam) -> Self
852 {
853 return unsafe { *<*const _>::from(value).cast::<Self>() };
854 }
855}
856
857impl ProxyTransportFam
858{
859 pub(crate)
860 fn decode(value: u8) -> HaProxRes<Self>
861 {
862 match value & protocol_raw::ProxyHdrV2::TRANSPT_MASK
863 {
864 v if ProxyTransportFam::UNSPEC as u8 == v =>
865 return Ok(Self::UNSPEC),
866 v if ProxyTransportFam::STREAM as u8 == v =>
867 return Ok(Self::STREAM),
868 v if ProxyTransportFam::DGRAM as u8 == v =>
869 return Ok(Self::DGRAM),
870 _ =>
871 return_error!(ProtocolUnknownData, "unknown transport {:02X}", value)
872 }
873 }
874}
875
876#[cfg(test)]
877mod tests
878{
879 use core::fmt;
880 use std::{slice, time::Instant};
881
882 use crate::protocol::{protocol::{PP2TlvClient, ProxyTransportFam, ProxyV2Addr}, protocol_composer::{HdrV2OpLocal, HdrV2OpProxy, ProxyHdrV2}, protocol_raw::{self, HEADER_MAGIC_V2, HEADER_MAGINC_LEN}, PP2TlvUniqId};
883 #[test]
884 fn test_hdr1()
885 {
886
887 for _ in 0..10
888 {
889 let s = Instant::now();
890 let _local = ProxyHdrV2::<HdrV2OpLocal>::new();
891
892 let e = s.elapsed();
893
894 println!("{:?}", e);
895 }
896
897 let buf = ProxyHdrV2::<HdrV2OpLocal>::new();
898
899
900
901 let mut sign: [u8; HEADER_MAGINC_LEN] = [0_u8; HEADER_MAGINC_LEN];
902 sign.copy_from_slice(HEADER_MAGIC_V2);
903 let ctrl =
904 vec![
905 protocol_raw::ProxyHdrV2
906 {
907 signature: sign,
908 ver_cmd: 0x20,
909 fam: 0,
910 len: 0,
911 address: [],
912 }
913 ];
914
915 println!("{} {}", buf.len(), size_of::<protocol_raw::ProxyHdrV2>());
916 let ctrl_buf = unsafe { slice::from_raw_parts(ctrl.as_ptr() as *const _ as *const u8, size_of::<protocol_raw::ProxyHdrV2>()) };
917
918 assert_eq!(buf.as_slice(), ctrl_buf);
919 }
920
921 #[test]
922 fn test_proxy_compose()
923 {
924 struct UniqIdHolder;
925 impl UniqIdHolder
926 {
927 const ID: &'static [u8] = b"ABCD12345678901234567890";
928 }
929 impl fmt::Display for UniqIdHolder
930 {
931 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
932 {
933 write!(f, "")
934 }
935 }
936 impl PP2TlvUniqId for UniqIdHolder
937 {
938 fn into_bytes(&self) -> Vec<u8>
939 {
940 Self::ID.to_vec()
941 }
942
943 fn get_len(&self) -> u16
944 {
945 Self::ID.len() as u16
946 }
947 }
948 for _ in 0..10
949 {
950 let addr: ProxyV2Addr = ProxyV2Addr::try_from(("127.0.0.1:4567", "127.0.0.1:443")).unwrap();
951 let id = UniqIdHolder;
952
953 let s = Instant::now();
954 let mut proxy =
955 ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
956
957 let mut plts = proxy.set_plts();
958 plts.add_crc32().unwrap();
959 plts.add_authority("www.example.com").unwrap();
960 plts.add_uniq_id(id).unwrap();
961 drop(plts);
962
963 let e = s.elapsed();
964
965 println!("prep: {:?}", e);
966
967 let s = Instant::now();
968 let _buf: Vec<u8> = proxy.try_into().unwrap();
969 let e = s.elapsed();
970
971 println!("{:?}", e);
972 }
973
974 return;
976 }
977
978 #[test]
979 fn test_hdr2()
980 {
981 let addr: ProxyV2Addr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
982
983 let s = Instant::now();
984 let mut proxy =
985 ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
986
987 let plts = proxy.set_plts();
988
989 let mut sub_ssl = plts.add_ssl(PP2TlvClient::PP2_CLIENT_SSL, 0).unwrap();
990
991 sub_ssl.add_ssl_sub_version("TLSv1.2").unwrap();
992
993 sub_ssl.done().unwrap();
994
995
996 let e = s.elapsed();
997
998 println!("prep: {:?}", e);
999
1000 let s = Instant::now();
1001 let buf: Vec<u8> = proxy.try_into().unwrap();
1002 let e = s.elapsed();
1003
1004 println!("{:?}", e);
1005
1006
1007 let reference =
1008 b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x1e\
1009 \x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
1010 \x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32";
1011
1012 assert_eq!(buf.as_slice(), reference.as_slice());
1015 }
1016}