2016-10-12 10:39:50 -07:00
|
|
|
use std::{io, net};
|
|
|
|
use std::sync::Arc;
|
2016-10-18 03:14:54 -07:00
|
|
|
use parking_lot::RwLock;
|
2016-10-19 17:51:20 -07:00
|
|
|
use futures::{Future, finished, failed, BoxFuture};
|
2016-10-12 10:39:50 -07:00
|
|
|
use futures::stream::Stream;
|
|
|
|
use futures_cpupool::CpuPool;
|
2016-10-20 04:19:19 -07:00
|
|
|
use tokio_core::io::IoFuture;
|
2016-10-12 10:39:50 -07:00
|
|
|
use tokio_core::reactor::Handle;
|
2016-10-20 04:19:19 -07:00
|
|
|
use message::Payload;
|
2016-10-19 17:51:20 -07:00
|
|
|
use session::Session;
|
|
|
|
use io::{ReadAnyMessage, SharedTcpStream};
|
|
|
|
use net::{connect, listen, Connections, Channel, Config as NetConfig};
|
2016-10-18 03:14:54 -07:00
|
|
|
use util::NodeTable;
|
2016-10-19 18:14:42 -07:00
|
|
|
use {Config, PeerInfo};
|
2016-10-19 17:51:20 -07:00
|
|
|
|
|
|
|
pub type BoxedMessageFuture = BoxFuture<<ReadAnyMessage<SharedTcpStream> as Future>::Item, <ReadAnyMessage<SharedTcpStream> as Future>::Error>;
|
2016-10-19 18:14:42 -07:00
|
|
|
pub type BoxedEmptyFuture = BoxFuture<(), ()>;
|
2016-10-19 17:51:20 -07:00
|
|
|
|
|
|
|
/// Network context.
|
|
|
|
#[derive(Default)]
|
|
|
|
pub struct Context {
|
|
|
|
/// Connections.
|
|
|
|
connections: Connections,
|
|
|
|
/// Node Table.
|
|
|
|
node_table: RwLock<NodeTable>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
2016-10-19 18:14:42 -07:00
|
|
|
pub fn connect(context: Arc<Context>, socket: net::SocketAddr, handle: &Handle, config: &NetConfig) -> BoxedEmptyFuture {
|
2016-10-19 17:51:20 -07:00
|
|
|
trace!("Trying to connect to: {}", socket);
|
|
|
|
let connection = connect(&socket, handle, config);
|
|
|
|
connection.then(move |result| {
|
|
|
|
match result {
|
|
|
|
Ok(Ok(connection)) => {
|
|
|
|
// successfull hanshake
|
|
|
|
trace!("Connected to {}", connection.address);
|
|
|
|
context.node_table.write().insert(connection.address, connection.services);
|
2016-10-19 18:14:42 -07:00
|
|
|
let session = Session::new();
|
|
|
|
let channel = context.connections.store(connection, session);
|
2016-10-20 04:19:19 -07:00
|
|
|
|
|
|
|
// initialize session and then start reading messages
|
|
|
|
channel.session().initialize(context.clone(), channel.clone())
|
|
|
|
.and_then(move |_| Context::on_message(context, channel))
|
|
|
|
.boxed()
|
2016-10-19 17:51:20 -07:00
|
|
|
},
|
|
|
|
Ok(Err(err)) => {
|
|
|
|
// protocol error
|
2016-10-19 18:14:42 -07:00
|
|
|
trace!("Handshake with {} failed", socket);
|
|
|
|
// TODO: close socket
|
2016-10-19 17:51:20 -07:00
|
|
|
finished(Err(err)).boxed()
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
// network error
|
2016-10-19 18:14:42 -07:00
|
|
|
trace!("Unable to connect to {}", socket);
|
2016-10-19 17:51:20 -07:00
|
|
|
failed(err).boxed()
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 18:14:42 -07:00
|
|
|
})
|
|
|
|
.then(|_| finished(()))
|
|
|
|
.boxed()
|
2016-10-19 17:51:20 -07:00
|
|
|
}
|
|
|
|
|
2016-10-19 18:14:42 -07:00
|
|
|
pub fn listen(context: Arc<Context>, handle: &Handle, config: NetConfig) -> Result<BoxedEmptyFuture, io::Error> {
|
2016-10-19 17:51:20 -07:00
|
|
|
trace!("Starting tcp server");
|
|
|
|
let listen = try!(listen(&handle, config));
|
|
|
|
let server = listen.then(move |result| {
|
|
|
|
match result {
|
|
|
|
Ok(Ok(connection)) => {
|
|
|
|
// successfull hanshake
|
|
|
|
trace!("Accepted connection from {}", connection.address);
|
|
|
|
context.node_table.write().insert(connection.address, connection.services);
|
2016-10-19 18:14:42 -07:00
|
|
|
let session = Session::new();
|
|
|
|
let channel = context.connections.store(connection, session);
|
2016-10-20 04:19:19 -07:00
|
|
|
|
|
|
|
// initialize session and then start reading messages
|
|
|
|
let cloned_context = context.clone();
|
|
|
|
channel.session().initialize(context.clone(), channel.clone())
|
|
|
|
.and_then(|_| Context::on_message(cloned_context, channel))
|
|
|
|
.boxed()
|
2016-10-19 17:51:20 -07:00
|
|
|
},
|
|
|
|
Ok(Err(err)) => {
|
|
|
|
// protocol error
|
2016-10-19 18:14:42 -07:00
|
|
|
// TODO: close socket
|
2016-10-19 17:51:20 -07:00
|
|
|
finished(Err(err)).boxed()
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
// network error
|
|
|
|
failed(err).boxed()
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 18:14:42 -07:00
|
|
|
})
|
|
|
|
.for_each(|_| Ok(()))
|
|
|
|
.then(|_| finished(()))
|
|
|
|
.boxed();
|
2016-10-19 17:51:20 -07:00
|
|
|
Ok(server)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn on_message(context: Arc<Context>, channel: Arc<Channel>) -> BoxedMessageFuture {
|
|
|
|
channel.read_message().then(move |result| {
|
|
|
|
match result {
|
2016-10-20 04:19:19 -07:00
|
|
|
Ok(Ok((command, payload))) => {
|
2016-10-19 17:51:20 -07:00
|
|
|
// successful read
|
|
|
|
trace!("Received {} message from {}", command, channel.peer_info().address);
|
2016-10-20 04:19:19 -07:00
|
|
|
// handle message and read the next one
|
|
|
|
channel.session().on_message(context.clone(), channel.clone(), command, payload)
|
|
|
|
.and_then(move |_| Context::on_message(context, channel))
|
|
|
|
.boxed()
|
2016-10-19 17:51:20 -07:00
|
|
|
},
|
|
|
|
Ok(Err(err)) => {
|
|
|
|
// protocol error
|
2016-10-19 18:14:42 -07:00
|
|
|
context.close_connection(channel.peer_info());
|
2016-10-19 17:51:20 -07:00
|
|
|
finished(Err(err)).boxed()
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
// network error
|
2016-10-19 18:14:42 -07:00
|
|
|
context.close_connection(channel.peer_info());
|
2016-10-19 17:51:20 -07:00
|
|
|
failed(err).boxed()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}).boxed()
|
|
|
|
}
|
|
|
|
|
2016-10-20 04:19:19 -07:00
|
|
|
pub fn send<T>(context: Arc<Context>, channel: Arc<Channel>, payload: &T) -> IoFuture<()> where T: Payload {
|
|
|
|
trace!("Sending {} message to {}", T::command(), channel.peer_info().address);
|
|
|
|
channel.write_message(payload).then(move |result| {
|
|
|
|
match result {
|
|
|
|
Ok(_) => {
|
|
|
|
// successful send
|
|
|
|
trace!("Sent {} message to {}", T::command(), channel.peer_info().address);
|
|
|
|
finished(()).boxed()
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
// network error
|
|
|
|
context.close_connection(channel.peer_info());
|
|
|
|
failed(err).boxed()
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}).boxed()
|
2016-10-19 17:51:20 -07:00
|
|
|
}
|
2016-10-19 18:14:42 -07:00
|
|
|
|
2016-10-20 04:19:19 -07:00
|
|
|
pub fn close_connection(&self, peer_info: PeerInfo) {
|
2016-10-19 18:14:42 -07:00
|
|
|
if let Some(channel) = self.connections.remove(peer_info.id) {
|
|
|
|
trace!("Disconnecting from {}", peer_info.address);
|
|
|
|
channel.shutdown();
|
|
|
|
self.node_table.write().note_failure(&peer_info.address);
|
|
|
|
}
|
|
|
|
}
|
2016-10-19 17:51:20 -07:00
|
|
|
}
|
2016-10-12 05:30:50 -07:00
|
|
|
|
|
|
|
pub struct P2P {
|
2016-10-12 10:39:50 -07:00
|
|
|
/// Global event loop handle.
|
|
|
|
event_loop_handle: Handle,
|
|
|
|
/// Worker thread pool.
|
|
|
|
pool: CpuPool,
|
|
|
|
/// P2P config.
|
|
|
|
config: Config,
|
2016-10-19 17:51:20 -07:00
|
|
|
/// Network context.
|
|
|
|
context: Arc<Context>,
|
2016-10-12 05:30:50 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl P2P {
|
2016-10-12 10:39:50 -07:00
|
|
|
pub fn new(config: Config, handle: Handle) -> Self {
|
2016-10-17 16:44:52 -07:00
|
|
|
let pool = CpuPool::new(config.threads);
|
2016-10-12 10:39:50 -07:00
|
|
|
|
2016-10-12 05:30:50 -07:00
|
|
|
P2P {
|
2016-10-12 10:39:50 -07:00
|
|
|
event_loop_handle: handle.clone(),
|
|
|
|
pool: pool.clone(),
|
|
|
|
config: config,
|
2016-10-19 17:51:20 -07:00
|
|
|
context: Arc::default(),
|
2016-10-12 05:30:50 -07:00
|
|
|
}
|
|
|
|
}
|
2016-10-12 10:39:50 -07:00
|
|
|
|
|
|
|
pub fn run(&self) -> Result<(), io::Error> {
|
2016-10-19 05:17:18 -07:00
|
|
|
for peer in self.config.peers.iter() {
|
|
|
|
self.connect(*peer)
|
2016-10-12 10:39:50 -07:00
|
|
|
}
|
|
|
|
|
2016-10-13 06:24:37 -07:00
|
|
|
try!(self.listen());
|
|
|
|
Ok(())
|
2016-10-12 10:39:50 -07:00
|
|
|
}
|
|
|
|
|
2016-10-13 00:59:09 -07:00
|
|
|
pub fn connect(&self, ip: net::IpAddr) {
|
2016-10-12 10:39:50 -07:00
|
|
|
let socket = net::SocketAddr::new(ip, self.config.connection.magic.port());
|
2016-10-19 18:14:42 -07:00
|
|
|
let connection = Context::connect(self.context.clone(), socket, &self.event_loop_handle, &self.config.connection);
|
2016-10-19 17:51:20 -07:00
|
|
|
let pool_work = self.pool.spawn(connection);
|
2016-10-12 10:39:50 -07:00
|
|
|
self.event_loop_handle.spawn(pool_work);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn listen(&self) -> Result<(), io::Error> {
|
2016-10-19 18:14:42 -07:00
|
|
|
let server = try!(Context::listen(self.context.clone(), &self.event_loop_handle, self.config.connection.clone()));
|
2016-10-13 00:59:09 -07:00
|
|
|
let pool_work = self.pool.spawn(server);
|
|
|
|
self.event_loop_handle.spawn(pool_work);
|
2016-10-13 00:17:29 -07:00
|
|
|
Ok(())
|
2016-10-12 10:39:50 -07:00
|
|
|
}
|
2016-10-13 00:59:09 -07:00
|
|
|
|
2016-10-19 17:51:20 -07:00
|
|
|
/*
|
2016-10-14 02:44:11 -07:00
|
|
|
pub fn broadcast<T>(&self, payload: T) where T: Payload {
|
2016-10-18 03:14:54 -07:00
|
|
|
let channels = self.connections.channels();
|
2016-10-18 05:29:38 -07:00
|
|
|
for (_id, channel) in channels.into_iter() {
|
|
|
|
self.send_to_channel(&payload, &channel);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn send<T>(&self, payload: T, peer: PeerId) where T: Payload {
|
|
|
|
let channels = self.connections.channels();
|
|
|
|
if let Some(channel) = channels.get(&peer) {
|
|
|
|
self.send_to_channel(&payload, channel);
|
2016-10-18 03:14:54 -07:00
|
|
|
}
|
2016-10-13 00:59:09 -07:00
|
|
|
}
|
2016-10-18 05:29:38 -07:00
|
|
|
|
|
|
|
fn send_to_channel<T>(&self, payload: &T, channel: &Arc<Channel>) where T: Payload {
|
|
|
|
let connections = self.connections.clone();
|
|
|
|
let node_table = self.node_table.clone();
|
|
|
|
let peer_info = channel.peer_info();
|
|
|
|
let write = channel.write_message(payload);
|
|
|
|
let pool_work = self.pool.spawn(write).then(move |result| {
|
|
|
|
match result {
|
|
|
|
Ok(_) => {
|
|
|
|
node_table.write().note_used(&peer_info.address);
|
|
|
|
},
|
|
|
|
Err(_err) => {
|
|
|
|
node_table.write().note_failure(&peer_info.address);
|
|
|
|
connections.remove(peer_info.id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finished(())
|
|
|
|
});
|
|
|
|
self.event_loop_handle.spawn(pool_work);
|
|
|
|
}
|
2016-10-19 17:51:20 -07:00
|
|
|
*/
|
2016-10-12 05:30:50 -07:00
|
|
|
}
|