diff --git a/src/routing/command.rs b/src/routing/command.rs index 57fd1a08f4..15328adaee 100644 --- a/src/routing/command.rs +++ b/src/routing/command.rs @@ -94,6 +94,8 @@ pub(crate) enum Command { // The key of the destination section that the joining node knows, if any. their_knowledge: Option, }, + /// Proposes a peer as offline + ProposeOffline(XorName), } impl Command { @@ -198,6 +200,7 @@ impl Debug for Command { .field("peer", peer) .field("previous_name", previous_name) .finish(), + Self::ProposeOffline(name) => f.debug_tuple("ProposeOffline").field(name).finish(), } } } diff --git a/src/routing/core.rs b/src/routing/core.rs index a3bf7c2520..069320a2a9 100644 --- a/src/routing/core.rs +++ b/src/routing/core.rs @@ -491,7 +491,7 @@ impl Core { self.propose_offline(name) } - fn propose_offline(&self, name: XorName) -> Result> { + pub fn propose_offline(&self, name: XorName) -> Result> { if let Some(info) = self.section.members().get(&name) { let info = info.clone().leave()?; diff --git a/src/routing/dispatcher.rs b/src/routing/dispatcher.rs index 1e907b2161..05b204d1d2 100644 --- a/src/routing/dispatcher.rs +++ b/src/routing/dispatcher.rs @@ -172,6 +172,7 @@ impl Dispatcher { .make_online_proposal(peer, previous_name, their_knowledge) .await } + Command::ProposeOffline(name) => self.core.lock().await.propose_offline(name), } } diff --git a/src/routing/mod.rs b/src/routing/mod.rs index 6ee867bfc5..9a1acabdcf 100644 --- a/src/routing/mod.rs +++ b/src/routing/mod.rs @@ -35,7 +35,7 @@ use crate::{ node::Node, peer::Peer, section::{EldersInfo, SectionChain}, - TransportConfig, MIN_ADULT_AGE, + Error, TransportConfig, MIN_ADULT_AGE, }; use bytes::Bytes; use ed25519_dalek::{Keypair, PublicKey, Signature, Signer, KEYPAIR_LENGTH}; @@ -166,6 +166,16 @@ impl Routing { self.dispatcher.clone().handle_commands(command).await } + /// Starts a proposal that a node has gone offline. + /// This can be done only by an Elder. + pub async fn propose_offline(&self, name: XorName) -> Result<()> { + if !self.is_elder().await { + return Err(Error::InvalidState); + } + let command = Command::ProposeOffline(name); + self.dispatcher.clone().handle_commands(command).await + } + /// Returns the current age of this node. pub async fn age(&self) -> u8 { self.dispatcher.core.lock().await.node().age()