74 lines
2.3 KiB
Rust
74 lines
2.3 KiB
Rust
use foxtrot::{
|
|
io::{Nonblocking, Readiness},
|
|
net::TcpListener,
|
|
Async,
|
|
};
|
|
use join_all::join_all;
|
|
use read_write_buf::ReadWriteBuf;
|
|
|
|
async fn echo(port: u16) -> Result<(), foxtrot::Error> {
|
|
let mut listener = Async::<TcpListener>::bind(([127, 0, 0, 1], port)).await?;
|
|
println!("bound listener");
|
|
|
|
loop {
|
|
let (mut stream, _addr) = listener.accept().await?;
|
|
println!("Accepted connection");
|
|
|
|
let mut interests = Readiness::read();
|
|
let mut ring_buf = ReadWriteBuf::<10>::new();
|
|
|
|
'l2: loop {
|
|
let readiness = stream.ready(interests).await?;
|
|
|
|
if readiness.is_hangup() {
|
|
break;
|
|
}
|
|
|
|
if readiness.is_read() {
|
|
while let Some(buf) = ring_buf.for_reading() {
|
|
match stream.read_nonblocking(buf)? {
|
|
Nonblocking::Ready(n) if n > 0 => {
|
|
let should_break = n < buf.len();
|
|
ring_buf.advance_read(n);
|
|
if should_break {
|
|
break;
|
|
}
|
|
}
|
|
Nonblocking::Ready(_) if ring_buf.is_empty() => break 'l2,
|
|
Nonblocking::Ready(_) | Nonblocking::WouldBlock => break,
|
|
}
|
|
}
|
|
|
|
if !ring_buf.is_empty() {
|
|
interests = Readiness::read() | Readiness::write();
|
|
}
|
|
}
|
|
|
|
if readiness.is_write() {
|
|
while let Some(buf) = ring_buf.for_writing() {
|
|
match stream.write_nonblocking(buf)? {
|
|
Nonblocking::Ready(n) => {
|
|
ring_buf.advance_write(n);
|
|
if ring_buf.is_empty() {
|
|
interests = Readiness::read();
|
|
}
|
|
}
|
|
Nonblocking::WouldBlock => {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
println!("Connection closed");
|
|
}
|
|
}
|
|
|
|
fn main() -> Result<(), foxtrot::Error> {
|
|
foxtrot::block_on(async move {
|
|
for res in join_all(vec![Box::pin(echo(4444)), Box::pin(echo(4445))]).await {
|
|
res?;
|
|
}
|
|
|
|
Ok(())
|
|
})?
|
|
}
|