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 are found in the packet. 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                return self.next();
713            }
714        }
715
716        // read type of the tlv
717        let tlv_type = 
718            match self.get_last_mut_cur().read_u8()
719            {
720                Ok(r) => r,
721                Err(e) =>
722                    return Some(ProxyV2TlvSource::new_io_error(e)),
723            };
724
725        // read length of the tlv's payload
726        let tlv_len = 
727            match self.get_last_mut_cur().read_u16::<BigEndian>()
728            {
729                Ok(r) => r,
730                Err(e) => 
731                    return Some(ProxyV2TlvSource::new_io_error(e)),
732            };
733
734        let tlv_range = 
735            self.get_last_cur().position() as usize .. (self.get_last_cur().position()+ tlv_len as u64) as usize;
736
737
738        // creating a cursor from slice to prevent parser going out of bounds by the declared size
739        let mut cur = 
740            Cursor::new(&self.get_last_cur().get_ref()[tlv_range]);
741
742        
743        // check in which range it is
744        let next_item = 
745            if PP2Tlvs::is_in_range(tlv_type, self.get_parent_tlv()) == true
746            {
747                ProxyV2TlvSource::new_internal(
748                    PP2Tlvs::restore(tlv_type, &mut cur)
749                )
750            }
751            else if EXT::is_in_range(tlv_type, self.get_parent_tlv()) == true
752            {
753                ProxyV2TlvSource::new_external(
754                    EXT::restore(tlv_type, &mut cur)
755                )
756            }
757            else
758            {
759                ProxyV2TlvSource::new_error(
760                    map_error!(ProtocolUnknownData, "TLV tpye: '{}' out of int/ext ranges", tlv_type)
761                )
762            };
763
764        // move cursor position forward
765        let new_pos = self.get_last_cur().position()+ tlv_len as u64;
766        self.get_last_mut_cur().set_position(new_pos);
767
768        if next_item.contains_subtype() == true
769        {
770            // push the current cursor
771            self.curs.push(
772                ProxyV2TlvIterTlv
773                {
774                    cur: cur,
775                    parent_tlv_idx: Some(tlv_type),
776                }
777            );
778        }
779
780        return Some(next_item);
781    }
782}
783
784#[cfg(test)]
785mod tests
786{
787    use std::{fmt, io::Cursor};
788
789    use byteorder::{BigEndian, ReadBytesExt};
790
791    use crate::{common, error::HaProxRes, protocol::{protocol::{HdrV2Command, PP2TlvClient, PP2Tlvs, ProtocolVersion, ProxyTransportFam, ProxyV2Addr, ProxyV2AddrType, PP2_TYPE_MIN_CUSTOM}, protocol_raw, PP2TlvDump, PP2TlvRestore}, return_error};
792
793    use super::ProxyV2Parser;
794
795    #[test]
796    fn test_0()
797    {
798        let pkt_ssl = 
799b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x2a\
800\x7f\x00\x00\x01\x7f\x00\x00\x43\x9d\xd2\x2e\x6b\x20\x00\x1b\x07\
801\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\x22\x00\
802\x09\x6d\x71\x74\x74\x75\x73\x65\x72\x31";
803
804        let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
805
806        assert_eq!(dec.get_transport().is_ok(), true);
807        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
808
809        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
810        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
811
812        assert_eq!(dec.get_address_family().is_ok(), true);
813        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
814
815        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
816        
817        let addr = dec.get_address().unwrap();
818
819        assert_eq!(addr.is_some(), true);
820
821        let addr = addr.unwrap();
822        let maddr = ProxyV2Addr::try_from(("127.0.0.1:40402", "127.0.0.67:11883")).unwrap();
823
824        assert_eq!(addr, maddr);
825
826        let tlv_iter = dec.get_tlvs_iter();
827
828        assert_eq!(tlv_iter.is_some(), true);
829
830        let mut tlv_iter = tlv_iter.unwrap();
831
832        let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
833
834        assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
835        let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
836
837        assert_eq!(client, PP2TlvClient::all());
838        assert_eq!(verify, 0);
839
840        let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
841
842        assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
843
844        let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
845
846        assert_eq!(ssl_version, "TLSv1.2");
847
848        let type_ssl_cn = tlv_iter.next().unwrap().take_internal().unwrap();
849
850        assert_eq!(type_ssl_cn.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_CN);
851
852        let PP2Tlvs::TypeSubtypeSslCn(ssl_cn) = type_ssl_cn else { panic!("wrong") };
853
854        assert_eq!(ssl_cn, "mqttuser1");
855    }
856
857    #[test]
858    fn test_1()
859    {
860
861        #[derive(Clone, Debug)]
862        pub enum ProxyV2Dummy2 
863        {
864            SomeTlvName(u32, u32),
865            OtherTlv,
866        }
867
868        impl fmt::Display for ProxyV2Dummy2
869        {
870            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
871            {
872                write!(f, "DUMMY external reader")
873            }
874        }
875
876        impl PP2TlvRestore for ProxyV2Dummy2
877        {
878            fn restore(tlv_type: u8, cur: &mut Cursor<&[u8]>) -> HaProxRes<Self> where Self: Sized 
879            {
880                match tlv_type
881                {
882                    0xE0 =>
883                    {
884                        let arg0 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
885                        let arg1 = cur.read_u32::<BigEndian>().map_err(common::map_io_err)?;
886
887                        return Ok(Self::SomeTlvName(arg0, arg1));
888                    },
889                    _ => 
890                        return_error!(ProtocolUnknownData, "unknown tlv_type: {}", tlv_type)
891                }
892                
893            }
894            
895            fn is_in_range(tlv_type: u8, _tlv_parent_type: Option<u8>) -> bool 
896            {
897                return tlv_type == PP2_TYPE_MIN_CUSTOM;
898            }
899            
900            fn contains_subtype(&self) -> bool 
901            {
902                return false;
903            }
904        }
905
906        impl PP2TlvDump for ProxyV2Dummy2
907        {
908            fn get_type(&self) -> u8 
909            {
910                let Self::SomeTlvName(..) = self else { panic!("wrong") };
911
912                return 0xE0;
913            }
914
915            fn dump(&self, _cur: &mut Cursor<Vec<u8>>) -> HaProxRes<()> 
916            {
917                todo!()
918            }
919        }
920
921        let pkt_ssl = 
922b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x29\
923\x7f\x00\x00\x01\x7f\x00\x00\x43\x9b\x4a\x2e\x6b\x20\x00\x0f\x01\
924\x00\x00\x00\x00\x21\x00\x07\x54\x4c\x53\x76\x31\x2e\x32\xE0\x00\
925\x08\x01\x02\x03\x04\x05\x06\x07\x08";
926
927        let dec = ProxyV2Parser::<ProxyV2Dummy2>::try_from_slice_custom(pkt_ssl.as_slice()).unwrap();
928
929        assert_eq!(dec.get_transport().is_ok(), true);
930        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
931
932        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
933        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
934
935        assert_eq!(dec.get_address_family().is_ok(), true);
936        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
937        
938        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
939
940        let addr = dec.get_address().unwrap();
941
942        assert_eq!(addr.is_some(), true);
943
944        let addr = addr.unwrap();
945        let maddr = ProxyV2Addr::try_from(("127.0.0.1:39754", "127.0.0.67:11883")).unwrap();
946
947        assert_eq!(addr, maddr);
948
949        let tlv_iter = dec.get_tlvs_iter();
950
951        assert_eq!(tlv_iter.is_some(), true);
952
953        let mut tlv_iter = tlv_iter.unwrap();
954
955        let type_ssl = tlv_iter.next().unwrap().take_internal().unwrap();
956
957        assert_eq!(type_ssl.get_type(), PP2Tlvs::TYPE_SSL);
958        let PP2Tlvs::TypeSsl { client, verify } = type_ssl else {panic!("wrong")};
959
960        assert_eq!(client, PP2TlvClient::PP2_CLIENT_SSL);
961        assert_eq!(verify, 0);
962
963        // --
964        let type_ssl_version = tlv_iter.next().unwrap().take_internal().unwrap();
965
966        assert_eq!(type_ssl_version.get_type(), PP2Tlvs::TYPE_SUBTYPE_SSL_VERSION);
967
968        let PP2Tlvs::TypeSubtypeSslVersion(ssl_version) = type_ssl_version else { panic!("wrong") };
969
970        assert_eq!(ssl_version, "TLSv1.2");
971
972        // ---
973        let ext_type_e0 = tlv_iter.next().unwrap().take_external().unwrap();
974
975        assert_eq!(ext_type_e0.get_type(), 0xE0);
976
977        let ProxyV2Dummy2::SomeTlvName(arg0, arg1) = ext_type_e0 else {panic!("wrong")};
978
979        assert_eq!(arg0, 0x01020304);
980        assert_eq!(arg1, 0x05060708);
981
982
983    }
984
985    #[test]
986    fn test_3()
987    {
988        let pkt_ssl = 
989b"\x0d\x0a\x0d\x0a\x00\x0d\x0a\x51\x55\x49\x54\x0a\x21\x11\x00\x0c\
990\x7f\x00\x00\x01\x7f\x00\x00\x01\x8c\x76\x00\x50";
991
992
993        let dec = ProxyV2Parser::try_from_slice(pkt_ssl.as_slice()).unwrap();
994
995        assert_eq!(dec.get_transport().is_ok(), true);
996        assert_eq!(dec.get_transport().unwrap(), ProxyTransportFam::STREAM);
997
998        assert_eq!(dec.get_proto_version(), ProtocolVersion::V2);
999        assert_eq!(dec.get_proto_command(), HdrV2Command::PROXY);
1000
1001        assert_eq!(dec.get_address_family().is_ok(), true);
1002        assert_eq!(dec.get_address_family().unwrap(), ProxyV2AddrType::AfInet);
1003
1004        assert_eq!(dec.get_palyload_len() as usize, pkt_ssl.len() - size_of::<protocol_raw::ProxyHdrV2>());
1005        
1006        let addr = dec.get_address().unwrap();
1007
1008        assert_eq!(addr.is_some(), true);
1009
1010        let addr = addr.unwrap();
1011        let maddr = ProxyV2Addr::try_from(("127.0.0.1:35958", "127.0.0.1:80")).unwrap();
1012
1013        assert_eq!(addr, maddr);
1014
1015        let tlv_iter = dec.get_tlvs_iter();
1016
1017        assert_eq!(tlv_iter.is_some(), false);
1018
1019    }
1020
1021}