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    pub const fn try_from_v2(value: v2::AddressPair) -> Result<Self, Unsupported> {
77        match value {
78            v2::AddressPair::Unspecified => Ok(Self::Unspecified),
79            v2::AddressPair::Inet {
80                src_ip,
81                dst_ip,
82                src_port,
83                dst_port,
84            } => Ok(Self::Inet {
85                src_ip,
86                dst_ip,
87                src_port,
88                dst_port,
89            }),
90            v2::AddressPair::Inet6 {
91                src_ip,
92                dst_ip,
93                src_port,
94                dst_port,
95            } => Ok(Self::Inet6 {
96                src_ip,
97                dst_ip,
98                src_port,
99                dst_port,
100            }),
101            v2::AddressPair::Unix { .. } => Err(Unsupported),
102        }
103    }
104
105    #[cfg(feature = "feat-uni-addr")]
106    /// Returns the source address.
107    pub fn src_uni_addr(&self) -> io::Result<Option<uni_addr::SocketAddr>> {
108        use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
109
110        match self {
111            Self::Unspecified => Ok(None),
112            Self::Inet { src_ip, src_port, .. } => Ok(Some(uni_addr::SocketAddr::Inet(SocketAddr::V4(
113                SocketAddrV4::new(*src_ip, *src_port),
114            )))),
115            Self::Inet6 { src_ip, src_port, .. } => Ok(Some(uni_addr::SocketAddr::Inet(SocketAddr::V6(
116                SocketAddrV6::new(*src_ip, *src_port, 0, 0),
117            )))),
118        }
119    }
120
121    #[cfg(feature = "feat-uni-addr")]
122    /// Returns the destination address.
123    pub fn dst_uni_addr(&self) -> io::Result<Option<uni_addr::SocketAddr>> {
124        use core::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
125
126        match self {
127            Self::Unspecified => Ok(None),
128            Self::Inet { dst_ip, dst_port, .. } => Ok(Some(uni_addr::SocketAddr::Inet(SocketAddr::V4(
129                SocketAddrV4::new(*dst_ip, *dst_port),
130            )))),
131            Self::Inet6 { dst_ip, dst_port, .. } => Ok(Some(uni_addr::SocketAddr::Inet(SocketAddr::V6(
132                SocketAddrV6::new(*dst_ip, *dst_port, 0, 0),
133            )))),
134        }
135    }
136}
137
138#[cfg(feature = "feat-codec-decode")]
139#[derive(Debug)]
140/// The result of decoding a PROXY Protocol v1 header.
141pub enum Decoded {
142    /// The PROXY Protocol v1 header and its extensions decoded.
143    Some(Header),
144
145    /// Partial data, the caller should read more data.
146    ///
147    /// However, it's hard to determine how much more data is needed like PROXY
148    /// Protocol v2.
149    Partial,
150
151    /// Not a PROXY Protocol v1 header.
152    None,
153}