Skip to content

Commit 2e7f996

Browse files
authored
net: refactor named pipe builders to not use bitfields (#5477)
1 parent 901f6d2 commit 2e7f996

File tree

1 file changed

+86
-108
lines changed

1 file changed

+86
-108
lines changed

tokio/src/net/windows/named_pipe.rs

Lines changed: 86 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,28 +1645,24 @@ impl AsRawHandle for NamedPipeClient {
16451645
}
16461646
}
16471647

1648-
// Helper to set a boolean flag as a bitfield.
1649-
macro_rules! bool_flag {
1650-
($f:expr, $t:expr, $flag:expr) => {{
1651-
let current = $f;
1652-
1653-
if $t {
1654-
$f = current | $flag;
1655-
} else {
1656-
$f = current & !$flag;
1657-
};
1658-
}};
1659-
}
1660-
16611648
/// A builder structure for construct a named pipe with named pipe-specific
16621649
/// options. This is required to use for named pipe servers who wants to modify
16631650
/// pipe-related options.
16641651
///
16651652
/// See [`ServerOptions::create`].
16661653
#[derive(Debug, Clone)]
16671654
pub struct ServerOptions {
1668-
open_mode: u32,
1669-
pipe_mode: u32,
1655+
// dwOpenMode
1656+
access_inbound: bool,
1657+
access_outbound: bool,
1658+
first_pipe_instance: bool,
1659+
write_dac: bool,
1660+
write_owner: bool,
1661+
access_system_security: bool,
1662+
// dwPipeMode
1663+
pipe_mode: PipeMode,
1664+
reject_remote_clients: bool,
1665+
// other options
16701666
max_instances: u32,
16711667
out_buffer_size: u32,
16721668
in_buffer_size: u32,
@@ -1687,8 +1683,14 @@ impl ServerOptions {
16871683
/// ```
16881684
pub fn new() -> ServerOptions {
16891685
ServerOptions {
1690-
open_mode: windows_sys::PIPE_ACCESS_DUPLEX | windows_sys::FILE_FLAG_OVERLAPPED,
1691-
pipe_mode: windows_sys::PIPE_TYPE_BYTE | windows_sys::PIPE_REJECT_REMOTE_CLIENTS,
1686+
access_inbound: true,
1687+
access_outbound: true,
1688+
first_pipe_instance: false,
1689+
write_dac: false,
1690+
write_owner: false,
1691+
access_system_security: false,
1692+
pipe_mode: PipeMode::Byte,
1693+
reject_remote_clients: true,
16921694
max_instances: windows_sys::PIPE_UNLIMITED_INSTANCES,
16931695
out_buffer_size: 65536,
16941696
in_buffer_size: 65536,
@@ -1705,14 +1707,7 @@ impl ServerOptions {
17051707
///
17061708
/// [`dwPipeMode`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
17071709
pub fn pipe_mode(&mut self, pipe_mode: PipeMode) -> &mut Self {
1708-
let is_msg = matches!(pipe_mode, PipeMode::Message);
1709-
// Pipe mode is implemented as a bit flag 0x4. Set is message and unset
1710-
// is byte.
1711-
bool_flag!(
1712-
self.pipe_mode,
1713-
is_msg,
1714-
windows_sys::PIPE_TYPE_MESSAGE | windows_sys::PIPE_READMODE_MESSAGE
1715-
);
1710+
self.pipe_mode = pipe_mode;
17161711
self
17171712
}
17181713

@@ -1808,7 +1803,7 @@ impl ServerOptions {
18081803
/// # Ok(()) }
18091804
/// ```
18101805
pub fn access_inbound(&mut self, allowed: bool) -> &mut Self {
1811-
bool_flag!(self.open_mode, allowed, windows_sys::PIPE_ACCESS_INBOUND);
1806+
self.access_inbound = allowed;
18121807
self
18131808
}
18141809

@@ -1906,7 +1901,7 @@ impl ServerOptions {
19061901
/// # Ok(()) }
19071902
/// ```
19081903
pub fn access_outbound(&mut self, allowed: bool) -> &mut Self {
1909-
bool_flag!(self.open_mode, allowed, windows_sys::PIPE_ACCESS_OUTBOUND);
1904+
self.access_outbound = allowed;
19101905
self
19111906
}
19121907

@@ -1974,11 +1969,7 @@ impl ServerOptions {
19741969
/// [`create`]: ServerOptions::create
19751970
/// [`FILE_FLAG_FIRST_PIPE_INSTANCE`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#pipe_first_pipe_instance
19761971
pub fn first_pipe_instance(&mut self, first: bool) -> &mut Self {
1977-
bool_flag!(
1978-
self.open_mode,
1979-
first,
1980-
windows_sys::FILE_FLAG_FIRST_PIPE_INSTANCE
1981-
);
1972+
self.first_pipe_instance = first;
19821973
self
19831974
}
19841975

@@ -2060,7 +2051,7 @@ impl ServerOptions {
20602051
///
20612052
/// [`WRITE_DAC`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20622053
pub fn write_dac(&mut self, requested: bool) -> &mut Self {
2063-
bool_flag!(self.open_mode, requested, windows_sys::WRITE_DAC);
2054+
self.write_dac = requested;
20642055
self
20652056
}
20662057

@@ -2070,7 +2061,7 @@ impl ServerOptions {
20702061
///
20712062
/// [`WRITE_OWNER`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20722063
pub fn write_owner(&mut self, requested: bool) -> &mut Self {
2073-
bool_flag!(self.open_mode, requested, windows_sys::WRITE_OWNER);
2064+
self.write_owner = requested;
20742065
self
20752066
}
20762067

@@ -2080,11 +2071,7 @@ impl ServerOptions {
20802071
///
20812072
/// [`ACCESS_SYSTEM_SECURITY`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea
20822073
pub fn access_system_security(&mut self, requested: bool) -> &mut Self {
2083-
bool_flag!(
2084-
self.open_mode,
2085-
requested,
2086-
windows_sys::ACCESS_SYSTEM_SECURITY
2087-
);
2074+
self.access_system_security = requested;
20882075
self
20892076
}
20902077

@@ -2095,11 +2082,7 @@ impl ServerOptions {
20952082
///
20962083
/// [`PIPE_REJECT_REMOTE_CLIENTS`]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createnamedpipea#pipe_reject_remote_clients
20972084
pub fn reject_remote_clients(&mut self, reject: bool) -> &mut Self {
2098-
bool_flag!(
2099-
self.pipe_mode,
2100-
reject,
2101-
windows_sys::PIPE_REJECT_REMOTE_CLIENTS
2102-
);
2085+
self.reject_remote_clients = reject;
21032086
self
21042087
}
21052088

@@ -2245,10 +2228,46 @@ impl ServerOptions {
22452228
) -> io::Result<NamedPipeServer> {
22462229
let addr = encode_addr(addr);
22472230

2231+
let pipe_mode = {
2232+
let mut mode = if matches!(self.pipe_mode, PipeMode::Message) {
2233+
windows_sys::PIPE_TYPE_MESSAGE | windows_sys::PIPE_READMODE_MESSAGE
2234+
} else {
2235+
windows_sys::PIPE_TYPE_BYTE | windows_sys::PIPE_READMODE_BYTE
2236+
};
2237+
if self.reject_remote_clients {
2238+
mode |= windows_sys::PIPE_REJECT_REMOTE_CLIENTS;
2239+
} else {
2240+
mode |= windows_sys::PIPE_ACCEPT_REMOTE_CLIENTS;
2241+
}
2242+
mode
2243+
};
2244+
let open_mode = {
2245+
let mut mode = windows_sys::FILE_FLAG_OVERLAPPED;
2246+
if self.access_inbound {
2247+
mode |= windows_sys::PIPE_ACCESS_INBOUND;
2248+
}
2249+
if self.access_outbound {
2250+
mode |= windows_sys::PIPE_ACCESS_OUTBOUND;
2251+
}
2252+
if self.first_pipe_instance {
2253+
mode |= windows_sys::FILE_FLAG_FIRST_PIPE_INSTANCE;
2254+
}
2255+
if self.write_dac {
2256+
mode |= windows_sys::WRITE_DAC;
2257+
}
2258+
if self.write_owner {
2259+
mode |= windows_sys::WRITE_OWNER;
2260+
}
2261+
if self.access_system_security {
2262+
mode |= windows_sys::ACCESS_SYSTEM_SECURITY;
2263+
}
2264+
mode
2265+
};
2266+
22482267
let h = windows_sys::CreateNamedPipeW(
22492268
addr.as_ptr(),
2250-
self.open_mode,
2251-
self.pipe_mode,
2269+
open_mode,
2270+
pipe_mode,
22522271
self.max_instances,
22532272
self.out_buffer_size,
22542273
self.in_buffer_size,
@@ -2270,7 +2289,8 @@ impl ServerOptions {
22702289
/// See [`ClientOptions::open`].
22712290
#[derive(Debug, Clone)]
22722291
pub struct ClientOptions {
2273-
desired_access: u32,
2292+
generic_read: bool,
2293+
generic_write: bool,
22742294
security_qos_flags: u32,
22752295
pipe_mode: PipeMode,
22762296
}
@@ -2291,7 +2311,8 @@ impl ClientOptions {
22912311
/// ```
22922312
pub fn new() -> Self {
22932313
Self {
2294-
desired_access: windows_sys::GENERIC_READ | windows_sys::GENERIC_WRITE,
2314+
generic_read: true,
2315+
generic_write: true,
22952316
security_qos_flags: windows_sys::SECURITY_IDENTIFICATION
22962317
| windows_sys::SECURITY_SQOS_PRESENT,
22972318
pipe_mode: PipeMode::Byte,
@@ -2305,7 +2326,7 @@ impl ClientOptions {
23052326
/// [`GENERIC_READ`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
23062327
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
23072328
pub fn read(&mut self, allowed: bool) -> &mut Self {
2308-
bool_flag!(self.desired_access, allowed, windows_sys::GENERIC_READ);
2329+
self.generic_read = allowed;
23092330
self
23102331
}
23112332

@@ -2316,7 +2337,7 @@ impl ClientOptions {
23162337
/// [`GENERIC_WRITE`]: https://docs.microsoft.com/en-us/windows/win32/secauthz/generic-access-rights
23172338
/// [`CreateFile`]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew
23182339
pub fn write(&mut self, allowed: bool) -> &mut Self {
2319-
bool_flag!(self.desired_access, allowed, windows_sys::GENERIC_WRITE);
2340+
self.generic_write = allowed;
23202341
self
23212342
}
23222343

@@ -2434,13 +2455,24 @@ impl ClientOptions {
24342455
) -> io::Result<NamedPipeClient> {
24352456
let addr = encode_addr(addr);
24362457

2458+
let desired_access = {
2459+
let mut access = 0;
2460+
if self.generic_read {
2461+
access |= windows_sys::GENERIC_READ;
2462+
}
2463+
if self.generic_write {
2464+
access |= windows_sys::GENERIC_WRITE;
2465+
}
2466+
access
2467+
};
2468+
24372469
// NB: We could use a platform specialized `OpenOptions` here, but since
24382470
// we have access to windows_sys it ultimately doesn't hurt to use
24392471
// `CreateFile` explicitly since it allows the use of our already
24402472
// well-structured wide `addr` to pass into CreateFileW.
24412473
let h = windows_sys::CreateFileW(
24422474
addr.as_ptr(),
2443-
self.desired_access,
2475+
desired_access,
24442476
0,
24452477
attrs as *mut _,
24462478
windows_sys::OPEN_EXISTING,
@@ -2453,13 +2485,9 @@ impl ClientOptions {
24532485
}
24542486

24552487
if matches!(self.pipe_mode, PipeMode::Message) {
2456-
let mut mode = windows_sys::PIPE_READMODE_MESSAGE;
2457-
let result = windows_sys::SetNamedPipeHandleState(
2458-
h,
2459-
&mut mode,
2460-
ptr::null_mut(),
2461-
ptr::null_mut(),
2462-
);
2488+
let mode = windows_sys::PIPE_READMODE_MESSAGE;
2489+
let result =
2490+
windows_sys::SetNamedPipeHandleState(h, &mode, ptr::null_mut(), ptr::null_mut());
24632491

24642492
if result == 0 {
24652493
return Err(io::Error::last_os_error());
@@ -2582,53 +2610,3 @@ unsafe fn named_pipe_info(handle: RawHandle) -> io::Result<PipeInfo> {
25822610
max_instances,
25832611
})
25842612
}
2585-
2586-
#[cfg(test)]
2587-
mod test {
2588-
use self::windows_sys::{
2589-
PIPE_READMODE_MESSAGE, PIPE_REJECT_REMOTE_CLIENTS, PIPE_TYPE_BYTE, PIPE_TYPE_MESSAGE,
2590-
};
2591-
use super::*;
2592-
2593-
#[test]
2594-
fn opts_default_pipe_mode() {
2595-
let opts = ServerOptions::new();
2596-
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
2597-
}
2598-
2599-
#[test]
2600-
fn opts_unset_reject_remote() {
2601-
let mut opts = ServerOptions::new();
2602-
opts.reject_remote_clients(false);
2603-
assert_eq!(opts.pipe_mode & PIPE_REJECT_REMOTE_CLIENTS, 0);
2604-
}
2605-
2606-
#[test]
2607-
fn opts_set_pipe_mode_maintains_reject_remote_clients() {
2608-
let mut opts = ServerOptions::new();
2609-
opts.pipe_mode(PipeMode::Byte);
2610-
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
2611-
2612-
opts.reject_remote_clients(false);
2613-
opts.pipe_mode(PipeMode::Byte);
2614-
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE);
2615-
2616-
opts.reject_remote_clients(true);
2617-
opts.pipe_mode(PipeMode::Byte);
2618-
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
2619-
2620-
opts.reject_remote_clients(false);
2621-
opts.pipe_mode(PipeMode::Message);
2622-
assert_eq!(opts.pipe_mode, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE);
2623-
2624-
opts.reject_remote_clients(true);
2625-
opts.pipe_mode(PipeMode::Message);
2626-
assert_eq!(
2627-
opts.pipe_mode,
2628-
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_REJECT_REMOTE_CLIENTS
2629-
);
2630-
2631-
opts.pipe_mode(PipeMode::Byte);
2632-
assert_eq!(opts.pipe_mode, PIPE_TYPE_BYTE | PIPE_REJECT_REMOTE_CLIENTS);
2633-
}
2634-
}

0 commit comments

Comments
 (0)