pub struct ServerOptions { /* private fields */ }
Expand description
A builder structure for construct a named pipe with named pipe-specific options. This is required to use for named pipe servers who wants to modify pipe-related options.
Implementations§
Source§impl ServerOptions
impl ServerOptions
Sourcepub fn new() -> ServerOptions
pub fn new() -> ServerOptions
Creates a new named pipe builder with the default settings.
use compio_fs::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-new";
let server = ServerOptions::new().create(PIPE_NAME).unwrap();
Sourcepub fn pipe_mode(&mut self, pipe_mode: PipeMode) -> &mut Self
pub fn pipe_mode(&mut self, pipe_mode: PipeMode) -> &mut Self
The pipe mode.
The default pipe mode is PipeMode::Byte
. See PipeMode
for
documentation of what each mode means.
This corresponds to specifying PIPE_TYPE_
and PIPE_READMODE_
in
dwPipeMode
.
Sourcepub fn access_inbound(&mut self, allowed: bool) -> &mut Self
pub fn access_inbound(&mut self, allowed: bool) -> &mut Self
The flow of data in the pipe goes from client to server only.
This corresponds to setting PIPE_ACCESS_INBOUND
.
§Errors
Server side prevents connecting by denying inbound access, client errors
with std::io::ErrorKind::PermissionDenied
when attempting to create
the connection.
use std::io;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-inbound-err1";
let _server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)
.unwrap();
let e = ClientOptions::new().open(PIPE_NAME).await.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
Disabling writing allows a client to connect, but errors with
std::io::ErrorKind::PermissionDenied
if a write is attempted.
use std::io;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
use compio_io::AsyncWrite;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-inbound-err2";
let server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)
.unwrap();
let mut client = ClientOptions::new()
.write(false)
.open(PIPE_NAME)
.await
.unwrap();
server.connect().await.unwrap();
let e = client.write("ping").await.0.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
§Examples
A unidirectional named pipe that only supports server-to-client communication.
use std::io;
use compio_buf::BufResult;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
use compio_io::{AsyncReadExt, AsyncWriteExt};
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-inbound";
let mut server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)
.unwrap();
let mut client = ClientOptions::new()
.write(false)
.open(PIPE_NAME)
.await
.unwrap();
server.connect().await.unwrap();
let write = server.write_all("ping");
let buf = Vec::with_capacity(4);
let read = client.read_exact(buf);
let (BufResult(write, _), BufResult(read, buf)) = futures_util::join!(write, read);
write.unwrap();
read.unwrap();
assert_eq!(&buf[..], b"ping");
Sourcepub fn access_outbound(&mut self, allowed: bool) -> &mut Self
pub fn access_outbound(&mut self, allowed: bool) -> &mut Self
The flow of data in the pipe goes from server to client only.
This corresponds to setting PIPE_ACCESS_OUTBOUND
.
§Errors
Server side prevents connecting by denying outbound access, client
errors with std::io::ErrorKind::PermissionDenied
when attempting to
create the connection.
use std::io;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-outbound-err1";
let server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)
.unwrap();
let e = ClientOptions::new().open(PIPE_NAME).await.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
Disabling reading allows a client to connect, but attempting to read
will error with std::io::ErrorKind::PermissionDenied
.
use std::io;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
use compio_io::AsyncRead;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-outbound-err2";
let server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)
.unwrap();
let mut client = ClientOptions::new()
.read(false)
.open(PIPE_NAME)
.await
.unwrap();
server.connect().await.unwrap();
let buf = Vec::with_capacity(4);
let e = client.read(buf).await.0.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
§Examples
A unidirectional named pipe that only supports client-to-server communication.
use compio_buf::BufResult;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
use compio_io::{AsyncReadExt, AsyncWriteExt};
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-access-outbound";
let mut server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)
.unwrap();
let mut client = ClientOptions::new()
.read(false)
.open(PIPE_NAME)
.await
.unwrap();
server.connect().await.unwrap();
let write = client.write_all("ping");
let buf = Vec::with_capacity(4);
let read = server.read_exact(buf);
let (BufResult(write, _), BufResult(read, buf)) = futures_util::join!(write, read);
write.unwrap();
read.unwrap();
println!("done reading and writing");
assert_eq!(&buf[..], b"ping");
Sourcepub fn first_pipe_instance(&mut self, first: bool) -> &mut Self
pub fn first_pipe_instance(&mut self, first: bool) -> &mut Self
If you attempt to create multiple instances of a pipe with this flag
set, creation of the first server instance succeeds, but creation of any
subsequent instances will fail with
std::io::ErrorKind::PermissionDenied
.
This option is intended to be used with servers that want to ensure that they are the only process listening for clients on a given named pipe. This is accomplished by enabling it for the first server instance created in a process.
This corresponds to setting FILE_FLAG_FIRST_PIPE_INSTANCE
.
§Errors
If this option is set and more than one instance of the server for a
given named pipe exists, calling create
will fail with
std::io::ErrorKind::PermissionDenied
.
use std::io;
use compio_fs::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-first-instance-error";
let server1 = ServerOptions::new()
.first_pipe_instance(true)
.create(PIPE_NAME)
.unwrap();
// Second server errs, since it's not the first instance.
let e = ServerOptions::new()
.first_pipe_instance(true)
.create(PIPE_NAME)
.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
§Examples
use std::io;
use compio_fs::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-first-instance";
let mut builder = ServerOptions::new();
builder.first_pipe_instance(true);
let server = builder.create(PIPE_NAME).unwrap();
let e = builder.create(PIPE_NAME).unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
drop(server);
// OK: since, we've closed the other instance.
let _server2 = builder.create(PIPE_NAME).unwrap();
Sourcepub fn write_dac(&mut self, requested: bool) -> &mut Self
pub fn write_dac(&mut self, requested: bool) -> &mut Self
Requests permission to modify the pipe’s discretionary access control list.
This corresponds to setting WRITE_DAC
in dwOpenMode.
§Examples
use std::{io, ptr};
use compio_driver::AsRawFd;
use compio_fs::named_pipe::ServerOptions;
use windows_sys::Win32::{
Foundation::ERROR_SUCCESS,
Security::{
Authorization::{SE_KERNEL_OBJECT, SetSecurityInfo},
DACL_SECURITY_INFORMATION,
},
};
const PIPE_NAME: &str = r"\\.\pipe\write_dac_pipe";
let mut pipe_template = ServerOptions::new();
pipe_template.write_dac(true);
let pipe = pipe_template.create(PIPE_NAME).unwrap();
unsafe {
assert_eq!(
ERROR_SUCCESS,
SetSecurityInfo(
pipe.as_raw_fd() as _,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
);
}
use std::{io, ptr};
use compio_driver::AsRawFd;
use compio_fs::named_pipe::ServerOptions;
use windows_sys::Win32::{
Foundation::ERROR_ACCESS_DENIED,
Security::{
Authorization::{SE_KERNEL_OBJECT, SetSecurityInfo},
DACL_SECURITY_INFORMATION,
},
};
const PIPE_NAME: &str = r"\\.\pipe\write_dac_pipe_fail";
let mut pipe_template = ServerOptions::new();
pipe_template.write_dac(false);
let pipe = pipe_template.create(PIPE_NAME).unwrap();
unsafe {
assert_eq!(
ERROR_ACCESS_DENIED,
SetSecurityInfo(
pipe.as_raw_fd() as _,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
);
}
Sourcepub fn write_owner(&mut self, requested: bool) -> &mut Self
pub fn write_owner(&mut self, requested: bool) -> &mut Self
Requests permission to modify the pipe’s owner.
This corresponds to setting WRITE_OWNER
in dwOpenMode.
Sourcepub fn access_system_security(&mut self, requested: bool) -> &mut Self
pub fn access_system_security(&mut self, requested: bool) -> &mut Self
Requests permission to modify the pipe’s system access control list.
This corresponds to setting ACCESS_SYSTEM_SECURITY
in dwOpenMode.
Sourcepub fn reject_remote_clients(&mut self, reject: bool) -> &mut Self
pub fn reject_remote_clients(&mut self, reject: bool) -> &mut Self
Indicates whether this server can accept remote clients or not. Remote clients are disabled by default.
This corresponds to setting PIPE_REJECT_REMOTE_CLIENTS
.
Sourcepub fn max_instances(&mut self, instances: usize) -> &mut Self
pub fn max_instances(&mut self, instances: usize) -> &mut Self
The maximum number of instances that can be created for this pipe. The first instance of the pipe can specify this value; the same number must be specified for other instances of the pipe. Acceptable values are in the range 1 through 254. The default value is unlimited.
This corresponds to specifying nMaxInstances
.
§Errors
The same numbers of max_instances
have to be used by all servers. Any
additional servers trying to be built which uses a mismatching value
might error.
use std::io;
use compio_fs::named_pipe::{ClientOptions, ServerOptions};
use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-max-instances";
let mut server = ServerOptions::new();
server.max_instances(2);
let s1 = server.create(PIPE_NAME).unwrap();
let c1 = ClientOptions::new().open(PIPE_NAME).await.unwrap();
let s2 = server.create(PIPE_NAME).unwrap();
let c2 = ClientOptions::new().open(PIPE_NAME).await.unwrap();
// Too many servers!
let e = server.create(PIPE_NAME).unwrap_err();
assert_eq!(e.raw_os_error(), Some(ERROR_PIPE_BUSY as i32));
// Still too many servers even if we specify a higher value!
let e = server.max_instances(100).create(PIPE_NAME).unwrap_err();
assert_eq!(e.raw_os_error(), Some(ERROR_PIPE_BUSY as i32));
§Panics
This function will panic if more than 254 instances are specified. If you do not wish to set an instance limit, leave it unspecified.
use compio_fs::named_pipe::ServerOptions;
let builder = ServerOptions::new().max_instances(255);
Sourcepub fn out_buffer_size(&mut self, buffer: u32) -> &mut Self
pub fn out_buffer_size(&mut self, buffer: u32) -> &mut Self
The number of bytes to reserve for the output buffer.
This corresponds to specifying nOutBufferSize
.
Sourcepub fn in_buffer_size(&mut self, buffer: u32) -> &mut Self
pub fn in_buffer_size(&mut self, buffer: u32) -> &mut Self
The number of bytes to reserve for the input buffer.
This corresponds to specifying nInBufferSize
.
Sourcepub fn create(&self, addr: impl AsRef<OsStr>) -> Result<NamedPipeServer>
pub fn create(&self, addr: impl AsRef<OsStr>) -> Result<NamedPipeServer>
Creates the named pipe identified by addr
for use as a server.
This uses the CreateNamedPipe
function.
§Examples
use compio_fs::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\compio-named-pipe-create";
let server = ServerOptions::new().create(PIPE_NAME).unwrap();
Trait Implementations§
Source§impl Clone for ServerOptions
impl Clone for ServerOptions
Source§fn clone(&self) -> ServerOptions
fn clone(&self) -> ServerOptions
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more