1use std::{borrow::{Cow}, io::{Cursor, Write}, marker::PhantomData, mem::offset_of};
16
17use byteorder::{BigEndian, WriteBytesExt};
18use crc32fast::Hasher;
19
20use crate::{common, protocol_raw, error::{HaProxErr, HaProxRes}, return_error};
21
22use super::
23{
24 protocol::
25 {
26 self,
27 HdrV2Command,
28 PP2TlvClient,
29 PP2Tlvs,
30 ProxyTransportFam,
31 ProxyV2Addr
32 },
33 PP2TlvDump,
34 PP2TlvUniqId,
35 ProxyV2OpCode
36};
37
38#[derive(Clone, Debug)]
55pub struct HdrV2OpLocal;
56
57#[derive(Clone, Debug)]
72pub struct HdrV2OpProxy;
73
74impl ProxyV2OpCode for HdrV2OpLocal
75{
76 const OPCODE: u8 = HdrV2Command::LOCAL as u8;
78}
79
80impl ProxyV2OpCode for HdrV2OpProxy
81{
82 const OPCODE: u8 = HdrV2Command::PROXY as u8;
84}
85
86#[derive(Debug)]
88pub struct TlvSubTypeSsl<'s>
89{
90 start: u64,
92
93 hdr: TlType<'s>,
95
96 constraints: &'static [std::ops::RangeInclusive<u8>]
98}
99
100impl<'s> TlvSubTypeSsl<'s>
101{
102 fn new(mut main_tp: TlType<'s>, constraints: &'static [std::ops::RangeInclusive<u8>],
103 client: PP2TlvClient, verify: u32) -> HaProxRes<Self>
104 {
105 let start = main_tp.hdr.buffer.position();
106
107 main_tp.add_tlv(PP2Tlvs::TypeSsl{client, verify}, None)?;
108
109 return Ok(
110 Self
111 {
112 start: start,
113 hdr: main_tp,
114 constraints: constraints
115 }
116 );
117 }
118
119 #[inline]
120 fn done_int(&mut self) -> HaProxRes<()>
121 {
122 let cur_pos = self.hdr.hdr.buffer.position();
123
124 self.hdr.hdr.buffer.set_position(self.start + offset_of!(protocol_raw::PP2Tlv, length_hi) as u64);self.hdr.hdr.buffer.write_u16::<BigEndian>((cur_pos - self.start - 3) as u16).map_err(common::map_io_err)?;
127
128 self.hdr.hdr.buffer.set_position(cur_pos);
129
130 return Ok(());
131 }
132
133 #[inline]
141 pub
142 fn done(mut self) -> HaProxRes<TlType<'s>>
143 {
144 self.done_int()?;
145
146
147 return Ok(self.hdr);
148 }
149
150 pub
161 fn add_ssl_sub_version(&mut self, ver: impl Into<String>) -> HaProxRes<()>
162 {
163 let version = ver.into();
164
165 common::is_printable_ascii_nowp(&version, "version")?;
166
167 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslVersion(Cow::Owned(version)), Some(self.constraints));
168 }
169
170 pub
181 fn add_ssl_sub_version_borrow<'a>(&mut self, ver: &'a str) -> HaProxRes<()>
182 {
183 common::is_printable_ascii_nowp(ver, "ssl_version")?;
184
185 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslVersion(Cow::Borrowed(ver)), Some(self.constraints));
186 }
187
188 pub
196 fn add_ssl_sub_cn(&mut self, cn: impl Into<String>) -> HaProxRes<()>
197 {
198 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslCn(Cow::Owned(cn.into())), Some(self.constraints));
199 }
200
201 pub
209 fn add_ssl_sub_cn_borrow<'a>(&mut self, cn: &'a str) -> HaProxRes<()>
210 {
211 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslCn(Cow::Borrowed(cn)), Some(self.constraints));
212 }
213
214 pub
225 fn add_ssl_sub_cipher(&mut self, cip: impl Into<String>) -> HaProxRes<()>
226 {
227 let cipher = cip.into();
228
229 common::is_printable_ascii_nowp(&cipher, "ssl_cipher")?;
230
231 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslCipher(Cow::Owned(cipher)), Some(self.constraints));
232 }
233
234 pub
245 fn add_ssl_sub_cipher_borrow<'a>(&mut self, cip: &'a str) -> HaProxRes<()>
246 {
247 common::is_printable_ascii_nowp(cip, "ssl_cipher")?;
248
249 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslCipher(Cow::Borrowed(cip)), Some(self.constraints));
250 }
251
252 pub
265 fn add_ssl_sub_sigalg(&mut self, sigalg: impl Into<String>) -> HaProxRes<()>
266 {
267 let sig_alg = sigalg.into();
268
269 common::is_printable_ascii_nowp(&sig_alg, "sig_alg")?;
270
271 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslSigAlg(Cow::Owned(sig_alg)), Some(self.constraints));
272 }
273
274 pub
287 fn add_ssl_sub_sigalg_borrow<'a>(&mut self, sigalg: &'a str) -> HaProxRes<()>
288 {
289 common::is_printable_ascii_nowp(sigalg, "ssl_sigalg")?;
290
291 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslSigAlg(Cow::Borrowed(sigalg)), Some(self.constraints));
292 }
293
294 pub
307 fn add_ssl_sub_keyalg(&mut self, key: impl Into<String>) -> HaProxRes<()>
308 {
309 let key_alg = key.into();
310
311 common::is_printable_ascii_nowp(&key_alg, "sig_alg")?;
312
313 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslKeyAlg(Cow::Owned(key_alg)), Some(self.constraints));
314 }
315
316 pub
329 fn add_ssl_sub_keyalg_borrow<'a>(&mut self, key: &'a str) -> HaProxRes<()>
330 {
331 common::is_printable_ascii_nowp(key, "ssl_sigalg")?;
332
333 return self.hdr.add_tlv(PP2Tlvs::TypeSubtypeSslKeyAlg(Cow::Borrowed(key)), Some(self.constraints));
334 }
335
336 pub
348 fn add_ssl_group(&mut self, group: impl Into<String>) -> HaProxRes<()>
349 {
350 let group_str = group.into();
351
352 common::is_printable_ascii_nowp(&group_str, "ssl_group")?;
353
354 return self.hdr.add_tlv(PP2Tlvs::TypeSubTypeSslGroup(group_str.into()), Some(self.constraints));
355 }
356
357 pub
369 fn add_ssl_group_group<'a>(&mut self, group: &'a str) -> HaProxRes<()>
370 {
371 common::is_printable_ascii_nowp(group, "ssl_group")?;
372
373 return self.hdr.add_tlv(PP2Tlvs::TypeSubTypeSslGroup(Cow::Borrowed(group)), Some(self.constraints));
374 }
375
376 pub
388 fn add_ssl_sig_scheme(&mut self, sig_schm: impl Into<String>) -> HaProxRes<()>
389 {
390 let sig_schm_str = sig_schm.into();
391
392 common::is_printable_ascii_nowp(&sig_schm_str, "ssl_sig_schm")?;
393
394 return self.hdr.add_tlv(PP2Tlvs::TypeSubTypeSslSigScheme(sig_schm_str.into()), Some(self.constraints));
395 }
396
397 pub
409 fn add_ssl_sig_scheme_borrow<'a>(&mut self, sig_schm: &'a str) -> HaProxRes<()>
410 {
411 common::is_printable_ascii_nowp(sig_schm, "sig_schm")?;
412
413 return self.hdr.add_tlv(PP2Tlvs::TypeSubTypeSslSigScheme(Cow::Borrowed(sig_schm)), Some(self.constraints));
414 }
415}
416
417#[derive(Debug)]
419pub struct TlType<'s>
420{
421 hdr: &'s mut ProxyHdrV2<HdrV2OpProxy>,
423
424 constraints: &'static [std::ops::RangeInclusive<u8>]
426}
427
428impl<'s> TlType<'s>
429{
430 fn new(hdr: &'s mut ProxyHdrV2<HdrV2OpProxy>, constraints: &'static [std::ops::RangeInclusive<u8>]) -> Self
431 {
432 return
433 Self
434 {
435 hdr,
436 constraints
437 };
438 }
439
440 pub
444 fn add_alpn<'a>(&mut self, alpns: impl Iterator<Item = &'a [u8]>) -> HaProxRes<()>
445 {
446 return
447 self
448 .add_tlv(
449 PP2Tlvs::TypeAlpn(
450 alpns
451 .map(|v| Cow::Borrowed(v))
452 .collect::<Vec<Cow<'a, [u8]>>>()
453 .into()
454 ),
455 None
456 );
457 }
458
459 pub
461 fn add_noop(&mut self) -> HaProxRes<()>
462 {
463 return self.add_tlv(PP2Tlvs::TypeNoop, None);
464 }
465
466 pub
475 fn add_netns(&mut self, ns: impl Into<String>) -> HaProxRes<()>
476 {
477 let ns_str = ns.into();
478
479 common::is_printable_ascii_nowp(&ns_str, "net_ns")?;
480
481 return self.add_tlv(PP2Tlvs::TypeNetNs(ns_str.into()), None);
482 }
483
484 pub
493 fn add_netns_borrowed<'a>(&mut self, ns: &'a str) -> HaProxRes<()>
494 {
495 common::is_printable_ascii_nowp(ns, "net_ns")?;
496
497 return self.add_tlv(PP2Tlvs::TypeNetNs(Cow::Borrowed(ns)), None);
498 }
499
500 pub
504 fn add_crc32(&mut self) -> HaProxRes<()>
505 {
506 return self.add_tlv(PP2Tlvs::TypeCrc32c(0), None);
507 }
508
509 pub
513 fn add_uniq_id<ID: PP2TlvUniqId>(&mut self, au: ID) -> HaProxRes<()>
514 {
515 let uniq_id = au.into_bytes();
516
517 return self.add_tlv(PP2Tlvs::TypeUniqId(uniq_id.into()), None);
518 }
519
520 pub
524 fn add_uniq_id_borrow<ID: PP2TlvUniqId>(&mut self, au: ID) -> HaProxRes<()>
525 {
526 let uniq_id = au.as_slice();
527
528 return self.add_tlv(PP2Tlvs::TypeUniqId(Cow::Borrowed(uniq_id)), None);
529 }
530
531 pub
535 fn add_authority(&mut self, authority: impl Into<String>) -> HaProxRes<()>
536 {
537 return self.add_tlv(PP2Tlvs::TypeAuthority(authority.into().into()), None);
538 }
539
540 pub
542 fn add_authority_borrrow<'a>(&mut self, authority: &'a str) -> HaProxRes<()>
543 {
544 return self.add_tlv(PP2Tlvs::TypeAuthority(Cow::Borrowed(authority)), None);
545 }
546
547 pub
551 fn add_ssl(self, client: PP2TlvClient, verify: u32) -> HaProxRes<TlvSubTypeSsl<'s>>
552 {
553 return TlvSubTypeSsl::new(self, PP2Tlvs::TLV_TYPE_SSL_SUB_RANGE, client, verify);
554 }
555
556 pub
558 fn add_tlv<TLV: PP2TlvDump>(&mut self, tlv: TLV,
559 opt_constr: Option<&'static [std::ops::RangeInclusive<u8>]>) -> HaProxRes<()>
560 {
561 let tlv_id: u8 = tlv.get_type();
562
563 let constr = opt_constr.unwrap_or(self.constraints);
564
565 if constr.iter().any(|idr| idr.contains(&tlv_id)) == false
566 {
567 return_error!(ArgumentEinval, "TLV: {} is subtype of other type or type!", tlv);
568 }
569
570 if tlv_id == PP2Tlvs::TypeCrc32c(0).into()
571 {
572 if self.hdr.crc_tlv_offset != 0
573 {
574 return_error!(ArgumentEinval, "duplicate PLT CRC!");
575 }
576
577 self.hdr.crc_tlv_offset = self.hdr.buffer.position();
578 }
579
580 self.hdr.buffer.write_u8(tlv_id).map_err(common::map_io_err)?;
582
583 let size_pos = self.hdr.buffer.position();
585
586 self.hdr.buffer.write_u16::<BigEndian>(0).map_err(common::map_io_err)?;
588
589 tlv.dump(&mut self.hdr.buffer)?;
591
592 let cur_pos = self.hdr.buffer.position();
594 self.hdr.buffer.set_position(size_pos);
595
596 self.hdr.buffer.write_u16::<BigEndian>((cur_pos - size_pos - 2) as u16).map_err(common::map_io_err)?;
598
599 self.hdr.buffer.set_position(cur_pos);
601
602 return Ok(());
603 }
604}
605
606#[derive(Clone, Debug)]
651pub struct ProxyHdrV2<OPC: ProxyV2OpCode>
652{
653 buffer: Cursor<Vec<u8>>,
655
656 crc_tlv_offset: u64,
658
659 _p: PhantomData<OPC>,
661}
662
663impl<OPC: ProxyV2OpCode> ProxyHdrV2<OPC>
664{
665 pub const HDR_MSG_LEN_OFFSET: u64 = offset_of!(protocol_raw::ProxyHdrV2, len) as u64;
667}
668
669impl ProxyHdrV2<HdrV2OpLocal>
671{
672 pub
674 fn new() -> Vec<u8>
675 {
676 return protocol_raw::MSG_HEADER_LOCAL_V2.to_vec();
677 }
678}
679
680impl ProxyHdrV2<HdrV2OpProxy>
682{
683 pub
701 fn new(transport: ProxyTransportFam, address: ProxyV2Addr) -> HaProxRes<Self>
702 {
703 let buf: Vec<u8> =
704 Vec::with_capacity(size_of::<protocol_raw::ProxyHdrV2>());
705
706 let mut cur = Cursor::new(buf);
707 cur.write_all(protocol_raw::HEADER_MAGIC_V2).map_err(common::map_io_err)?;
711
712 cur.write_u8(0x20 | HdrV2OpProxy::OPCODE).map_err(common::map_io_err)?;
714
715 cur.write_u8(((address.as_addr_family() as u8) << 4) | transport as u8).map_err(common::map_io_err)?;
717
718 cur.write_u16::<BigEndian>(address.get_len()).map_err(common::map_io_err)?;
720
721 address.write(&mut cur)?;
723
724 return Ok(
725 Self
726 {
727 buffer: cur,
728 crc_tlv_offset: 0,
729 _p: PhantomData
730 }
731 );
732 }
733
734 pub
736 fn set_plts<'s>(&'s mut self) -> TlType<'s>
737 {
738 return TlType::new(self, PP2Tlvs::TLV_TYPE_MAIN_RANGES);
739 }
740
741 fn finalize(&mut self) -> HaProxRes<()>
742 {
743 let last_off = self.buffer.position();
744
745 self.buffer.set_position(Self::HDR_MSG_LEN_OFFSET);
747
748 let tlv_len = last_off - size_of::<protocol_raw::ProxyHdrV2>() as u64;
749
750 self.buffer.write_u16::<BigEndian>(tlv_len as u16).map_err(common::map_io_err)?;
751
752 if self.crc_tlv_offset > 0
753 {
754 let mut hasher = Hasher::new();
756
757 hasher.update(self.buffer.get_ref());
759
760 self.buffer.set_position(self.crc_tlv_offset + protocol::TLV_HEADER_LEN as u64);
762
763 self.buffer.write_u32::<BigEndian>(hasher.finalize()).map_err(common::map_io_err)?;
765 }
766 return Ok(());
767 }
768
769
770}
771
772impl TryFrom<ProxyHdrV2<HdrV2OpProxy>> for Vec<u8>
775{
776 type Error = HaProxErr;
777
778 fn try_from(mut value: ProxyHdrV2<HdrV2OpProxy>) -> Result<Self, Self::Error>
779 {
780 value.finalize()?;
781
782 return Ok(value.buffer.into_inner());
783 }
784}
785
786impl<'sz> PP2TlvDump for PP2Tlvs<'sz>
787{
788 fn get_type(&self) -> u8
789 {
790 return self.into();
791 }
792
793 fn dump(&self, cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()>
794 {
795 match self
796 {
797 Self::TypeAlpn(items) =>
798 {
799 for alpn in items.iter(){
802 cur.write_u16::<BigEndian>(alpn.len() as u16).map_err(common::map_io_err)?;
804
805 cur.write_all(alpn).map_err(common::map_io_err)?;
807 }
808 },
809 Self::TypeAuthority(auth) =>
810 {
811 cur.write_all(auth.as_bytes()).map_err(common::map_io_err)?;
813 },
814 Self::TypeCrc32c(crc) =>
815 {
816 cur.write_u32::<BigEndian>(*crc).map_err(common::map_io_err)?;
817 },
818 Self::TypeNoop =>
819 {
820
821 },
822 Self::TypeUniqId(items) =>
823 {
824 cur.write_all(items).map_err(common::map_io_err)?;
825 },
826 Self::TypeSsl{client, verify} =>
827 {
828 cur.write_u8(client.bits()).map_err(common::map_io_err)?;
830
831 cur.write_u32::<BigEndian>(*verify).map_err(common::map_io_err)?;
833 },
834 Self::TypeSubtypeSslVersion(v) =>
835 {
836 cur.write_all(v.as_bytes()).map_err(common::map_io_err)?;
837 },
838 Self::TypeSubtypeSslCn(cn) =>
839 {
840 cur.write_all(cn.as_bytes()).map_err(common::map_io_err)?;
841 },
842 Self::TypeSubtypeSslCipher(c) =>
843 {
844 cur.write_all(c.as_bytes()).map_err(common::map_io_err)?;
845 },
846 Self::TypeSubtypeSslSigAlg(sa) =>
847 {
848 cur.write_all(sa.as_bytes()).map_err(common::map_io_err)?;
849 },
850 Self::TypeSubtypeSslKeyAlg(ka) =>
851 {
852 cur.write_all(ka.as_bytes()).map_err(common::map_io_err)?;
853 },
854 Self::TypeSubTypeSslGroup(group) =>
855 {
856 cur.write_all(group.as_bytes()).map_err(common::map_io_err)?;
857 },
858 Self::TypeSubTypeSslSigScheme(sig) =>
859 {
860 cur.write_all(sig.as_bytes()).map_err(common::map_io_err)?;
861 }
862 Self::TypeNetNs(ns) =>
863 {
864 cur.write_all(ns.as_bytes()).map_err(common::map_io_err)?;
865 },
866 }
867
868 return Ok(());
869 }
870}
871
872#[cfg(test)]
873mod tests
874{
875 use std::{fmt, io::Cursor};
876
877 use byteorder::{BigEndian, WriteBytesExt};
878
879 use crate::{common::map_io_err, protocol_v2::{protocol::{PP2TlvClient, PP2Tlvs}, PP2TlvDump}, HaProxRes, ProxyTransportFam, ProxyV2Addr};
880
881 use super::{HdrV2OpProxy, ProxyHdrV2};
882
883 #[test]
884 fn test_comp0()
885 {
886 let addr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
887
888 let mut comp =
889 ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
890
891 let plts = comp.set_plts();
892
893 let mut ssl = plts.add_ssl(PP2TlvClient::PP2_CLIENT_SSL, 0).unwrap();
894
895 ssl.add_ssl_sub_version("TLSv1.2").unwrap();
896
897 ssl.done().unwrap();
898
899 let pkt: Vec<u8> = comp.try_into().unwrap();
900
901 let ctrl =
902b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x1e\
903\x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
904\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32";
905
906 assert_eq!(pkt.as_slice(), ctrl.as_slice());
907 }
908
909 #[test]
910 fn test_comp1()
911 {
912 #[derive(Clone, Debug)]
913 pub enum ProxyV2Dummy2
914 {
915 SomeTlvName(u32, u32),
916 }
917
918 impl fmt::Display for ProxyV2Dummy2
919 {
920 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
921 {
922 write!(f, "DUMMY external reader")
923 }
924 }
925
926 impl PP2TlvDump for ProxyV2Dummy2
927 {
928 fn get_type(&self) -> u8
929 {
930 #[allow(irrefutable_let_patterns)]
931 let Self::SomeTlvName(..) = self else { panic!("wrong") };
932
933 return 0xE0;
934 }
935
936 fn dump(&self, cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()>
937 {
938 match self
939 {
940 Self::SomeTlvName(arg0, arg1) =>
941 {
942 cur.write_u32::<BigEndian>(*arg0).map_err(map_io_err)?;
943 cur.write_u32::<BigEndian>(*arg1).map_err(map_io_err)?;
944 }
945 }
946
947 return Ok(());
948 }
949 }
950
951
952
953 let addr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
954
955 let mut comp =
956 ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
957
958 let plts = comp.set_plts();
959
960 let mut ssl = plts.add_ssl(PP2TlvClient::PP2_CLIENT_SSL, 0).unwrap();
961
962 ssl.add_ssl_sub_version("TLSv1.2").unwrap();
963
964 let mut plts = ssl.done().unwrap();
965
966
967 let cust_plt = ProxyV2Dummy2::SomeTlvName(0x01020304, 0x05060708);
968
969 plts.add_tlv(cust_plt, Some(&[0xE0..=0xE0])).unwrap();
970
971 drop(plts);
972
973 let pkt: Vec<u8> = comp.try_into().unwrap();
974
975 let ctrl =
976b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x29\
977\x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
978\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\xE0\x00\
979\x08\x01\x02\x03\x04\x05\x06\x07\x08";
980
981 assert_eq!(pkt.as_slice(), ctrl.as_slice());
982 }
983
984 #[test]
985 fn test_alpns()
986 {
987 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
988
989 let alpn = PP2Tlvs::TypeAlpn(vec![b"test".as_slice().to_vec().into()].into());
990
991 alpn.dump(&mut cur).unwrap();
992
993 let reference = b"\x00\x04test";
996
997 let generated = cur.into_inner();
998
999 assert_eq!(generated.as_slice(), reference.as_slice());
1000 }
1001
1002 #[test]
1003 fn test_authority()
1004 {
1005 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1006
1007 let alpn = PP2Tlvs::TypeAuthority("tset".into());
1008
1009 alpn.dump(&mut cur).unwrap();
1010
1011 let reference = b"tset";
1014
1015 let generated = cur.into_inner();
1016
1017 assert_eq!(generated.as_slice(), reference.as_slice());
1018 }
1019
1020 #[test]
1021 fn test_crc32()
1022 {
1023 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1024
1025 let alpn = PP2Tlvs::TypeCrc32c(0xABCDEF01);
1026
1027 alpn.dump(&mut cur).unwrap();
1028
1029 let reference = b"\xab\xcd\xef\x01";
1032
1033 let generated = cur.into_inner();
1034
1035 assert_eq!(generated.as_slice(), reference.as_slice());
1036 }
1037
1038 #[test]
1039 fn test_netns()
1040 {
1041 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1042
1043 let alpn = PP2Tlvs::TypeNetNs("tstt".into());
1044
1045 alpn.dump(&mut cur).unwrap();
1046
1047 let reference = b"tstt";
1050
1051 let generated = cur.into_inner();
1052
1053 assert_eq!(generated.as_slice(), reference.as_slice());
1054 }
1055
1056 #[test]
1057 fn test_noop()
1058 {
1059 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1060
1061 let alpn = PP2Tlvs::TypeNoop;
1062
1063 alpn.dump(&mut cur).unwrap();
1064
1065 let reference = b"";
1066
1067 let generated = cur.into_inner();
1068
1069 assert_eq!(generated.as_slice(), reference.as_slice());
1070 }
1071
1072 #[test]
1073 fn test_ssl()
1074 {
1075 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1076
1077 let alpn = PP2Tlvs::TypeSsl{ client: PP2TlvClient::PP2_CLIENT_SSL, verify: 0x00003210};
1078
1079 alpn.dump(&mut cur).unwrap();
1080
1081 let reference = b"\x01\x00\x00\x32\x10";
1084
1085 let generated = cur.into_inner();
1086
1087 assert_eq!(generated.as_slice(), reference.as_slice());
1088 }
1089
1090 #[test]
1091 fn test_uniqid()
1092 {
1093 const ID: &'static [u8] = b"ABCD12345678901234567890";
1094
1095 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1096
1097 let alpn = PP2Tlvs::TypeUniqId(ID.into());
1098
1099 alpn.dump(&mut cur).unwrap();
1100
1101 let reference = ID;
1102
1103 let generated = cur.into_inner();
1104
1105 assert_eq!(generated.as_slice(), reference);
1106 }
1107
1108 #[test]
1109 fn test_ssl_cipher()
1110 {
1111 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1112
1113 let ciph = PP2Tlvs::TypeSubtypeSslCipher("ECDHE-RSA-AES128-GCM-SHA256".into());
1114
1115 ciph.dump(&mut cur).unwrap();
1116
1117 let reference = b"ECDHE-RSA-AES128-GCM-SHA256";
1120
1121 let generated = cur.into_inner();
1122
1123 assert_eq!(generated.as_slice(), reference.as_slice());
1124 }
1125
1126 #[test]
1127 fn test_ssl_cn()
1128 {
1129 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1130
1131 let cn = PP2Tlvs::TypeSubtypeSslCn("example.com".into());
1132
1133 cn.dump(&mut cur).unwrap();
1134
1135 let reference = b"example.com";
1138
1139 let generated = cur.into_inner();
1140
1141 assert_eq!(generated.as_slice(), reference.as_slice());
1142 }
1143
1144 #[test]
1145 fn test_ssl_keyalg()
1146 {
1147 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1148
1149 let keyalg = PP2Tlvs::TypeSubtypeSslKeyAlg("RSA2048".into());
1150
1151 keyalg.dump(&mut cur).unwrap();
1152
1153 let reference = b"RSA2048";
1156
1157 let generated = cur.into_inner();
1158
1159 assert_eq!(generated.as_slice(), reference.as_slice());
1160 }
1161
1162 #[test]
1163 fn test_ssl_sigalg()
1164 {
1165 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1166
1167 let sigalg = PP2Tlvs::TypeSubtypeSslSigAlg("SHA256".into());
1168
1169 sigalg.dump(&mut cur).unwrap();
1170
1171 let reference = b"SHA256";
1174
1175 let generated = cur.into_inner();
1176
1177 assert_eq!(generated.as_slice(), reference.as_slice());
1178 }
1179
1180 #[test]
1181 fn test_ssl_version()
1182 {
1183 let mut cur = Cursor::new(Vec::<u8>::with_capacity(64));
1184
1185 let vers = PP2Tlvs::TypeSubtypeSslVersion("TLSv1_3".into());
1186
1187 vers.dump(&mut cur).unwrap();
1188
1189 let reference = b"TLSv1_3";
1192
1193 let generated = cur.into_inner();
1194
1195 assert_eq!(generated.as_slice(), reference.as_slice());
1196 }
1197}