2 releases
0.1.1 | Oct 16, 2024 |
---|---|
0.1.0 | Oct 6, 2024 |
#249 in Unix APIs
83KB
2K
SLoC
winpipe
Blocking rust wrapper for Windows named pipes with very similar api to UnixStream/UnixListen.
Listening for a pipe (server)
use winpipe::WinListener;
use std::io;
use std::io::{Read, Write};
use std::time::Duration;
fn listen_for_pipes() -> io::Result<()>{
let listener = WinListener::bind("\\\\.\\pipe\\my_pipe_is_cool")?;
loop {
let (mut stream, _addr) = listener.accept()?;
stream.set_write_timeout(Some(Duration::from_millis(5000)))?;
stream.set_read_timeout(Some(Duration::from_millis(5000)))?;
stream.write("Hello World".as_bytes())?;
let mut buffer = vec![0u8; 64];
let received = stream.read(buffer.as_mut_slice())?;
println!("Received {:?}", &buffer[..received])
//DROPPING Closes the pipe
}
}
Connecting a pipe
use winpipe::WinStream;
use std::io;
use std::io::{Read, Write};
use std::time::Duration;
fn connect_pipe() -> io::Result<()>{
let mut stream = WinStream::connect("\\\\.\\pipe\\my_pipe_is_cool")?;
stream.set_write_timeout(Some(Duration::from_millis(5000)))?;
stream.set_read_timeout(Some(Duration::from_millis(5000)))?;
stream.write("Hello World".as_bytes())?;
let mut buffer = vec![0u8; 64];
let received = stream.read(buffer.as_mut_slice())?;
println!("Received {:?}", &buffer[..received]);
//DROPPING Closes the pipe
Ok(())
}
Tip for writing the same IPC code for Windows and Unix
Create type aliases for UnixListen, UnixStream and unix::SocketAddress. On Unix targets let the alias point to the implementations of the stdlib. On Windows targets let the alias point to WinListen, WinStream and WinPipeSocketAddress.
You should only require very few conditional compilation blocks as long as you do not use the advanced features of Unix Sockets (such as for example sharing file descriptors).
Implementation Details
- All pipes are created/opened by this crate are PIPE_TYPE_STREAM. PIPE_TYPE_PACKET is not implemented.
- The default timeout for both read and write is infinite.
- Setting a timeout or calling WinStream::set_nonblocking(true) concurrently will interrupt ongoing read/write calls.
- Dropping WinStream may block up to 5s in a call to FlushFileBuffers.
- The io buffer sizes supplied to the Windows API are 0x1_00_00 (64kb)
- There is no connection backlog
- It's not possible to implement one given Windows API limitations.
- As long as you do not actively call WinListener::accept() or WinListener::incoming()::next() no client will be able to connect.
- Connecting client pipes is implemented using CreateFileA and 200ms polling. It will try to connect for 1s (~4-5 times) before returning ErrorKind::ConnectionRefused
- a custom timeout can be passed with
WinStream::connect_with_timeout
. At least 1 attempt to connect will always be made!
- a custom timeout can be passed with
- This library uses the
log
crate to log all system calls using the trace! macro.- If you are troubleshooting problems then I recommend using a log format which includes the thread id!
- To disable usage of the log crate use default-features=false in your Cargo.toml when including winpipe.
Dependencies
~0–35MB
~526K SLoC