use mio::{Ready,Token,Event}; use mio::tcp::TcpListener; use std::net::SocketAddr; use std::io::{Result,ErrorKind}; use config::Config; use eventloop::{Machine,Context,EventLoop}; use itf_http; struct Listener { sock: TcpListener, addr: SocketAddr, io: Token } impl Listener { fn new(addr: &SocketAddr) -> Result { trace!("Binding {}", addr); let sock = try!(TcpListener::bind(addr)); Ok(Listener { sock: sock, addr: *addr, io: Token(0) }) } } impl Machine for Listener { fn init(&mut self, ctx: &mut Context) { self.io = ctx.assign(); ctx.register(&self.sock, self.io, Ready::readable()); info!("Listening on {}", self.addr); } fn handle(&mut self, ctx: &mut Context, _: Event) { // TODO: max_connections or something match self.sock.accept() { Err(err) => { match err.kind() { ErrorKind::WouldBlock | ErrorKind::Interrupted | ErrorKind::TimedOut => { }, _ => { error!("Error accepting on {}: {}", self.addr, err); // If the error is persistent, we may be getting into an infinite loop. // TODO: Have a back-off timer here (especially for EMFILE). } } }, Ok((sock, addr)) => { debug!("{}: New connection", addr); ctx.spawn(Box::new(itf_http::ItfHttp::new(sock, addr))); } } } } pub fn setup(ev: &mut EventLoop, cfg: &Config) -> Result<()> { for itf in &cfg.itf { for addr in &itf.addr { let lst = try!(Listener::new(&addr)); ev.spawn(Box::new(lst)); } } Ok(()) }