use mill_io::error::Result;
use mill_io::EventLoop;
use mill_net::errors::{NetworkError, NetworkEvent};
use mill_net::tcp::{config::TcpServerConfig, traits::*, ConnectionId, ServerContext, TcpServer};
use mio::Token;
use std::sync::Arc;
#[derive(Clone, Default)]
struct EchoHandler;
impl NetworkHandler for EchoHandler {
fn on_event(&self, _ctx: &ServerContext, event: NetworkEvent) -> Result<()> {
match event {
NetworkEvent::ConnectionEstablished(conn_id, addr) => {
println!("[INFO] New client connected: {:?} from {}", conn_id, addr);
}
NetworkEvent::ConnectionClosed(conn_id) => {
println!("[INFO] Client disconnected: {:?}", conn_id);
}
NetworkEvent::Listening(addr) => {
println!("[INFO] Server listening on {}", addr);
}
}
Ok(())
}
fn on_connect(&self, _ctx: &ServerContext, _conn_id: ConnectionId) -> Result<()> {
Ok(())
}
fn on_data(&self, ctx: &ServerContext, conn_id: ConnectionId, data: &[u8]) -> Result<()> {
let message = String::from_utf8_lossy(data);
println!(
"[INFO] Received {} bytes from {:?}: {}",
data.len(),
conn_id,
message.trim_end()
);
ctx.send_to(conn_id, data)?;
Ok(())
}
fn on_disconnect(&self, _ctx: &ServerContext, _conn_id: ConnectionId) -> Result<()> {
Ok(())
}
fn on_error(&self, _ctx: &ServerContext, conn_id: Option<ConnectionId>, error: NetworkError) {
if let Some(id) = conn_id {
eprintln!("[ERROR] Error on connection {:?}: {}", id, error);
} else {
eprintln!("[ERROR] Server error: {}", error);
}
}
}
fn main() -> Result<()> {
let event_loop = Arc::new(EventLoop::default());
let config = TcpServerConfig::builder()
.address("127.0.0.1:8080".parse().unwrap())
.build();
let handler = EchoHandler;
let server = Arc::new(TcpServer::new(config.clone(), handler)?);
server.start(&event_loop, Token(0))?;
println!("[INFO] Echo server listening on {}", config.address);
event_loop.run()?;
Ok(())
}