use std::{ io::{BufRead, BufReader}, net::{IpAddr, SocketAddr, TcpListener, TcpStream}, }; use anyhow::Result; use tokio::spawn; pub struct SmtpServer { listener: TcpListener, running: bool, } impl SmtpServer { pub fn new(ip: [u8; 4], port: u16) -> Result { Ok(Self { listener: TcpListener::bind((IpAddr::from(ip), port))?, running: false, }) } // TODO: trap SIGINT to stop server? pub async fn run(&mut self) -> Result<()> { self.running = true; while self.running { let (stream, addr) = self.listener.accept()?; let session = SessionHandler { stream, addr, state: SessionState::default(), }; spawn(session.run()); } Ok(()) } } struct SessionHandler { stream: TcpStream, addr: SocketAddr, state: SessionState, } impl SessionHandler { async fn run(mut self) -> Result<()> { let mut r = BufReader::new(&self.stream); let mut buffer = String::new(); loop { if r.read_line(&mut buffer)? == 0 { break; } log::debug!("Received '{}' from '{}'", buffer.trim(), self.addr); self.state.apply().await; buffer.clear(); } log::info!("Connection closed by {}", self.addr); Ok(()) } } #[derive(Default)] struct SessionState {} impl SessionState { async fn apply(&mut self) { todo!() } }