use super::*; use std::io::*; use std::net::*; use std::thread; use std::time::Duration; use crate::model::*; mod protocol_connection; use self::protocol_connection::*; pub fn listen_forever(handler: H, config: &ProtocolConfig) -> io::Result<()> where H: 'static + ProtocolHandler + Sized, { let listener = TcpListener::bind((config.listen_addr.as_str(), config.port))?; for mut connection in listener.incoming() { // If there is an successful connection, // set timeouts. // We ignore errors here, so they will be caught in the clients thread. let _ = connection.as_mut().map(|stream| { stream.set_read_timeout(Duration::from_secs(config.read_timeout_s).into())?; stream.set_write_timeout(Duration::from_secs(config.read_timeout_s).into()) }); let mut handler = handler.clone(); let _ = thread::spawn(move || client_loop(connection?, handler)); } Ok(()) } fn client_loop(connection: TcpStream, handler: H) -> io::Result<()> where H: 'static + ProtocolHandler + Sized, { let mut connection = Connection::from_tcp(connection)?; loop { let package = connection.receive()?; match package { Package::Error(_, _) => { // Just clone the connection. break; } Package::Binary(_) => { connection.send(&Package::Error(400, "Unexpected Binary".to_string()))?; break; } Package::JsonTrue | Package::JsonFalse | Package::JsonNull => { connection.send(&Package::Error( 400, "Unexpected true, false or null. ".to_string(), ))?; break; } Package::Json(Command::Ping {}) => { connection.send(&Package::Json(Command::Pong {}))?; } Package::Json(Command::Pong {}) => { // Ignore } // TODO: lots _ => unimplemented!(), } } Ok(()) }