91 lines
2.9 KiB
Rust
91 lines
2.9 KiB
Rust
extern crate syscall;
|
|
|
|
use std::{
|
|
fs::File,
|
|
io::{self, prelude::*},
|
|
os::unix::io::{AsRawFd, FromRawFd},
|
|
thread,
|
|
time::Duration
|
|
};
|
|
|
|
fn from_syscall_error(error: syscall::Error) -> io::Error {
|
|
io::Error::from_raw_os_error(error.errno as i32)
|
|
}
|
|
|
|
fn main() -> io::Result<()> {
|
|
let mut buf = [0; 5];
|
|
let server = File::create("chan:hello_world")?;
|
|
{
|
|
let mut client = File::open("chan:hello_world")?;
|
|
// First client not accepted yet
|
|
assert_eq!(File::open("chan:hello_world").unwrap_err().kind(), io::ErrorKind::ConnectionRefused);
|
|
|
|
let stream = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
|
|
let mut stream = unsafe { File::from_raw_fd(stream) };
|
|
|
|
println!("Testing basic I/O...");
|
|
|
|
stream.write(b"abc")?;
|
|
stream.flush()?;
|
|
println!("-> Wrote message");
|
|
|
|
assert_eq!(client.read(&mut buf)?, 3);
|
|
assert_eq!(&buf[..3], b"abc");
|
|
println!("-> Read message");
|
|
|
|
println!("Testing close...");
|
|
|
|
drop(client);
|
|
assert_eq!(stream.write(b"a").unwrap_err().kind(), io::ErrorKind::BrokenPipe);
|
|
assert_eq!(stream.read(&mut buf)?, 0);
|
|
}
|
|
println!("Testing alternative connect method...");
|
|
let client = syscall::dup(server.as_raw_fd(), b"connect").map_err(from_syscall_error)?;
|
|
let mut client = unsafe { File::from_raw_fd(client) };
|
|
|
|
let stream = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
|
|
let mut stream = unsafe { File::from_raw_fd(stream) };
|
|
|
|
println!("Testing blocking I/O...");
|
|
|
|
let mut client_clone = client.try_clone()?;
|
|
|
|
let thread = thread::spawn(move || -> io::Result<()> {
|
|
println!("--> Thread: Sleeping for 1 second...");
|
|
thread::sleep(Duration::from_secs(1));
|
|
println!("--> Thread: Writing...");
|
|
client_clone.write(b"def")?;
|
|
client_clone.flush()?;
|
|
Ok(())
|
|
});
|
|
|
|
assert_eq!(stream.read(&mut buf)?, 3);
|
|
assert_eq!(&buf[..3], b"def");
|
|
println!("-> Read message");
|
|
|
|
thread.join().unwrap().unwrap();
|
|
|
|
println!("Testing non-blocking I/O...");
|
|
|
|
syscall::fcntl(client.as_raw_fd(), syscall::F_SETFL, syscall::O_NONBLOCK)
|
|
.map_err(from_syscall_error)?;
|
|
syscall::fcntl(server.as_raw_fd(), syscall::F_SETFL, syscall::O_NONBLOCK)
|
|
.map_err(from_syscall_error)?;
|
|
assert_eq!(client.read(&mut buf).unwrap_err().kind(), io::ErrorKind::WouldBlock);
|
|
println!("-> Read would block");
|
|
match syscall::dup(server.as_raw_fd(), b"listen") {
|
|
Ok(stream) => {
|
|
unsafe { File::from_raw_fd(stream); }
|
|
panic!("this is supposed to fail");
|
|
},
|
|
Err(err) => {
|
|
let err = from_syscall_error(err);
|
|
assert_eq!(err.kind(), io::ErrorKind::WouldBlock);
|
|
}
|
|
}
|
|
println!("-> Accept would block");
|
|
|
|
println!("Everything tested!");
|
|
Ok(())
|
|
}
|