91 lines
2.4 KiB
Rust
91 lines
2.4 KiB
Rust
use std::io;
|
|
use std::io::prelude::*;
|
|
use std::net::{TcpListener,TcpStream,SocketAddr};
|
|
use std::process::exit;
|
|
use std::collections::VecDeque;
|
|
use std::thread::sleep;
|
|
use std::time::Duration;
|
|
|
|
static PORT:u16 = 55555;
|
|
static IDLE_THRESH:usize = 1024;
|
|
|
|
fn main() {
|
|
|
|
'recovery:loop {
|
|
|
|
let listener = match TcpListener::bind(&format!("[::]:{}",PORT)) {
|
|
Err(why) => {
|
|
eprintln!("failed to bind TCP listener: {}",why);
|
|
exit(1);
|
|
},
|
|
Ok(l) => l,
|
|
};
|
|
listener.set_nonblocking(true).expect("cannot set listener to nonblocking");
|
|
|
|
let mut connections:VecDeque<(TcpStream,SocketAddr)> = VecDeque::new();
|
|
let mut bottle:[u8;1] = [0x00];
|
|
let mut idlecycles:usize = 0;
|
|
|
|
'processor:loop {
|
|
idlecycles += 1;
|
|
|
|
match listener.accept() {
|
|
Err(why) => match why.kind() {
|
|
io::ErrorKind::WouldBlock => (),
|
|
_ => {
|
|
eprintln!("failed to accept new connection: {}",why);
|
|
break 'processor;
|
|
},
|
|
},
|
|
Ok((stream,address)) => {
|
|
println!("+ connection opened by {}",address);
|
|
stream.set_nonblocking(true).expect("cannot set stream to nonblocking");
|
|
stream.set_nodelay(true).expect("cannot set stream to nodelay");
|
|
connections.push_back((stream,address));
|
|
},
|
|
};
|
|
|
|
match connections.pop_front() {
|
|
None => sleep(Duration::from_millis(1)),
|
|
Some((mut stream,address)) => match stream.read(&mut bottle) {
|
|
Err(why) => match why.kind() {
|
|
io::ErrorKind::WouldBlock => connections.push_back((stream,address)),
|
|
_ => println!("- connection to {} failed: read error: {}",address,why),
|
|
},
|
|
Ok(n) => match n {
|
|
0 => {
|
|
println!("- connection to {} closed: read reached end of stream",address);
|
|
},
|
|
_ => {
|
|
for _ in 0..connections.len() {
|
|
if let Some((mut otherstream,otheraddress)) = connections.pop_front() {
|
|
match otherstream.write(&bottle) {
|
|
Err(why) => println!("- connection to {} failed: write error: {}",otheraddress,why),
|
|
Ok(n) => match n {
|
|
0 => {
|
|
println!("- connection to {} closed: write reached end of stream",otheraddress);
|
|
},
|
|
_ => {
|
|
connections.push_back((otherstream,otheraddress));
|
|
},
|
|
},
|
|
};
|
|
}
|
|
}
|
|
connections.push_back((stream,address));
|
|
idlecycles = 0;
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
if idlecycles > IDLE_THRESH {
|
|
sleep(Duration::from_millis(1));
|
|
}
|
|
|
|
}
|
|
|
|
} // 'recovery
|
|
|
|
}
|