haprox_rs/protocol/
protocol_parser.rs

1/*-
2 * haprox-rs - a HaProxy protocol parser.
3 * 
4 * Copyright 2025 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. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
11 */
12
13use std::mem::offset_of;
14use std::{borrow::Cow, fmt, io::Cursor, marker::PhantomData};
15use std::io::Read;
16use byteorder::{BigEndian, ReadBytesExt};
17use crc32fast::Hasher;
18
19use crate::common::map_io_err;
20use crate::{common, error::{HaProxErr, HaProxRes}, map_error, return_error};
21
22use super::
23{
24    protocol::
25    {
26        HdrV2Command, 
27        PP2TlvClient, 
28        PP2Tlvs, 
29        ProtocolVersion, 
30        ProxyTransportFam, 
31        ProxyV2Addr, 
32        ProxyV2AddrType
33    }, 
34    protocol_raw, 
35    PP2TlvRestore
36};
37
38/// A HaProxy V2 parser main instance.
39pub struct ProxyV2Parser<'t, EXT: PP2TlvRestore = ProxyV2Dummy>
40{
41    /// A received packed which should contain the proxy pkt.
42    buffer: &'t [u8],
43
44    /// Phantom for the extension for the protocol.
45    _p: PhantomData<EXT>
46}
47
48impl<'t> ProxyV2Parser<'t>
49{
50    /// Constructs the instance from the temporary reference to the buffer. 
51    pub 
52    fn try_from_slice(value: &'t [u8]) -> HaProxRes<Self>
53    {
54        let pkt_size = Self::new_from(value)?;
55
56        let tmp = Self{ buffer: &value[0..pkt_size], _p: PhantomData };
57
58        tmp.post_check()?;
59
60        return Ok(tmp);
61    }
62}
63
64impl<'t, EXT: PP2TlvRestore> ProxyV2Parser<'t, EXT>
65{
66    /// Constructs the instance from the temporary reference to the buffer
67    /// with custom extenal TLV parser for custom TLV extensions.
68    pub 
69    fn try_from_slice_custom(value: &'t [u8]) -> HaProxRes<Self>
70    {
71        let pkt_size = Self::new_from(value)?;
72
73        let tmp = Self{ buffer: &value[0..pkt_size], _p: PhantomData };
74
75        tmp.post_check()?;
76
77        return Ok(tmp);
78    }
79}
80
81impl<'t, EXT: PP2TlvRestore> ProxyV2Parser<'t, EXT>
82{
83    fn post_check(&self) -> HaProxRes<()>
84    {
85        let _ = self.get_address_family()?;
86        let _ = self.get_transport()?;
87
88        return Ok(());
89    }
90
91    /// Internal function.
92    /// 
93    /// Checks the header for the specific pattern to determine if this is a HaProxy
94    /// mesage and if it initial header bits are valid.
95    fn new_from(value: &[u8]) -> HaProxRes<usize>
96    {
97        if value.len() <= protocol_raw::HEADER_MAGIC_V1.len()
98        {
99            return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown", 
100                value);
101        }
102        else if &value[0..protocol_raw::HEADER_MAGIC_V1.len()] == protocol_raw::HEADER_MAGIC_V1
103        {
104            return_error!(ProtocolNotSuported, "V1 protocol is not supported");
105        }
106        else if value.len() < size_of::<protocol_raw::ProxyHdrV2>()
107        {
108            return_error!(ProtocolMsgIncomplete, "protocol with footprint '{:02X?}' unknown", 
109                value);
110        }
111        else if &value[0..protocol_raw::HEADER_MAGIC_V2.len()] != protocol_raw::HEADER_MAGIC_V2
112        {
113            return_error!(IncorrectBanner, "protocol with footprint '{:02X?}' unknown", 
114                value);
115        }
116        else if value[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)] & protocol_raw::ProxyHdrV2::VERSION_MASK != 
117            protocol_raw::ProxyHdrV2::VERSION_RAW
118        {
119            return_error!(MalformedData, "protocol version '{:02X?}' incorrect", 
120                value[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
121        }
122
123        let payload_len =  
124            [
125                value[offset_of!(protocol_raw::ProxyHdrV2, len)],
126                value[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
127            ];
128
129        let full_size = u16::from_be_bytes(payload_len) + protocol_raw::ProxyHdrV2::HEADER_LEN as u16;
130
131        if value.len() < full_size as usize
132        {
133            return_error!(ProtocolMsgIncomplete, "fragmented pkt received, declared len + header: {}, received len: {}",
134                full_size, value.len());
135        }
136
137        return Ok(full_size as usize);
138    }
139
140    /// Extracts and decodes the protocol version from the packet.
141    pub 
142    fn get_proto_version(&self) -> ProtocolVersion
143    {
144        return ProtocolVersion::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
145    }
146
147    /// Extracts and decodes the protocol command code from the packet.
148    pub 
149    fn get_proto_command(&self) -> HdrV2Command
150    {
151        return HdrV2Command::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, ver_cmd)]);
152    }
153
154    /// Extracts and decodes the transport type from the packet.
155    pub 
156    fn get_transport(&self) -> HaProxRes<ProxyTransportFam>
157    {
158        return ProxyTransportFam::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, fam)]);
159    }
160
161    /// Extracts and decodes the address family from the packet. It doesnot extract address. 
162    pub 
163    fn get_address_family(&self) -> HaProxRes<ProxyV2AddrType>
164    {
165        return ProxyV2AddrType::decode(self.buffer[offset_of!(protocol_raw::ProxyHdrV2, fam)]);
166    }
167
168    /// Returns the size of the packet (without header len).
169    pub 
170    fn get_palyload_len(&self) -> u16
171    {
172        let hi =  
173            [
174                self
175                    .buffer[offset_of!(protocol_raw::ProxyHdrV2, len)],
176                self
177                    .buffer[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
178            ];
179            
180
181        return u16::from_be_bytes(hi);
182    }
183
184    /// Returns the full size of the packet.
185    pub 
186    fn get_full_len(&self) -> u16
187    {
188        let hi =  
189            [
190                self
191                    .buffer[offset_of!(protocol_raw::ProxyHdrV2, len)],
192                self
193                    .buffer[offset_of!(protocol_raw::ProxyHdrV2, len)+1]
194            ];
195            
196
197        return u16::from_be_bytes(hi) + protocol_raw::ProxyHdrV2::HEADER_LEN as u16;
198    }
199
200    /// Extracts the address section from the packet. The address family can be obtained from the 
201    /// returned instance.
202    /// 
203    /// # Returns
204    /// 
205    /// A [HaProxRes] is returned with:
206    /// 
207    /// * [Result::Ok] - the  [Option] with:
208    /// 
209    /// * * [Option::Some] - a parsed address is returned in form of [ProxyV2Addr]
210    /// 
211    /// * * [Option::None] - if address family is unspecified.
212    /// 
213    /// * [Result::Err] - an error description.
214    pub 
215    fn get_address(&self) -> HaProxRes<Option<ProxyV2Addr>>
216    {
217        let addr_fam = self.get_address_family()?;
218
219        let Some(addr_len) = addr_fam.get_size_by_addr_family()
220        else { return Ok(None) };
221
222        let buf_len = self.buffer.len() - size_of::<protocol_raw::ProxyHdrV2>();
223
224        if buf_len < addr_len as usize
225        {
226            return_error!(ProtocolMsgIncomplete, "cannot read address, msg len: '{}', addr len: '{}'", 
227                buf_len, addr_len);
228        }
229
230        let mut cur = Cursor::new(&self.buffer.as_ref()[offset_of!(protocol_raw::ProxyHdrV2, address)..]);
231
232        return ProxyV2Addr::read(addr_fam, &mut cur);
233    }
234
235    /// Creates an iterator over TLVs which could be in the payload of the packer. This is flat iterator i.e if
236    /// TLV contains a subcodes, it will be returned as it is just in a 1D array. You should track
237    /// if item contains a subcode and a subcode is returned.
238    pub 
239    fn get_tlvs_iter(&self) -> Option<ProxyV2TlvIter<'_, EXT>>
240    {
241        let addr_fam = self.get_address_family().ok()?.get_size_by_addr_family()?;
242
243        if self.get_palyload_len() - addr_fam == 0
244        {
245            return None;
246        }
247
248        let addr_size = self.get_address_family().ok()?.get_size_by_addr_family()? as usize;
249
250        let tlv_offset_start = 
251            offset_of!(protocol_raw::ProxyHdrV2, address) + addr_size;
252
253        let itr = 
254            ProxyV2TlvIter
255            {
256                curs: 
257                    vec![
258                        ProxyV2TlvIterTlv
259                        {
260                            cur: Cursor::new(&self.buffer.as_ref()[tlv_offset_start..]),
261                            parent_tlv_idx: None,
262                        },
263                    ],
264                _p: PhantomData
265            };
266
267        return Some(itr);
268    }
269
270    /// Calculates the CRC of message and returns the result.
271    pub 
272    fn check_crc(&self) -> HaProxRes<bool>
273    {
274        /*let PP2Tlvs::TypeCrc32c(crcpkt) = crc 
275            else { return_error!(ArgumentEinval, "PP2Tlvs type is not TypeCrc32c") };*/
276
277        let mut crc32: Option<u32> = None;
278
279        // init hasher
280        let mut hasher = Hasher::new();
281
282        let addr_fam_len = 
283            self
284                .get_address_family()?
285                .get_size_by_addr_family()
286                .ok_or_else(||
287                    map_error!(ArgumentEinval, "unknown address family")
288                )? as usize;
289
290        
291        let full_hdr_len = addr_fam_len + protocol_raw::ProxyHdrV2::HEADER_LEN;
292        
293        // calculate crc header
294        hasher.update(&self.buffer[0..full_hdr_len]);
295
296        let payload_len = self.get_palyload_len() as usize - addr_fam_len;
297
298        let mut cur = Cursor::new(&self.buffer[full_hdr_len..]);
299
300        while cur.position() < payload_len as u64
301        {
302            let s = cur.position() as usize;
303
304            let op = cur.read_u8().map_err(map_io_err)?;
305            let len = cur.read_u16::<BigEndian>().map_err(map_io_err)?;
306
307            if op == PP2Tlvs::TYPE_CRC32C
308            {
309                crc32 = Some(cur.read_u32::<BigEndian>().map_err(map_io_err)?);
310
311                hasher.update(&[op]);
312                hasher.update(len.to_be_bytes().as_slice());
313                hasher.update(&[0]);
314            }
315            else
316            {
317                let last = s+2+len as usize;
318
319                hasher.update(&self.buffer[s..last]);
320                cur.set_position(last as u64);
321            }
322        }
323
324        if let Some(cr) = crc32
325        {
326            return Ok(cr == hasher.finalize());
327        }
328        else
329        {
330            return_error!(ArgumentEinval, "no CRC TLV found!");
331        }
332    }
333}
334
335
336/// A dummy implementation of the TVL protocol extension.
337#[derive(Clone, Debug)]
338pub enum ProxyV2Dummy {}
339
340impl fmt::Display for ProxyV2Dummy
341{
342    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
343    {
344        write!(f, "DUMMY external reader")
345    }
346}
347
348impl PP2TlvRestore for ProxyV2Dummy
349{
350    fn restore(_tlv_type: u8, _cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized 
351    {
352        return_error!(ArgumentEinval, "assertion trap, DUMMY external decoder");
353    }
354    
355    fn is_in_range(_tlv_type: u8, _tlv_parent_type: Option<u8>) -> bool 
356    {
357        return false;
358    }
359
360    fn contains_subtype(&self) -> bool 
361    {
362        return false;
363    }
364}
365
366/// Implementation of the [PP2TlvRestore] for the build-in protocol [PP2Tlvs] items.
367impl PP2TlvRestore for PP2Tlvs
368{
369    fn contains_subtype(&self) -> bool 
370    {
371        return self.contains_subtype();    
372    }
373
374    fn is_in_range(tlv_type: u8, tlv_parent_type: Option<u8>) -> bool 
375    {
376        if let Some(p_tlv) = tlv_parent_type
377        {
378            if p_tlv == Self::TYPE_SSL
379            {
380                return Self::TLV_TYPE_SSL_SUB_RANGE.iter().any(|tlv| tlv.contains(&tlv_type));
381            }
382            else
383            {
384                return false;
385            }
386        }
387
388        return Self::TLV_TYPE_MAIN_RANGES.iter().any(|tlv| tlv.contains(&tlv_type));
389    }
390
391    fn restore(tlv_type: u8, cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized 
392    {
393        let tlv_len = cur.get_ref().len();
394
395        match tlv_type
396        {
397            Self::TYPE_ALPN =>
398            {
399                let mut alpns: Vec<Vec<u8>> = Vec::with_capacity(2);
400
401                while let Some(alpn_len) = cur.read_u16::<BigEndian>().ok()
402                {
403                    let mut alpn: Vec<u8> = vec![0_u8; alpn_len as usize];
404
405                    cur.read_exact(&mut alpn).map_err(common::map_io_err)?;
406
407                    alpns.push(alpn);
408                }
409
410                return Ok(Self::TypeAlpn(alpns));
411            },
412            Self::TYPE_AUTHORITY =>
413            {
414                let mut authority: Vec<u8> = vec![0_u8; tlv_len];
415
416                cur.read_exact(&mut authority).map_err(common::map_io_err)?;
417
418                return Ok(
419                    Self::TypeAuthority(
420                        String::from_utf8(authority)
421                            .map_err(|e| 
422                                map_error!(MalformedData, "TLV TYPE_AUTHORITY restore error: '{}'", e)
423                            )?
424                    )
425                );
426            },
427            Self::TYPE_CRC32C => 
428            {
429                let crc = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
430
431                return Ok(Self::TypeCrc32c(crc));
432            },
433            Self::TYPE_NOOP => 
434            {
435                return Ok(Self::TypeNoop);
436            },
437            Self::TYPE_UNIQID =>
438            {
439                let mut authority: Vec<u8> = vec![0_u8; tlv_len];
440
441                cur.read_exact(&mut authority).map_err(common::map_io_err)?;
442
443                return Ok(
444                    Self::TypeUniqId(authority)
445                );
446            },
447            Self::TYPE_SSL =>
448            {
449                let client_bits = cur.read_u8().map_err(common::map_io_err)?;
450
451                let client = 
452                    PP2TlvClient::from_bits(client_bits)
453                        .ok_or_else(|| map_error!(ProtocolUnknownData, "TLV TYPE_SSL unknown client bits: {}", client_bits))?;
454
455                let verify = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
456
457                return Ok(
458                    Self::TypeSsl{ client: client, verify: verify }
459                );
460            },
461            Self::TYPE_SUBTYPE_SSL_VERSION => 
462            {
463                let mut ssl_version: Vec<u8> = vec![0_u8; tlv_len];
464
465                cur.read_exact(&mut ssl_version).map_err(common::map_io_err)?;
466
467                let ssl_version_str = 
468                    String::from_utf8(ssl_version)
469                        .map_err(|e| 
470                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
471                        )?;
472
473                return Ok(
474                    Self::TypeSubtypeSslVersion(Cow::Owned(ssl_version_str))
475                );
476            },
477            Self::TYPE_SUBTYPE_SSL_CN =>
478            {
479                let mut ssl_cn: Vec<u8> = vec![0_u8; tlv_len];
480
481                cur.read_exact(&mut ssl_cn).map_err(common::map_io_err)?;
482
483                let ssl_cn = 
484                    String::from_utf8(ssl_cn)
485                        .map_err(|e| 
486                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
487                        )?;
488
489                return Ok(
490                    Self::TypeSubtypeSslCn(Cow::Owned(ssl_cn))
491                );
492            },
493            Self::TYPE_SUBTYPE_SSL_CIPHER => 
494            {
495                let mut ssl_cipher: Vec<u8> = vec![0_u8; tlv_len];
496
497                cur.read_exact(&mut ssl_cipher).map_err(common::map_io_err)?;
498
499                let ssl_cipher = 
500                    String::from_utf8(ssl_cipher)
501                        .map_err(|e| 
502                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
503                        )?;
504
505                return Ok(
506                    Self::TypeSubtypeSslCipher(Cow::Owned(ssl_cipher))
507                );
508            },
509            Self::TYPE_SUBTYPE_SSL_SIGALG =>
510            {
511                let mut ssl_sigalg: Vec<u8> = vec![0_u8; tlv_len];
512
513                cur.read_exact(&mut ssl_sigalg).map_err(common::map_io_err)?;
514
515                let ssl_sigalg = 
516                    String::from_utf8(ssl_sigalg)
517                        .map_err(|e| 
518                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
519                        )?;
520
521                return Ok(
522                    Self::TypeSubtypeSslSigAlg(Cow::Owned(ssl_sigalg))
523                );
524            },
525            Self::TYPE_SUBTYPE_SSL_KEYALG =>
526            {
527                let mut ssl_keyalg: Vec<u8> = vec![0_u8; tlv_len];
528
529                cur.read_exact(&mut ssl_keyalg).map_err(common::map_io_err)?;
530
531                let ssl_keyalg = 
532                    String::from_utf8(ssl_keyalg)
533                        .map_err(|e| 
534                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
535                        )?;
536
537                return Ok(
538                    Self::TypeSubtypeSslKeyAlg(Cow::Owned(ssl_keyalg))
539                );
540            },
541            Self::TYPE_NETNS => 
542            {
543                let mut netns: Vec<u8> = vec![0_u8; tlv_len];
544
545                cur.read_exact(&mut netns).map_err(common::map_io_err)?;
546
547                let netns = 
548                    String::from_utf8(netns)
549                        .map_err(|e| 
550                            map_error!(MalformedData, "TLV TYPE_SUBTYPE_SSL_VERSION restore error: '{}'", e)
551                        )?;
552
553                return Ok(
554                    Self::TypeNetNs(netns)
555                );
556            },
557            _ => 
558                return_error!(ProtocolUnknownData, "unknown TLV type: {}", tlv_type)
559        }
560    }
561}
562
563/// An `enum` which is returned by the TLV iterator. It may contain either parsed TLV or 
564/// error description which occured during parsing. Normally, in case of error, the 
565/// parsing should be stopped and connection dropped.
566#[derive(Debug, Clone, PartialEq, Eq)]
567pub enum ProxyV2TlvSource<EXT: PP2TlvRestore>
568{
569    /// A base implementation of the protocl.
570    Internal(PP2Tlvs),
571
572    /// A user's extension to the protocol.
573    External(EXT),
574    
575    /// Error during parsing.
576    Error(HaProxErr),
577}
578
579impl<EXT: PP2TlvRestore> ProxyV2TlvSource<EXT>
580{
581    fn new_internal(pp2: HaProxRes<PP2Tlvs>) -> Self
582    {
583        return 
584            pp2.map_or_else(|e| Self::Error(e), |f| Self::Internal(f));
585    }
586
587    fn new_external(pp2: HaProxRes<EXT>) -> Self
588    {
589        return 
590            pp2.map_or_else(|e| Self::Error(e), |f| Self::External(f));
591    }
592
593    fn new_error(err: HaProxErr) -> Self
594    {
595        return Self::Error(err);
596    }
597
598    fn new_io_error(err: std::io::Error) -> Self
599    {
600        return Self::Error(map_error!(IoError, "while reading TLV, error: {}", err));
601    }
602
603    /// Consumes the instance returning the [PP2Tlvs] build-in TLV through [Option]. 
604    /// If instance os not `Internal` then instance will be lost.
605    pub 
606    fn take_internal(self) -> Option<PP2Tlvs>
607    {
608        let Self::Internal(s) = self else {return None};
609
610        return Some(s);
611    }
612
613    /// Consumes the instance returning the [PP2Tlvs] build-in TLV through [Option]. 
614    /// If instance os not `External` then instance will be lost.
615    pub 
616    fn take_external(self) -> Option<EXT>
617    {
618        let Self::External(s) = self else {return None};
619
620        return Some(s);
621    }
622
623    /// Checks if current instance constains the subtype. For `Error` `false` is
624    /// always returned.
625    pub 
626    fn contains_subtype(&self) -> bool
627    {
628        match self
629        {
630            Self::Internal(i) => 
631                return i.contains_subtype(),
632            Self::External(e) => 
633                return e.contains_subtype(),
634            _ => 
635                return false
636        }
637    }
638    
639}
640
641/// TLV iterator instance.
642#[derive(Debug)]
643struct ProxyV2TlvIterTlv<'iter>
644{
645    /// A cursor to the current data.
646    cur: Cursor<&'iter [u8]>,
647
648    /// A parent (previous) TLV's ID.
649    parent_tlv_idx: Option<u8>,
650}
651
652/// A multilayer iterator instance.
653#[derive(Debug)]
654pub struct ProxyV2TlvIter<'iter, EXT>
655{
656    /// A heap of the cursors. If iterator reaches subtype, the
657    /// previous cursor will be pushed to heap.
658    curs: Vec<ProxyV2TlvIterTlv<'iter>>,
659
660    /// A phantom.
661    _p: PhantomData<EXT>
662}
663
664impl<'iter, EXT: PP2TlvRestore> ProxyV2TlvIter<'iter, EXT>
665{
666    fn get_last_cur(&self) -> &Cursor<&'iter [u8]>
667    {
668        return &self.curs.last().unwrap().cur;
669    }
670
671    fn get_last_mut_cur(&mut self) -> &mut Cursor<&'iter [u8]>
672    {
673        return &mut self.curs.last_mut().unwrap().cur;
674    }
675
676    fn get_parent_tlv(&self) -> Option<u8>
677    {
678        return self.curs.last().unwrap().parent_tlv_idx;
679    }
680
681    /*
682    fn get_last_cur(&self) -> &ProxyV2TlvIterTlv<'iter>
683    {
684        return self.curs.last().unwrap();
685    }
686
687    fn get_last_mut_cur(&mut self) -> &mut ProxyV2TlvIterTlv<'iter>
688    {
689        return self.curs.last_mut().unwrap();
690    }
691     */
692}
693
694impl<'iter, EXT: PP2TlvRestore> Iterator for ProxyV2TlvIter<'iter, EXT>
695{
696    type Item = ProxyV2TlvSource<EXT>;
697
698    fn next(&mut self) -> Option<Self::Item> 
699    {
700        // check if the end of the section was reached
701        if self.get_last_cur().get_ref().len() <= self.get_last_cur().position() as usize
702        {
703            if self.curs.len() == 1
704            {
705                // nothing left
706                return None;
707            }
708            else
709            {
710                // return back on one level
711                let _ = self.curs.pop();
712
713                return self.next();
714            }
715        }
716
717        // read type of the tlv
718        let tlv_type = 
719            match self.get_last_mut_cur().read_u8()
720            {
721                Ok(r) => r,
722                Err(e) =>
723                    return Some(ProxyV2TlvSource::new_io_error(e)),
724            };
725
726        // read length of the tlv's payload
727        let tlv_len = 
728            match self.get_last_mut_cur().read_u16::<BigEndian>()
729            {
730                Ok(r) => r,
731                Err(e) => 
732                    return Some(ProxyV2TlvSource::new_io_error(e)),
733            };
734
735        let tlv_range = 
736            self.get_last_cur().position() as usize .. (self.get_last_cur().position()+ tlv_len as u64) as usize;
737
738
739        // creating a cursor from slice to prevent parser going out of bounds by the declared size
740        let mut cur = 
741            Cursor::new(&self.get_last_cur().get_ref()[tlv_range]);
742
743        
744        // check in which range it is
745        let next_item = 
746            if PP2Tlvs::is_in_range(tlv_type, self.get_parent_tlv()) == true
747            {
748                ProxyV2TlvSource::new_internal(
749                    PP2Tlvs::restore(tlv_type, &mut cur)
750                )
751            }
752            else if EXT::is_in_range(tlv_type, self.get_parent_tlv()) == true
753            {
754                ProxyV2TlvSource::new_external(
755                    EXT::restore(tlv_type, &mut cur)
756                )
757            }
758            else
759            {
760                ProxyV2TlvSource::new_error(
761                    map_error!(ProtocolUnknownData, "TLV tpye: '{}' out of int/ext ranges", tlv_type)
762                )
763            };
764
765        // move cursor position forward
766        let new_pos = self.get_last_cur().position()+ tlv_len as u64;
767        self.get_last_mut_cur().set_position(new_pos);
768
769        if next_item.contains_subtype() == true
770        {
771            // push the current cursor
772            self.curs.push(
773                ProxyV2TlvIterTlv
774                {
775                    cur: cur,
776                    parent_tlv_idx: Some(tlv_type),
777                }
778            );
779        }
780
781        return Some(next_item);
782    }
783}
784
785#[cfg(test)]
786mod tests
787{
788    use std::{fmt, io::Cursor};
789
790    use byteorder::{BigEndian, ReadBytesExt};
791
792    use crate::{common, error::HaProxRes, protocol::{protocol::{HdrV2Command, PP2TlvClient, PP2Tlvs, ProtocolVersion, ProxyTransportFam, ProxyV2Addr, ProxyV2AddrType, PP2_TYPE_MIN_CUSTOM}, protocol_raw, PP2TlvDump, PP2TlvRestore}, return_error};
793
794    use super::ProxyV2Parser;
795
796    #[test]
797    fn test_0()
798    {
799        let pkt_ssl = 
800b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x2a\
801\x7f\x00\x00\x01\x7f\x00\x00\x43\x9d\xd2\x2e\x6b\x20\x00\x1b\x07\
802\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\x22\x00\
803\x09\x6d\x71\x74\x74\x75\x73\x65\x72\x31";
804
805        let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
806
807        assert_eq!(dec.get_transport().is_ok(), true);
808        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
809
810        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
811        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
812
813        assert_eq!(dec.get_address_family().is_ok(), true);
814        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
815
816        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
817        
818        let addr = dec.get_address().unwrap();
819
820        assert_eq!(addr.is_some(), true);
821
822        let addr = addr.unwrap();
823        let maddr = ProxyV2Addr::try_from(("127.0.0.1:40402", "127.0.0.67:11883")).unwrap();
824
825        assert_eq!(addr, maddr);
826
827        let tlv_iter = dec.get_tlvs_iter();
828
829        assert_eq!(tlv_iter.is_some(), true);
830
831        let mut tlv_iter = tlv_iter.unwrap();
832
833        let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
834
835        assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
836        let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
837
838        assert_eq!(client, PP2TlvClient::all());
839        assert_eq!(verify, 0);
840
841        let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
842
843        assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
844
845        let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
846
847        assert_eq!(ssl_version, "TLSv1.2");
848
849        let type_ssl_cn = tlv_iter.next().unwrap().take_internal().unwrap();
850
851        assert_eq!(type_ssl_cn.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_CN);
852
853        let PP2Tlvs::TypeSubtypeSslCn(ssl_cn) = type_ssl_cn else { panic!("wrong") };
854
855        assert_eq!(ssl_cn, "mqttuser1");
856    }
857
858    #[test]
859    fn test_1()
860    {
861
862        #[derive(Clone, Debug)]
863        pub enum ProxyV2Dummy2 
864        {
865            SomeTlvName(u32, u32),
866            OtherTlv,
867        }
868
869        impl fmt::Display for ProxyV2Dummy2
870        {
871            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
872            {
873                write!(f, "DUMMY external reader")
874            }
875        }
876
877        impl PP2TlvRestore for ProxyV2Dummy2
878        {
879            fn restore(tlv_type: u8, cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized 
880            {
881                match tlv_type
882                {
883                    0xE0 =>
884                    {
885                        let arg0 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
886                        let arg1 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
887
888                        return Ok(Self::SomeTlvName(arg0, arg1));
889                    },
890                    _ => 
891                        return_error!(ProtocolUnknownData, "unknown tlv_type: {}", tlv_type)
892                }
893                
894            }
895            
896            fn is_in_range(tlv_type: u8, _tlv_parent_type: Option<u8>) -> bool 
897            {
898                return tlv_type == PP2_TYPE_MIN_CUSTOM;
899            }
900            
901            fn contains_subtype(&self) -> bool 
902            {
903                return false;
904            }
905        }
906
907        impl PP2TlvDump for ProxyV2Dummy2
908        {
909            fn get_type(&self) -> u8 
910            {
911                let Self::SomeTlvName(..) = self else { panic!("wrong") };
912
913                return 0xE0;
914            }
915
916            fn dump(&self, _cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()> 
917            {
918                todo!()
919            }
920        }
921
922        let pkt_ssl = 
923b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x29\
924\x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
925\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\xE0\x00\
926\x08\x01\x02\x03\x04\x05\x06\x07\x08";
927
928        let dec = ProxyV2Parser::<ProxyV2Dummy2>::try_from_slice_custom(pkt_ssl.as_slice()).unwrap();
929
930        assert_eq!(dec.get_transport().is_ok(), true);
931        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
932
933        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
934        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
935
936        assert_eq!(dec.get_address_family().is_ok(), true);
937        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
938        
939        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
940
941        let addr = dec.get_address().unwrap();
942
943        assert_eq!(addr.is_some(), true);
944
945        let addr = addr.unwrap();
946        let maddr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
947
948        assert_eq!(addr, maddr);
949
950        let tlv_iter = dec.get_tlvs_iter();
951
952        assert_eq!(tlv_iter.is_some(), true);
953
954        let mut tlv_iter = tlv_iter.unwrap();
955
956        let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
957
958        assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
959        let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
960
961        assert_eq!(client, PP2TlvClient::PP2_CLIENT_SSL);
962        assert_eq!(verify, 0);
963
964        // --
965        let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
966
967        assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
968
969        let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
970
971        assert_eq!(ssl_version, "TLSv1.2");
972
973        // ---
974        let ext_type_e0 = tlv_iter.next().unwrap().take_external().unwrap();
975
976        assert_eq!(ext_type_e0.get_type(), 0xE0);
977
978        let ProxyV2Dummy2::SomeTlvName(arg0, arg1) = ext_type_e0 else {panic!("wrong")};
979
980        assert_eq!(arg0, 0x01020304);
981        assert_eq!(arg1, 0x05060708);
982
983
984    }
985
986    #[test]
987    fn test_3()
988    {
989        let pkt_ssl = 
990b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x0c\
991\x7f\x00\x00\x01\x7f\x00\x00\x01\x8c\x76\x00\x50";
992
993
994        let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
995
996        assert_eq!(dec.get_transport().is_ok(), true);
997        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
998
999        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
1000        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
1001
1002        assert_eq!(dec.get_address_family().is_ok(), true);
1003        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
1004
1005        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
1006        
1007        let addr = dec.get_address().unwrap();
1008
1009        assert_eq!(addr.is_some(), true);
1010
1011        let addr = addr.unwrap();
1012        let maddr = ProxyV2Addr::try_from(("127.0.0.1:35958", "127.0.0.1:80")).unwrap();
1013
1014        assert_eq!(addr, maddr);
1015
1016        let tlv_iter = dec.get_tlvs_iter();
1017
1018        assert_eq!(tlv_iter.is_some(), false);
1019
1020    }
1021
1022}