proxy_protocol_codec/v1/
model.rs

1//! PROXY Protocol v1 header models
2
3use core::fmt;
4use core::net::{Ipv4Addr, Ipv6Addr};
5#[cfg(feature = "feat-uni-addr")]
6use std::io;
7
8#[cfg(feature = "feat-codec-decode")]
9use crate::v1::Header;
10#[cfg(feature = "feat-codec-v2")]
11use crate::v2;
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14/// The address type, which can be either an IPv4/IPv6 address or a UNIX socket
15/// address.
16pub enum AddressPair {
17    /// Unknown
18    Unspecified,
19
20    /// The address is an IPv4 address.
21    Inet {
22        /// SRC IPv4 address.
23        src_ip: Ipv4Addr,
24
25        /// DST IPv4 address.
26        dst_ip: Ipv4Addr,
27
28        /// SRC port.
29        src_port: u16,
30
31        /// DST port.
32        dst_port: u16,
33    },
34
35    /// The address is an IPv6 address.
36    Inet6 {
37        /// SRC IPv4 address.
38        src_ip: Ipv6Addr,
39
40        /// DST IPv4 address.
41        dst_ip: Ipv6Addr,
42
43        /// SRC port.
44        src_port: u16,
45
46        /// DST port.
47        dst_port: u16,
48    },
49}
50
51#[cfg(feature = "feat-codec-v2")]
52impl TryFrom<v2::AddressPair> for AddressPair {
53    type Error = Unsupported;
54
55    fn try_from(value: v2::AddressPair) -> Result<Self, Self::Error> {
56        AddressPair::try_from_v2(value)
57    }
58}
59
60#[cfg(feature = "feat-codec-v2")]
61#[derive(Debug)]
62/// An unsupported address type, such as a UNIX socket address.
63pub struct Unsupported;
64
65#[cfg(feature = "feat-codec-v2")]
66impl fmt::Display for Unsupported {
67    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
68        write!(f, "unsupported address type")
69    }
70}
71
72impl AddressPair {
73    #[cfg(feature = "feat-codec-v2")]
74    #[inline]
75    /// Converts a [`v2::AddressPair`] to an [`AddressPair`].
76    ///
77    /// # Errors
78    ///
79    /// See [`Unsupported`].
80    pub const fn try_from_v2(value: v2::AddressPair) -> Result<Self, Unsupported> {
81        match value {
82            v2::AddressPair::Unspecified => Ok(Self::Unspecified),
83            v2::AddressPair::Inet {
84                src_ip,
85                dst_ip,
86                src_port,
87                dst_port,
88            } => Ok(Self::Inet {
89                src_ip,
90                dst_ip,
91                src_port,
92                dst_port,
93            }),
94            v2::AddressPair::Inet6 {
95                src_ip,
96                dst_ip,
97                src_port,
98                dst_port,
99            } => Ok(Self::Inet6 {
100                src_ip,
101                dst_ip,
102                src_port,
103                dst_port,
104            }),
105            v2::AddressPair::Unix { .. } => Err(Unsupported),
106        }
107    }
108
109    #[cfg(feature = "feat-uni-addr")]
110    /// Returns the source address.
111    ///
112    /// # Errors
113    ///
114    /// This is infallible, but kept for API consistency.
115    pub fn src_uni_addr(&self) -> io::Result<Option<uni_addr::UniAddr>> {
116        use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
117
118        match self {
119            Self::Unspecified => Ok(None),
120            Self::Inet { src_ip, src_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V4(
121                SocketAddrV4::new(*src_ip, *src_port),
122            )))),
123            Self::Inet6 { src_ip, src_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V6(
124                SocketAddrV6::new(*src_ip, *src_port, 0, 0),
125            )))),
126        }
127    }
128
129    #[cfg(feature = "feat-uni-addr")]
130    /// Returns the destination address.
131    ///
132    /// # Errors
133    ///
134    /// This is infallible, but kept for API consistency.
135    pub fn dst_uni_addr(&self) -> io::Result<Option<uni_addr::UniAddr>> {
136        use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
137
138        match self {
139            Self::Unspecified => Ok(None),
140            Self::Inet { dst_ip, dst_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V4(
141                SocketAddrV4::new(*dst_ip, *dst_port),
142            )))),
143            Self::Inet6 { dst_ip, dst_port, .. } => Ok(Some(uni_addr::UniAddr::from(SocketAddr::V6(
144                SocketAddrV6::new(*dst_ip, *dst_port, 0, 0),
145            )))),
146        }
147    }
148}
149
150#[cfg(feature = "feat-codec-decode")]
151#[derive(Debug)]
152/// The result of decoding a PROXY Protocol v1 header.
153pub enum Decoded {
154    /// The PROXY Protocol v1 header and its extensions decoded.
155    Some(Header),
156
157    /// Partial data, the caller should read more data.
158    ///
159    /// However, it's hard to determine how much more data is needed like PROXY
160    /// Protocol v2.
161    Partial,
162
163    /// Not a PROXY Protocol v1 header.
164    None,
165}