use std::{io, net::SocketAddr};
use compio::{
BufResult,
io::{AsyncRead, AsyncWriteExt},
net::{TcpListener, TcpStream},
runtime::Runtime,
};
use compio_pool::{LocalPool, ManageConnection, Pool};
struct Buffers;
impl ManageConnection for Buffers {
type Connection = Vec<u8>;
type Error = io::Error;
async fn connect(&self) -> io::Result<Vec<u8>> {
Ok(Vec::with_capacity(16 * 1024))
}
async fn is_valid(&self, _buf: &mut Vec<u8>) -> io::Result<()> {
Ok(())
}
fn has_broken(&self, _buf: &mut Vec<u8>) -> bool {
false
}
}
fn main() -> io::Result<()> {
let addr: SocketAddr = std::env::args()
.nth(1)
.unwrap_or_else(|| "127.0.0.1:7000".into())
.parse()
.map_err(|e| io::Error::new(io::ErrorKind::InvalidInput, format!("bad address: {e}")))?;
let capacity: u32 = std::env::args()
.nth(2)
.and_then(|s| s.parse().ok())
.unwrap_or(1024);
let pool = Pool::builder().max_size(capacity).build(Buffers);
let runtime = Runtime::builder().build().expect("build compio runtime");
runtime.block_on(async move {
let local = pool.local();
let listener = TcpListener::bind(addr).await?;
println!("task_echo on {addr}: 1 runtime, capacity {capacity}");
loop {
let Ok((stream, _peer)) = listener.accept().await else {
continue;
};
let _ = stream.set_nodelay(true);
compio::runtime::spawn(serve(local.clone(), stream)).detach();
}
})
}
async fn serve(local: LocalPool<Buffers>, mut stream: TcpStream) {
let mut lease = match local.get().await {
Ok(lease) => lease,
Err(_) => return,
};
loop {
let mut buf = std::mem::take(&mut *lease);
buf.clear();
let BufResult(read, buf) = stream.read(buf).await;
match read {
Ok(0) | Err(_) => {
*lease = buf;
return;
}
Ok(_) => {}
}
let BufResult(written, buf) = stream.write_all(buf).await;
*lease = buf;
if written.is_err() {
return;
}
}
}