From a7b7f6bb97995eb977de70222fb1f40890d16ded Mon Sep 17 00:00:00 2001 From: Titouan Rigoudy Date: Fri, 15 Jul 2016 15:56:51 +0200 Subject: [PATCH] Add bare-bones listening socket. --- src/client.rs | 6 +++ src/config.rs | 3 ++ src/proto/handler.rs | 87 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/client.rs b/src/client.rs index 99d335d..6e4b78d 100644 --- a/src/client.rs +++ b/src/client.rs @@ -123,6 +123,12 @@ impl Client { ).unwrap() )); + self.send_to_server(server::ServerRequest::SetListenPortRequest( + server::SetListenPortRequest { + port: config::LISTEN_PORT, + } + )); + loop { match self.recv() { IncomingMessage::Proto(response) => diff --git a/src/config.rs b/src/config.rs index 50d9b6d..7f7d18f 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,6 +9,9 @@ pub const PASSWORD: &'static str = "ijklmnop"; pub const SERVER_HOST : &'static str = "server.slsknet.org"; pub const SERVER_PORT : u16 = 2242; +pub const LISTEN_HOST: &'static str = "0.0.0.0"; +pub const LISTEN_PORT: u16 = 2243; + pub const CONTROL_HOST: &'static str = "localhost"; pub const CONTROL_PORT: u16 = 2244; diff --git a/src/proto/handler.rs b/src/proto/handler.rs index 04f29f3..db9f12e 100644 --- a/src/proto/handler.rs +++ b/src/proto/handler.rs @@ -1,5 +1,7 @@ +use std::fmt; use std::io; use std::net; +use std::net::ToSocketAddrs; use std::sync::mpsc; use mio; @@ -20,6 +22,8 @@ use super::peer; // between client and handler that would otherwise be needed. const SERVER_TOKEN: usize = config::MAX_PEERS; +const LISTEN_TOKEN: usize = config::MAX_PEERS + 1; + /*====================* * REQUEST - RESPONSE * *====================*/ @@ -91,9 +95,25 @@ struct Handler { peer_streams: slab::Slab, usize>, + listener: mio::tcp::TcpListener, + client_tx: mpsc::Sender, } +fn listener_bind(addr_spec: U) -> io::Result + where U: ToSocketAddrs + fmt::Debug +{ + for socket_addr in try!(addr_spec.to_socket_addrs()) { + if let Ok(listener) = mio::tcp::TcpListener::bind(&socket_addr) { + return Ok(listener) + } + } + Err(io::Error::new( + io::ErrorKind::Other, + format!("Cannot bind to {:?}", addr_spec) + )) +} + impl Handler { fn new( client_tx: mpsc::Sender, @@ -109,6 +129,14 @@ impl Handler { info!("Connected to server at {}:{}", host, port); + let listener = try!( + listener_bind((config::LISTEN_HOST, config::LISTEN_PORT)) + ); + info!( + "Listening for connections on {}:{}", + config::LISTEN_HOST, config::LISTEN_PORT + ); + try!(event_loop.register( server_stream.evented(), mio::Token(SERVER_TOKEN), @@ -116,11 +144,20 @@ impl Handler { mio::PollOpt::edge() | mio::PollOpt::oneshot() )); + try!(event_loop.register( + &listener, + mio::Token(LISTEN_TOKEN), + mio::EventSet::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot() + )); + Ok(Handler { server_stream: server_stream, peer_streams: slab::Slab::new(config::MAX_PEERS), + listener: listener, + client_tx: client_tx, }) } @@ -221,16 +258,46 @@ impl mio::Handler for Handler { fn ready(&mut self, event_loop: &mut mio::EventLoop, token: mio::Token, event_set: mio::EventSet) { - if token.0 == SERVER_TOKEN { - let intent = self.server_stream.on_ready(event_set); - self.process_server_intent(intent, event_loop); - } else { - let intent = match self.peer_streams.get_mut(token.0) { - Some(peer_stream) => peer_stream.on_ready(event_set), - - None => unreachable!("Unknown token {} is ready", token.0), - }; - self.process_peer_intent(intent, token, event_loop); + match token { + mio::Token(LISTEN_TOKEN) => { + if event_set.is_readable() { + // A peer wants to connect to us. + match self.listener.accept() { + Ok(Some(sock)) => { + // TODO add it to peer streams + info!("Peer connection accepted"); + }, + + Ok(None) => { + warn!("No peer connection to accept"); + }, + + Err(err) => { + error!("Cannot accept peer connection: {}", err); + } + } + } + event_loop.reregister( + &self.listener, + token, + mio::EventSet::all(), + mio::PollOpt::edge() | mio::PollOpt::oneshot() + ).unwrap(); + }, + + mio::Token(SERVER_TOKEN) => { + let intent = self.server_stream.on_ready(event_set); + self.process_server_intent(intent, event_loop); + }, + + mio::Token(peer_id) => { + let intent = match self.peer_streams.get_mut(peer_id) { + Some(peer_stream) => peer_stream.on_ready(event_set), + + None => unreachable!("Unknown peer {} is ready", peer_id), + }; + self.process_peer_intent(intent, token, event_loop); + } } }