-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
net: Provide a raw NamedPipe implementation and builders #3760
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 24 commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
fd4f217
net: Provide a raw NamedPipe implementation and builders
udoprog 11b486f
rustfmt
udoprog 006f364
only test named pipes on windows
udoprog 036a9a3
examples can't use path dependencies
udoprog d04700a
Merge remote-tracking branch 'upstream/master' into more-low-level-na…
udoprog 97a8942
re-enable examples
udoprog aa950e7
add access controls for client and info fn
udoprog 82a74be
new examples are only support on windows
udoprog 8f2c1e9
add local asyncify for tokio::net
udoprog ff4c6b3
rustfmt
udoprog 89b05a9
more documentation, tests, idiomatic listen and connect
udoprog 7c07f79
fix example
udoprog ef03f09
enable windows-specific docs to build on non-windows
udoprog 2acf90b
Revert "enable windows-specific docs to build on non-windows"
udoprog b5d5d85
make sure cross platform documentation for named pipes work
udoprog b25019b
fix private doc link
udoprog edf4fa5
switch to options style building
udoprog 8fb3c7f
add peeking functionality
udoprog 491f70b
fix non-windows build failure
udoprog 06147b5
fix link
udoprog a2d300f
mark more things as #[non_exhaustive]
udoprog f349c27
use ReadBuf in NamedPipe::peek
udoprog ec66427
make wait_named_pipe non-async
udoprog 435a84f
fix rustdoc
udoprog 08db16b
first batch of review fixes
udoprog a8a207d
rip wait_named_pipe
udoprog 591de4e
remove dead links
udoprog 88b6a9f
remove panicky FromRawHandle impl
udoprog 056c5de
make from_raw_handle pub
udoprog 0d6af11
adjust documentation
udoprog 18505ff
avoid additional allocations in encode_addr
udoprog 7586e38
clamp buffers
udoprog 6099b0c
remove shutdown logic in doctest
udoprog 477a569
allow setting security_qos_flags and ensure SECURITY_SQOS_PRESENT is set
udoprog 50ff91c
adjust safety documentation to mention it can be null
udoprog e7b1010
document the behavior of max_instances
udoprog bb28d50
add missing constant in doc building
udoprog da2920b
Update tokio/src/net/windows/named_pipe.rs
udoprog ed598ca
fix some broken and weird links
udoprog e4dd1a0
use winapi instead of redefining a const
udoprog 5753f3c
more missing doc items
udoprog 31b8584
refactor weird links
udoprog 2a6acd9
use *mut c_void for opaque pointers
udoprog e355dca
rustfmt again
udoprog eb863cb
create_with_security_attributes to *_raw and improved docs
udoprog 3f272d0
rename named_pipe builders and remove re-export
udoprog f5c822c
rename ClientOptions::create to ClientOptions::open
udoprog c8761a3
doc nits
udoprog 93b7dd0
enabled I/O
udoprog 7d1d277
improve docs and lie less
udoprog 93b8ff1
no aliasing of traits to _
udoprog ebe98dd
Update tokio/src/net/windows/named_pipe.rs
udoprog 47c951e
remove comment and just connect
udoprog fb9ed13
separate doc tests for errors and examples
udoprog 890d81d
separate doctess for errors and examples
udoprog 19248e4
try_from_raw_handle to from_raw_handle
udoprog dc694fd
vec! instead of array
udoprog 1f85125
remove peek-related fns
udoprog 960522e
Separate NamedPipe{Client,Server}
udoprog File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use std::io; | ||
|
||
#[cfg(windows)] | ||
async fn windows_main() -> io::Result<()> { | ||
use std::time::Duration; | ||
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; | ||
use tokio::net::windows::{NamedPipeClientOptions, NamedPipeOptions}; | ||
use tokio::time; | ||
use winapi::shared::winerror; | ||
|
||
const PIPE_NAME: &str = r"\\.\pipe\named-pipe-multi-client"; | ||
const N: usize = 10; | ||
|
||
// The first server needs to be constructed early so that clients can | ||
// be correctly connected. Otherwise a waiting client will error. | ||
// | ||
// Here we also make use of `first_pipe_instance`, which will ensure | ||
// that there are no other servers up and running already. | ||
let mut server = NamedPipeOptions::new() | ||
.first_pipe_instance(true) | ||
.create(PIPE_NAME)?; | ||
|
||
let server = tokio::spawn(async move { | ||
// Artificial workload. | ||
time::sleep(Duration::from_secs(1)).await; | ||
|
||
for _ in 0..N { | ||
// Wait for client to connect. | ||
server.connect().await?; | ||
let mut inner = server; | ||
|
||
// Construct the next server to be connected before sending the one | ||
// we already have of onto a task. This ensures that the server | ||
// isn't closed (after it's done in the task) before a new one is | ||
// available. Otherwise the client might error with | ||
// `io::ErrorKind::NotFound`. | ||
server = NamedPipeOptions::new().create(PIPE_NAME)?; | ||
|
||
let _ = tokio::spawn(async move { | ||
let mut buf = [0u8; 4]; | ||
inner.read_exact(&mut buf).await?; | ||
inner.write_all(b"pong").await?; | ||
Ok::<_, io::Error>(()) | ||
}); | ||
} | ||
|
||
Ok::<_, io::Error>(()) | ||
}); | ||
|
||
let mut clients = Vec::new(); | ||
|
||
for _ in 0..N { | ||
clients.push(tokio::spawn(async move { | ||
// This showcases a generic connect loop. | ||
// | ||
// We immediately try to create a client, if it's not found or | ||
// the pipe is busy we use the specialized wait function on the | ||
// client builder. | ||
let mut client = loop { | ||
match NamedPipeClientOptions::new().create(PIPE_NAME) { | ||
Ok(client) => break client, | ||
Err(e) if e.raw_os_error() == Some(winerror::ERROR_PIPE_BUSY as i32) => (), | ||
Err(e) => return Err(e), | ||
} | ||
|
||
time::sleep(Duration::from_millis(5)).await; | ||
}; | ||
|
||
let mut buf = [0u8; 4]; | ||
client.write_all(b"ping").await?; | ||
client.read_exact(&mut buf).await?; | ||
Ok::<_, io::Error>(buf) | ||
})); | ||
} | ||
|
||
for client in clients { | ||
let result = client.await?; | ||
assert_eq!(&result?[..], b"pong"); | ||
} | ||
|
||
server.await??; | ||
Ok(()) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> io::Result<()> { | ||
#[cfg(windows)] | ||
{ | ||
windows_main().await?; | ||
} | ||
|
||
#[cfg(not(windows))] | ||
{ | ||
println!("Named pipes are only supported on Windows!"); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
use std::io; | ||
|
||
#[cfg(windows)] | ||
async fn windows_main() -> io::Result<()> { | ||
use tokio::io::{AsyncReadExt as _, AsyncWriteExt as _}; | ||
use tokio::net::windows::{NamedPipeClientOptions, NamedPipeOptions}; | ||
|
||
const PIPE_NAME: &str = r"\\.\pipe\tokio-named-pipe-peek-consumed"; | ||
const N: usize = 1000; | ||
|
||
let mut server = NamedPipeOptions::new().create(PIPE_NAME)?; | ||
let mut client = NamedPipeClientOptions::new().create(PIPE_NAME)?; | ||
server.connect().await?; | ||
|
||
let client = tokio::spawn(async move { | ||
for _ in 0..N { | ||
client.write_all(b"ping").await?; | ||
} | ||
|
||
let mut buf = [0u8; 4]; | ||
client.read_exact(&mut buf).await?; | ||
|
||
Ok::<_, io::Error>(buf) | ||
}); | ||
|
||
let mut buf = [0u8; 4]; | ||
let mut available = 0; | ||
|
||
for n in 0..N { | ||
if available < 4 { | ||
println!("read_exact: (n: {}, available: {})", n, available); | ||
server.read_exact(&mut buf).await?; | ||
assert_eq!(&buf[..], b"ping"); | ||
|
||
let info = server.peek(None)?; | ||
available = info.total_bytes_available; | ||
continue; | ||
} | ||
|
||
println!("read_exact: (n: {}, available: {})", n, available); | ||
server.read_exact(&mut buf).await?; | ||
available -= buf.len(); | ||
assert_eq!(&buf[..], b"ping"); | ||
} | ||
|
||
server.write_all(b"pong").await?; | ||
|
||
let buf = client.await??; | ||
assert_eq!(&buf[..], b"pong"); | ||
Ok(()) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> io::Result<()> { | ||
#[cfg(windows)] | ||
{ | ||
windows_main().await?; | ||
} | ||
|
||
#[cfg(not(windows))] | ||
{ | ||
println!("Named pipes are only supported on Windows!"); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use std::io; | ||
|
||
#[cfg(windows)] | ||
async fn windows_main() -> io::Result<()> { | ||
use tokio::io::AsyncWriteExt as _; | ||
use tokio::io::{AsyncBufReadExt as _, BufReader}; | ||
use tokio::net::windows::{NamedPipeClientOptions, NamedPipeOptions}; | ||
|
||
const PIPE_NAME: &str = r"\\.\pipe\named-pipe-single-client"; | ||
|
||
let server = NamedPipeOptions::new().create(PIPE_NAME)?; | ||
|
||
let server = tokio::spawn(async move { | ||
// Note: we wait for a client to connect. | ||
server.connect().await?; | ||
|
||
let mut server = BufReader::new(server); | ||
|
||
let mut buf = String::new(); | ||
server.read_line(&mut buf).await?; | ||
server.write_all(b"pong\n").await?; | ||
Ok::<_, io::Error>(buf) | ||
}); | ||
|
||
let client = tokio::spawn(async move { | ||
// There's no need to use a connect loop here, since we know that the | ||
// server is already up - `create` was called before spawning any of the | ||
// tasks. | ||
let client = NamedPipeClientOptions::new().create(PIPE_NAME)?; | ||
|
||
let mut client = BufReader::new(client); | ||
|
||
let mut buf = String::new(); | ||
client.write_all(b"ping\n").await?; | ||
client.read_line(&mut buf).await?; | ||
Ok::<_, io::Error>(buf) | ||
}); | ||
|
||
let (server, client) = tokio::try_join!(server, client)?; | ||
|
||
assert_eq!(server?, "ping\n"); | ||
assert_eq!(client?, "pong\n"); | ||
|
||
Ok(()) | ||
} | ||
|
||
#[tokio::main] | ||
async fn main() -> io::Result<()> { | ||
#[cfg(windows)] | ||
{ | ||
windows_main().await?; | ||
} | ||
|
||
#[cfg(not(windows))] | ||
{ | ||
println!("Named pipes are only supported on Windows!"); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
//! Types which are documented locally in the Tokio crate, but does not actually | ||
//! live here. | ||
//! | ||
//! **Note** this module is only visible on docs.rs, you cannot use it directly | ||
//! in your own code. | ||
|
||
/// The name of a type which is not defined here. | ||
/// | ||
/// This is typically used as an alias for another type, like so: | ||
/// | ||
/// ```rust,ignore | ||
/// /// See [some::other::location](https://example.com). | ||
/// type DEFINED_ELSEWHERE = crate::doc::NotDefinedHere; | ||
/// ``` | ||
/// | ||
/// This type is uninhabitable like the [`never` type] to ensure that no one | ||
/// will ever accidentally use it. | ||
/// | ||
/// [`never` type]: https://doc.rust-lang.org/std/primitive.never.html | ||
pub enum NotDefinedHere {} | ||
|
||
pub mod os; | ||
pub mod winapi; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
//! See [std::os](https://doc.rust-lang.org/std/os/index.html). | ||
|
||
/// Platform-specific extensions to `std` for Windows. | ||
/// | ||
/// See [std::os::windows](https://doc.rust-lang.org/std/os/windows/index.html). | ||
pub mod windows { | ||
/// Windows-specific extensions to general I/O primitives. | ||
/// | ||
/// See [std::os::windows::io](https://doc.rust-lang.org/std/os/windows/io/index.html). | ||
pub mod io { | ||
/// See [std::os::windows::io::RawHandle](https://doc.rust-lang.org/std/os/windows/io/type.RawHandle.html) | ||
pub type RawHandle = crate::doc::NotDefinedHere; | ||
|
||
/// See [std::os::windows::io::AsRawHandle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html) | ||
pub trait AsRawHandle { | ||
/// See [std::os::windows::io::FromRawHandle::from_raw_handle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html#tymethod.as_raw_handle) | ||
fn as_raw_handle(&self) -> RawHandle; | ||
} | ||
|
||
/// See [std::os::windows::io::FromRawHandle](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html) | ||
pub trait FromRawHandle { | ||
/// See [std::os::windows::io::FromRawHandle::from_raw_handle](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html#tymethod.from_raw_handle) | ||
unsafe fn from_raw_handle(handle: RawHandle) -> Self; | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
//! See [winapi]. | ||
//! | ||
//! [winapi]: https://docs.rs/winapi | ||
|
||
/// See [winapi::shared](https://docs.rs/winapi/*/winapi/shared/index.html). | ||
pub mod shared { | ||
/// See [winapi::shared::winerror](https://docs.rs/winapi/*/winapi/shared/winerror/index.html). | ||
#[allow(non_camel_case_types)] | ||
pub mod winerror { | ||
/// See [winapi::shared::winerror::ERROR_ACCESS_DENIED][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_ACCESS_DENIED.html | ||
pub type ERROR_ACCESS_DENIED = crate::doc::NotDefinedHere; | ||
|
||
/// See [winapi::shared::winerror::ERROR_PIPE_BUSY][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_PIPE_BUSY.html | ||
pub type ERROR_PIPE_BUSY = crate::doc::NotDefinedHere; | ||
|
||
/// See [winapi::shared::winerror::ERROR_MORE_DATA][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/shared/winerror/constant.ERROR_MORE_DATA.html | ||
pub type ERROR_MORE_DATA = crate::doc::NotDefinedHere; | ||
} | ||
} | ||
|
||
/// See [winapi::um](https://docs.rs/winapi/*/winapi/um/index.html). | ||
pub mod um { | ||
/// See [winapi::um::winbase](https://docs.rs/winapi/*/winapi/um/winbase/index.html). | ||
#[allow(non_camel_case_types)] | ||
pub mod winbase { | ||
/// See [winapi::um::winbase::PIPE_TYPE_MESSAGE][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_TYPE_MESSAGE.html | ||
pub type PIPE_TYPE_MESSAGE = crate::doc::NotDefinedHere; | ||
|
||
/// See [winapi::um::winbase::PIPE_TYPE_BYTE][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_TYPE_BYTE.html | ||
pub type PIPE_TYPE_BYTE = crate::doc::NotDefinedHere; | ||
|
||
/// See [winapi::um::winbase::PIPE_CLIENT_END][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_CLIENT_END.html | ||
pub type PIPE_CLIENT_END = crate::doc::NotDefinedHere; | ||
|
||
/// See [winapi::um::winbase::PIPE_SERVER_END][winapi] | ||
/// | ||
/// [winapi]: https://docs.rs/winapi/*/winapi/um/winbase/constant.PIPE_SERVER_END.html | ||
pub type PIPE_SERVER_END = crate::doc::NotDefinedHere; | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.