parity-zcash/p2p/src/p2p.rs

232 lines
6.7 KiB
Rust
Raw Normal View History

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;
use futures::{Future, finished, failed, BoxFuture};
2016-10-12 10:39:50 -07:00
use futures::stream::Stream;
use futures_cpupool::CpuPool;
use tokio_core::io::IoFuture;
2016-10-12 10:39:50 -07:00
use tokio_core::reactor::Handle;
use message::Payload;
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};
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<(), ()>;
/// 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 {
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);
// initialize session and then start reading messages
channel.session().initialize(context.clone(), channel.clone())
.and_then(move |_| Context::on_message(context, channel))
.boxed()
},
Ok(Err(err)) => {
// protocol error
2016-10-19 18:14:42 -07:00
trace!("Handshake with {} failed", socket);
// TODO: close socket
finished(Err(err)).boxed()
},
Err(err) => {
// network error
2016-10-19 18:14:42 -07:00
trace!("Unable to connect to {}", socket);
failed(err).boxed()
}
}
2016-10-19 18:14:42 -07:00
})
.then(|_| finished(()))
.boxed()
}
2016-10-19 18:14:42 -07:00
pub fn listen(context: Arc<Context>, handle: &Handle, config: NetConfig) -> Result<BoxedEmptyFuture, io::Error> {
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);
// 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()
},
Ok(Err(err)) => {
// protocol error
2016-10-19 18:14:42 -07:00
// TODO: close socket
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();
Ok(server)
}
pub fn on_message(context: Arc<Context>, channel: Arc<Channel>) -> BoxedMessageFuture {
channel.read_message().then(move |result| {
match result {
Ok(Ok((command, payload))) => {
// successful read
trace!("Received {} message from {}", command, channel.peer_info().address);
// 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()
},
Ok(Err(err)) => {
// protocol error
2016-10-19 18:14:42 -07:00
context.close_connection(channel.peer_info());
finished(Err(err)).boxed()
},
Err(err) => {
// network error
2016-10-19 18:14:42 -07:00
context.close_connection(channel.peer_info());
failed(err).boxed()
}
}
}).boxed()
}
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 18:14:42 -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-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,
/// 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,
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> {
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);
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
/*
pub fn broadcast<T>(&self, payload: T) where T: Payload {
2016-10-18 03:14:54 -07:00
let channels = self.connections.channels();
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
}
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-12 05:30:50 -07:00
}