Skip to content

Commit 9f7d4e7

Browse files
author
germaniuss
committed
🧵zb : Use async versions of UnixStream when possible
When connecting to a UnixSocket a blocking/threaded API is being used. This commit changes this to use `tokio::net::UnixStream` and `Async<std::os::unix::net::UnixStream>` when possible preventing the use of extra threads. The windows version continues using the blocking/threaded API. The `UnixStream::connect_addr` function from `SocketAddrExt` is no longer used since neither tokio nor async-io supports it. Instead, we use the plain `connect` functions in both environments, since they allow for abstract names when the path is prepended with '\0' (a null byte).
1 parent b3f0a61 commit 9f7d4e7

1 file changed

Lines changed: 34 additions & 45 deletions

File tree

‎zbus/src/address/transport/unix.rs‎

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@ use super::encode_percents;
1515
#[cfg(not(feature = "tokio"))]
1616
use async_io::Async;
1717

18-
#[cfg(target_os = "linux")]
19-
use std::os::linux::net::SocketAddrExt;
20-
#[cfg(unix)]
21-
use std::os::unix::net::{SocketAddr, UnixStream};
18+
#[cfg(all(unix, not(feature = "tokio")))]
19+
use std::os::unix::net::UnixStream;
2220
#[cfg(all(windows, not(feature = "tokio")))]
2321
use uds_windows::UnixStream;
2422

@@ -71,58 +69,49 @@ impl Unix {
7169

7270
#[cfg(not(feature = "tokio"))]
7371
pub(super) async fn connect(self) -> Result<Async<UnixStream>> {
74-
let stream = self.get_stream().await?;
75-
Async::new(stream).map_err(|e| Error::InputOutput(e.into()))
72+
let addr = self.take_addr()?;
73+
74+
#[cfg(unix)]
75+
let stream = Async::<UnixStream>::connect(addr).await;
76+
77+
#[cfg(not(unix))]
78+
let stream = {
79+
let stream = crate::Task::spawn_blocking(
80+
move || -> Result<_> {
81+
let stream = UnixStream::connect(addr)?;
82+
stream.set_nonblocking(true)?;
83+
84+
Ok(stream)
85+
},
86+
"unix stream connection",
87+
)
88+
.await??;
89+
Async::new(stream)
90+
};
91+
92+
stream.map_err(|e| Error::InputOutput(e.into()))
7693
}
7794

7895
#[cfg(all(unix, feature = "tokio"))]
7996
pub(super) async fn connect(self) -> Result<tokio::net::UnixStream> {
80-
let stream = self.get_stream().await?;
81-
tokio::net::UnixStream::from_std(stream).map_err(|e| Error::InputOutput(e.into()))
97+
let addr = self.take_addr()?;
98+
tokio::net::UnixStream::connect(addr)
99+
.await
100+
.map_err(|e| Error::InputOutput(e.into()))
82101
}
83102

84103
#[cfg(any(unix, not(feature = "tokio")))]
85-
async fn get_stream(self) -> Result<UnixStream> {
86-
#[cfg(unix)]
87-
let addr = self.take_socket_addr()?;
88-
#[cfg(windows)]
89-
let addr = self.take_path_addr()?;
90-
91-
crate::Task::spawn_blocking(
92-
move || -> Result<_> {
93-
#[cfg(unix)]
94-
let stream = UnixStream::connect_addr(&addr)?;
95-
#[cfg(windows)]
96-
let stream = UnixStream::connect(addr)?;
97-
stream.set_nonblocking(true)?;
98-
99-
Ok(stream)
100-
},
101-
"unix stream connection",
102-
)
103-
.await?
104-
}
105-
106-
#[cfg(all(windows, not(feature = "tokio")))]
107-
fn take_path_addr(self) -> Result<PathBuf> {
108-
// This is a `path` in case of Windows until uds_windows provides the needed API:
109-
// https://github.com/haraldh/rust_uds_windows/issues/14
104+
fn take_addr(self) -> Result<PathBuf> {
105+
// This is a `path` because neither uds_windows, tokio, nor async_io provide
106+
// the SocketAddrExt functions.
110107
match self.take_path() {
111108
UnixSocket::File(path) => Ok(path),
112-
UnixSocket::Dir(_) | UnixSocket::TmpDir(_) => {
113-
// You can't connect to a unix:dir.
114-
Err(Error::Unsupported)
115-
}
116-
}
117-
}
118-
119-
#[cfg(unix)]
120-
fn take_socket_addr(self) -> Result<SocketAddr> {
121-
match self.take_path() {
122-
UnixSocket::File(path) => Ok(SocketAddr::from_pathname(path)?),
123109
#[cfg(target_os = "linux")]
124110
UnixSocket::Abstract(name) => {
125-
Ok(SocketAddr::from_abstract_name(name.as_encoded_bytes())?)
111+
use std::{ffi::OsString, os::unix::ffi::OsStringExt, path::PathBuf};
112+
let mut v = name.into_vec();
113+
v.insert(0, 0);
114+
Ok(PathBuf::from(OsString::from_vec(v)))
126115
}
127116
UnixSocket::Dir(_) | UnixSocket::TmpDir(_) => {
128117
// You can't connect to a unix:dir.

0 commit comments

Comments
 (0)