openssh/
port_forwarding.rs

1#[cfg(feature = "native-mux")]
2use super::native_mux_impl;
3
4#[cfg(feature = "process-mux")]
5use std::ffi::OsStr;
6
7use std::borrow::Cow;
8use std::fmt;
9use std::net::{self, SocketAddr};
10use std::path::{Path, PathBuf};
11
12/// Type of forwarding
13#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14pub enum ForwardType {
15    /// Forward requests to a port on the local machine to remote machine.
16    Local,
17
18    /// Forward requests to a port on the remote machine to local machine.
19    Remote,
20}
21
22#[cfg(feature = "native-mux")]
23impl From<ForwardType> for native_mux_impl::ForwardType {
24    fn from(fwd_type: ForwardType) -> Self {
25        use native_mux_impl::ForwardType::*;
26
27        match fwd_type {
28            ForwardType::Local => Local,
29            ForwardType::Remote => Remote,
30        }
31    }
32}
33
34/// TCP/Unix socket
35#[derive(Clone, Debug, Eq, PartialEq, Hash)]
36pub enum Socket<'a> {
37    /// Unix socket.
38    #[cfg(unix)]
39    #[cfg_attr(docsrs, doc(cfg(unix)))]
40    UnixSocket {
41        /// Filesystem path
42        path: Cow<'a, Path>,
43    },
44
45    /// Tcp socket.
46    TcpSocket {
47        /// Hostname.
48        host: Cow<'a, str>,
49        /// Port.
50        port: u16,
51    },
52}
53
54impl From<SocketAddr> for Socket<'static> {
55    fn from(addr: SocketAddr) -> Self {
56        Socket::TcpSocket {
57            host: addr.ip().to_string().into(),
58            port: addr.port(),
59        }
60    }
61}
62
63macro_rules! impl_from_addr {
64    ($ip:ty) => {
65        impl From<($ip, u16)> for Socket<'static> {
66            fn from((ip, port): ($ip, u16)) -> Self {
67                SocketAddr::new(ip.into(), port).into()
68            }
69        }
70    };
71}
72
73impl_from_addr!(net::IpAddr);
74impl_from_addr!(net::Ipv4Addr);
75impl_from_addr!(net::Ipv6Addr);
76
77impl<'a> From<Cow<'a, Path>> for Socket<'a> {
78    fn from(path: Cow<'a, Path>) -> Self {
79        Socket::UnixSocket { path }
80    }
81}
82
83impl<'a> From<&'a Path> for Socket<'a> {
84    fn from(path: &'a Path) -> Self {
85        Socket::UnixSocket {
86            path: Cow::Borrowed(path),
87        }
88    }
89}
90
91impl From<PathBuf> for Socket<'static> {
92    fn from(path: PathBuf) -> Self {
93        Socket::UnixSocket {
94            path: Cow::Owned(path),
95        }
96    }
97}
98
99impl From<Box<Path>> for Socket<'static> {
100    fn from(path: Box<Path>) -> Self {
101        Socket::UnixSocket {
102            path: Cow::Owned(path.into()),
103        }
104    }
105}
106
107impl Socket<'_> {
108    /// Create a new TcpSocket
109    pub fn new<'a, S>(host: S, port: u16) -> Socket<'a>
110    where
111        S: Into<Cow<'a, str>>,
112    {
113        Socket::TcpSocket {
114            host: host.into(),
115            port,
116        }
117    }
118
119    #[cfg(feature = "process-mux")]
120    pub(crate) fn as_os_str(&self) -> Cow<'_, OsStr> {
121        match self {
122            #[cfg(unix)]
123            Socket::UnixSocket { path } => Cow::Borrowed(path.as_os_str()),
124            Socket::TcpSocket { host, port } => Cow::Owned(format!("{host}:{port}").into()),
125        }
126    }
127}
128
129#[cfg(feature = "native-mux")]
130impl<'a> From<Socket<'a>> for native_mux_impl::Socket<'a> {
131    fn from(socket: Socket<'a>) -> Self {
132        use native_mux_impl::Socket::*;
133
134        match socket {
135            #[cfg(unix)]
136            Socket::UnixSocket { path } => UnixSocket { path },
137            Socket::TcpSocket { host, port } => TcpSocket {
138                host,
139                port: port as u32,
140            },
141        }
142    }
143}
144
145impl<'a> fmt::Display for Socket<'a> {
146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147        match self {
148            #[cfg(unix)]
149            Socket::UnixSocket { path } => {
150                write!(f, "{}", path.display())
151            }
152            Socket::TcpSocket { host, port } => write!(f, "{host}:{port}"),
153        }
154    }
155}