Struct tokio::net::windows::named_pipe::ServerOptions
source · pub struct ServerOptions { /* private fields */ }
net
only.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 tokio::net::windows::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-new";
let server = ServerOptions::new().create(PIPE_NAME)?;
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 corresponding to specifying 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 tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-inbound-err1";
let _server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)?;
let e = ClientOptions::new()
.open(PIPE_NAME)
.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 tokio::io::AsyncWriteExt;
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-inbound-err2";
let server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)?;
let mut client = ClientOptions::new()
.write(false)
.open(PIPE_NAME)?;
server.connect().await?;
let e = client.write(b"ping").await.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 tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-inbound";
let mut server = ServerOptions::new()
.access_inbound(false)
.create(PIPE_NAME)?;
let mut client = ClientOptions::new()
.write(false)
.open(PIPE_NAME)?;
server.connect().await?;
let write = server.write_all(b"ping");
let mut buf = [0u8; 4];
let read = client.read_exact(&mut buf);
let ((), read) = tokio::try_join!(write, read)?;
assert_eq!(read, 4);
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 tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-outbound-err1";
let server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)?;
let e = ClientOptions::new()
.open(PIPE_NAME)
.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 tokio::io::AsyncReadExt;
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-outbound-err2";
let server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)?;
let mut client = ClientOptions::new()
.read(false)
.open(PIPE_NAME)?;
server.connect().await?;
let mut buf = [0u8; 4];
let e = client.read(&mut buf).await.unwrap_err();
assert_eq!(e.kind(), io::ErrorKind::PermissionDenied);
Examples
A unidirectional named pipe that only supports client-to-server communication.
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions};
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-access-outbound";
let mut server = ServerOptions::new()
.access_outbound(false)
.create(PIPE_NAME)?;
let mut client = ClientOptions::new()
.read(false)
.open(PIPE_NAME)?;
server.connect().await?;
let write = client.write_all(b"ping");
let mut buf = [0u8; 4];
let read = server.read_exact(&mut buf);
let ((), read) = tokio::try_join!(write, read)?;
println!("done reading and writing");
assert_eq!(read, 4);
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 tokio::net::windows::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-first-instance-error";
let server1 = ServerOptions::new()
.first_pipe_instance(true)
.create(PIPE_NAME)?;
// 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 tokio::net::windows::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-first-instance";
let mut builder = ServerOptions::new();
builder.first_pipe_instance(true);
let server = builder.create(PIPE_NAME)?;
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)?;
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, os::windows::prelude::AsRawHandle, ptr};
use tokio::net::windows::named_pipe::ServerOptions;
use windows_sys::{
Win32::Foundation::ERROR_SUCCESS,
Win32::Security::DACL_SECURITY_INFORMATION,
Win32::Security::Authorization::{SetSecurityInfo, SE_KERNEL_OBJECT},
};
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)?;
unsafe {
assert_eq!(
ERROR_SUCCESS,
SetSecurityInfo(
pipe.as_raw_handle() as _,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
ptr::null_mut(),
)
);
}
use std::{io, os::windows::prelude::AsRawHandle, ptr};
use tokio::net::windows::named_pipe::ServerOptions;
use windows_sys::{
Win32::Foundation::ERROR_ACCESS_DENIED,
Win32::Security::DACL_SECURITY_INFORMATION,
Win32::Security::Authorization::{SetSecurityInfo, SE_KERNEL_OBJECT},
};
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)?;
unsafe {
assert_eq!(
ERROR_ACCESS_DENIED,
SetSecurityInfo(
pipe.as_raw_handle() 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 tokio::net::windows::named_pipe::{ServerOptions, ClientOptions};
use windows_sys::Win32::Foundation::ERROR_PIPE_BUSY;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-max-instances";
let mut server = ServerOptions::new();
server.max_instances(2);
let s1 = server.create(PIPE_NAME)?;
let c1 = ClientOptions::new().open(PIPE_NAME);
let s2 = server.create(PIPE_NAME)?;
let c2 = ClientOptions::new().open(PIPE_NAME);
// 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 tokio::net::windows::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.
Errors
This errors if called outside of a Tokio Runtime, or in a runtime that has not enabled I/O, or if any OS-specific I/O errors occur.
Examples
use tokio::net::windows::named_pipe::ServerOptions;
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-create";
let server = ServerOptions::new().create(PIPE_NAME)?;
sourcepub unsafe fn create_with_security_attributes_raw(
&self,
addr: impl AsRef<OsStr>,
attrs: *mut c_void
) -> Result<NamedPipeServer>
pub unsafe fn create_with_security_attributes_raw( &self, addr: impl AsRef<OsStr>, attrs: *mut c_void ) -> Result<NamedPipeServer>
Creates the named pipe identified by addr
for use as a server.
This is the same as create
except that it supports providing the raw
pointer to a structure of SECURITY_ATTRIBUTES
which will be passed
as the lpSecurityAttributes
argument to CreateFile
.
Errors
This errors if called outside of a Tokio Runtime, or in a runtime that has not enabled I/O, or if any OS-specific I/O errors occur.
Safety
The attrs
argument must either be null or point at a valid instance of
the SECURITY_ATTRIBUTES
structure. If the argument is null, the
behavior is identical to calling the create
method.
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