Network shutdown
This commit is contained in:
parent
a03da30510
commit
b38488dd07
@ -41,6 +41,10 @@ pub enum SyncMessage {
|
|||||||
NewChainHead,
|
NewChainHead,
|
||||||
/// A block is ready
|
/// A block is ready
|
||||||
BlockVerified,
|
BlockVerified,
|
||||||
|
/// Start network command.
|
||||||
|
StartNetwork,
|
||||||
|
/// Stop network command.
|
||||||
|
StopNetwork,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IO Message type used for Network service
|
/// IO Message type used for Network service
|
||||||
@ -48,17 +52,20 @@ pub type NetSyncMessage = NetworkIoMessage<SyncMessage>;
|
|||||||
|
|
||||||
/// Client service setup. Creates and registers client and network services with the IO subsystem.
|
/// Client service setup. Creates and registers client and network services with the IO subsystem.
|
||||||
pub struct ClientService {
|
pub struct ClientService {
|
||||||
net_service: NetworkService<SyncMessage>,
|
net_service: Arc<NetworkService<SyncMessage>>,
|
||||||
client: Arc<Client>,
|
client: Arc<Client>,
|
||||||
panic_handler: Arc<PanicHandler>
|
panic_handler: Arc<PanicHandler>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientService {
|
impl ClientService {
|
||||||
/// Start the service in a separate thread.
|
/// Start the service in a separate thread.
|
||||||
pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc<Miner>) -> Result<ClientService, Error> {
|
pub fn start(config: ClientConfig, spec: Spec, net_config: NetworkConfiguration, db_path: &Path, miner: Arc<Miner>, enable_network: bool) -> Result<ClientService, Error> {
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
let mut net_service = try!(NetworkService::start(net_config));
|
let net_service = try!(NetworkService::new(net_config));
|
||||||
panic_handler.forward_from(&net_service);
|
panic_handler.forward_from(&net_service);
|
||||||
|
if enable_network {
|
||||||
|
try!(net_service.start());
|
||||||
|
}
|
||||||
|
|
||||||
info!("Starting {}", net_service.host_info());
|
info!("Starting {}", net_service.host_info());
|
||||||
info!("Configured for {} using {:?} engine", spec.name, spec.engine.name());
|
info!("Configured for {} using {:?} engine", spec.name, spec.engine.name());
|
||||||
@ -70,7 +77,7 @@ impl ClientService {
|
|||||||
try!(net_service.io().register_handler(client_io));
|
try!(net_service.io().register_handler(client_io));
|
||||||
|
|
||||||
Ok(ClientService {
|
Ok(ClientService {
|
||||||
net_service: net_service,
|
net_service: Arc::new(net_service),
|
||||||
client: client,
|
client: client,
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
})
|
})
|
||||||
@ -82,8 +89,8 @@ impl ClientService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get general IO interface
|
/// Get general IO interface
|
||||||
pub fn io(&mut self) -> &mut IoService<NetSyncMessage> {
|
pub fn register_io_handler(&self, handler: Arc<IoHandler<NetSyncMessage> + Send>) -> Result<(), IoError> {
|
||||||
self.net_service.io()
|
self.net_service.io().register_handler(handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get client interface
|
/// Get client interface
|
||||||
@ -92,8 +99,8 @@ impl ClientService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get network service component
|
/// Get network service component
|
||||||
pub fn network(&mut self) -> &mut NetworkService<SyncMessage> {
|
pub fn network(&mut self) -> Arc<NetworkService<SyncMessage>> {
|
||||||
&mut self.net_service
|
self.net_service.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ Account Options:
|
|||||||
--no-import-keys Do not import keys from legacy clients.
|
--no-import-keys Do not import keys from legacy clients.
|
||||||
|
|
||||||
Networking Options:
|
Networking Options:
|
||||||
|
--no-network Disable p2p networking.
|
||||||
--port PORT Override the port on which the node should listen
|
--port PORT Override the port on which the node should listen
|
||||||
[default: 30303].
|
[default: 30303].
|
||||||
--peers NUM Try to maintain that many peers [default: 25].
|
--peers NUM Try to maintain that many peers [default: 25].
|
||||||
@ -266,6 +267,7 @@ pub struct Args {
|
|||||||
pub flag_format: Option<String>,
|
pub flag_format: Option<String>,
|
||||||
pub flag_jitvm: bool,
|
pub flag_jitvm: bool,
|
||||||
pub flag_no_color: bool,
|
pub flag_no_color: bool,
|
||||||
|
pub flag_no_network: bool,
|
||||||
// legacy...
|
// legacy...
|
||||||
pub flag_geth: bool,
|
pub flag_geth: bool,
|
||||||
pub flag_nodekey: Option<String>,
|
pub flag_nodekey: Option<String>,
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use ethcore::client::Client;
|
use ethcore::client::Client;
|
||||||
use ethcore::service::NetSyncMessage;
|
use ethcore::service::{NetSyncMessage, SyncMessage};
|
||||||
use ethsync::EthSync;
|
use ethsync::EthSync;
|
||||||
use util::keys::store::AccountService;
|
use util::keys::store::AccountService;
|
||||||
use util::{TimerToken, IoHandler, IoContext};
|
use util::{TimerToken, IoHandler, IoContext, NetworkService, NetworkIoMessage};
|
||||||
|
|
||||||
use informant::Informant;
|
use informant::Informant;
|
||||||
|
|
||||||
@ -33,6 +33,7 @@ pub struct ClientIoHandler {
|
|||||||
pub sync: Arc<EthSync>,
|
pub sync: Arc<EthSync>,
|
||||||
pub accounts: Arc<AccountService>,
|
pub accounts: Arc<AccountService>,
|
||||||
pub info: Informant,
|
pub info: Informant,
|
||||||
|
pub network: Arc<NetworkService<SyncMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
||||||
@ -48,6 +49,20 @@ impl IoHandler<NetSyncMessage> for ClientIoHandler {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn message(&self, _io: &IoContext<NetSyncMessage>, message: &NetSyncMessage) {
|
||||||
|
match *message {
|
||||||
|
NetworkIoMessage::User(SyncMessage::StartNetwork) => {
|
||||||
|
info!("Starting network");
|
||||||
|
self.network.start().unwrap_or_else(|e| warn!("Error starting network: {:?}", e));
|
||||||
|
},
|
||||||
|
NetworkIoMessage::User(SyncMessage::StopNetwork) => {
|
||||||
|
info!("Stopping network");
|
||||||
|
self.network.stop().unwrap_or_else(|e| warn!("Error stopping network: {:?}", e));
|
||||||
|
},
|
||||||
|
_ => {/* Ignore other messages */},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
|||||||
|
|
||||||
// Build client
|
// Build client
|
||||||
let mut service = ClientService::start(
|
let mut service = ClientService::start(
|
||||||
client_config, spec, net_settings, Path::new(&conf.path()), miner.clone()
|
client_config, spec, net_settings, Path::new(&conf.path()), miner.clone(), !conf.args.flag_no_network
|
||||||
).unwrap_or_else(|e| die_with_error("Client", e));
|
).unwrap_or_else(|e| die_with_error("Client", e));
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
panic_handler.forward_from(&service);
|
||||||
@ -208,7 +208,7 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
|||||||
let network_settings = Arc::new(conf.network_settings());
|
let network_settings = Arc::new(conf.network_settings());
|
||||||
|
|
||||||
// Sync
|
// Sync
|
||||||
let sync = EthSync::register(service.network(), sync_config, client.clone());
|
let sync = EthSync::register(service.network().deref(), sync_config, client.clone());
|
||||||
|
|
||||||
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
let deps_for_rpc_apis = Arc::new(rpc_apis::Dependencies {
|
||||||
signer_port: conf.signer_port(),
|
signer_port: conf.signer_port(),
|
||||||
@ -269,8 +269,9 @@ fn execute_client(conf: Configuration, spec: Spec, client_config: ClientConfig)
|
|||||||
info: Informant::new(conf.have_color()),
|
info: Informant::new(conf.have_color()),
|
||||||
sync: sync.clone(),
|
sync: sync.clone(),
|
||||||
accounts: account_service.clone(),
|
accounts: account_service.clone(),
|
||||||
|
network: service.network(),
|
||||||
});
|
});
|
||||||
service.io().register_handler(io_handler).expect("Error registering IO handler");
|
service.register_io_handler(io_handler).expect("Error registering IO handler");
|
||||||
|
|
||||||
// Handle exit
|
// Handle exit
|
||||||
wait_for_exit(panic_handler, rpc_server, dapps_server, signer_server);
|
wait_for_exit(panic_handler, rpc_server, dapps_server, signer_server);
|
||||||
@ -309,7 +310,7 @@ fn execute_export(conf: Configuration) {
|
|||||||
|
|
||||||
// Build client
|
// Build client
|
||||||
let service = ClientService::start(
|
let service = ClientService::start(
|
||||||
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()),
|
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false
|
||||||
).unwrap_or_else(|e| die_with_error("Client", e));
|
).unwrap_or_else(|e| die_with_error("Client", e));
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
panic_handler.forward_from(&service);
|
||||||
@ -380,7 +381,7 @@ fn execute_import(conf: Configuration) {
|
|||||||
|
|
||||||
// Build client
|
// Build client
|
||||||
let service = ClientService::start(
|
let service = ClientService::start(
|
||||||
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()),
|
client_config, spec, net_settings, Path::new(&conf.path()), Arc::new(Miner::default()), false
|
||||||
).unwrap_or_else(|e| die_with_error("Client", e));
|
).unwrap_or_else(|e| die_with_error("Client", e));
|
||||||
|
|
||||||
panic_handler.forward_from(&service);
|
panic_handler.forward_from(&service);
|
||||||
|
@ -47,4 +47,14 @@ impl<S> Net for NetClient<S> where S: SyncProvider + 'static {
|
|||||||
// right now (11 march 2016), we are always listening for incoming connections
|
// right now (11 march 2016), we are always listening for incoming connections
|
||||||
Ok(Value::Bool(true))
|
Ok(Value::Bool(true))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_network(&self, _: Params) -> Result<Value, Error> {
|
||||||
|
take_weak!(self.sync).start_network();
|
||||||
|
Ok(Value::Bool(true))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_network(&self, _: Params) -> Result<Value, Error> {
|
||||||
|
take_weak!(self.sync).stop_network();
|
||||||
|
Ok(Value::Bool(true))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,5 +59,11 @@ impl SyncProvider for TestSyncProvider {
|
|||||||
fn status(&self) -> SyncStatus {
|
fn status(&self) -> SyncStatus {
|
||||||
self.status.read().unwrap().clone()
|
self.status.read().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_network(&self) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_network(&self) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,12 +30,20 @@ pub trait Net: Sized + Send + Sync + 'static {
|
|||||||
/// Otherwise false.
|
/// Otherwise false.
|
||||||
fn is_listening(&self, _: Params) -> Result<Value, Error>;
|
fn is_listening(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
|
/// Start the network.
|
||||||
|
fn start_network(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
|
/// Stop the network.
|
||||||
|
fn stop_network(&self, _: Params) -> Result<Value, Error>;
|
||||||
|
|
||||||
/// Should be used to convert object to io delegate.
|
/// Should be used to convert object to io delegate.
|
||||||
fn to_delegate(self) -> IoDelegate<Self> {
|
fn to_delegate(self) -> IoDelegate<Self> {
|
||||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||||
delegate.add_method("net_version", Net::version);
|
delegate.add_method("net_version", Net::version);
|
||||||
delegate.add_method("net_peerCount", Net::peer_count);
|
delegate.add_method("net_peerCount", Net::peer_count);
|
||||||
delegate.add_method("net_listening", Net::is_listening);
|
delegate.add_method("net_listening", Net::is_listening);
|
||||||
|
delegate.add_method("net_start", Net::start_network);
|
||||||
|
delegate.add_method("net_stop", Net::stop_network);
|
||||||
delegate
|
delegate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,10 @@ use util::network::{NetworkProtocolHandler, NetworkService, NetworkContext, Peer
|
|||||||
use util::TimerToken;
|
use util::TimerToken;
|
||||||
use util::{U256, ONE_U256};
|
use util::{U256, ONE_U256};
|
||||||
use ethcore::client::Client;
|
use ethcore::client::Client;
|
||||||
use ethcore::service::SyncMessage;
|
use ethcore::service::{SyncMessage, NetSyncMessage};
|
||||||
use io::NetSyncIo;
|
use io::NetSyncIo;
|
||||||
|
use util::io::IoChannel;
|
||||||
|
use util::NetworkIoMessage;
|
||||||
use chain::ChainSync;
|
use chain::ChainSync;
|
||||||
|
|
||||||
mod chain;
|
mod chain;
|
||||||
@ -98,6 +100,10 @@ impl Default for SyncConfig {
|
|||||||
pub trait SyncProvider: Send + Sync {
|
pub trait SyncProvider: Send + Sync {
|
||||||
/// Get sync status
|
/// Get sync status
|
||||||
fn status(&self) -> SyncStatus;
|
fn status(&self) -> SyncStatus;
|
||||||
|
/// Start the network
|
||||||
|
fn start_network(&self);
|
||||||
|
/// Stop the network
|
||||||
|
fn stop_network(&self);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ethereum network protocol handler
|
/// Ethereum network protocol handler
|
||||||
@ -105,18 +111,21 @@ pub struct EthSync {
|
|||||||
/// Shared blockchain client. TODO: this should evetually become an IPC endpoint
|
/// Shared blockchain client. TODO: this should evetually become an IPC endpoint
|
||||||
chain: Arc<Client>,
|
chain: Arc<Client>,
|
||||||
/// Sync strategy
|
/// Sync strategy
|
||||||
sync: RwLock<ChainSync>
|
sync: RwLock<ChainSync>,
|
||||||
|
/// IO communication chnnel.
|
||||||
|
io_channel: RwLock<IoChannel<NetSyncMessage>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use self::chain::{SyncStatus, SyncState};
|
pub use self::chain::{SyncStatus, SyncState};
|
||||||
|
|
||||||
impl EthSync {
|
impl EthSync {
|
||||||
/// Creates and register protocol with the network service
|
/// Creates and register protocol with the network service
|
||||||
pub fn register(service: &mut NetworkService<SyncMessage>, config: SyncConfig, chain: Arc<Client>) -> Arc<EthSync> {
|
pub fn register(service: &NetworkService<SyncMessage>, config: SyncConfig, chain: Arc<Client>) -> Arc<EthSync> {
|
||||||
let sync = ChainSync::new(config, chain.deref());
|
let sync = ChainSync::new(config, chain.deref());
|
||||||
let sync = Arc::new(EthSync {
|
let sync = Arc::new(EthSync {
|
||||||
chain: chain,
|
chain: chain,
|
||||||
sync: RwLock::new(sync),
|
sync: RwLock::new(sync),
|
||||||
|
io_channel: RwLock::new(IoChannel::disconnected()),
|
||||||
});
|
});
|
||||||
service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler");
|
service.register_protocol(sync.clone(), "eth", &[62u8, 63u8]).expect("Error registering eth protocol handler");
|
||||||
sync
|
sync
|
||||||
@ -138,11 +147,20 @@ impl SyncProvider for EthSync {
|
|||||||
fn status(&self) -> SyncStatus {
|
fn status(&self) -> SyncStatus {
|
||||||
self.sync.read().unwrap().status()
|
self.sync.read().unwrap().status()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn start_network(&self) {
|
||||||
|
self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StartNetwork)).expect("Error sending IO notification");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stop_network(&self) {
|
||||||
|
self.io_channel.read().unwrap().send(NetworkIoMessage::User(SyncMessage::StopNetwork)).expect("Error sending IO notification");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NetworkProtocolHandler<SyncMessage> for EthSync {
|
impl NetworkProtocolHandler<SyncMessage> for EthSync {
|
||||||
fn initialize(&self, io: &NetworkContext<SyncMessage>) {
|
fn initialize(&self, io: &NetworkContext<SyncMessage>) {
|
||||||
io.register_timer(0, 1000).expect("Error registering sync timer");
|
io.register_timer(0, 1000).expect("Error registering sync timer");
|
||||||
|
*self.io_channel.write().unwrap() = io.io_channel();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&self, io: &NetworkContext<SyncMessage>, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
fn read(&self, io: &NetworkContext<SyncMessage>, peer: &PeerId, packet_id: u8, data: &[u8]) {
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
use std::sync::*;
|
use std::sync::*;
|
||||||
use std::thread::{self, JoinHandle};
|
use std::thread::{self, JoinHandle};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::ops::Deref;
|
||||||
use mio::*;
|
use mio::*;
|
||||||
|
use crossbeam::sync::chase_lev;
|
||||||
|
use slab::Slab;
|
||||||
use error::*;
|
use error::*;
|
||||||
use io::{IoError, IoHandler};
|
use io::{IoError, IoHandler};
|
||||||
use crossbeam::sync::chase_lev;
|
|
||||||
use io::worker::{Worker, Work, WorkType};
|
use io::worker::{Worker, Work, WorkType};
|
||||||
use panics::*;
|
use panics::*;
|
||||||
|
|
||||||
@ -33,6 +35,14 @@ pub type HandlerId = usize;
|
|||||||
|
|
||||||
/// Maximum number of tokens a handler can use
|
/// Maximum number of tokens a handler can use
|
||||||
pub const TOKENS_PER_HANDLER: usize = 16384;
|
pub const TOKENS_PER_HANDLER: usize = 16384;
|
||||||
|
const MAX_HANDLERS: usize = 8;
|
||||||
|
|
||||||
|
fn compare_arcs<T: ?Sized>(a: Arc<T>, b: Arc<T>) -> bool {
|
||||||
|
let p1 = &*a as *const T;
|
||||||
|
let p2 = &*b as *const T;
|
||||||
|
info!("{:p} == {:p} : {}", p1, p2 , p1 == p2);
|
||||||
|
p1 == p2
|
||||||
|
}
|
||||||
|
|
||||||
/// Messages used to communicate with the event loop from other threads.
|
/// Messages used to communicate with the event loop from other threads.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -43,6 +53,9 @@ pub enum IoMessage<Message> where Message: Send + Clone + Sized {
|
|||||||
AddHandler {
|
AddHandler {
|
||||||
handler: Arc<IoHandler<Message>+Send>,
|
handler: Arc<IoHandler<Message>+Send>,
|
||||||
},
|
},
|
||||||
|
RemoveHandler {
|
||||||
|
handler_id: HandlerId,
|
||||||
|
},
|
||||||
AddTimer {
|
AddTimer {
|
||||||
handler_id: HandlerId,
|
handler_id: HandlerId,
|
||||||
token: TimerToken,
|
token: TimerToken,
|
||||||
@ -138,6 +151,15 @@ impl<Message> IoContext<Message> where Message: Send + Clone + 'static {
|
|||||||
pub fn channel(&self) -> IoChannel<Message> {
|
pub fn channel(&self) -> IoChannel<Message> {
|
||||||
self.channel.clone()
|
self.channel.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Unregister current IO handler.
|
||||||
|
pub fn unregister_handler(&self) -> Result<(), IoError> {
|
||||||
|
try!(self.channel.send_io(IoMessage::RemoveHandler {
|
||||||
|
handler_id: self.handler,
|
||||||
|
}));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
@ -149,7 +171,7 @@ struct UserTimer {
|
|||||||
/// Root IO handler. Manages user handlers, messages and IO timers.
|
/// Root IO handler. Manages user handlers, messages and IO timers.
|
||||||
pub struct IoManager<Message> where Message: Send + Sync {
|
pub struct IoManager<Message> where Message: Send + Sync {
|
||||||
timers: Arc<RwLock<HashMap<HandlerId, UserTimer>>>,
|
timers: Arc<RwLock<HashMap<HandlerId, UserTimer>>>,
|
||||||
handlers: Vec<Arc<IoHandler<Message>>>,
|
handlers: Slab<Arc<IoHandler<Message>>, HandlerId>,
|
||||||
workers: Vec<Worker>,
|
workers: Vec<Worker>,
|
||||||
worker_channel: chase_lev::Worker<Work<Message>>,
|
worker_channel: chase_lev::Worker<Work<Message>>,
|
||||||
work_ready: Arc<Condvar>,
|
work_ready: Arc<Condvar>,
|
||||||
@ -175,7 +197,7 @@ impl<Message> IoManager<Message> where Message: Send + Sync + Clone + 'static {
|
|||||||
|
|
||||||
let mut io = IoManager {
|
let mut io = IoManager {
|
||||||
timers: Arc::new(RwLock::new(HashMap::new())),
|
timers: Arc::new(RwLock::new(HashMap::new())),
|
||||||
handlers: Vec::new(),
|
handlers: Slab::new(MAX_HANDLERS),
|
||||||
worker_channel: worker,
|
worker_channel: worker,
|
||||||
workers: workers,
|
workers: workers,
|
||||||
work_ready: work_ready,
|
work_ready: work_ready,
|
||||||
@ -192,10 +214,7 @@ impl<Message> Handler for IoManager<Message> where Message: Send + Clone + Sync
|
|||||||
fn ready(&mut self, _event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
|
fn ready(&mut self, _event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
|
||||||
let handler_index = token.as_usize() / TOKENS_PER_HANDLER;
|
let handler_index = token.as_usize() / TOKENS_PER_HANDLER;
|
||||||
let token_id = token.as_usize() % TOKENS_PER_HANDLER;
|
let token_id = token.as_usize() % TOKENS_PER_HANDLER;
|
||||||
if handler_index >= self.handlers.len() {
|
let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone();
|
||||||
panic!("Unexpected stream token: {}", token.as_usize());
|
|
||||||
}
|
|
||||||
let handler = self.handlers[handler_index].clone();
|
|
||||||
|
|
||||||
if events.is_hup() {
|
if events.is_hup() {
|
||||||
self.worker_channel.push(Work { work_type: WorkType::Hup, token: token_id, handler: handler.clone(), handler_id: handler_index });
|
self.worker_channel.push(Work { work_type: WorkType::Hup, token: token_id, handler: handler.clone(), handler_id: handler_index });
|
||||||
@ -214,12 +233,9 @@ impl<Message> Handler for IoManager<Message> where Message: Send + Clone + Sync
|
|||||||
fn timeout(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
|
fn timeout(&mut self, event_loop: &mut EventLoop<Self>, token: Token) {
|
||||||
let handler_index = token.as_usize() / TOKENS_PER_HANDLER;
|
let handler_index = token.as_usize() / TOKENS_PER_HANDLER;
|
||||||
let token_id = token.as_usize() % TOKENS_PER_HANDLER;
|
let token_id = token.as_usize() % TOKENS_PER_HANDLER;
|
||||||
if handler_index >= self.handlers.len() {
|
let handler = self.handlers.get(handler_index).unwrap_or_else(|| panic!("Unexpected stream token: {}", token.as_usize())).clone();
|
||||||
panic!("Unexpected timer token: {}", token.as_usize());
|
|
||||||
}
|
|
||||||
if let Some(timer) = self.timers.read().unwrap().get(&token.as_usize()) {
|
if let Some(timer) = self.timers.read().unwrap().get(&token.as_usize()) {
|
||||||
event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer");
|
event_loop.timeout_ms(token, timer.delay).expect("Error re-registering user timer");
|
||||||
let handler = self.handlers[handler_index].clone();
|
|
||||||
self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler, handler_id: handler_index });
|
self.worker_channel.push(Work { work_type: WorkType::Timeout, token: token_id, handler: handler, handler_id: handler_index });
|
||||||
self.work_ready.notify_all();
|
self.work_ready.notify_all();
|
||||||
}
|
}
|
||||||
@ -232,12 +248,14 @@ impl<Message> Handler for IoManager<Message> where Message: Send + Clone + Sync
|
|||||||
event_loop.shutdown();
|
event_loop.shutdown();
|
||||||
},
|
},
|
||||||
IoMessage::AddHandler { handler } => {
|
IoMessage::AddHandler { handler } => {
|
||||||
let handler_id = {
|
let handler_id = self.handlers.insert(handler.clone()).unwrap_or_else(|_| panic!("Too many handlers registered"));
|
||||||
self.handlers.push(handler.clone());
|
|
||||||
self.handlers.len() - 1
|
|
||||||
};
|
|
||||||
handler.initialize(&IoContext::new(IoChannel::new(event_loop.channel()), handler_id));
|
handler.initialize(&IoContext::new(IoChannel::new(event_loop.channel()), handler_id));
|
||||||
},
|
},
|
||||||
|
IoMessage::RemoveHandler { handler_id } => {
|
||||||
|
// TODO: flush event loop
|
||||||
|
self.handlers.remove(handler_id);
|
||||||
|
info!("{} left", self.handlers.count());
|
||||||
|
},
|
||||||
IoMessage::AddTimer { handler_id, token, delay } => {
|
IoMessage::AddTimer { handler_id, token, delay } => {
|
||||||
let timer_id = token + handler_id * TOKENS_PER_HANDLER;
|
let timer_id = token + handler_id * TOKENS_PER_HANDLER;
|
||||||
let timeout = event_loop.timeout_ms(Token(timer_id), delay).expect("Error registering user timer");
|
let timeout = event_loop.timeout_ms(Token(timer_id), delay).expect("Error registering user timer");
|
||||||
@ -267,9 +285,12 @@ impl<Message> Handler for IoManager<Message> where Message: Send + Clone + Sync
|
|||||||
handler.update_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop);
|
handler.update_stream(token, Token(token + handler_id * TOKENS_PER_HANDLER), event_loop);
|
||||||
},
|
},
|
||||||
IoMessage::UserMessage(data) => {
|
IoMessage::UserMessage(data) => {
|
||||||
for n in 0 .. self.handlers.len() {
|
//TODO: better way to iterate the slab
|
||||||
let handler = self.handlers[n].clone();
|
for id in 0 .. MAX_HANDLERS {
|
||||||
self.worker_channel.push(Work { work_type: WorkType::Message(data.clone()), token: 0, handler: handler, handler_id: n });
|
if let Some(h) = self.handlers.get(id) {
|
||||||
|
let handler = h.clone();
|
||||||
|
self.worker_channel.push(Work { work_type: WorkType::Message(data.clone()), token: 0, handler: handler, handler_id: id });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.work_ready.notify_all();
|
self.work_ready.notify_all();
|
||||||
}
|
}
|
||||||
@ -351,8 +372,8 @@ impl<Message> IoService<Message> where Message: Send + Sync + Clone + 'static {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Regiter a IO hadnler with the event loop.
|
/// Regiter an IO handler with the event loop.
|
||||||
pub fn register_handler(&mut self, handler: Arc<IoHandler<Message>+Send>) -> Result<(), IoError> {
|
pub fn register_handler(&self, handler: Arc<IoHandler<Message>+Send>) -> Result<(), IoError> {
|
||||||
try!(self.host_channel.send(IoMessage::AddHandler {
|
try!(self.host_channel.send(IoMessage::AddHandler {
|
||||||
handler: handler,
|
handler: handler,
|
||||||
}));
|
}));
|
||||||
@ -360,13 +381,13 @@ impl<Message> IoService<Message> where Message: Send + Sync + Clone + 'static {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send a message over the network. Normaly `HostIo::send` should be used. This can be used from non-io threads.
|
/// Send a message over the network. Normaly `HostIo::send` should be used. This can be used from non-io threads.
|
||||||
pub fn send_message(&mut self, message: Message) -> Result<(), IoError> {
|
pub fn send_message(&self, message: Message) -> Result<(), IoError> {
|
||||||
try!(self.host_channel.send(IoMessage::UserMessage(message)));
|
try!(self.host_channel.send(IoMessage::UserMessage(message)));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new message channel
|
/// Create a new message channel
|
||||||
pub fn channel(&mut self) -> IoChannel<Message> {
|
pub fn channel(&self) -> IoChannel<Message> {
|
||||||
IoChannel { channel: Some(self.host_channel.clone()) }
|
IoChannel { channel: Some(self.host_channel.clone()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ const MAX_HANDSHAKES: usize = 80;
|
|||||||
const MAX_HANDSHAKES_PER_ROUND: usize = 32;
|
const MAX_HANDSHAKES_PER_ROUND: usize = 32;
|
||||||
const MAINTENANCE_TIMEOUT: u64 = 1000;
|
const MAINTENANCE_TIMEOUT: u64 = 1000;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
/// Network service configuration
|
/// Network service configuration
|
||||||
pub struct NetworkConfiguration {
|
pub struct NetworkConfiguration {
|
||||||
/// Directory path to store network configuration. None means nothing will be saved
|
/// Directory path to store network configuration. None means nothing will be saved
|
||||||
@ -233,6 +233,11 @@ impl<'s, Message> NetworkContext<'s, Message> where Message: Send + Sync + Clone
|
|||||||
self.io.message(NetworkIoMessage::User(msg));
|
self.io.message(NetworkIoMessage::User(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send an IO message
|
||||||
|
pub fn io_channel(&self) -> IoChannel<NetworkIoMessage<Message>> {
|
||||||
|
self.io.channel()
|
||||||
|
}
|
||||||
|
|
||||||
/// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected.
|
/// Disable current protocol capability for given peer. If no capabilities left peer gets disconnected.
|
||||||
pub fn disable_peer(&self, peer: PeerId) {
|
pub fn disable_peer(&self, peer: PeerId) {
|
||||||
//TODO: remove capability, disconnect if no capabilities left
|
//TODO: remove capability, disconnect if no capabilities left
|
||||||
@ -327,7 +332,7 @@ pub struct Host<Message> where Message: Send + Sync + Clone {
|
|||||||
|
|
||||||
impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
||||||
/// Create a new instance
|
/// Create a new instance
|
||||||
pub fn new(config: NetworkConfiguration) -> Result<Host<Message>, UtilError> {
|
pub fn new(config: NetworkConfiguration, stats: Arc<NetworkStats>) -> Result<Host<Message>, UtilError> {
|
||||||
let mut listen_address = match config.listen_address {
|
let mut listen_address = match config.listen_address {
|
||||||
None => SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
None => SocketAddr::from_str("0.0.0.0:30304").unwrap(),
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
@ -371,7 +376,7 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
handlers: RwLock::new(HashMap::new()),
|
handlers: RwLock::new(HashMap::new()),
|
||||||
timers: RwLock::new(HashMap::new()),
|
timers: RwLock::new(HashMap::new()),
|
||||||
timer_counter: RwLock::new(USER_TIMER),
|
timer_counter: RwLock::new(USER_TIMER),
|
||||||
stats: Arc::new(NetworkStats::default()),
|
stats: stats,
|
||||||
pinned_nodes: Vec::new(),
|
pinned_nodes: Vec::new(),
|
||||||
num_sessions: AtomicUsize::new(0),
|
num_sessions: AtomicUsize::new(0),
|
||||||
};
|
};
|
||||||
@ -383,10 +388,6 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
Ok(host)
|
Ok(host)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stats(&self) -> Arc<NetworkStats> {
|
|
||||||
self.stats.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_node(&mut self, id: &str) {
|
pub fn add_node(&mut self, id: &str) {
|
||||||
match Node::from_str(id) {
|
match Node::from_str(id) {
|
||||||
Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); },
|
Err(e) => { debug!(target: "network", "Could not add node {}: {:?}", id, e); },
|
||||||
@ -401,8 +402,8 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn client_version(&self) -> String {
|
pub fn client_version() -> String {
|
||||||
self.info.read().unwrap().client_version.clone()
|
version()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn external_url(&self) -> Option<String> {
|
pub fn external_url(&self) -> Option<String> {
|
||||||
@ -415,6 +416,23 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
r
|
r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn stop(&self, io: &IoContext<NetworkIoMessage<Message>>) -> Result<(), UtilError> {
|
||||||
|
let mut to_kill = Vec::new();
|
||||||
|
for e in self.sessions.write().unwrap().iter_mut() {
|
||||||
|
let mut s = e.lock().unwrap();
|
||||||
|
if !s.keep_alive(io) {
|
||||||
|
s.disconnect(io, DisconnectReason::PingTimeout);
|
||||||
|
to_kill.push(s.token());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for p in to_kill {
|
||||||
|
trace!(target: "network", "Ping timeout: {}", p);
|
||||||
|
self.kill_connection(p, io, true);
|
||||||
|
}
|
||||||
|
io.unregister_handler();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn init_public_interface(&self, io: &IoContext<NetworkIoMessage<Message>>) -> Result<(), UtilError> {
|
fn init_public_interface(&self, io: &IoContext<NetworkIoMessage<Message>>) -> Result<(), UtilError> {
|
||||||
io.clear_timer(INIT_PUBLIC).unwrap();
|
io.clear_timer(INIT_PUBLIC).unwrap();
|
||||||
if self.info.read().unwrap().public_endpoint.is_some() {
|
if self.info.read().unwrap().public_endpoint.is_some() {
|
||||||
@ -767,6 +785,13 @@ impl<Message> Host<Message> where Message: Send + Sync + Clone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<Message> Drop for Host<Message> where Message: Send + Sync + Clone {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
info!("Dropping host");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Message: Send + Sync + Clone + 'static {
|
impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
/// Initialize networking
|
/// Initialize networking
|
||||||
fn initialize(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
fn initialize(&self, io: &IoContext<NetworkIoMessage<Message>>) {
|
||||||
@ -831,8 +856,8 @@ impl<Message> IoHandler<NetworkIoMessage<Message>> for Host<Message> where Messa
|
|||||||
},
|
},
|
||||||
_ => match self.timers.read().unwrap().get(&token).cloned() {
|
_ => match self.timers.read().unwrap().get(&token).cloned() {
|
||||||
Some(timer) => match self.handlers.read().unwrap().get(timer.protocol).cloned() {
|
Some(timer) => match self.handlers.read().unwrap().get(timer.protocol).cloned() {
|
||||||
None => { warn!(target: "network", "No handler found for protocol: {:?}", timer.protocol) },
|
None => { warn!(target: "network", "No handler found for protocol: {:?}", timer.protocol) },
|
||||||
Some(h) => { h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone()), timer.token); }
|
Some(h) => { h.timeout(&NetworkContext::new(io, timer.protocol, None, self.sessions.clone()), timer.token); }
|
||||||
},
|
},
|
||||||
None => { warn!("Unknown timer token: {}", token); } // timer is not registerd through us
|
None => { warn!("Unknown timer token: {}", token); } // timer is not registerd through us
|
||||||
}
|
}
|
||||||
|
@ -28,33 +28,33 @@ use io::*;
|
|||||||
pub struct NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
pub struct NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
io_service: IoService<NetworkIoMessage<Message>>,
|
io_service: IoService<NetworkIoMessage<Message>>,
|
||||||
host_info: String,
|
host_info: String,
|
||||||
host: Arc<Host<Message>>,
|
host: RwLock<Option<Arc<Host<Message>>>>,
|
||||||
stats: Arc<NetworkStats>,
|
stats: Arc<NetworkStats>,
|
||||||
panic_handler: Arc<PanicHandler>
|
panic_handler: Arc<PanicHandler>,
|
||||||
|
config: NetworkConfiguration,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'static {
|
||||||
/// Starts IO event loop
|
/// Starts IO event loop
|
||||||
pub fn start(config: NetworkConfiguration) -> Result<NetworkService<Message>, UtilError> {
|
pub fn new(config: NetworkConfiguration) -> Result<NetworkService<Message>, UtilError> {
|
||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
let mut io_service = try!(IoService::<NetworkIoMessage<Message>>::start());
|
let io_service = try!(IoService::<NetworkIoMessage<Message>>::start());
|
||||||
panic_handler.forward_from(&io_service);
|
panic_handler.forward_from(&io_service);
|
||||||
|
|
||||||
let host = Arc::new(try!(Host::new(config)));
|
let stats = Arc::new(NetworkStats::new());
|
||||||
let stats = host.stats().clone();
|
let host_info = Host::<Message>::client_version();
|
||||||
let host_info = host.client_version();
|
|
||||||
try!(io_service.register_handler(host.clone()));
|
|
||||||
Ok(NetworkService {
|
Ok(NetworkService {
|
||||||
io_service: io_service,
|
io_service: io_service,
|
||||||
host_info: host_info,
|
host_info: host_info,
|
||||||
stats: stats,
|
stats: stats,
|
||||||
panic_handler: panic_handler,
|
panic_handler: panic_handler,
|
||||||
host: host,
|
host: RwLock::new(None),
|
||||||
|
config: config,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Regiter a new protocol handler with the event loop.
|
/// Regiter a new protocol handler with the event loop.
|
||||||
pub fn register_protocol(&mut self, handler: Arc<NetworkProtocolHandler<Message>+Send + Sync>, protocol: ProtocolId, versions: &[u8]) -> Result<(), NetworkError> {
|
pub fn register_protocol(&self, handler: Arc<NetworkProtocolHandler<Message>+Send + Sync>, protocol: ProtocolId, versions: &[u8]) -> Result<(), NetworkError> {
|
||||||
try!(self.io_service.send_message(NetworkIoMessage::AddHandler {
|
try!(self.io_service.send_message(NetworkIoMessage::AddHandler {
|
||||||
handler: handler,
|
handler: handler,
|
||||||
protocol: protocol,
|
protocol: protocol,
|
||||||
@ -69,8 +69,8 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns underlying io service.
|
/// Returns underlying io service.
|
||||||
pub fn io(&mut self) -> &mut IoService<NetworkIoMessage<Message>> {
|
pub fn io(&self) -> &IoService<NetworkIoMessage<Message>> {
|
||||||
&mut self.io_service
|
&self.io_service
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns network statistics.
|
/// Returns network statistics.
|
||||||
@ -80,12 +80,37 @@ impl<Message> NetworkService<Message> where Message: Send + Sync + Clone + 'stat
|
|||||||
|
|
||||||
/// Returns external url if available.
|
/// Returns external url if available.
|
||||||
pub fn external_url(&self) -> Option<String> {
|
pub fn external_url(&self) -> Option<String> {
|
||||||
self.host.external_url()
|
let host = self.host.read().unwrap();
|
||||||
|
host.as_ref().and_then(|h| h.external_url())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns external url if available.
|
/// Returns external url if available.
|
||||||
pub fn local_url(&self) -> String {
|
pub fn local_url(&self) -> Option<String> {
|
||||||
self.host.local_url()
|
let host = self.host.read().unwrap();
|
||||||
|
host.as_ref().map(|h| h.local_url())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Start network IO
|
||||||
|
pub fn start(&self) -> Result<(), UtilError> {
|
||||||
|
let mut host = self.host.write().unwrap();
|
||||||
|
if host.is_none() {
|
||||||
|
let h = Arc::new(try!(Host::new(self.config.clone(), self.stats.clone())));
|
||||||
|
try!(self.io_service.register_handler(h.clone()));
|
||||||
|
*host = Some(h);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop network IO
|
||||||
|
pub fn stop(&self) -> Result<(), UtilError> {
|
||||||
|
let mut host = self.host.write().unwrap();
|
||||||
|
if let Some(ref host) = *host {
|
||||||
|
info!("Unregistering handler");
|
||||||
|
let io = IoContext::new(self.io_service.channel(), 0); //TODO: take token id from host
|
||||||
|
host.stop(&io);
|
||||||
|
}
|
||||||
|
*host = None;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ impl NetworkStats {
|
|||||||
self.sessions.load(Ordering::Relaxed)
|
self.sessions.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
/// Create a new empty instance.
|
||||||
pub fn new() -> NetworkStats {
|
pub fn new() -> NetworkStats {
|
||||||
NetworkStats {
|
NetworkStats {
|
||||||
recv: AtomicUsize::new(0),
|
recv: AtomicUsize::new(0),
|
||||||
|
Loading…
Reference in New Issue
Block a user