use std::fmt;
use std::net::{IpAddr, SocketAddr};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum ProxyAddress {
Inet(SocketAddr),
Unix(Vec<u8>),
}
impl ProxyAddress {
pub fn as_inet(&self) -> Option<SocketAddr> {
match self {
Self::Inet(addr) => Some(*addr),
_ => None,
}
}
pub fn as_unix(&self) -> Option<&[u8]> {
match self {
Self::Unix(path) => Some(path),
_ => None,
}
}
pub fn ip(&self) -> Option<IpAddr> {
self.as_inet().map(|a| a.ip())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ProxyInfo {
pub version: Version,
pub command: Command,
pub transport: Option<Transport>,
pub source: Option<ProxyAddress>,
pub destination: Option<ProxyAddress>,
pub tlvs: Tlvs,
}
impl ProxyInfo {
pub fn source_inet(&self) -> Option<SocketAddr> {
self.source.as_ref().and_then(ProxyAddress::as_inet)
}
pub fn destination_inet(&self) -> Option<SocketAddr> {
self.destination.as_ref().and_then(ProxyAddress::as_inet)
}
pub fn source_ip(&self) -> Option<IpAddr> {
self.source.as_ref().and_then(ProxyAddress::ip)
}
pub fn destination_ip(&self) -> Option<IpAddr> {
self.destination.as_ref().and_then(ProxyAddress::ip)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Version {
V1,
V2,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Command {
Local,
Proxy,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Transport {
pub family: AddressFamily,
pub protocol: TransportProtocol,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum AddressFamily {
Inet,
Inet6,
Unix,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum TransportProtocol {
Stream,
Datagram,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub struct Tlvs {
pub alpn: Option<Vec<u8>>,
pub authority: Option<String>,
pub crc32c: Option<u32>,
pub unique_id: Option<Vec<u8>>,
pub netns: Option<String>,
pub ssl: Option<SslInfo>,
pub raw: Vec<(u8, Vec<u8>)>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
pub struct SslInfo {
pub client_flags: SslClientFlags,
pub verified: bool,
pub version: Option<String>,
pub cipher: Option<String>,
pub sig_alg: Option<String>,
pub key_alg: Option<String>,
pub cn: Option<String>,
pub group: Option<String>,
pub sig_scheme: Option<String>,
pub client_cert: Option<Vec<u8>>,
}
bitflags::bitflags! {
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
pub struct SslClientFlags: u8 {
const SSL = 0x01;
const CERT_CONN = 0x02;
const CERT_SESS = 0x04;
}
}
impl fmt::Display for ProxyAddress {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Inet(addr) => write!(f, "{addr}"),
Self::Unix(path) => match std::str::from_utf8(path) {
Ok(s) => write!(f, "{s}"),
Err(_) => write!(f, "<unix:{} bytes>", path.len()),
},
}
}
}
impl From<SocketAddr> for ProxyAddress {
fn from(addr: SocketAddr) -> Self {
Self::Inet(addr)
}
}
impl From<std::net::SocketAddrV4> for ProxyAddress {
fn from(addr: std::net::SocketAddrV4) -> Self {
Self::Inet(SocketAddr::V4(addr))
}
}
impl From<std::net::SocketAddrV6> for ProxyAddress {
fn from(addr: std::net::SocketAddrV6) -> Self {
Self::Inet(SocketAddr::V6(addr))
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::V1 => write!(f, "v1"),
Self::V2 => write!(f, "v2"),
}
}
}
impl fmt::Display for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Local => write!(f, "LOCAL"),
Self::Proxy => write!(f, "PROXY"),
}
}
}
impl fmt::Display for AddressFamily {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Inet => write!(f, "IPv4"),
Self::Inet6 => write!(f, "IPv6"),
Self::Unix => write!(f, "Unix"),
}
}
}
impl fmt::Display for TransportProtocol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Stream => write!(f, "stream"),
Self::Datagram => write!(f, "datagram"),
}
}
}