Files
RedBear-OS/examples/chan.rs
T
2018-06-02 11:56:51 +02:00

173 lines
5.2 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 dup = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
let mut dup = unsafe { File::from_raw_fd(dup) };
println!("Testing basic I/O...");
dup.write(b"abc")?;
dup.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!(dup.write(b"a").unwrap_err().kind(), io::ErrorKind::NotConnected);
assert_eq!(dup.read(&mut buf)?, 0);
}
let mut client = File::open("chan:hello_world")?;
let dup = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
let mut dup = unsafe { File::from_raw_fd(dup) };
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!(dup.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(dup) => {
unsafe { File::from_raw_fd(dup); }
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!("Testing events...");
let thread = thread::spawn(move || -> io::Result<()> {
println!("--> Thread: Sleeping for 1 second...");
thread::sleep(Duration::from_secs(1));
println!("--> Thread: Writing...");
client.write(b"hello")?;
client.flush()?;
println!("--> Thread: Sleeping for 1 second...");
thread::sleep(Duration::from_secs(1));
println!("--> Thread: Dropping...");
drop(client);
println!("--> Thread: Sleeping for 3 seconds...");
thread::sleep(Duration::from_secs(3));
println!("--> Thread: Opening new...");
let mut client = File::open("chan:hello_world")?;
let mut buf = [0; 5];
assert_eq!(client.read(&mut buf)?, 0);
println!("--> Thread: Closing...");
Ok(())
});
let mut event_file = File::open("event:")?;
let mut time_file = File::open(format!("time:{}", syscall::CLOCK_MONOTONIC))?;
let mut time = syscall::TimeSpec::default();
time_file.read(&mut time)?;
time.tv_sec += 3;
time_file.write(&time)?;
event_file.write(&syscall::Event {
id: dup.as_raw_fd(),
flags: syscall::EVENT_READ | syscall::EVENT_WRITE,
data: 0
})?;
event_file.write(&syscall::Event {
id: server.as_raw_fd(),
flags: syscall::EVENT_WRITE | syscall::EVENT_READ,
data: 1
})?;
event_file.write(&syscall::Event {
id: time_file.as_raw_fd(),
flags: syscall::EVENT_READ,
data: 2
})?;
let mut event = syscall::Event::default();
event_file.read(&mut event)?;
assert_eq!(event.id, dup.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_WRITE);
assert_eq!(event.data, 0);
println!("-> Read event");
for _ in 0..2 {
event_file.read(&mut event)?;
assert_eq!(event.id, dup.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_READ);
assert_eq!(event.data, 0);
println!("-> Read event");
dup.read(&mut buf)?;
}
event_file.read(&mut event)?;
assert_eq!(event.id, time_file.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_READ);
assert_eq!(event.data, 2);
println!("-> Timed out");
event_file.read(&mut event)?;
assert_eq!(event.id, server.as_raw_fd());
assert_eq!(event.flags, syscall::EVENT_WRITE);
assert_eq!(event.data, 1);
println!("-> Read accept event");
let dup = syscall::dup(server.as_raw_fd(), b"listen").map_err(from_syscall_error)?;
let dup = unsafe { File::from_raw_fd(dup) };
drop(dup);
thread.join().unwrap()?;
println!("Everything tested!");
Ok(())
}