diff --git a/Cargo.toml b/Cargo.toml index 6730082ae8164f6d04d93c83da89e248e6e4c779..64347951aa7f46121b296e89d4542d298f6d171d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ license = "AGPL-3.0" [dependencies] duniter-core = { path = "./core" } +# durs-skeleton-module = { path = "./skeleton-module" } durs-ws2p = { path = "./ws2p" } durs-ws2p-v1-legacy = { path = "./ws2p-v1-legacy" } structopt= "0.2.*" @@ -32,6 +33,7 @@ members = [ "module", "network", "network-documents", + # "skeleton-module", "tui", "wot", "ws2p", diff --git a/blockchain/lib.rs b/blockchain/lib.rs index b4e8a9bf1cd3e398cb78e1332e9d6e5b1f766a94..b348315e179c7a1d487045bea99cf34e15335e36 100644 --- a/blockchain/lib.rs +++ b/blockchain/lib.rs @@ -95,8 +95,8 @@ pub static DISTANCE_CALCULATOR: &'static RustyDistanceCalculator = &RustyDistanc /// Blockchain Module #[derive(Debug)] pub struct BlockchainModule { - /// Rooter sender - pub rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + /// Router sender + pub router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, /// Name of the user datas profile pub profile: String, /// Currency @@ -152,7 +152,7 @@ impl BlockchainModule { } /// Loading blockchain configuration pub fn load_blockchain_conf<DC: DuniterConf>( - rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, profile: &str, conf: &DC, _keys: RequiredKeysContent, @@ -185,7 +185,7 @@ impl BlockchainModule { // Instanciate BlockchainModule BlockchainModule { - rooter_sender, + router_sender, profile: profile.to_string(), currency: conf.currency(), currency_params, @@ -271,12 +271,12 @@ impl BlockchainModule { } /// Send network request fn request_network(&self, _req_id: ModuleReqId, request: &OldNetworkRequest) -> ModuleReqId { - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::Role(ModuleRole::InterNodesNetwork), DursMsgContent::OldNetworkRequest(*request), ))) - .unwrap_or_else(|_| panic!("Fail to send OldNetworkRequest to rooter")); + .unwrap_or_else(|_| panic!("Fail to send OldNetworkRequest to router")); request.get_req_id() } /// Send blockchain event @@ -286,20 +286,20 @@ impl BlockchainModule { DALEvent::RevertBlocks(_) => ModuleEvent::RevertBlocks, _ => return, }; - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::Event(module_event), DursMsgContent::DALEvent(event.clone()), ))) - .unwrap_or_else(|_| panic!("Fail to send DalEvent to rooter")); + .unwrap_or_else(|_| panic!("Fail to send DalEvent to router")); } fn send_req_response(&self, requester: DursMsgReceiver, response: &DALResponse) { - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( requester, DursMsgContent::DALResponse(Box::new(response.clone())), ))) - .unwrap_or_else(|_| panic!("Fail to send ReqRes to rooter")); + .unwrap_or_else(|_| panic!("Fail to send ReqRes to router")); } fn receive_network_documents<W: WebOfTrust>( &mut self, diff --git a/core/lib.rs b/core/lib.rs index ba7b2c047f2d96223a3ed69433800bfbf49aaeaa..6a9a8ded2dea5c357f873961c26c2b6b7746a843 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -48,7 +48,7 @@ extern crate threadpool; pub mod change_conf; pub mod cli; -pub mod rooter; +pub mod router; use duniter_blockchain::{BlockchainModule, DBExQuery, DBExTxQuery, DBExWotQuery}; pub use duniter_conf::{ChangeGlobalConf, DuRsConf, DuniterKeyPairs}; @@ -172,8 +172,8 @@ pub struct DuniterCore<'a, 'b: 'a, DC: DuniterConf> { pub keypairs: Option<DuniterKeyPairs>, /// Run duration. Zero = infinite duration. pub run_duration_in_secs: u64, - /// Sender channel of rooter thread - pub rooter_sender: Option<mpsc::Sender<RooterThreadMessage<DursMsg>>>, + /// Sender channel of router thread + pub router_sender: Option<mpsc::Sender<RouterThreadMessage<DursMsg>>>, /// Count the number of plugged modules pub modules_count: usize, /// Count the number of plugged network modules @@ -206,7 +206,7 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { }, keypairs: None, run_duration_in_secs, - rooter_sender: None, + router_sender: None, modules_count: 1, // Count blockchain module network_modules_count: 0, thread_pool: ThreadPool::new(*THREAD_POOL_SIZE), @@ -214,8 +214,9 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { } /// Inject cli subcommand pub fn inject_cli_subcommand<M: DuniterModule<DuRsConf, DursMsg>>(&mut self) { - //self.cli_conf = TupleApp(&self.cli_conf.0.clone().subcommand(M::ModuleOpt::clap())); - self.plugins_cli_conf.push(M::ModuleOpt::clap()); + if M::have_subcommand() { + self.plugins_cli_conf.push(M::ModuleOpt::clap()); + } } /// Execute user command pub fn match_user_command(&mut self) -> bool { @@ -287,15 +288,15 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { // Store user command self.user_command = Some(UserCommand::ListModules(ListModulesOpt::from_clap(matches))); - // Start rooter thread - self.rooter_sender = Some(rooter::start_rooter(0, profile.clone(), conf, vec![])); + // Start router thread + self.router_sender = Some(router::start_router(0, profile.clone(), conf, vec![])); true } else if let Some(_matches) = cli_args.subcommand_matches("start") { // Store user command self.user_command = Some(UserCommand::Start()); - // Start rooter thread - self.rooter_sender = Some(rooter::start_rooter( + // Start router thread + self.router_sender = Some(router::start_router( self.run_duration_in_secs, profile.clone(), conf, @@ -316,8 +317,8 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { cautious: opts.cautious_mode, verif_hashs: opts.unsafe_mode, })); - // Start rooter thread - self.rooter_sender = Some(rooter::start_rooter(0, profile.clone(), conf, vec![])); + // Start router thread + self.router_sender = Some(router::start_router(0, profile.clone(), conf, vec![])); true } else if let Some(matches) = cli_args.subcommand_matches("sync_ts") { let opts = SyncTsOpt::from_clap(matches); @@ -436,20 +437,20 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { mpsc::Receiver<DursMsg>, ) = mpsc::channel(); - let rooter_sender = if let Some(ref rooter_sender) = self.rooter_sender { - rooter_sender + let router_sender = if let Some(ref router_sender) = self.router_sender { + router_sender } else { - panic!("Try to start core without rooter_sender !"); + panic!("Try to start core without router_sender !"); }; - // Send expected modules count to rooter thread - rooter_sender - .send(RooterThreadMessage::ModulesCount(self.modules_count)) - .expect("Fatal error: fail to send expected modules count to rooter thread !"); + // Send expected modules count to router thread + router_sender + .send(RouterThreadMessage::ModulesCount(self.modules_count)) + .expect("Fatal error: fail to send expected modules count to router thread !"); - // Send blockchain module registration to rooter thread - rooter_sender - .send(RooterThreadMessage::ModuleRegistration( + // Send blockchain module registration to router thread + router_sender + .send(RouterThreadMessage::ModuleRegistration( BlockchainModule::name(), blockchain_sender, vec![ModuleRole::BlockchainDatas, ModuleRole::BlockValidation], @@ -457,11 +458,11 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { vec![], vec![], )) - .expect("Fatal error: fail to send blockchain registration to rooter thread !"); + .expect("Fatal error: fail to send blockchain registration to router thread !"); // Instantiate blockchain module and load is conf let mut blockchain_module = BlockchainModule::load_blockchain_conf( - rooter_sender.clone(), + router_sender.clone(), &self.soft_meta_datas.profile, &self.soft_meta_datas.conf, RequiredKeysContent::MemberKeyPair(None), @@ -479,10 +480,10 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { self.network_modules_count += 1; if let Some(UserCommand::Sync(ref network_sync)) = self.user_command { // Start module in a new thread - let rooter_sender = self - .rooter_sender + let router_sender = self + .router_sender .clone() - .expect("Try to start a core without rooter_sender !"); + .expect("Try to start a core without router_sender !"); let soft_meta_datas = self.soft_meta_datas.clone(); let module_conf_json = self .soft_meta_datas @@ -503,7 +504,7 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { &soft_meta_datas, required_keys, module_conf, - rooter_sender, + router_sender, sync_params, ) .unwrap_or_else(|_| { @@ -534,10 +535,10 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { if enabled { if let Some(UserCommand::Start()) = self.user_command { // Start module in a new thread - let rooter_sender_clone = self - .rooter_sender + let router_sender_clone = self + .router_sender .clone() - .expect("Try to start a core without rooter_sender !"); + .expect("Try to start a core without router_sender !"); let soft_meta_datas = self.soft_meta_datas.clone(); let module_conf_json = self .soft_meta_datas @@ -557,7 +558,7 @@ impl<'a, 'b: 'a> DuniterCore<'b, 'a, DuRsConf> { &soft_meta_datas, required_keys, module_conf, - rooter_sender_clone, + router_sender_clone, false, ) .unwrap_or_else(|_| { diff --git a/core/rooter.rs b/core/router.rs similarity index 92% rename from core/rooter.rs rename to core/router.rs index 1dce12f5578f4450a9617700c031d7c51839bb9b..51c3758a2b770ec5fffc8d5640e362e469f71c36 100644 --- a/core/rooter.rs +++ b/core/router.rs @@ -33,7 +33,7 @@ static MAX_REGISTRATION_DELAY: &'static u64 = &20; fn start_broadcasting_thread( start_time: SystemTime, run_duration_in_secs: u64, - receiver: &mpsc::Receiver<RooterThreadMessage<DursMsg>>, + receiver: &mpsc::Receiver<RouterThreadMessage<DursMsg>>, external_followers: &[mpsc::Sender<DursMsgContent>], ) { // Define variables @@ -50,10 +50,10 @@ fn start_broadcasting_thread( match receiver.recv_timeout(Duration::from_secs(1)) { Ok(mess) => { match mess { - RooterThreadMessage::ModulesCount(modules_count) => { + RouterThreadMessage::ModulesCount(modules_count) => { expected_registrations_count = Some(modules_count) } - RooterThreadMessage::ModuleRegistration( + RouterThreadMessage::ModuleRegistration( module_static_name, module_sender, sender_roles, @@ -144,7 +144,7 @@ fn start_broadcasting_thread( // Add this sender to modules_senders modules_senders.insert(module_static_name, module_sender); } - RooterThreadMessage::ModuleMessage(msg) => match msg.0 { + RouterThreadMessage::ModuleMessage(msg) => match msg.0 { DursMsgReceiver::One(_) => {} DursMsgReceiver::All => { for (module_static_name, module_sender) in &modules_senders { @@ -219,7 +219,7 @@ fn start_broadcasting_thread( Err(e) => match e { RecvTimeoutError::Timeout => continue, RecvTimeoutError::Disconnected => { - panic!("Fatal error : rooter thread disconnnected !") + panic!("Fatal error : router thread disconnnected !") } }, } @@ -241,17 +241,13 @@ fn start_broadcasting_thread( } /// Start conf thread -fn start_conf_thread( - profile: &str, - conf: &mut DuRsConf, - receiver: &mpsc::Receiver<DursMsgContent>, -) { +fn start_conf_thread(profile: &str, mut conf: DuRsConf, receiver: &mpsc::Receiver<DursMsgContent>) { loop { match receiver.recv() { Ok(msg) => { if let DursMsgContent::SaveNewModuleConf(module_static_name, new_json_conf) = msg { conf.set_module_conf(module_static_name.to_string(), new_json_conf); - duniter_conf::write_conf_file(&profile, conf) + duniter_conf::write_conf_file(&profile, &conf) .expect("Fail to write new module conf in conf file ! "); } } @@ -312,27 +308,27 @@ fn store_msg_in_pool( } } -/// Start rooter thread -pub fn start_rooter( +/// Start router thread +pub fn start_router( run_duration_in_secs: u64, profile: String, conf: DuRsConf, external_followers: Vec<mpsc::Sender<DursMsgContent>>, -) -> mpsc::Sender<RooterThreadMessage<DursMsg>> { +) -> mpsc::Sender<RouterThreadMessage<DursMsg>> { let start_time = SystemTime::now(); - // Create rooter channel - let (rooter_sender, rooter_receiver): ( - mpsc::Sender<RooterThreadMessage<DursMsg>>, - mpsc::Receiver<RooterThreadMessage<DursMsg>>, + // Create router channel + let (router_sender, router_receiver): ( + mpsc::Sender<RouterThreadMessage<DursMsg>>, + mpsc::Receiver<RouterThreadMessage<DursMsg>>, ) = mpsc::channel(); - // Create rooter thread + // Create router thread thread::spawn(move || { // Create broadcasting thread channel let (broadcasting_sender, broadcasting_receiver): ( - mpsc::Sender<RooterThreadMessage<DursMsg>>, - mpsc::Receiver<RooterThreadMessage<DursMsg>>, + mpsc::Sender<RouterThreadMessage<DursMsg>>, + mpsc::Receiver<RouterThreadMessage<DursMsg>>, ) = mpsc::channel(); // Create broadcasting thread @@ -353,7 +349,7 @@ pub fn start_rooter( // Create conf thread thread::spawn(move || { - start_conf_thread(&profile, &mut conf.clone(), &conf_receiver); + start_conf_thread(&profile, conf, &conf_receiver); }); // Define variables @@ -362,20 +358,20 @@ pub fn start_rooter( // Wait to receiver modules senders loop { - match rooter_receiver.recv_timeout(Duration::from_secs(1)) { + match router_receiver.recv_timeout(Duration::from_secs(1)) { Ok(mess) => { match mess { - RooterThreadMessage::ModulesCount(expected_registrations_count) => { + RouterThreadMessage::ModulesCount(expected_registrations_count) => { // Relay to broadcasting thread broadcasting_sender - .send(RooterThreadMessage::ModulesCount( + .send(RouterThreadMessage::ModulesCount( expected_registrations_count, )) .expect( "Fail to relay ModulesCount message to broadcasting thread !", ); } - RooterThreadMessage::ModuleRegistration( + RouterThreadMessage::ModuleRegistration( module_static_name, module_sender, events_subscription, @@ -403,7 +399,7 @@ pub fn start_rooter( modules_senders.insert(module_static_name, module_sender.clone()); // Relay to broadcasting thread broadcasting_sender - .send(RooterThreadMessage::ModuleRegistration( + .send(RouterThreadMessage::ModuleRegistration( module_static_name, module_sender, events_subscription, @@ -416,12 +412,12 @@ pub fn start_rooter( ); // Log the number of modules_senders received info!( - "Rooter thread receive {} module senders", + "Router thread receive {} module senders", modules_senders.len() ); } - RooterThreadMessage::ModuleMessage(msg) => { - trace!("Rooter thread receive ModuleMessage({:?})", msg); + RouterThreadMessage::ModuleMessage(msg) => { + trace!("Router thread receive ModuleMessage({:?})", msg); match msg.0 { DursMsgReceiver::All => { let stop = if let DursMsgContent::Stop() = msg.1 { @@ -430,7 +426,7 @@ pub fn start_rooter( false }; broadcasting_sender - .send(RooterThreadMessage::ModuleMessage(msg)) + .send(RouterThreadMessage::ModuleMessage(msg)) .expect("Fail to relay message to broadcasting thread !"); if stop { break; @@ -445,14 +441,14 @@ pub fn start_rooter( .expect("Fail to reach conf thread !"); } else { broadcasting_sender - .send(RooterThreadMessage::ModuleMessage(msg)) + .send(RouterThreadMessage::ModuleMessage(msg)) .expect( "Fail to relay specific role message to broadcasting thread !", ); } } DursMsgReceiver::Event(_module_event) => broadcasting_sender - .send(RooterThreadMessage::ModuleMessage(msg)) + .send(RouterThreadMessage::ModuleMessage(msg)) .expect("Fail to relay specific event message to broadcasting thread !"), DursMsgReceiver::One(module_static_name) => { if let Some(module_sender) = @@ -491,7 +487,8 @@ pub fn start_rooter( Err(e) => match e { RecvTimeoutError::Timeout => continue, RecvTimeoutError::Disconnected => { - panic!("Fatal error : rooter thread disconnnected !") + warn!("Router thread disconnnected... break main loop."); + break; } }, } @@ -503,7 +500,7 @@ pub fn start_rooter( > run_duration_in_secs { broadcasting_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::All, DursMsgContent::Stop(), ))) @@ -511,8 +508,8 @@ pub fn start_rooter( break; } } - info!("Rooter thread stop.") + info!("Router thread stop.") }); - rooter_sender + router_sender } diff --git a/module/lib.rs b/module/lib.rs index 55625dd376819d2481f3ae56db23317a3618b1fa..251afbdad3d800925504d595e32a8c731da403dc 100644 --- a/module/lib.rs +++ b/module/lib.rs @@ -207,17 +207,17 @@ pub enum ModuleEvent { /// Type returned by module initialization function pub enum ModuleInitError { /// Fail to load configuration - FailToLoadConf(), + FailToLoadConf(&'static str), /// Unknow error UnknowError(), } #[derive(Debug, Clone)] -/// Type sent by each module to the rooter during initialization -pub enum RooterThreadMessage<M: ModuleMessage> { +/// Type sent by each module to the router during initialization +pub enum RouterThreadMessage<M: ModuleMessage> { /// Number of expected modules ModulesCount(usize), - /// Registration of the module at the rooter + /// Registration of the module at the router ModuleRegistration( ModuleStaticName, mpsc::Sender<M>, @@ -343,17 +343,18 @@ pub trait DuniterModule<DC: DuniterConf, M: ModuleMessage> { } /// Execute injected subcommand fn exec_subcommand( - soft_meta_datas: &SoftwareMetaDatas<DC>, - keys: RequiredKeysContent, - module_conf: Self::ModuleConf, - subcommand_args: Self::ModuleOpt, - ); + _soft_meta_datas: &SoftwareMetaDatas<DC>, + _keys: RequiredKeysContent, + _module_conf: Self::ModuleConf, + _subcommand_args: Self::ModuleOpt, + ) { + } /// Launch the module fn start( soft_meta_datas: &SoftwareMetaDatas<DC>, keys: RequiredKeysContent, module_conf: Self::ModuleConf, - main_sender: mpsc::Sender<RooterThreadMessage<M>>, + main_sender: mpsc::Sender<RouterThreadMessage<M>>, load_conf_only: bool, ) -> Result<(), ModuleInitError>; } diff --git a/network/lib.rs b/network/lib.rs index 16d3bc43baa844c1f8a45aa6de3d23eca87b915d..a27bad7b0c08a64d7e30d201e7115241494bd93c 100644 --- a/network/lib.rs +++ b/network/lib.rs @@ -67,7 +67,7 @@ pub trait NetworkModule<DC: DuniterConf, M: ModuleMessage>: ApiModule<DC, M> { soft_meta_datas: &SoftwareMetaDatas<DC>, keys: RequiredKeysContent, module_conf: <Self as DuniterModule<DC, M>>::ModuleConf, - main_sender: mpsc::Sender<RooterThreadMessage<M>>, + main_sender: mpsc::Sender<RouterThreadMessage<M>>, sync_params: SyncParams, ) -> Result<(), ModuleInitError>; } diff --git a/skeleton-module/Cargo.toml b/skeleton-module/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..278f80893862bed3b66a7c14ad7ae187ffac2b95 --- /dev/null +++ b/skeleton-module/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "durs-skeleton-module" +version = "0.1.0" +authors = ["name <mail@domain.tld>"] +description = "Module template to copy to create a new Durs module." +license = "AGPL-3.0" + +[lib] +path = "lib.rs" + +[dependencies] +duniter-conf = { path = "../conf" } +duniter-dal = { path = "../dal" } +duniter-message = { path = "../message" } +duniter-module = { path = "../module" } +duniter-network = { path = "../network" } +dup-crypto = { path = "../crypto" } +log = "0.4.*" +serde = "1.0.*" +serde_derive = "1.0.*" +serde_json = "1.0.*" +structopt= "0.2.*" + +[features] +# Treat warnings as a build error. +strict = [] \ No newline at end of file diff --git a/skeleton-module/lib.rs b/skeleton-module/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..8b9f579986f47e8d4736cbd8b36e994d4d59082b --- /dev/null +++ b/skeleton-module/lib.rs @@ -0,0 +1,307 @@ +// Copyright (C) 2018 The Duniter Project Developers. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +//! Module template to copy to create a new Durs module. + +#![cfg_attr(feature = "strict", deny(warnings))] +#![deny( + missing_docs, + missing_debug_implementations, + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unsafe_code, + unstable_features, + unused_import_braces, + unused_qualifications +)] + +#[macro_use] +extern crate log; +#[macro_use] +extern crate serde_derive; +#[macro_use] +extern crate structopt; + +extern crate duniter_conf; +extern crate duniter_dal; +extern crate duniter_message; +extern crate duniter_module; +extern crate dup_crypto; +extern crate serde; +extern crate serde_json; + +use duniter_conf::DuRsConf; +use duniter_dal::dal_event::DALEvent; +use duniter_message::*; +use duniter_module::*; +use std::ops::Deref; +use std::sync::mpsc; +use std::thread; +use std::time::{Duration, SystemTime}; + +/// Name of your module +pub static MODULE_NAME: &'static str = "skeleton"; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +/// Skeleton Module Configuration +pub struct SkeletonConf { + test_fake_conf_field: String, +} + +impl Default for SkeletonConf { + fn default() -> Self { + SkeletonConf { + test_fake_conf_field: String::from("default value"), + } + } +} + +#[derive(Debug, Copy, Clone)] +/// Message from others thread of skeleton module +pub enum SkeletonThreadMsg {} + +#[derive(Debug, Clone)] +/// Format of messages received by the skeleton module +pub enum SkeletonMsg { + /// Message from another module + DursMsg(Box<DursMsg>), + /// Message from others thread of skeleton module + SkeletonThreadMsg(SkeletonThreadMsg), +} + +#[derive(StructOpt, Debug, Clone)] +#[structopt( + name = "skeleton", + raw(setting = "structopt::clap::AppSettings::ColoredHelp") +)] +/// Skeleton subcommand options +pub struct SkeletonOpt { + /// Change test conf fake field + pub new_conf_field: String, +} + +#[derive(Debug, Clone)] +/// Data that the Skeleton module needs to cache +pub struct SkeletonModuleDatas { + /// Sender of all child threads (except the proxy thread) + pub child_threads: Vec<mpsc::Sender<SkeletonMsg>>, + /// Any data + pub field: usize, +} + +#[derive(Debug, Copy, Clone)] +/// Skeleton module +pub struct SkeletonModule {} + +impl Default for SkeletonModule { + fn default() -> SkeletonModule { + SkeletonModule {} + } +} + +impl DuniterModule<DuRsConf, DursMsg> for SkeletonModule { + type ModuleConf = SkeletonConf; + type ModuleOpt = SkeletonOpt; + + fn name() -> ModuleStaticName { + ModuleStaticName(MODULE_NAME) + } + fn priority() -> ModulePriority { + //ModulePriority::Recommended() + ModulePriority::Optional() + } + fn ask_required_keys() -> RequiredKeys { + RequiredKeys::None() + } + fn have_subcommand() -> bool { + true + } + fn exec_subcommand( + soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, + _keys: RequiredKeysContent, + module_conf: Self::ModuleConf, + subcommand_args: Self::ModuleOpt, + ) { + let mut conf = soft_meta_datas.conf.clone(); + let new_skeleton_conf = SkeletonConf { + test_fake_conf_field: subcommand_args.new_conf_field.clone(), + }; + conf.set_module_conf( + MODULE_NAME.to_owned(), + serde_json::value::to_value(new_skeleton_conf) + .expect("Fail to jsonifie SkeletonConf !"), + ); + duniter_conf::write_conf_file(&soft_meta_datas.profile, &conf) + .expect("Fail to write new conf file ! "); + println!( + "Succesfully exec skeleton subcommand whit terminal name : {} and conf={:?}!", + subcommand_args.new_conf_field, module_conf + ) + } + fn start( + _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, + _keys: RequiredKeysContent, + _conf: Self::ModuleConf, + router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, + load_conf_only: bool, + ) -> Result<(), ModuleInitError> { + let _start_time = SystemTime::now(); + + // load conf + if load_conf_only { + // Check conf validity + // ... + let conf_valid = true; + + // If the configuration is valid, we return OK. + if conf_valid { + return Ok(()); + } else { + // If the configuration is invalid, an error message is returned + return Err(ModuleInitError::FailToLoadConf( + "write the details of the error here", + )); + } + } + + // Instanciate Skeleton module datas + let datas = SkeletonModuleDatas { + child_threads: Vec::new(), + field: 3, + }; + + // Create skeleton main thread channel + let (skeleton_sender, skeleton_receiver): ( + mpsc::Sender<SkeletonMsg>, + mpsc::Receiver<SkeletonMsg>, + ) = mpsc::channel(); + + // Create proxy channel + let (proxy_sender, proxy_receiver): ( + mpsc::Sender<DursMsg>, + mpsc::Receiver<DursMsg>, + ) = mpsc::channel(); + + // Launch a proxy thread that transform DursMsgContent() to SkeleonMsg::DursMsgContent(DursMsgContent()) + let router_sender_clone = router_sender.clone(); + let skeleton_sender_clone = skeleton_sender.clone(); + thread::spawn(move || { + // Send skeleton module registration to router thread + router_sender_clone + .send(RouterThreadMessage::ModuleRegistration( + ModuleStaticName(MODULE_NAME), + proxy_sender, // Messages sent by the router will be received by your proxy thread + vec![ModuleRole::UserInterface], // Roles assigned to your module + vec![ModuleEvent::NewValidBlock], // Events to which your module subscribes + vec![], + vec![], + )) + .expect("Fatal error : skeleton module fail to register to router !"); // The registration of your module must be successful, in case of failure the program must be interrupted. + + // If we are here it means that your module has successfully registered, we indicate it in the debug level log, it can be helpful. + debug!("Send skeleton module registration to router thread."); + + /* + * Main loop of your proxy thread + */ + loop { + match proxy_receiver.recv() { + Ok(message) => { + let stop = if let DursMsg(_, DursMsgContent::Stop()) = message { + true + } else { + false + }; + if skeleton_sender_clone + .send(SkeletonMsg::DursMsg(Box::new(message))) + .is_err() + { + // Log error + warn!( + "Skeleton proxy : fail to relay DursMsg to skeleton main thread !" + ) + } + if stop { + break; + } + } + Err(e) => { + // Log error + warn!("{}", e); + break; + } + } + } + }); + + /* + * Main loop of your module + */ + loop { + // Get messages + match skeleton_receiver.recv_timeout(Duration::from_millis(250)) { + Ok(ref message) => match *message { + SkeletonMsg::DursMsg(ref duniter_message) => { + match (*duniter_message.deref()).1 // Match Durs message content + { + DursMsgContent::Stop() => { + // Relay stop signal to all child threads + let _result_stop_propagation: Result< + (), + mpsc::SendError<SkeletonMsg>, + > = datas + .child_threads + .iter() + .map(|t| t.send(SkeletonMsg::DursMsg(Box::new(DursMsg(DursMsgReceiver::All, DursMsgContent::Stop()))))) + .collect(); + // Relay stop signal to router + let _result = router_sender.send(RouterThreadMessage::ModuleMessage(DursMsg(DursMsgReceiver::All, DursMsgContent::Stop()))); + // Break main loop + break; + } + DursMsgContent::DALEvent(ref dal_event) => match *dal_event { + DALEvent::StackUpValidBlock(ref _block, ref _blockstamp) => { + // Do something when the node has stacked a new block at its local blockchain + } + DALEvent::RevertBlocks(ref _blocks) => { + // Do something when the node has destacked blocks from its local blockchain (roll back) + } + _ => {} // Do nothing for events that don't concern your module. + }, + _ => {} // Do nothing for DursMsgContent variants that don't concern your module. + } + } + SkeletonMsg::SkeletonThreadMsg(ref _child_thread_msg) => { + // Do something when receive a message from child thread. + } + }, + Err(e) => match e { + mpsc::RecvTimeoutError::Disconnected => { + panic!("Disconnected skeleton module !"); + } + mpsc::RecvTimeoutError::Timeout => { + // If you arrive here it's because your main thread did not receive anything at the end of the timeout. + // This is quite normal and happens regularly when there is little activity, there is nothing particular to do. + } + }, + } + // If you want your module's main thread to do things even when it doesn't receive any messages, this is the place where it can do them. + // ... + } + // If we reach this point it means that the module has stopped correctly, so we return OK. + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index 0ef666e3306801eb8c037a5ad749443cbc36cf6e..2fcc961973d70e01098216cbbab4220a4afd003c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -33,6 +33,7 @@ extern crate duniter_core; #[cfg(unix)] extern crate duniter_tui; +//extern crate durs_skeleton_module; extern crate durs_ws2p_v1_legacy; //extern crate durs_ws2p; extern crate structopt; @@ -40,6 +41,7 @@ extern crate structopt; pub use duniter_core::{cli::DursOpt, DuRsConf, DuniterCore, UserCommand}; #[cfg(unix)] pub use duniter_tui::TuiModule; +//pub use durs_skeleton_module::SkeletonModule; pub use durs_ws2p_v1_legacy::WS2PModule; //pub use durs_ws2p::WS2Pv2Module; use structopt::StructOpt; @@ -49,8 +51,8 @@ use structopt::StructOpt; #[cfg(not(target_arch = "arm"))] fn main() { durs_core_server!( - durs_inject_cli![WS2PModule, TuiModule /*,DasaModule*/], - durs_plug!([WS2PModule], [TuiModule /*,DasaModule*/]) + durs_inject_cli![WS2PModule /*, SkeletonModule ,DasaModule*/], + durs_plug!([WS2PModule], [TuiModule /*, SkeletonModule ,DasaModule*/]) ); } #[cfg(unix)] diff --git a/tui/lib.rs b/tui/lib.rs index 21beb0fe31b9155653149ca65d27ddff0db1e634..2d4dbb1abaa267b55c5a528e9e87754c47b06ded 100644 --- a/tui/lib.rs +++ b/tui/lib.rs @@ -93,16 +93,13 @@ pub enum TuiMess { /// Tui module pub struct TuiModule {} -#[derive(StructOpt, Debug, Clone)] +#[derive(StructOpt, Debug, Copy, Clone)] #[structopt( name = "tui", raw(setting = "structopt::clap::AppSettings::ColoredHelp") )] /// Tui subcommand options -pub struct TuiOpt { - /// Change test conf fake field - pub new_conf_field: String, -} +pub struct TuiOpt {} #[derive(Debug, Clone)] /// Network connexion (data to display) @@ -405,35 +402,11 @@ impl DuniterModule<DuRsConf, DursMsg> for TuiModule { fn ask_required_keys() -> RequiredKeys { RequiredKeys::None() } - fn have_subcommand() -> bool { - true - } - fn exec_subcommand( - soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, - _keys: RequiredKeysContent, - module_conf: Self::ModuleConf, - subcommand_args: TuiOpt, - ) { - let mut conf = soft_meta_datas.conf.clone(); - let new_tui_conf = TuiConf { - test_fake_conf_field: subcommand_args.new_conf_field.clone(), - }; - conf.set_module_conf( - Self::name().to_string(), - serde_json::value::to_value(new_tui_conf).expect("Fail to jsonifie TuiConf !"), - ); - duniter_conf::write_conf_file(&soft_meta_datas.profile, &conf) - .expect("Fail to write new Tui conf file ! "); - println!( - "Succesfully exec tui subcommand whit terminal name : {} and conf={:?}!", - subcommand_args.new_conf_field, module_conf - ) - } fn start( _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: Self::ModuleConf, - main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + main_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, load_conf_only: bool, ) -> Result<(), ModuleInitError> { let start_time = SystemTime::now(); //: DateTime<Utc> = Utc::now(); @@ -467,7 +440,7 @@ impl DuniterModule<DuRsConf, DursMsg> for TuiModule { thread::spawn(move || { // Send proxy sender to main main_sender - .send(RooterThreadMessage::ModuleRegistration( + .send(RouterThreadMessage::ModuleRegistration( TuiModule::name(), proxy_sender, vec![ModuleRole::UserInterface], diff --git a/ws2p-v1-legacy/datas.rs b/ws2p-v1-legacy/datas.rs index 8eda264256f9351a62cd24200dffa133acb2f84c..fecfb7aecad44c9e623fab5421966acebb3dc0c5 100644 --- a/ws2p-v1-legacy/datas.rs +++ b/ws2p-v1-legacy/datas.rs @@ -28,7 +28,7 @@ use *; #[derive(Debug)] pub struct WS2PModuleDatas { - pub rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + pub router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, pub currency: Option<String>, pub key_pair: Option<KeyPairEnum>, pub conf: WS2PConf, @@ -66,8 +66,8 @@ impl WS2PModuleDatas { if self.count_dal_requests == std::u32::MAX { self.count_dal_requests = 0; } - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::Role(ModuleRole::BlockchainDatas), DursMsgContent::Request(DursReq { requester: WS2PModule::name(), @@ -75,19 +75,19 @@ impl WS2PModuleDatas { content: DursReqContent::DALRequest(req.clone()), }), ))) - .expect("Fail to send message to rooter !"); + .expect("Fail to send message to router !"); } pub fn send_network_req_response( &self, requester: ModuleStaticName, response: NetworkResponse, ) { - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::One(requester), DursMsgContent::NetworkResponse(response), ))) - .expect("Fail to send message to rooter !"); + .expect("Fail to send message to router !"); } pub fn send_network_event(&self, event: &NetworkEvent) { let module_event = match event { @@ -108,12 +108,12 @@ impl WS2PModuleDatas { NetworkEvent::ReceiveHeads(_) => ModuleEvent::NewValidHeadFromNetwork, NetworkEvent::ReceivePeers(_) => ModuleEvent::NewValidPeerFromNodeNetwork, }; - self.rooter_sender - .send(RooterThreadMessage::ModuleMessage(DursMsg( + self.router_sender + .send(RouterThreadMessage::ModuleMessage(DursMsg( DursMsgReceiver::Event(module_event), DursMsgContent::NetworkEvent(event.clone()), ))) - .expect("Fail to send network event to rooter !"); + .expect("Fail to send network event to router !"); } pub fn get_network_consensus(&self) -> Result<Blockstamp, NetworkConsensusError> { let mut count_known_blockstamps = 0; diff --git a/ws2p-v1-legacy/lib.rs b/ws2p-v1-legacy/lib.rs index a8e71cae6215544fd33aa38c4f0faf899d9913fe..c7c6112d526ba5449c9e115e24770d1c700c7d45 100644 --- a/ws2p-v1-legacy/lib.rs +++ b/ws2p-v1-legacy/lib.rs @@ -225,7 +225,7 @@ impl NetworkModule<DuRsConf, DursMsg> for WS2PModule { _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + _main_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, _sync_params: SyncParams, ) -> Result<(), ModuleInitError> { println!("Downlaod blockchain from network..."); @@ -270,7 +270,7 @@ impl DuniterModule<DuRsConf, DursMsg> for WS2PModule { soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, keys: RequiredKeysContent, conf: WS2PConf, - rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, load_conf_only: bool, ) -> Result<(), ModuleInitError> { // Get start time @@ -278,7 +278,7 @@ impl DuniterModule<DuRsConf, DursMsg> for WS2PModule { // Define WS2PModuleDatas let mut ws2p_module = WS2PModuleDatas { - rooter_sender: rooter_sender.clone(), + router_sender: router_sender.clone(), key_pair: None, currency: None, conf, @@ -324,8 +324,8 @@ impl DuniterModule<DuRsConf, DursMsg> for WS2PModule { // Launch a proxy thread that transform DursMsg to WS2PThreadSignal(DursMsg) thread::spawn(move || { // Send proxy sender to main - rooter_sender - .send(RooterThreadMessage::ModuleRegistration( + router_sender + .send(RouterThreadMessage::ModuleRegistration( WS2PModule::name(), proxy_sender_clone, vec![ModuleRole::InterNodesNetwork], diff --git a/ws2p/lib.rs b/ws2p/lib.rs index 4e1ba400daa26a212b8864028d92650d38315522..4a37782acf12c28b0557ffed4ccb99dcfbea52fa 100644 --- a/ws2p/lib.rs +++ b/ws2p/lib.rs @@ -124,7 +124,7 @@ impl NetworkModule<DuRsConf, DursMsg> for WS2Pv2Module { _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _main_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + _main_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, _sync_params: SyncParams, ) -> Result<(), ModuleInitError> { unimplemented!() @@ -167,7 +167,7 @@ impl DuniterModule<DuRsConf, DursMsg> for WS2Pv2Module { _soft_meta_datas: &SoftwareMetaDatas<DuRsConf>, _keys: RequiredKeysContent, _conf: WS2PConf, - _rooter_sender: mpsc::Sender<RooterThreadMessage<DursMsg>>, + _router_sender: mpsc::Sender<RouterThreadMessage<DursMsg>>, _load_conf_only: bool, ) -> Result<(), ModuleInitError> { unimplemented!()