diff --git a/src/error.rs b/src/error.rs index 26c767311..9d512ced9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -297,6 +297,9 @@ pub enum Error { #[error("System clock is not correct!")] InvalidClock, + #[error("Unsupported OS")] + UnsupportedOS, + // ============================================== // Wrappers for other error types in this library // ============================================== diff --git a/src/net/acceptor.rs b/src/net/acceptor.rs index 432ed2cee..2ff1adbee 100644 --- a/src/net/acceptor.rs +++ b/src/net/acceptor.rs @@ -43,15 +43,15 @@ impl Acceptor { let listener = transport.listen_on(accept_url.clone()); if let Err(err) = listener { - error!("TCP Setup failed: {}", err); - return Err(Error::BindFailed(accept_url.clone().to_string())) + error!("Setup for {} failed: {}", accept_url, err); + return Err(Error::BindFailed(accept_url.as_str().into())) } let listener = listener?.await; if let Err(err) = listener { - error!("TCP Bind listener failed: {}", err); - return Err(Error::BindFailed(accept_url.to_string())) + error!("Bind listener to {} failed: {}", accept_url, err); + return Err(Error::BindFailed(accept_url.as_str().into())) } let listener = listener?; @@ -103,15 +103,15 @@ impl Acceptor { let listener = transport.clone().listen_on(accept_url.clone()); if let Err(err) = listener { - error!("TOR Setup failed: {}", err); - return Err(Error::BindFailed(accept_url.clone().to_string())) + error!("Setup for {} failed: {}", accept_url, err); + return Err(Error::BindFailed(accept_url.as_str().into())) } let listener = listener?.await; if let Err(err) = listener { - error!("TOR Bind listener failed: {}", err); - return Err(Error::BindFailed(accept_url.to_string())) + error!("Bind listener to {} failed: {}", accept_url, err); + return Err(Error::BindFailed(accept_url.as_str().into())) } let listener = listener?; diff --git a/src/net/connector.rs b/src/net/connector.rs index 7de097aee..f5d93aacf 100644 --- a/src/net/connector.rs +++ b/src/net/connector.rs @@ -43,14 +43,14 @@ impl Connector { let stream = transport.dial(connect_url.clone()); if let Err(err) = stream { - error!("TCP Setup failed: {}", err); + error!("Setup for {} failed: {}", connect_url, err); return Err(Error::ConnectFailed) } let stream = stream?.await; if let Err(err) = stream { - error!("TCP Connection failed: {}", err); + error!("Connection to {} failed: {}", connect_url, err); return Err(Error::ConnectFailed) } @@ -76,14 +76,14 @@ impl Connector { let stream = transport.clone().dial(connect_url.clone()); if let Err(err) = stream { - error!("TOR Setup failed: {}", err); + error!("Setup for {} failed: {}", connect_url, err); return Err(Error::ConnectFailed) } let stream = stream?.await; if let Err(err) = stream { - error!("TOR Connection failed: {}", err); + error!("Connection to {} failed: {}", connect_url, err); return Err(Error::ConnectFailed) } diff --git a/src/net/mod.rs b/src/net/mod.rs index 95cc49304..c125d3723 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -100,4 +100,5 @@ pub use session::{SESSION_ALL, SESSION_INBOUND, SESSION_MANUAL, SESSION_OUTBOUND pub use settings::{Settings, SettingsPtr}; pub use transport::{ TcpTransport, TorTransport, Transport, TransportListener, TransportName, TransportStream, + UnixTransport, }; diff --git a/src/net/transport.rs b/src/net/transport.rs index fb5977e3f..9aa8a0b3e 100644 --- a/src/net/transport.rs +++ b/src/net/transport.rs @@ -17,6 +17,9 @@ pub use tcp::TcpTransport; mod tor; pub use tor::TorTransport; +mod unix; +pub use unix::UnixTransport; + /// A helper function to convert SocketAddr to Url and add scheme pub(crate) fn socket_addr_to_url(addr: SocketAddr, scheme: &str) -> Result { let url = Url::parse(&format!("{}://{}", scheme, addr))?; diff --git a/src/net/transport/unix.rs b/src/net/transport/unix.rs new file mode 100644 index 000000000..9c5c020a7 --- /dev/null +++ b/src/net/transport/unix.rs @@ -0,0 +1,69 @@ +use async_std::os::unix::net::{UnixListener, UnixStream}; + +use async_trait::async_trait; +use log::{debug, error}; +use url::Url; + +use super::{TransportListener, TransportStream}; +use crate::{Error, Result}; + +fn unix_socket_addr_to_string(addr: std::os::unix::net::SocketAddr) -> String { + addr.as_pathname().unwrap_or(&std::path::PathBuf::from("")).to_str().unwrap_or("").into() +} + +#[async_trait] +impl TransportListener for UnixListener { + async fn next(&self) -> Result<(Box, Url)> { + let (stream, peer_addr) = match self.accept().await { + Ok((s, a)) => (s, a), + Err(err) => { + error!("Error listening for connections: {}", err); + return Err(Error::AcceptConnectionFailed(unix_socket_addr_to_string( + self.local_addr()?, + ))) + } + }; + let url = Url::parse(&unix_socket_addr_to_string(peer_addr))?; + Ok((Box::new(stream), url)) + } +} + +impl TransportStream for UnixStream {} + +#[derive(Copy, Clone)] +pub struct UnixTransport {} + +impl UnixTransport { + pub fn new() -> Self { + Self {} + } + pub async fn listen(self, url: Url) -> Result { + match url.scheme() { + "unix" => {} + x => return Err(Error::UnsupportedTransport(x.to_string())), + } + + if !cfg!(unix) { + return Err(Error::UnsupportedOS) + } + + let listener = UnixListener::bind(url.as_str()).await?; + debug!("{} transport: listening on {}", url.scheme(), url); + Ok(listener) + } + + pub async fn dial(self, url: Url) -> Result { + match url.scheme() { + "unix" => {} + x => return Err(Error::UnsupportedTransport(x.to_string())), + } + + if !cfg!(unix) { + return Err(Error::UnsupportedOS) + } + + let stream = UnixStream::connect(url.as_str()).await?; + debug!("{} transport: dialing to {}", url.scheme(), url); + Ok(stream) + } +}