Support multiple connectors to listener

This commit is contained in:
jD91mZM2
2019-04-25 17:06:37 +02:00
parent 50e0b499f4
commit 85f6cea0bd
3 changed files with 210 additions and 176 deletions
+33 -35
View File
@@ -9,17 +9,14 @@ use std::{
fn from_syscall_error(error: syscall::Error) -> io::Error {
io::Error::from_raw_os_error(error.errno as i32)
}
fn nonblock(file: &File) -> io::Result<()> {
syscall::fcntl(file.as_raw_fd() as usize, syscall::F_SETFL, syscall::O_NONBLOCK)
.map(|_| ())
.map_err(from_syscall_error)
}
fn main() -> io::Result<()> {
let server = File::create("chan:log")?;
let mut event_file = File::open("event:")?;
nonblock(&server)?;
syscall::fcntl(server.as_raw_fd() as usize, syscall::F_SETFL, syscall::O_NONBLOCK)
.map(|_| ())
.map_err(from_syscall_error)?;
event_file.write(&syscall::Event {
id: server.as_raw_fd() as usize,
data: 0,
@@ -36,41 +33,28 @@ fn main() -> io::Result<()> {
if event.data == 0 {
println!("Listener recevied flags: {}", event.flags);
if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
let stream = syscall::dup(server.as_raw_fd() as usize, b"listen").map_err(from_syscall_error)?;
let stream = unsafe { File::from_raw_fd(stream as RawFd) };
loop {
let stream = match syscall::dup(server.as_raw_fd() as usize, b"listen").map_err(from_syscall_error) {
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
stream => stream?
};
let stream = unsafe { File::from_raw_fd(stream as RawFd) };
nonblock(&stream)?;
event_file.write(&syscall::Event {
id: stream.as_raw_fd() as usize,
data: next_id,
flags: syscall::EVENT_READ | syscall::EVENT_WRITE,
})?;
event_file.write(&syscall::Event {
id: stream.as_raw_fd() as usize,
data: next_id,
flags: syscall::EVENT_READ | syscall::EVENT_WRITE,
})?;
clients.insert(next_id, stream);
next_id += 1;
clients.insert(next_id, stream);
println!("-> Spawned client #{}", next_id);
next_id += 1;
}
}
} else {
println!("Client #{} received flags: {}", event.data, event.flags);
let client = clients.get_mut(&event.data).unwrap();
if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
println!("-> Writing");
const BUF: &str = "Hello from the log server\n";
let mut written = 0;
while written < BUF.len() {
let len = match client.write(BUF[written..].as_bytes()) {
Ok(0) => {
println!("--> EOF");
clients.remove(&event.data);
continue 'outer;
},
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
len => len?
};
println!("--> Wrote {}/{} bytes: {:?}", len, BUF.len(), &BUF[written..]);
written += len;
}
}
if event.flags & syscall::EVENT_READ == syscall::EVENT_READ {
println!("-> Reading");
let mut buf = [0; 128];
@@ -84,7 +68,21 @@ fn main() -> io::Result<()> {
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
len => len?
};
println!("--> Read {}/128 bytes: {:?}", len, str::from_utf8(&buf));
println!("--> Read {}/128 bytes: {:?}", len, str::from_utf8(&buf[..len]));
}
}
if event.flags & syscall::EVENT_WRITE == syscall::EVENT_WRITE {
println!("-> Writing");
const BUF: &str = "Hello from the log server\n";
let mut written = 0;
while written < BUF.len() {
let len = match client.write(BUF[written..].as_bytes()) {
Ok(0) => panic!("EOF should never happen here"),
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => break,
len => len?
};
println!("--> Wrote {}/{} bytes: {:?}", len, BUF.len(), &BUF[written..]);
written += len;
}
}
}
+17 -7
View File
@@ -1,5 +1,5 @@
use std::{
fs::File,
fs::{File, OpenOptions},
io::{self, prelude::*},
os::unix::io::{AsRawFd, FromRawFd, RawFd},
thread,
@@ -23,11 +23,24 @@ 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);
println!("Testing O_EXCL...");
assert_eq!(
OpenOptions::new()
.write(true)
.create_new(true)
.open("chan:hello_world").unwrap_err().kind(),
io::ErrorKind::AlreadyExists
);
println!("Testing connecting...");
File::open("chan:hello_world")?; // closed connection will silently be skipped
let mut client = File::create("chan:hello_world")?; // O_CREAT without O_EXCL does nothing
let tmp = File::open("chan:hello_world")?; // multiple connections are handled
let mut stream = dup(&server, "listen")?;
assert!(dup(&server, "listen").is_ok());
drop(tmp);
println!("Testing basic I/O...");
@@ -89,9 +102,6 @@ fn main() -> io::Result<()> {
println!("-> Write before accept would block");
}
assert_eq!(dup(&server, "listen").unwrap_err().kind(), io::ErrorKind::ConnectionReset);
println!("-> Server can't accept dropped client");
let mut client = dup(&server, "connect")?;
nonblock(&client)?;