|
|
@ -11,10 +11,14 @@ use config; |
|
|
|
|
|
|
|
|
use super::{Intent, Stream, SendPacket};
|
|
|
use super::{Intent, Stream, SendPacket};
|
|
|
use super::server::*;
|
|
|
use super::server::*;
|
|
|
|
|
|
use super::peer;
|
|
|
|
|
|
|
|
|
const SERVER_TOKEN: usize = 0;
|
|
|
const SERVER_TOKEN: usize = 0;
|
|
|
const INIT_PEER_TOKEN: usize = 1;
|
|
|
const INIT_PEER_TOKEN: usize = 1;
|
|
|
|
|
|
|
|
|
|
|
|
type ServerStream = Stream<mio::tcp::TcpStream, ServerResponseSender>;
|
|
|
|
|
|
type PeerStream = Stream<mio::tcp::TcpStream, PeerResponseSender>;
|
|
|
|
|
|
|
|
|
/*====================*
|
|
|
/*====================*
|
|
|
* REQUEST - RESPONSE *
|
|
|
* REQUEST - RESPONSE *
|
|
|
*====================*/
|
|
|
*====================*/
|
|
|
@ -22,6 +26,7 @@ const INIT_PEER_TOKEN: usize = 1; |
|
|
#[derive(Debug)]
|
|
|
#[derive(Debug)]
|
|
|
pub enum Request {
|
|
|
pub enum Request {
|
|
|
ConnectToPeer(net::Ipv4Addr, u16),
|
|
|
ConnectToPeer(net::Ipv4Addr, u16),
|
|
|
|
|
|
PeerMessage(usize, peer::Message),
|
|
|
ServerRequest(ServerRequest)
|
|
|
ServerRequest(ServerRequest)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -29,6 +34,8 @@ pub enum Request { |
|
|
pub enum Response {
|
|
|
pub enum Response {
|
|
|
ConnectToPeerError(net::Ipv4Addr, u16),
|
|
|
ConnectToPeerError(net::Ipv4Addr, u16),
|
|
|
ConnectToPeerSuccess(net::Ipv4Addr, u16, usize),
|
|
|
ConnectToPeerSuccess(net::Ipv4Addr, u16, usize),
|
|
|
|
|
|
PeerConnectionClosed(usize),
|
|
|
|
|
|
PeerMessage(peer::Message),
|
|
|
ServerResponse(ServerResponse),
|
|
|
ServerResponse(ServerResponse),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -54,11 +61,11 @@ impl SendPacket for ServerResponseSender { |
|
|
pub struct PeerResponseSender(mpsc::Sender<Response>, usize);
|
|
|
pub struct PeerResponseSender(mpsc::Sender<Response>, usize);
|
|
|
|
|
|
|
|
|
impl SendPacket for PeerResponseSender {
|
|
|
impl SendPacket for PeerResponseSender {
|
|
|
type Value = u32;
|
|
|
|
|
|
|
|
|
type Value = peer::Message;
|
|
|
type Error = mpsc::SendError<Response>;
|
|
|
type Error = mpsc::SendError<Response>;
|
|
|
|
|
|
|
|
|
fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> {
|
|
|
fn send_packet(&mut self, value: Self::Value) -> Result<(), Self::Error> {
|
|
|
Ok(())
|
|
|
|
|
|
|
|
|
self.0.send(Response::PeerMessage(value))
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -69,10 +76,9 @@ impl SendPacket for PeerResponseSender { |
|
|
/// This struct handles all the soulseek connections, to the server and to
|
|
|
/// This struct handles all the soulseek connections, to the server and to
|
|
|
/// peers.
|
|
|
/// peers.
|
|
|
struct Handler {
|
|
|
struct Handler {
|
|
|
server_stream: Stream<mio::tcp::TcpStream, ServerResponseSender>,
|
|
|
|
|
|
|
|
|
server_stream: ServerStream,
|
|
|
|
|
|
|
|
|
peer_streams: |
|
|
|
|
|
slab::Slab<Stream<mio::tcp::TcpStream, PeerResponseSender>, usize>,
|
|
|
|
|
|
|
|
|
peer_streams: slab::Slab<PeerStream, usize>,
|
|
|
|
|
|
|
|
|
client_tx: mpsc::Sender<Response>,
|
|
|
client_tx: mpsc::Sender<Response>,
|
|
|
}
|
|
|
}
|
|
|
@ -141,7 +147,12 @@ impl Handler { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn connect_to_peer(&mut self, ip: net::Ipv4Addr, port: u16) {
|
|
|
|
|
|
|
|
|
fn connect_to_peer(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
ip: net::Ipv4Addr,
|
|
|
|
|
|
port: u16,
|
|
|
|
|
|
event_loop: &mut mio::EventLoop<Self>)
|
|
|
|
|
|
{
|
|
|
let vacant_entry = match self.peer_streams.vacant_entry() {
|
|
|
let vacant_entry = match self.peer_streams.vacant_entry() {
|
|
|
Some(vacant_entry) => vacant_entry,
|
|
|
Some(vacant_entry) => vacant_entry,
|
|
|
None => {
|
|
|
None => {
|
|
|
@ -158,7 +169,7 @@ impl Handler { |
|
|
|
|
|
|
|
|
info!("Connecting to peer {}:{}", ip, port);
|
|
|
info!("Connecting to peer {}:{}", ip, port);
|
|
|
|
|
|
|
|
|
let tcp_stream = match Self::connect((ip, port)) {
|
|
|
|
|
|
|
|
|
let mut tcp_stream = match Self::connect((ip, port)) {
|
|
|
Ok(tcp_stream) => tcp_stream,
|
|
|
Ok(tcp_stream) => tcp_stream,
|
|
|
Err(err) => {
|
|
|
Err(err) => {
|
|
|
error!("Cannot connect to peer {}:{}: {}", ip, port, err);
|
|
|
error!("Cannot connect to peer {}:{}: {}", ip, port, err);
|
|
|
@ -170,18 +181,58 @@ impl Handler { |
|
|
}
|
|
|
}
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
let token = vacant_entry.index();
|
|
|
|
|
|
|
|
|
let peer_id = vacant_entry.index();
|
|
|
|
|
|
|
|
|
|
|
|
event_loop.register(
|
|
|
|
|
|
&mut tcp_stream,
|
|
|
|
|
|
mio::Token(peer_id),
|
|
|
|
|
|
mio::EventSet::readable(),
|
|
|
|
|
|
mio::PollOpt::edge() | mio::PollOpt::oneshot()
|
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
|
|
|
let peer_stream = Stream::new(
|
|
|
let peer_stream = Stream::new(
|
|
|
tcp_stream, PeerResponseSender(self.client_tx.clone(), token)
|
|
|
|
|
|
|
|
|
tcp_stream, PeerResponseSender(self.client_tx.clone(), peer_id)
|
|
|
);
|
|
|
);
|
|
|
|
|
|
|
|
|
vacant_entry.insert(peer_stream);
|
|
|
vacant_entry.insert(peer_stream);
|
|
|
|
|
|
|
|
|
|
|
|
// This is actually false, because the socket might still be connecting
|
|
|
|
|
|
// asynchronously.
|
|
|
|
|
|
// We will know if the connection worked or not when we get an event
|
|
|
|
|
|
// and try to read or write.
|
|
|
|
|
|
// There is nothing too wrong about telling the client it worked though,
|
|
|
|
|
|
// and closing the connection as soon as the client tries to use it,
|
|
|
|
|
|
// at which point the client will forget about the whole thing.
|
|
|
self.client_tx.send(
|
|
|
self.client_tx.send(
|
|
|
Response::ConnectToPeerSuccess(ip, port, token)
|
|
|
|
|
|
|
|
|
Response::ConnectToPeerSuccess(ip, port, peer_id)
|
|
|
).unwrap();
|
|
|
).unwrap();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn process_peer_intent(
|
|
|
|
|
|
&mut self,
|
|
|
|
|
|
intent: Intent,
|
|
|
|
|
|
token: mio::Token,
|
|
|
|
|
|
event_loop: &mut mio::EventLoop<Self>)
|
|
|
|
|
|
{
|
|
|
|
|
|
match intent {
|
|
|
|
|
|
Intent::Done => {
|
|
|
|
|
|
self.peer_streams.remove(token.0);
|
|
|
|
|
|
self.client_tx.send(Response::PeerConnectionClosed(token.0))
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
Intent::Continue(event_set) => {
|
|
|
|
|
|
if let Some(peer_stream) = self.peer_streams.get_mut(token.0) {
|
|
|
|
|
|
event_loop.reregister(
|
|
|
|
|
|
peer_stream.evented(),
|
|
|
|
|
|
token,
|
|
|
|
|
|
event_set,
|
|
|
|
|
|
mio::PollOpt::edge() | mio::PollOpt::oneshot()
|
|
|
|
|
|
).unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
impl mio::Handler for Handler {
|
|
|
impl mio::Handler for Handler {
|
|
|
@ -195,7 +246,11 @@ impl mio::Handler for Handler { |
|
|
let intent = self.server_stream.on_ready(event_set);
|
|
|
let intent = self.server_stream.on_ready(event_set);
|
|
|
self.process_server_intent(intent, event_loop);
|
|
|
self.process_server_intent(intent, event_loop);
|
|
|
} else {
|
|
|
} else {
|
|
|
unreachable!("Unknown token!");
|
|
|
|
|
|
|
|
|
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"),
|
|
|
|
|
|
};
|
|
|
|
|
|
self.process_peer_intent(intent, token, event_loop);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -204,7 +259,23 @@ impl mio::Handler for Handler { |
|
|
{
|
|
|
{
|
|
|
match request {
|
|
|
match request {
|
|
|
Request::ConnectToPeer(ip, port) =>
|
|
|
Request::ConnectToPeer(ip, port) =>
|
|
|
self.connect_to_peer(ip, port),
|
|
|
|
|
|
|
|
|
self.connect_to_peer(ip, port, event_loop),
|
|
|
|
|
|
|
|
|
|
|
|
Request::PeerMessage(peer_id, message) => {
|
|
|
|
|
|
let intent = match self.peer_streams.get_mut(peer_id) {
|
|
|
|
|
|
Some(peer_stream) => peer_stream.on_notify(&message),
|
|
|
|
|
|
None => {
|
|
|
|
|
|
error!(
|
|
|
|
|
|
"Cannot send peer message {:?}: unknown id {}",
|
|
|
|
|
|
message, peer_id
|
|
|
|
|
|
);
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
self.process_peer_intent(
|
|
|
|
|
|
intent, mio::Token(peer_id), event_loop
|
|
|
|
|
|
);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
Request::ServerRequest(server_request) => {
|
|
|
Request::ServerRequest(server_request) => {
|
|
|
let intent = self.server_stream.on_notify(&server_request);
|
|
|
let intent = self.server_stream.on_notify(&server_request);
|
|
|
|