haprox_rs/protocol_v2/
protocol.rs

1/*-
2 * haprox-rs - a HaProxy protocol parser.
3 * 
4 * Copyright 2025 (c) Aleksandr Morozov
5 * The scram-rs crate can be redistributed and/or modified
6 * under the terms of either of the following licenses:
7 *
8 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
9 *
10 *   2. The MIT License (MIT)
11 *                     
12 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
13 */
14
15use std::borrow::Cow;
16use std::ffi::CStr;
17use std::fmt;
18use std::io::{Cursor, Read, Write};
19use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
20use std::ops::RangeInclusive;
21use std::os::unix::ffi::OsStrExt;
22use std::os::unix::net;
23use std::str::FromStr;
24
25use bitflags::bitflags;
26use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
27
28use crate::{ReadExtZeroCopy, common, map_error, return_error};
29use crate::error::{HaProxErr, HaProxRes};
30
31use crate::protocol_raw::{self, HEADER_UNIX_ADDR_LEN};
32
33// -----
34// The following range of 16 type values is reserved for application-specific
35// data and will be never used by the PROXY Protocol. If you need more values
36// consider extending the range with a type field in your TLVs.
37
38/// values is reserved for application-specific data and will be never 
39/// used by the PROXY Protocol (minimal type)
40pub const PP2_TYPE_MIN_CUSTOM: u8 = 0xE0;
41
42/// values is reserved for application-specific data and will be never 
43/// used by the PROXY Protocol (max type)
44pub const PP2_TYPE_MAX_CUSTOM: u8 = 0xEF;
45
46// ----
47// The following range of 8 values is reserved for future use, potentially to
48// extend the protocol with multibyte type values.
49
50/// reserved for temporary experimental use by application developers and protocol 
51/// designers (min range)
52pub const PP2_TYPE_MIN_EXPERIMENT: u8 = 0xF0;
53
54/// reserved for temporary experimental use by application developers and protocol 
55/// designers (max range)
56pub const PP2_TYPE_MAX_EXPERIMENT: u8 = 0xF7;
57
58// ----
59// The following range of 8 values is reserved for future use, potentially to
60// extend the protocol with multibyte type values.
61
62/// reserved for future use (min range)
63pub const PP2_TYPE_MIN_FUTURE: u8 = 0xF8;
64
65/// reserved for future use (max range)
66pub const PP2_TYPE_MAX_FUTURE: u8 = 0xFF;
67
68
69//----
70/// Max length of the TLV's payload uniq ID.
71pub const MAX_UNIQ_ID_LEN_BYTES: u16 = 128;
72
73/// Header length of TLV
74pub const TLV_HEADER_LEN: u16 = 3;
75
76
77
78// https://www.haproxy.org/download/3.2/doc/proxy-protocol.txt
79// https://datatracker.ietf.org/doc/html/rfc7301
80
81/// An OP codes definotions.
82#[repr(u8)]
83#[derive(Clone, Copy, PartialEq, Eq, Debug)]
84pub enum HdrV2Command
85{
86    LOCAL = 0,
87    PROXY = 1,
88    UNKNOWN,
89}
90
91impl From<HdrV2Command> for u8
92{
93    fn from(value: HdrV2Command) -> Self 
94    {
95        if value == HdrV2Command::UNKNOWN
96        {
97            panic!("can not encode the unknown command");
98        }
99
100        return value as u8;
101    }
102}
103
104impl HdrV2Command
105{
106    pub(crate)
107    fn decode(raw: u8) -> Self
108    {
109        match raw & protocol_raw::ProxyHdrV2::COMMAND_MASK
110        {
111            r if r == HdrV2Command::LOCAL.into() => return Self::LOCAL,
112            r if r == HdrV2Command::PROXY.into() => return Self::PROXY,
113            _ => return Self::UNKNOWN,
114        }
115    }
116}
117
118/// Defines the protocol versions.
119#[repr(u8)]
120#[derive(Clone, Copy, PartialEq, Eq, Debug)]
121pub enum ProtocolVersion
122{
123    V1 = 1,
124    V2 = 2,
125    UNKNOWN,
126}
127
128impl From<ProtocolVersion> for u8
129{
130    fn from(value: ProtocolVersion) -> Self 
131    {
132        if value == ProtocolVersion::UNKNOWN
133        {
134            panic!("can not encode the unknown version");
135        }
136
137        return (value as u8) << 4;
138    }
139}
140
141impl ProtocolVersion
142{
143    pub(crate)
144    fn decode(raw: u8) -> Self
145    {
146        match raw >> 4
147        {
148            1 => return Self::V1,
149            2 => return Self::V2,
150            _ => return Self::UNKNOWN,
151        }
152    }
153}
154
155bitflags! {
156    /// A client flags.
157    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
158    pub struct PP2TlvClient: u8 
159    {
160        /// client connected over SSL/TLS
161        const PP2_CLIENT_SSL = 0x01;
162        
163        /// client provided a certificate over the current connection
164        const PP2_CLIENT_CERT_CONN = 0x02;
165
166        /// client provided a certificate at least once over the TLS session this 
167        /// connection belongs to
168        const PP2_CLIENT_CERT_SESS = 0x04;
169    }
170}
171
172/// A specific for PP2Tlv SSL.
173#[derive(Clone, Debug, PartialEq, Eq)]
174pub struct PP2TlvsTypeSsl<'zc>
175{
176    /// client came with something
177    pub(crate) client: PP2TlvClient, 
178                
179    /// field will be zero if the client presented a certificate
180    /// and it was successfully verified, and non-zero otherwise.
181    pub(crate) verify: u32, 
182
183    /// included sub TLVs
184    pub(crate) sub_tlv: Vec<PP2Tlvs<'zc>>
185}
186
187impl<'zc> fmt::Display for PP2TlvsTypeSsl<'zc>
188{
189    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
190    {
191        write!(f, "CLIENT: {:?}, VERIFY: {}, TLVs: {}", 
192            self.client, self.verify, 
193            self.sub_tlv.iter().map(|t| t.to_string()).collect::<Vec<String>>().join(", "))
194    }
195}
196
197/*
198impl From<PP2TlvsTypeSsl> for PP2Tlvs
199{
200    fn from(value: PP2TlvsTypeSsl) -> Self where Self: PP2TlvDump
201    {
202        return Self::TypeSsl(value);
203    }
204}*/
205
206/// Can be used for testing.
207#[repr(u8)]
208#[derive(Clone, Debug, PartialEq, Eq)]
209pub enum PP2Tlvs<'zc>
210{
211    /// Application-Layer Protocol Negotiation (ALPN).
212    TypeAlpn(Cow<'zc, [Cow<'zc, [u8]>]>) = PP2Tlvs::TYPE_ALPN,
213
214    /// "SNI" i.e the "server_name" extension as defined by RFC3546
215    /// UTF8-encoded string
216    TypeAuthority(Cow<'zc, str>) = PP2Tlvs::TYPE_AUTHORITY,
217
218    /// 32-bit number storing the CRC32c checksum of the PROXY protocol header
219    TypeCrc32c(u32) = PP2Tlvs::TYPE_CRC32C,
220
221    /// The TLV of this type should be ignored when parsed. The value is zero or more
222    /// bytes. Can be used for data padding or alignment. Note that it can be used
223    /// to align only by 3 or more bytes because a TLV can not be smaller than that.
224    TypeNoop = PP2Tlvs::TYPE_NOOP,
225
226    /// opaque byte sequence of up to 128 bytes generated by the upstream proxy 
227    /// that uniquely identifies the connection.
228    TypeUniqId(Cow<'zc, [u8]>) = PP2Tlvs::TYPE_UNIQID,
229
230    /// SSL properties
231    TypeSsl
232    {
233        client: PP2TlvClient,
234        verify: u32,
235    } = PP2Tlvs::TYPE_SSL,
236
237    /// US-ASCII string representation of the TLS version (format?)
238    TypeSubtypeSslVersion(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION,
239
240    /// In all cases, the string representation (in UTF8) of the Common Name field
241    /// (OID: 2.5.4.3) of the client certificate's Distinguished Name, is appended
242    /// using the TLV format and the type PP2_SUBTYPE_SSL_CN. E.g. "example.com".
243    TypeSubtypeSslCn(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_CN,
244    
245    /// US-ASCII string name of the used cipher, for example "ECDHE-RSA-AES128-GCM-SHA256".
246    TypeSubtypeSslCipher(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_CIPHER,
247
248    /// US-ASCII string name of the algorithm used to sign the certificate presented by the 
249    /// frontend when the incoming connection was made over an SSL/TLS transport layer, for example
250    /// "SHA256".
251    TypeSubtypeSslSigAlg(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_SIGALG,
252
253    /// US-ASCII string name of the algorithm used to generate the key of the certificate 
254    /// presented by the frontend when the incoming connection was made over an SSL/TLS 
255    /// transport layer, for example "RSA2048".
256    TypeSubtypeSslKeyAlg(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_KEYALG,
257
258    /// US-ASCII string name of the key exchange algorithm used for the frontend TLS 
259    /// connection, for example "secp256r1".
260    TypeSubTypeSslGroup(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_GROUP,
261
262    /// US-ASCII string name of the algorithm the frontend used to sign the ServerKeyExchange or
263    /// CertificateVerify message, for example "rsa_pss_rsae_sha256".
264    TypeSubTypeSslSigScheme(Cow<'zc, str>) = PP2Tlvs::TYPE_SUBTYPE_SSL_SIG_SCHEME,
265
266    /// US-ASCII string representation of the namespace's name
267    TypeNetNs(Cow<'zc, str>) = PP2Tlvs::TYPE_NETNS,
268}
269
270impl<'zc> fmt::Display for PP2Tlvs<'zc>
271{
272    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
273    {
274        let id: u8 = self.into();
275
276        match self
277        {
278            Self::TypeAlpn(alpns) => 
279            {
280                let alpns_dec = 
281                    alpns
282                        .iter()
283                        .map(
284                            |a| 
285                            std
286                                ::str
287                                ::from_utf8(a)
288                                    .map_err(|e| map_error!(MalformedData, "{}", e))
289                        )
290                        .collect::<HaProxRes<Vec<&str>>>()
291                        .map_err(|_e| fmt::Error)?
292                        .join(",");
293
294                write!(f, "ALPNS({:02X}): {}", id, alpns_dec)
295            },
296            Self::TypeAuthority(sni) => 
297                write!(f, "SNI({:02X}): {}", id, sni),
298            Self::TypeCrc32c(crc) => 
299                write!(f, "CRC({:02X}): {}", id, crc),
300            Self::TypeNoop => 
301                write!(f, "NOOP({:02X})", id),
302            Self::TypeUniqId(items) => 
303                write!(f, "UNIQID({:02X}): {:02X?}", id, items),
304            Self::TypeSsl{client, verify} => 
305                write!(f, "SSL({:02X}): client: {:?}, verify: {}", id, client, verify),
306            Self::TypeSubtypeSslVersion(ver) => 
307                write!(f, "SSL VERSION({:02X}): {}", id, ver),
308            Self::TypeSubtypeSslCn(cn) => 
309                write!(f, "SSL CN({:02X}): {}", id, cn),
310            Self::TypeSubtypeSslCipher(c) => 
311                write!(f, "SSL CIPHER({:02X}): {}", id, c),
312            Self::TypeSubtypeSslSigAlg(sa) => 
313                write!(f, "SSL SIGALG({:02X}): {}", id, sa),
314            Self::TypeSubtypeSslKeyAlg(ka) => 
315                write!(f, "SSL KEYALG({:02X}): {}", id, ka),
316            Self::TypeSubTypeSslGroup(group) =>
317                write!(f, "SSL GROUP({:02X}): {}", id, group),
318            Self::TypeSubTypeSslSigScheme(sig) =>
319                write!(f, "SSL SIG_SCHEME({:02X}): {}", id, sig),
320            Self::TypeNetNs(ns) => 
321                write!(f, "NETNS({:02X}): {}", id, ns),
322        }
323    }
324}
325
326impl<'zc> From<PP2Tlvs<'zc>> for u8
327{
328    fn from(value: PP2Tlvs<'zc>) -> Self 
329    {
330        return (&value).into();
331    }
332}
333
334impl<'zc> From<&PP2Tlvs<'zc>> for u8
335{
336    fn from(value: &PP2Tlvs) -> Self 
337    {
338        return unsafe { *<*const _>::from(value).cast::<Self>() };
339    }
340}
341
342
343
344impl<'zc> PP2Tlvs<'zc>
345{
346    /// A constraints by range of all types.
347    pub const TLV_TYPE_MAIN_RANGES: &'static [RangeInclusive<u8>] = 
348        &[
349            Self::TYPE_ALPN..=Self::TYPE_SSL,  
350            Self::TYPE_NETNS ..= Self::TYPE_NETNS
351        ];
352
353    /// A constraints for the SSL subtypes.
354    pub const TLV_TYPE_SSL_SUB_RANGE: &'static [RangeInclusive<u8>] = 
355        &[Self::TYPE_SUBTYPE_SSL_VERSION ..= Self::TYPE_SUBTYPE_SSL_SIG_SCHEME];
356
357    pub const TYPE_ALPN: u8 = 0x01;
358
359    pub const TYPE_AUTHORITY: u8 = 0x02;
360
361    pub const TYPE_CRC32C: u8 = 0x03;
362
363    pub const TYPE_NOOP: u8 = 0x04;
364
365    pub const TYPE_UNIQID: u8 = 0x05;
366
367    pub const TYPE_SSL: u8 = 0x20;
368
369    pub const TYPE_SUBTYPE_SSL_VERSION: u8 = 0x21;
370
371    pub const TYPE_SUBTYPE_SSL_CN: u8 = 0x22;
372    
373    pub const TYPE_SUBTYPE_SSL_CIPHER: u8 = 0x23;
374
375    pub const TYPE_SUBTYPE_SSL_SIGALG: u8 = 0x24;
376
377    pub const TYPE_SUBTYPE_SSL_KEYALG: u8 = 0x25;
378
379    /// TLV PP2_SUBTYPE_SSL_GROUP provides the US-ASCII string name
380    pub const TYPE_SUBTYPE_SSL_GROUP: u8 = 0x26;
381
382    pub const TYPE_SUBTYPE_SSL_SIG_SCHEME: u8 = 0x27;
383
384
385    pub const TYPE_NETNS: u8 = 0x30;
386
387    pub 
388    fn contains_subtype(&self) -> bool
389    {
390        let Self::TypeSsl{ .. } = self else { return false };
391
392        return true;
393    }
394
395    pub 
396    fn conntains_subtype_discr(discr: u8) -> bool
397    {
398        return discr == Self::TYPE_SSL;
399    }
400
401    pub(crate) 
402    fn is_in_range(tlv_type: u8, tlv_parent_type: Option<u8>) -> bool 
403    {
404        if let Some(p_tlv) = tlv_parent_type
405        {
406            if p_tlv == Self::TYPE_SSL
407            {
408                return Self::TLV_TYPE_SSL_SUB_RANGE.iter().any(|tlv| tlv.contains(&tlv_type));
409            }
410            else
411            {
412                return false;
413            }
414        }
415
416        return Self::TLV_TYPE_MAIN_RANGES.iter().any(|tlv| tlv.contains(&tlv_type));
417    }
418
419    pub(crate) 
420    fn restore_copying(tlv_type: u8, cur: &mut Cursor<&'zc [u8]>) -> HaProxRes<Self>
421    {
422        let tlv_len = cur.get_ref().len();
423
424        match tlv_type
425        {
426            Self::TYPE_ALPN =>
427            {
428                let mut alpns: Vec<Cow<'zc, [u8]>> = Vec::with_capacity(2);
429
430                while let Some(alpn_len) = cur.read_u16::<BigEndian>().ok()
431                {
432                    let mut alpn: Vec<u8> = vec![0_u8; alpn_len as usize];
433
434                    cur.read_exact(&mut alpn).map_err(common::map_io_err)?;
435
436                    alpns.push(alpn.into());
437                }
438
439                return Ok(Self::TypeAlpn(alpns.into()));
440            },
441            Self::TYPE_AUTHORITY =>
442            {
443                let mut authority: Vec<u8> = vec![0_u8; tlv_len];
444
445                cur.read_exact(&mut authority).map_err(common::map_io_err)?;
446
447                return Ok(
448                    Self::TypeAuthority(
449                        String::from_utf8(authority)
450                            .map_err(|e| 
451                                map_error!(MalformedData, "TLV TYPE_AUTHORITY restore error: '{}'", e)
452                            )?
453                            .into()
454                    )
455                );
456            },
457            Self::TYPE_CRC32C => 
458            {
459                let crc = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
460
461                return Ok(Self::TypeCrc32c(crc));
462            },
463            Self::TYPE_NOOP => 
464            {
465                return Ok(Self::TypeNoop);
466            },
467            Self::TYPE_UNIQID =>
468            {
469                let mut authority: Vec<u8> = vec![0_u8; tlv_len];
470
471                cur.read_exact(&mut authority).map_err(common::map_io_err)?;
472
473                return Ok(
474                    Self::TypeUniqId(authority.into())
475                );
476            },
477            Self::TYPE_SSL =>
478            {
479                let client_bits = cur.read_u8().map_err(common::map_io_err)?;
480
481                let client = 
482                    PP2TlvClient::from_bits(client_bits)
483                        .ok_or_else(|| map_error!(ProtocolUnknownData, "TLV TYPE_SSL unknown client bits: {}", client_bits))?;
484
485                let verify = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
486
487                return Ok(
488                    Self::TypeSsl{ client: client, verify: verify }
489                );
490            },
491            Self::TYPE_SUBTYPE_SSL_VERSION => 
492            {
493                let mut ssl_version: Vec<u8> = vec![0_u8; tlv_len];
494
495                cur.read_exact(&mut ssl_version).map_err(common::map_io_err)?;
496
497                let ssl_version_str = 
498                    String::from_utf8(ssl_version)
499                        .map_err(|e| 
500                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
501                        )
502                        .and_then(|v|
503                            common::is_printable_ascii_nowp(&v, "ssl_version")
504                                .and(Ok(v))
505                        )?;
506
507                return Ok(
508                    Self::TypeSubtypeSslVersion(Cow::Owned(ssl_version_str))
509                );
510            },
511            Self::TYPE_SUBTYPE_SSL_CN =>
512            {
513                let mut ssl_cn: Vec<u8> = vec![0_u8; tlv_len];
514
515                cur.read_exact(&mut ssl_cn).map_err(common::map_io_err)?;
516
517                let ssl_cn = 
518                    String::from_utf8(ssl_cn)
519                        .map_err(|e| 
520                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
521                        )?;
522
523                return Ok(
524                    Self::TypeSubtypeSslCn(Cow::Owned(ssl_cn))
525                );
526            },
527            Self::TYPE_SUBTYPE_SSL_CIPHER => 
528            {
529                let mut ssl_cipher: Vec<u8> = vec![0_u8; tlv_len];
530
531                cur.read_exact(&mut ssl_cipher).map_err(common::map_io_err)?;
532
533                let ssl_cipher = 
534                    String::from_utf8(ssl_cipher)
535                        .map_err(|e| 
536                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
537                        )
538                        .and_then(|v|
539                            common::is_printable_ascii_nowp(&v, "cipher")
540                                .and(Ok(v))
541                        )?;
542
543                return Ok(
544                    Self::TypeSubtypeSslCipher(Cow::Owned(ssl_cipher))
545                );
546            },
547            Self::TYPE_SUBTYPE_SSL_SIGALG =>
548            {
549                let mut ssl_sigalg: Vec<u8> = vec![0_u8; tlv_len];
550
551                cur.read_exact(&mut ssl_sigalg).map_err(common::map_io_err)?;
552
553                let ssl_sigalg = 
554                    String::from_utf8(ssl_sigalg)
555                        .map_err(|e| 
556                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
557                        )
558                        .and_then(|v|
559                            common::is_printable_ascii_nowp(&v, "sig_alg")
560                                .and(Ok(v))
561                        )?;
562
563                return Ok(
564                    Self::TypeSubtypeSslSigAlg(Cow::Owned(ssl_sigalg))
565                );
566            },
567            Self::TYPE_SUBTYPE_SSL_KEYALG =>
568            {
569                let mut ssl_keyalg: Vec<u8> = vec![0_u8; tlv_len];
570
571                cur.read_exact(&mut ssl_keyalg).map_err(common::map_io_err)?;
572
573                let ssl_keyalg = 
574                    String::from_utf8(ssl_keyalg)
575                        .map_err(|e| 
576                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
577                        )
578                        .and_then(|v|
579                            common::is_printable_ascii_nowp(&v, "key_alg")
580                                .and(Ok(v))
581                        )?;
582
583                return Ok(
584                    Self::TypeSubtypeSslKeyAlg(Cow::Owned(ssl_keyalg))
585                );
586            },
587            Self::TYPE_SUBTYPE_SSL_GROUP => 
588            {
589                let mut ssl_group: Vec<u8> = vec![0_u8; tlv_len];
590
591                cur.read_exact(&mut ssl_group).map_err(common::map_io_err)?;
592
593                let ssl_group = 
594                    String::from_utf8(ssl_group)
595                        .map_err(|e| 
596                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
597                        )
598                        .and_then(|v|
599                            common::is_printable_ascii_nowp(&v, "ssl_group")
600                                .and(Ok(v))
601                        )?;
602
603                return Ok(
604                    Self::TypeSubTypeSslGroup(Cow::Owned(ssl_group))
605                );
606            },
607            Self::TYPE_SUBTYPE_SSL_SIG_SCHEME => 
608            {
609                let mut ssl_sig_scheme: Vec<u8> = vec![0_u8; tlv_len];
610
611                cur.read_exact(&mut ssl_sig_scheme).map_err(common::map_io_err)?;
612
613                let ssl_sig_scheme = 
614                    String::from_utf8(ssl_sig_scheme)
615                        .map_err(|e| 
616                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
617                        )
618                        .and_then(|v|
619                            common::is_printable_ascii_nowp(&v, "ssl_sig_scheme")
620                                .and(Ok(v))
621                        )?;
622
623                return Ok(
624                    Self::TypeSubTypeSslSigScheme(Cow::Owned(ssl_sig_scheme))
625                );
626            },
627            Self::TYPE_NETNS => 
628            {
629                let mut netns: Vec<u8> = vec![0_u8; tlv_len];
630
631                cur.read_exact(&mut netns).map_err(common::map_io_err)?;
632
633                let netns = 
634                    String::from_utf8(netns)
635                        .map_err(|e| 
636                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
637                        )
638                        .and_then(|v|
639                            common::is_printable_ascii_nowp(&v, "netns")
640                                .and(Ok(v))
641                        )?;
642
643                return Ok(
644                    Self::TypeNetNs(netns.into())
645                );
646            },
647            _ => 
648                return_error!(ProtocolUnknownData, "unknown TLV type: {}", tlv_type)
649        }
650    }
651
652    pub(crate) 
653    fn restore_zerocopy(tlv_type: u8, cur: &mut Cursor<&'zc [u8]>) -> HaProxRes<Self>
654    {
655        let tlv_len = cur.get_ref().len();
656
657        match tlv_type
658        {
659            Self::TYPE_ALPN =>
660            {
661                let mut alpns: Vec<Cow<'zc, [u8]>> = Vec::with_capacity(2);
662
663                while let Some(alpn_len) = cur.read_u16::<BigEndian>().ok()
664                {
665                    let alpn = 
666                        cur.borrow_exact(alpn_len as usize).map_err(common::map_io_err)?;
667
668                    alpns.push(Cow::Borrowed(alpn));
669                }
670
671                return Ok(Self::TypeAlpn(alpns.into()));
672            },
673            Self::TYPE_AUTHORITY =>
674            {
675                let authority = 
676                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
677
678                return Ok(
679                    Self::TypeAuthority(
680                        Cow::Borrowed(
681                            str::from_utf8(authority)
682                                .map_err(|e| 
683                                    map_error!(MalformedData, "TLV TYPE_AUTHORITY restore error: '{}'", e)
684                                )?
685                        )
686                    )
687                );
688            },
689            Self::TYPE_CRC32C => 
690            {
691                let crc = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
692
693                return Ok(Self::TypeCrc32c(crc));
694            },
695            Self::TYPE_NOOP => 
696            {
697                return Ok(Self::TypeNoop);
698            },
699            Self::TYPE_UNIQID =>
700            {
701                let uniq_id = 
702                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
703
704                return Ok(
705                    Self::TypeUniqId(Cow::Borrowed(uniq_id))
706                );
707            },
708            Self::TYPE_SSL =>
709            {
710                let client_bits = cur.read_u8().map_err(common::map_io_err)?;
711
712                let client = 
713                    PP2TlvClient::from_bits(client_bits)
714                        .ok_or_else(|| map_error!(ProtocolUnknownData, "TLV TYPE_SSL unknown client bits: {}", client_bits))?;
715
716                let verify = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
717
718                return Ok(
719                    Self::TypeSsl{ client: client, verify: verify }
720                );
721            },
722            Self::TYPE_SUBTYPE_SSL_VERSION => 
723            {
724                let ssl_version = 
725                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
726
727                let ssl_version_str = 
728                    str::from_utf8(ssl_version)
729                        .map_err(|e| 
730                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
731                        )
732                        .and_then(|v|
733                            common::is_printable_ascii_nowp(&v, "ssl_version")
734                                .and(Ok(v))
735                        )?;
736
737                return Ok(
738                    Self::TypeSubtypeSslVersion(Cow::Borrowed(ssl_version_str))
739                );
740            },
741            Self::TYPE_SUBTYPE_SSL_CN =>
742            {
743                let ssl_cn = 
744                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
745
746                let ssl_cn = 
747                    str::from_utf8(ssl_cn)
748                        .map_err(|e| 
749                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
750                        )?;
751
752                return Ok(
753                    Self::TypeSubtypeSslCn(Cow::Borrowed(ssl_cn))
754                );
755            },
756            Self::TYPE_SUBTYPE_SSL_CIPHER => 
757            {
758                let ssl_cipher = 
759                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
760
761                let ssl_cipher = 
762                    str::from_utf8(ssl_cipher)
763                        .map_err(|e| 
764                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
765                        )
766                        .and_then(|v|
767                            common::is_printable_ascii_nowp(&v, "cipher")
768                                .and(Ok(v))
769                        )?;
770
771                return Ok(
772                    Self::TypeSubtypeSslCipher(Cow::Borrowed(ssl_cipher))
773                );
774            },
775            Self::TYPE_SUBTYPE_SSL_SIGALG =>
776            {
777                let ssl_sigalg = 
778                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
779
780                let ssl_sigalg = 
781                    str::from_utf8(ssl_sigalg)
782                        .map_err(|e| 
783                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
784                        )
785                        .and_then(|v|
786                            common::is_printable_ascii_nowp(&v, "sig_alg")
787                                .and(Ok(v))
788                        )?;
789
790                return Ok(
791                    Self::TypeSubtypeSslSigAlg(Cow::Borrowed(ssl_sigalg))
792                );
793            },
794            Self::TYPE_SUBTYPE_SSL_KEYALG =>
795            {
796                let ssl_keyalg = 
797                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
798
799                let ssl_keyalg = 
800                    str::from_utf8(ssl_keyalg)
801                        .map_err(|e| 
802                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
803                        )
804                        .and_then(|v|
805                            common::is_printable_ascii_nowp(&v, "key_alg")
806                                .and(Ok(v))
807                        )?;
808
809                return Ok(
810                    Self::TypeSubtypeSslKeyAlg(Cow::Borrowed(ssl_keyalg))
811                );
812            },
813            Self::TYPE_SUBTYPE_SSL_GROUP => 
814            {
815                let ssl_group = 
816                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
817
818                let ssl_group = 
819                    str::from_utf8(ssl_group)
820                        .map_err(|e| 
821                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
822                        )
823                        .and_then(|v|
824                            common::is_printable_ascii_nowp(&v, "ssl_group")
825                                .and(Ok(v))
826                        )?;
827
828                return Ok(
829                    Self::TypeSubTypeSslGroup(Cow::Borrowed(ssl_group))
830                );
831            },
832            Self::TYPE_SUBTYPE_SSL_SIG_SCHEME => 
833            {
834                let ssl_sig_scheme = 
835                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
836
837                let ssl_sig_scheme = 
838                    str::from_utf8(ssl_sig_scheme)
839                        .map_err(|e| 
840                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
841                        )
842                        .and_then(|v|
843                            common::is_printable_ascii_nowp(&v, "ssl_sig_scheme")
844                                .and(Ok(v))
845                        )?;
846
847                return Ok(
848                    Self::TypeSubTypeSslSigScheme(Cow::Borrowed(ssl_sig_scheme))
849                );
850            },
851            Self::TYPE_NETNS => 
852            {
853                let netns = 
854                    cur.borrow_exact(tlv_len as usize).map_err(common::map_io_err)?;
855
856                let netns = 
857                    str::from_utf8(netns)
858                        .map_err(|e| 
859                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
860                        )
861                        .and_then(|v|
862                            common::is_printable_ascii_nowp(&v, "netns")
863                                .and(Ok(v))
864                        )?;
865
866                return Ok(
867                    Self::TypeNetNs(Cow::Borrowed(netns))
868                );
869            },
870            _ => 
871                return_error!(ProtocolUnknownData, "unknown TLV type: {}", tlv_type)
872        }
873    }
874}
875
876/// A quote from protocol descr:
877/// > other values are unspecified and must not be emitted in version 2 of this
878/// > protocol and must be rejected as invalid by receivers.
879#[repr(u8)]
880#[derive(Clone, Copy, Debug, PartialEq, Eq)]
881pub enum ProxyV2AddrType
882{
883    /// A quote from protocol descr:
884    /// > the connection is forwarded for an unknown, unspecified
885    /// > or unsupported protocol. The sender should use this family when sending
886    /// > LOCAL commands or when dealing with unsupported protocol families. The
887    /// > receiver is free to accept the connection anyway and use the real endpoint
888    /// > addresses or to reject it. The receiver should ignore address information.
889    AfUnspec = 0x00,
890
891    /// A quote from protocol descr:
892    /// > the forwarded connection uses the AF_INET address family
893    /// > (IPv4). The addresses are exactly 4 bytes each in network byte order,
894    /// > followed by transport protocol information (typically ports).
895    AfInet = 0x01,
896
897    /// A quote from protocol descr:
898    /// > the forwarded connection uses the AF_INET6 address family
899    /// > (IPv6). The addresses are exactly 16 bytes each in network byte order,
900    /// > followed by transport protocol information (typically ports).
901    AfInet6 = 0x02,
902
903    /// A quote from protocol descr:
904    /// > the forwarded connection uses the AF_UNIX address family
905    /// > (UNIX). The addresses are exactly 108 bytes each.
906    AfUnix = 0x03,
907}
908
909impl From<ProxyV2AddrType> for u8
910{
911    fn from(value: ProxyV2AddrType) -> Self 
912    {
913        return value as u8;
914    }
915}
916
917impl ProxyV2AddrType
918{
919    pub const DEF_IPV4_ADDR_LEN: u16 = 12;
920    pub const DEF_IPV6_ADDR_LEN: u16 = 36;
921    pub const DEF_UNIX_ADDR_LEN: u16 = 216;
922
923    pub(crate) 
924    fn decode(raw: u8) -> HaProxRes<Self>
925    {
926        match raw >> 4
927        {
928            r if r == ProxyV2AddrType::AfUnspec.into() => 
929                return Ok(Self::AfUnspec),
930            r if r == ProxyV2AddrType::AfInet.into() => 
931                return Ok(Self::AfInet),
932            r if r == ProxyV2AddrType::AfInet6.into() => 
933                return Ok(Self::AfInet6),
934            r if r == ProxyV2AddrType::AfUnix.into() => 
935                return Ok(Self::AfUnix),
936            r => 
937                return_error!(ProtocolUnknownData, "can not decode address type: '{:02X}'", r),
938        }
939    }
940
941    pub 
942    fn get_size_by_addr_family(&self) -> Option<u16>
943    {
944        match self
945        {
946            Self::AfUnspec => 
947                return None,
948            Self::AfInet => 
949                return Some(Self::DEF_IPV4_ADDR_LEN),
950            Self::AfInet6 => 
951                return Some(Self::DEF_IPV6_ADDR_LEN),
952            Self::AfUnix => 
953                return Some(Self::DEF_UNIX_ADDR_LEN),
954        }
955    }
956}
957
958
959/// An address re-representation. Can be initialized using `TryFrom` 
960/// implementations.
961/// 
962/// TryFrom("ip:port", "ip:port")
963/// TryFrom(IpAddr, u16, IpAddr, u16)
964/// TryFrom(net::SocketAddr, net::SocketAddr)
965/// TryFrom(SocketAddr, SocketAddr)
966/// 
967/// The type will be determined automatically.
968#[derive(Clone, Debug)]
969pub enum ProxyV2Addr
970{
971    /// AF_INET, AF_INET6
972    Ip
973    {
974        src: SocketAddr,
975        dst: SocketAddr,
976    },
977
978    /// AF_UNIX
979    Unix
980    {
981        src: net::SocketAddr,
982        dst: net::SocketAddr,
983    }
984}
985
986impl Eq for ProxyV2Addr {}
987
988impl PartialEq for ProxyV2Addr
989{
990    fn eq(&self, other: &Self) -> bool 
991    {
992        match (self, other) 
993        {
994            (
995                Self::Ip { src: l_src, dst: l_dst }, 
996                Self::Ip { src: r_src, dst: r_dst }
997            ) => 
998                l_src == r_src && l_dst == r_dst,
999
1000            (
1001                Self::Unix { src: l_src, dst: l_dst }, 
1002                Self::Unix { src: r_src, dst: r_dst }
1003            ) => 
1004                l_src.as_pathname() == r_src.as_pathname() && l_dst.as_pathname() == r_dst.as_pathname(),
1005            _ => false,
1006        }
1007    }
1008}
1009
1010impl fmt::Display for ProxyV2Addr
1011{
1012    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1013    {
1014        match self
1015        {
1016            ProxyV2Addr::Ip{ src, dst } => 
1017                write!(f, "SRC: {}, DST: {}", src, dst),
1018            ProxyV2Addr::Unix{ src, dst } => 
1019                write!(f, "SRC: {:?}, DST: {:?}", src, dst)
1020        }
1021    }
1022}
1023
1024impl TryFrom<(IpAddr, u16, IpAddr, u16)> for ProxyV2Addr
1025{
1026    type Error = HaProxErr;
1027
1028    /// # Arguments
1029    /// 
1030    /// * `value.0` - source IP address [IpAddr]
1031    /// 
1032    /// * `value.1` - source port [u16]
1033    /// 
1034    /// * `value.2` - destination IP address [IpAddr]
1035    /// 
1036    /// * `value.3` - destination port [u16]
1037    fn try_from(value: (IpAddr, u16, IpAddr, u16)) -> Result<Self, Self::Error> 
1038    {
1039        let src = SocketAddr::new(value.0, value.1);
1040        let dst = SocketAddr::new(value.2, value.3);
1041
1042        return Ok(Self::Ip{ src: src, dst: dst });
1043    }
1044}
1045
1046impl TryFrom<(SocketAddr, SocketAddr)> for ProxyV2Addr
1047{
1048    type Error = HaProxErr;
1049
1050    /// # Arguments
1051    /// 
1052    /// * `value.0` - source address [SocketAddr]
1053    /// 
1054    /// * `value.1` - destination address [SocketAddr]
1055    fn try_from(value: (SocketAddr, SocketAddr)) -> Result<Self, Self::Error> 
1056    {
1057        return Ok(Self::Ip{ src: value.0, dst: value.1 });
1058    }
1059}
1060
1061/// Attempts to convert from tuple (source, dst) from [net::SocketAddr] into [ProxyV2Addr].  
1062impl TryFrom<(net::SocketAddr, net::SocketAddr)> for ProxyV2Addr
1063{
1064    type Error = HaProxErr;
1065
1066    /// # Arguments
1067    /// 
1068    /// * `value.0` - source address [net::SocketAddr]
1069    /// 
1070    /// * `value.1` - destination address [net::SocketAddr]
1071    fn try_from(value: (net::SocketAddr, net::SocketAddr)) -> Result<Self, Self::Error> 
1072    {
1073        return Ok(Self::Unix{ src: value.0, dst: value.1 });
1074    }
1075}
1076
1077/// Attempts to convert tuple (source, destination) from [str] into [ProxyV2Addr].
1078impl TryFrom<(&str, &str)> for ProxyV2Addr
1079{
1080    type Error = HaProxErr;
1081
1082    /// # Arguments
1083    /// 
1084    /// * `value.0` - source address [str]
1085    /// 
1086    /// * `value.1` - destination address [str]
1087    fn try_from(value: (&str, &str)) -> Result<Self, Self::Error> 
1088    {
1089        if let Ok(src) = SocketAddr::from_str(value.0)
1090        {
1091            let Ok(dst) = SocketAddr::from_str(value.1)
1092            else 
1093            {
1094                return_error!(ArgumentEinval, "can not convert '{}' to SocketAddr", 
1095                    common::sanitize_str_unicode(value.1));
1096            };
1097
1098            return Ok(Self::Ip{ src: src, dst: dst });
1099        }
1100        else if let Ok(src) = net::SocketAddr::from_pathname(value.0)
1101        {
1102            let Ok(dst) = net::SocketAddr::from_pathname(value.1)
1103            else 
1104            {
1105                return_error!(ArgumentEinval, "can not convert '{}' to net::SocketAddr", 
1106                    common::sanitize_str_unicode(value.1));
1107            };
1108
1109            return Ok(Self::Unix{ src: src, dst: dst });
1110        }
1111        else
1112        {
1113            return_error!(ArgumentEinval, "can not convert '{}' to either SocketAddr or net::SocketAddr", 
1114                common::sanitize_str_unicode(value.0));
1115        }
1116    }
1117}
1118
1119impl ProxyV2Addr
1120{
1121    /// Returns the length in bytes for the current address. It returns full size, but not
1122    /// the actual ocupied length (for unix addresses).
1123    #[inline]
1124    pub 
1125    fn get_len(&self) -> u16
1126    {
1127        return self.as_addr_family().get_size_by_addr_family().unwrap();
1128    }
1129
1130    /// Returns the address type.
1131    #[inline]
1132    pub 
1133    fn as_addr_family(&self) -> ProxyV2AddrType
1134    {
1135        match self
1136        {
1137            ProxyV2Addr::Ip{ src, .. } => 
1138            {
1139                if src.is_ipv4() == true
1140                {
1141                    return ProxyV2AddrType::AfInet;
1142                }
1143                else
1144                {
1145                    return ProxyV2AddrType::AfInet6;
1146                }
1147            }
1148            ProxyV2Addr::Unix{ .. } => 
1149                return ProxyV2AddrType::AfUnix
1150        }
1151    }
1152
1153    /// Reads the address section of the HaProxy. The address family should be 
1154    /// obtained from the same packet before. The `cur` must point to the beginning
1155    /// of the address block.
1156    /// 
1157    /// # Returns
1158    /// 
1159    /// The [Result] is returned. The [Option::None] will be returned only if the
1160    /// `addr_fam` is [ProxyV2AddrType::AfUnspec].
1161    pub 
1162    fn read(addr_fam: ProxyV2AddrType, cur: &mut Cursor<&[u8]>) -> HaProxRes<Option<Self>>
1163    {
1164        match addr_fam
1165        {
1166            ProxyV2AddrType::AfUnspec => Ok(None),
1167            ProxyV2AddrType::AfInet => 
1168            {
1169                let src = IpAddr::from(Ipv4Addr::from_bits(cur.read_u32::<BigEndian>().map_err(common::map_io_err)?));
1170                let dst = IpAddr::from(Ipv4Addr::from_bits(cur.read_u32::<BigEndian>().map_err(common::map_io_err)?));
1171                let src_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
1172                let dst_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
1173
1174                return Ok(Some(Self::try_from((src, src_port, dst, dst_port))?));
1175            },
1176            ProxyV2AddrType::AfInet6 => 
1177            {
1178                let src = IpAddr::from(Ipv6Addr::from_bits(cur.read_u128::<BigEndian>().map_err(common::map_io_err)?));
1179                let dst = IpAddr::from(Ipv6Addr::from_bits(cur.read_u128::<BigEndian>().map_err(common::map_io_err)?));
1180                let src_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
1181                let dst_port = cur.read_u16::<BigEndian>().map_err(common::map_io_err)?;
1182
1183                return Ok(Some(Self::try_from((src, src_port, dst, dst_port))?));
1184            },
1185            ProxyV2AddrType::AfUnix => 
1186            {
1187                let mut n_src: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
1188                cur.read(&mut n_src).map_err(common::map_io_err)?;
1189
1190                let mut n_dst: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
1191                cur.read(&mut n_dst).map_err(common::map_io_err)?;
1192
1193                let src_s = 
1194                    net::SocketAddr::from_pathname(
1195                        CStr::from_bytes_until_nul(&n_src)
1196                            .map_err(|e| 
1197                                map_error!(MalformedData, "cannot read unix path, error: {}", e)
1198                            )?
1199                            .to_str()
1200                            .map_err(|e|
1201                                map_error!(MalformedData, "cannot read unix path, error: {}", e)
1202                            )?
1203                    )
1204                    .map_err(|e|
1205                        map_error!(MalformedData, "cannot read unix path, error: {}", e)
1206                    )?;
1207
1208                let dst_s = 
1209                    net::SocketAddr::from_pathname(
1210                        CStr::from_bytes_until_nul(&n_dst)
1211                            .map_err(|e| 
1212                                map_error!(MalformedData, "cannot read unix path, error: {}", e)
1213                            )?
1214                            .to_str()
1215                            .map_err(|e|
1216                                map_error!(MalformedData, "cannot read unix path, error: {}", e)
1217                            )?
1218                    )
1219                    .map_err(|e|
1220                        map_error!(MalformedData, "cannot read unix path, error: {}", e)
1221                    )?;
1222
1223                return Ok(Some(Self::try_from((src_s, dst_s))?));
1224            },
1225        }
1226    }
1227
1228    /// Writes the content of the current instance to packet in format of 
1229    /// the HaProxy address. The `cur` [Cursor] should point to the
1230    /// beginning of the address block.
1231    pub  
1232    fn write(&self, cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()>
1233    {
1234        match self
1235        {
1236            ProxyV2Addr::Ip{ src, dst } => 
1237            {
1238                match src.ip()
1239                {
1240                    IpAddr::V4(ipv4_addr) => 
1241                        cur.write_u32::<BigEndian>(ipv4_addr.to_bits()).map_err(common::map_io_err)?,
1242                    IpAddr::V6(ipv6_addr) => 
1243                        cur.write_u128::<BigEndian>(ipv6_addr.to_bits()).map_err(common::map_io_err)?,
1244                }
1245
1246                match dst.ip()
1247                {
1248                    IpAddr::V4(ipv4_addr) => 
1249                        cur.write_u32::<BigEndian>(ipv4_addr.to_bits()).map_err(common::map_io_err)?,
1250                    IpAddr::V6(ipv6_addr) => 
1251                        cur.write_u128::<BigEndian>(ipv6_addr.to_bits()).map_err(common::map_io_err)?,
1252                }
1253
1254                cur.write_u16::<BigEndian>(src.port()).map_err(common::map_io_err)?;
1255                cur.write_u16::<BigEndian>(dst.port()).map_err(common::map_io_err)?;
1256            },
1257            ProxyV2Addr::Unix { src, dst } => 
1258            {
1259                let src_p = 
1260                    src.as_pathname().ok_or_else(|| map_error!(ArgumentEinval, "UNIX src socket addr is not path"))?;
1261                let dst_p = 
1262                    dst.as_pathname().ok_or_else(|| map_error!(ArgumentEinval, "UNIX src socket addr is not path"))?;
1263
1264                let src_b = src_p.as_os_str().as_bytes();
1265                let dst_b = dst_p.as_os_str().as_bytes();
1266
1267                if src_b.len() > HEADER_UNIX_ADDR_LEN
1268                {
1269                    return_error!(ArgumentEinval, "socket path: '{}' longer than: '{}'", 
1270                        src_p.display(), HEADER_UNIX_ADDR_LEN);
1271                }
1272                else if dst_b.len() > HEADER_UNIX_ADDR_LEN
1273                {
1274                    return_error!(ArgumentEinval, "socket path: '{}' longer than: '{}'", 
1275                        dst_p.display(), HEADER_UNIX_ADDR_LEN);
1276                }
1277
1278                
1279                let mut n_src: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
1280                n_src[0..src_b.len()].copy_from_slice(src_b);
1281
1282                cur.write_all(&n_src).map_err(common::map_io_err)?;
1283
1284                let mut n_dst: [u8; HEADER_UNIX_ADDR_LEN] = [0_u8; HEADER_UNIX_ADDR_LEN];
1285                n_dst[0..dst_b.len()].copy_from_slice(dst_b);
1286
1287                cur.write_all(&n_dst).map_err(common::map_io_err)?;
1288            }
1289        }
1290
1291        return Ok(());
1292    }
1293}
1294
1295/// A transport family.
1296/// > Other values are unspecified and must not be emitted in version 2 of this
1297/// > protocol and must be rejected as invalid by receivers.`
1298#[repr(u8)]
1299#[derive(Clone, Debug, PartialEq, Eq)]
1300pub enum ProxyTransportFam
1301{
1302    /// > the connection is forwarded for an unknown, unspecified
1303    /// > or unsupported protocol. The sender should use this family when sending
1304    /// > LOCAL commands or when dealing with unsupported protocol families. The
1305    /// > receiver is free to accept the connection anyway and use the real endpoint
1306    /// > addresses or to reject it. The receiver should ignore address information.
1307    UNSPEC = 0x00,
1308
1309    /// > the forwarded connection uses a SOCK_STREAM protocol (eg:
1310    /// > TCP or UNIX_STREAM). When used with AF_INET/AF_INET6 (TCP), the addresses
1311    /// > are followed by the source and destination ports represented on 2 bytes
1312    /// > each in network byte order.
1313    STREAM,
1314
1315    /// > the forwarded connection uses a SOCK_DGRAM protocol (eg:
1316    /// > UDP or UNIX_DGRAM). When used with AF_INET/AF_INET6 (UDP), the addresses
1317    /// > are followed by the source and destination ports represented on 2 bytes
1318    /// > each in network byte order.
1319    DGRAM,
1320}
1321
1322impl fmt::Display for ProxyTransportFam
1323{
1324    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
1325    {
1326        match self
1327        {
1328            Self::UNSPEC => write!(f, "UNSPEC"),
1329            Self::STREAM => write!(f, "STREAM"),
1330            Self::DGRAM => write!(f, "DGRAM"),
1331        }
1332    }
1333}
1334
1335impl From<ProxyTransportFam> for u8
1336{
1337    fn from(value: ProxyTransportFam) -> Self 
1338    {
1339        return value as u8;
1340    }
1341}
1342
1343impl From<&ProxyTransportFam> for u8
1344{
1345    fn from(value: &ProxyTransportFam) -> Self 
1346    {
1347        return unsafe { *<*const _>::from(value).cast::<Self>() };
1348    }
1349}
1350
1351impl ProxyTransportFam
1352{
1353    pub(crate) 
1354    fn decode(value: u8) -> HaProxRes<Self>
1355    {
1356        match value & protocol_raw::ProxyHdrV2::TRANSPT_MASK
1357        {
1358            v if ProxyTransportFam::UNSPEC as u8 == v => 
1359                return Ok(Self::UNSPEC),
1360            v if ProxyTransportFam::STREAM as u8 == v => 
1361                return Ok(Self::STREAM),
1362            v if ProxyTransportFam::DGRAM as u8 == v => 
1363                return Ok(Self::DGRAM),
1364            _ => 
1365                return_error!(ProtocolUnknownData, "unknown transport {:02X}", value)
1366        }
1367    }
1368}
1369
1370#[cfg(test)]
1371mod tests
1372{
1373    use core::fmt;
1374    use std::{slice, time::Instant};
1375
1376    use crate::{protocol_raw::{self, HEADER_MAGIC_V2, HEADER_MAGINC_LEN}, protocol_v2::{PP2TlvUniqId, protocol::{PP2TlvClient, ProxyTransportFam, ProxyV2Addr}, protocol_composer::{HdrV2OpLocal, HdrV2OpProxy, ProxyHdrV2}}};
1377    #[test]
1378    fn test_hdr1()
1379    {
1380        
1381        for _ in 0..10
1382        {
1383            let s = Instant::now();
1384            let _local = ProxyHdrV2::<HdrV2OpLocal>::new();
1385
1386            let e = s.elapsed();
1387
1388            println!("{:?}", e);
1389        }
1390
1391        let buf = ProxyHdrV2::<HdrV2OpLocal>::new();
1392
1393
1394        
1395        let mut sign: [u8; HEADER_MAGINC_LEN] = [0_u8; HEADER_MAGINC_LEN];
1396        sign.copy_from_slice(HEADER_MAGIC_V2);
1397        let ctrl =
1398            vec![
1399                protocol_raw::ProxyHdrV2
1400                {
1401                    signature: sign,
1402                    ver_cmd: 0x20,
1403                    fam: 0,
1404                    len: 0,
1405                    address: [],
1406                }
1407            ];
1408
1409            println!("{} {}", buf.len(), size_of::<protocol_raw::ProxyHdrV2>());
1410        let ctrl_buf = unsafe { slice::from_raw_parts(ctrl.as_ptr() as *const _ as *const u8, size_of::<protocol_raw::ProxyHdrV2>()) };
1411
1412        assert_eq!(buf.as_slice(), ctrl_buf);
1413    }
1414
1415    #[test]
1416    fn test_proxy_compose()
1417    {
1418        struct UniqIdHolder;
1419        impl UniqIdHolder
1420        {
1421            const ID: &'static [u8] = b"ABCD12345678901234567890";
1422        }
1423        impl fmt::Display for UniqIdHolder
1424        {
1425            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result 
1426            {
1427                write!(f, "")
1428            }
1429        }
1430        impl PP2TlvUniqId for UniqIdHolder
1431        {
1432            fn into_bytes(&self) -> Vec<u8> 
1433            {
1434                Self::ID.to_vec()
1435            }
1436
1437            fn as_slice<'a>(&'a self) -> &'a [u8] 
1438            {
1439                Self::ID    
1440            }
1441        
1442            fn get_len(&self) -> u16 
1443            {
1444                Self::ID.len() as u16
1445            }
1446        }
1447        for _ in 0..10
1448        {
1449            let addr: ProxyV2Addr = ProxyV2Addr::try_from(("127.0.0.1:4567", "127.0.0.1:443")).unwrap();
1450            let id = UniqIdHolder;
1451
1452            let s = Instant::now();
1453            let mut proxy = 
1454                ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
1455
1456            let mut plts = proxy.set_plts();
1457            plts.add_crc32().unwrap();
1458            plts.add_authority("www.example.com").unwrap();
1459            plts.add_uniq_id(id).unwrap();
1460            drop(plts);
1461
1462            let e = s.elapsed();
1463
1464            println!("prep: {:?}", e);
1465        
1466            let s = Instant::now();
1467            let _buf: Vec<u8> = proxy.try_into().unwrap();
1468            let e = s.elapsed();
1469
1470            println!("{:?}", e);
1471        }
1472
1473       // assert_eq!(buf.as_slice(), ctrl_buf);
1474       return;
1475    }
1476
1477    #[test]
1478    fn test_hdr2()
1479    {
1480        let addr: ProxyV2Addr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
1481
1482        let s = Instant::now();
1483        let mut proxy = 
1484            ProxyHdrV2::<HdrV2OpProxy>::new(ProxyTransportFam::STREAM, addr).unwrap();
1485      
1486        let plts = proxy.set_plts();
1487
1488        let mut sub_ssl = plts.add_ssl(PP2TlvClient::PP2_CLIENT_SSL, 0).unwrap();
1489
1490        sub_ssl.add_ssl_sub_version("TLSv1.2").unwrap();
1491
1492        sub_ssl.done().unwrap();
1493
1494
1495        let e = s.elapsed();
1496
1497        println!("prep: {:?}", e);
1498
1499        let s = Instant::now();
1500        let buf: Vec<u8> = proxy.try_into().unwrap();
1501        let e = s.elapsed();
1502
1503        println!("{:?}", e);
1504        
1505        
1506        let reference = 
1507            b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x1e\
1508            \x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
1509            \x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32";
1510
1511        //println!("{:02X?}\n{:02X?}", buf.as_slice(), reference.as_slice());
1512
1513        assert_eq!(buf.as_slice(), reference.as_slice());
1514    }
1515}