openssh/
port_forwarding.rs1#[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, IpAddr, SocketAddr};
10use std::path::{Path, PathBuf};
11
12#[derive(Copy, Clone, Debug, Eq, PartialEq)]
14pub enum ForwardType {
15 Local,
17
18 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#[derive(Clone, Debug, Eq, PartialEq, Hash)]
36pub enum Socket<'a> {
37 #[cfg(unix)]
39 #[cfg_attr(docsrs, doc(cfg(unix)))]
40 UnixSocket {
41 path: Cow<'a, Path>,
43 },
44
45 TcpSocket {
47 host: Cow<'a, str>,
49 port: u16,
51 },
52}
53
54impl From<SocketAddr> for Socket<'static> {
55 fn from(addr: SocketAddr) -> Self {
56 let host = match addr.ip() {
57 IpAddr::V4(v4) => v4.to_string(),
58 IpAddr::V6(v6) => format!("[{v6}]"),
59 };
60 Socket::TcpSocket {
61 host: host.into(),
62 port: addr.port(),
63 }
64 }
65}
66
67macro_rules! impl_from_addr {
68 ($ip:ty) => {
69 impl From<($ip, u16)> for Socket<'static> {
70 fn from((ip, port): ($ip, u16)) -> Self {
71 SocketAddr::new(ip.into(), port).into()
72 }
73 }
74 };
75}
76
77impl_from_addr!(net::IpAddr);
78impl_from_addr!(net::Ipv4Addr);
79impl_from_addr!(net::Ipv6Addr);
80
81impl<'a> From<Cow<'a, Path>> for Socket<'a> {
82 fn from(path: Cow<'a, Path>) -> Self {
83 Socket::UnixSocket { path }
84 }
85}
86
87impl<'a> From<&'a Path> for Socket<'a> {
88 fn from(path: &'a Path) -> Self {
89 Socket::UnixSocket {
90 path: Cow::Borrowed(path),
91 }
92 }
93}
94
95impl From<PathBuf> for Socket<'static> {
96 fn from(path: PathBuf) -> Self {
97 Socket::UnixSocket {
98 path: Cow::Owned(path),
99 }
100 }
101}
102
103impl From<Box<Path>> for Socket<'static> {
104 fn from(path: Box<Path>) -> Self {
105 Socket::UnixSocket {
106 path: Cow::Owned(path.into()),
107 }
108 }
109}
110
111impl Socket<'_> {
112 pub fn new<'a, S>(host: S, port: u16) -> Socket<'a>
114 where
115 S: Into<Cow<'a, str>>,
116 {
117 Socket::TcpSocket {
118 host: host.into(),
119 port,
120 }
121 }
122
123 #[cfg(feature = "process-mux")]
124 pub(crate) fn as_os_str(&self) -> Cow<'_, OsStr> {
125 match self {
126 #[cfg(unix)]
127 Socket::UnixSocket { path } => Cow::Borrowed(path.as_os_str()),
128 Socket::TcpSocket { host, port } => Cow::Owned(format!("{host}:{port}").into()),
129 }
130 }
131}
132
133#[cfg(feature = "native-mux")]
134impl<'a> From<Socket<'a>> for native_mux_impl::Socket<'a> {
135 fn from(socket: Socket<'a>) -> Self {
136 use native_mux_impl::Socket::*;
137
138 match socket {
139 #[cfg(unix)]
140 Socket::UnixSocket { path } => UnixSocket { path },
141 Socket::TcpSocket { host, port } => TcpSocket {
142 host,
143 port: port as u32,
144 },
145 }
146 }
147}
148
149impl<'a> fmt::Display for Socket<'a> {
150 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151 match self {
152 #[cfg(unix)]
153 Socket::UnixSocket { path } => {
154 write!(f, "{}", path.display())
155 }
156 Socket::TcpSocket { host, port } => write!(f, "{host}:{port}"),
157 }
158 }
159}