winpipe/
lib.rs

1//! # winpipe
2//! Blocking wrapper for Windows named pipes with very similar api to UnixStream/UnixListen.
3//!
4//!
5//! ## Listening for a pipe (server)
6//! ```rust
7//! use winpipe::WinListener;
8//! use std::io;
9//!
10//! use std::io::{Read, Write};
11//!
12//! use std::time::Duration;
13//!
14//! fn listen_for_pipes() -> io::Result<()>{
15//!     let listener = WinListener::bind("\\\\.\\pipe\\my_pipe_is_cool")?;
16//!
17//!     loop {
18//!         let (mut stream, _addr) = listener.accept()?;
19//!         stream.set_write_timeout(Some(Duration::from_millis(5000)))?;
20//!         stream.set_read_timeout(Some(Duration::from_millis(5000)))?;
21//!
22//!         stream.write("Hello World".as_bytes())?;
23//!         let mut buffer = vec![0u8; 64];
24//!         let received = stream.read(buffer.as_mut_slice())?;
25//!         println!("Received {:?}", &buffer[..received])
26//!         //DROPPING Closes the pipe
27//!     }
28//! }
29//! ```
30//! ## Connecting a pipe
31//! ```rust
32//! use winpipe::WinStream;
33//! use std::io;
34//!
35//! use std::io::{Read, Write};
36//!
37//! use std::time::Duration;
38//!
39//! fn connect_pipe() -> io::Result<()>{
40//!     let mut stream = WinStream::connect("\\\\.\\pipe\\my_pipe_is_cool")?;
41//!
42//!     stream.set_write_timeout(Some(Duration::from_millis(5000)))?;
43//!     stream.set_read_timeout(Some(Duration::from_millis(5000)))?;
44//!
45//!     stream.write("Hello World".as_bytes())?;
46//!     let mut buffer = vec![0u8; 64];
47//!     let received = stream.read(buffer.as_mut_slice())?;
48//!     println!("Received {:?}", &buffer[..received]);
49//!     //DROPPING Closes the pipe
50//!     Ok(())
51//! }
52//! ```
53//! ## Tip for writing the same IPC code for Windows and Unix
54//! Create type aliases for UnixListen, UnixStream and unix::SocketAddress.
55//! On Unix targets let the alias point to the implementations of the stdlib.
56//! On Windows targets let the alias point to WinListen, WinStream and WinPipeSocketAddress.
57//!
58//! You should only require very few conditional compilation blocks as long as you do not use
59//! the advanced features of Unix Sockets (such as for example sharing file descriptors).
60//!
61//! ## Implementation Details
62//! * All pipes are created/opened by this crate are PIPE_TYPE_STREAM. PIPE_TYPE_PACKET is not implemented.
63//! * The default timeout for both read and write is infinite.
64//! * Setting a timeout or calling WinStream::set_nonblocking(true) concurrently will interrupt ongoing read/write calls.
65//! * Dropping WinStream may block up to 5s in a call to FlushFileBuffers.
66//! * The io buffer sizes supplied to the Windows API are 0x1_00_00 (64kb)
67//! * There is no connection backlog
68//!     * It's not possible to implement one given Windows API limitations.
69//!     * As long as you do not actively call WinListener::accept() or WinListener::incoming()::next() no client will be able to connect.
70//! * Connecting client pipes is implemented using CreateFileA and 200ms polling. It will try to connect for 1s (~4-5 times) before returning ErrorKind::ConnectionRefused
71//!     * a custom timeout can be passed with `WinStream::connect_with_timeout`. At least 1 attempt to connect will always be made!
72//! * This library uses the `log` crate to log all system calls using the trace! macro.
73//!     * If you are troubleshooting problems then I recommend using a log format which includes the thread id!
74//!     + To disable usage of the log crate use default-features=false in your Cargo.toml when including winpipe.
75//!
76#[cfg(target_os = "windows")]
77mod pipe;
78#[cfg(target_os = "windows")]
79pub use pipe::*;