extern crate futures; extern crate gopher_core; extern crate tokio_core; extern crate tokio_io; extern crate tokio_service; use futures::{future, Future, Sink, Stream}; use gopher_core::codec::ServerCodec; use gopher_core::{DirEntity, ItemType, GopherRequest, GopherResponse, GopherStr}; use std::io; use tokio_io::AsyncRead; use tokio_core::reactor::Core; use tokio_core::net::TcpListener; use tokio_service::{NewService, Service}; pub struct HelloGopherServer; impl Service for HelloGopherServer { type Request = GopherRequest; type Response = GopherResponse; type Error = io::Error; type Future = future::FutureResult; fn call(&self, request: Self::Request) -> Self::Future { println!("got request {:?}", request); let response = match &request.selector[..] { b"" => match request.query.as_ref() { None => GopherResponse::Menu(vec![ DirEntity { item_type: ItemType::File, name: GopherStr::from_latin1(b"Hello, world"), selector: GopherStr::from_latin1(b"hello"), host: GopherStr::from_latin1(b"0.0.0.0"), port: 12345, }, DirEntity { item_type: ItemType::File, name: GopherStr::from_latin1(b"Goodbye, world"), selector: GopherStr::from_latin1(b"bye"), host: GopherStr::from_latin1(b"0.0.0.0"), port: 12345, }, ]), // Compatibility hack for gopher+ clients: Some(_) => GopherResponse::GopherPlusRedirect(DirEntity { item_type: ItemType::Dir, name: GopherStr::from_latin1(b"Main menu"), selector: GopherStr::from_latin1(b""), host: GopherStr::from_latin1(b"0.0.0.0"), port: 12345, }) }, b"hello" => GopherResponse::TextFile( GopherStr::from_latin1(b"Hello, world.\r\nWelcome to Gopher.").into_buf()), b"bye" => GopherResponse::TextFile(GopherStr::from_latin1(b"Goodbye!").into_buf()), _ => GopherResponse::error(GopherStr::from_latin1(b"File not found")), }; future::ok(response) } } fn serve(s: S) -> io::Result<()> where S: NewService + 'static { let mut core = Core::new()?; let handle = core.handle(); let address = "0.0.0.0:12345".parse().unwrap(); let listener = TcpListener::bind(&address, &handle)?; let connections = listener.incoming(); let server = connections.for_each(move |(socket, _peer_addr)| { let (writer, reader) = socket.framed(ServerCodec).split(); let service = s.new_service()?; let response = reader.take(1).and_then(move |request| service.call(request)); let server = writer.send_all(response).then(|_| Ok(())); handle.spawn(server); Ok(()) }); core.run(server) } fn main() { serve(|| Ok(HelloGopherServer)).unwrap(); }