Skip to content

Commit 01f5223

Browse files
committed
Store named pipe path instead of querying it again
The windows API for querying the named pipe path explicitly mentions that it shouldn't be used with pipes. To avoid that, store the path of the pipe when binging it, and reuse that value. Signed-off-by: Jorge Prendes <jorge.prendes@gmail.com>
1 parent ce5075d commit 01f5223

File tree

1 file changed

+10
-78
lines changed

1 file changed

+10
-78
lines changed

src/asynchronous/transport/windows.rs

Lines changed: 10 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
use std::convert::TryFrom;
2-
use std::io::{Error as IoError, Result as IoResult};
3-
use std::mem::{replace, zeroed};
4-
use std::os::windows::ffi::OsStringExt as _;
1+
use std::io::Result as IoResult;
2+
use std::mem::replace;
53
use std::time::Duration;
6-
use std::os::windows::io::AsRawHandle;
74

85
use async_stream::stream;
96
use tokio::net::windows::named_pipe::{
107
ClientOptions, NamedPipeClient, NamedPipeServer, ServerOptions,
118
};
129
use tokio::time::sleep;
13-
use windows_sys::Win32::Foundation::{ERROR_MORE_DATA, ERROR_PIPE_BUSY};
14-
use windows_sys::Win32::Storage::FileSystem::*;
10+
use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
1511

1612
use super::{Listener, Socket};
1713

@@ -20,7 +16,7 @@ impl Listener {
2016
let listener = ServerOptions::new()
2117
.first_pipe_instance(true)
2218
.create(addr.as_ref())?;
23-
Self::try_from(listener)
19+
Ok(Self::from((listener, addr)))
2420
}
2521
}
2622

@@ -39,19 +35,18 @@ impl Socket {
3935
}
4036
}
4137

42-
impl TryFrom<NamedPipeServer> for Listener {
43-
type Error = IoError;
44-
fn try_from(mut listener: NamedPipeServer) -> IoResult<Self> {
45-
let name = get_pipe_name(&listener)?;
46-
Ok(Self::new(stream! {
38+
impl<T: AsRef<str>> From<(NamedPipeServer, T)> for Listener {
39+
fn from((mut listener, addr): (NamedPipeServer, T)) -> Self {
40+
let addr = addr.as_ref().to_string();
41+
Self::new(stream! {
4742
loop {
4843
yield listener
4944
.connect()
5045
.await
51-
.and_then(|_| ServerOptions::new().create(&name))
46+
.and_then(|_| ServerOptions::new().create(&addr))
5247
.map(|l| replace(&mut listener, l));
5348
}
54-
}))
49+
})
5550
}
5651
}
5752

@@ -66,66 +61,3 @@ impl From<NamedPipeClient> for Socket {
6661
Self::new(socket)
6762
}
6863
}
69-
70-
fn get_pipe_name(pipe: &impl AsRawHandle) -> IoResult<std::ffi::OsString> {
71-
let mut info: FILE_NAME_INFO = unsafe { zeroed() };
72-
let handle = pipe.as_raw_handle();
73-
74-
let success = unsafe {
75-
GetFileInformationByHandleEx(
76-
handle as _,
77-
FileNameInfo,
78-
&mut info as *mut FILE_NAME_INFO as _,
79-
size_of::<FILE_NAME_INFO>() as _,
80-
)
81-
};
82-
83-
// First call to GetFileInformationByHandleEx should fail with ERROR_MORE_DATA.
84-
// This gives us the size we need to allocate to store the data.
85-
if success == 0 {
86-
let err = IoError::last_os_error();
87-
if err.raw_os_error() != Some(ERROR_MORE_DATA as i32) {
88-
return Err(err);
89-
}
90-
}
91-
92-
// Allocate enough space for a second call to GetFileInformationByHandleEx.
93-
let size = size_of::<FILE_NAME_INFO>() + info.FileNameLength as usize;
94-
let mut info = vec![0u8; size];
95-
96-
let success = unsafe {
97-
GetFileInformationByHandleEx(handle as _, FileNameInfo, info.as_mut_ptr() as _, size as _)
98-
};
99-
100-
// If the second call fails, bail out.
101-
if success == 0 {
102-
return Err(IoError::last_os_error());
103-
}
104-
105-
let info = info.as_ptr() as *const FILE_NAME_INFO;
106-
let info = unsafe { info.as_ref() }.unwrap();
107-
108-
let name = unsafe {
109-
std::slice::from_raw_parts(info.FileName.as_ptr() as _, (info.FileNameLength / 2) as _)
110-
};
111-
let name = std::ffi::OsString::from_wide(name);
112-
let mut full_name = std::ffi::OsString::from(r"\\.\pipe");
113-
full_name.extend([name]);
114-
115-
Ok(full_name)
116-
}
117-
118-
#[tokio::test]
119-
async fn test_get_pipe_name() {
120-
let listener = ServerOptions::new()
121-
.first_pipe_instance(true)
122-
.create(r"\\.\pipe\hello_world")
123-
.unwrap();
124-
125-
let name = get_pipe_name(&listener)
126-
.unwrap()
127-
.to_string_lossy()
128-
.to_string();
129-
130-
assert_eq!(name, r"\\.\pipe\hello_world");
131-
}

0 commit comments

Comments
 (0)