// Copyright 2021 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. Please review the Licences for the specific language governing
// permissions and limitations relating to use of the SAFE Network Software.
use bytes::Bytes;
use ed25519_dalek::Keypair;
use hex_fmt::HexFmt;
pub use qp2p::{RecvStream, SendStream};
use sn_messaging::{client::ClientMsg, node::Signed, DstLocation, EndUser, SrcLocation};
use std::{
collections::BTreeSet,
fmt::{self, Debug, Formatter},
net::SocketAddr,
sync::Arc,
};
use xor_name::{Prefix, XorName};
/// A flag in EldersChanged event, indicating
/// whether the node got promoted, demoted or did not change.
#[derive(Debug)]
pub enum NodeElderChange {
/// The node was promoted to Elder.
Promoted,
/// The node was demoted to Adult.
Demoted,
/// There was no change to the node.
None,
}
/// Bound name of elders and section_key, section_prefix info together.
#[derive(Debug, Clone, PartialEq)]
pub struct Elders {
/// The prefix of the section.
pub prefix: Prefix,
/// The BLS public key of a section.
pub key: bls::PublicKey,
/// Remaining Elders in our section.
pub remaining: BTreeSet<XorName>,
/// New Elders in our section.
pub added: BTreeSet<XorName>,
/// Removed Elders in our section.
pub removed: BTreeSet<XorName>,
}
/// An Event raised by a `Node` or `Client` via its event sender.
///
/// These are sent by sn_routing to the library's user. It allows the user to handle requests and
/// responses, and to react to changes in the network.
///
/// `Request` and `Response` events from section locations are only raised once the majority has
/// been reached, i.e. enough members of the section have sent the same message.
#[allow(clippy::large_enum_variant)]
pub enum Event {
/// Received a message.
MessageReceived {
/// The content of the message.
content: Bytes,
/// The source location that sent the message.
src: SrcLocation,
/// The destination location that receives the message.
dst: DstLocation,
/// The signed if the message was set to be aggregated at source.
signed: Option<Signed>,
/// The Sender's Section PK.
section_pk: bls::PublicKey,
},
/// A new peer joined our section.
MemberJoined {
/// Name of the node
name: XorName,
/// Previous name before relocation or `None` if it is a new node.
previous_name: Option<XorName>,
/// Age of the node
age: u8,
},
/// A node left our section.
MemberLeft {
/// Name of the node
name: XorName,
/// Age of the node
age: u8,
},
/// Our section has split.
SectionSplit {
/// The Elders of our section.
elders: Elders,
/// The Elders of the sibling section.
sibling_elders: Elders,
/// Promoted, demoted or no change?
self_status_change: NodeElderChange,
},
/// The set of elders in our section has changed.
EldersChanged {
/// The Elders of our section.
elders: Elders,
/// Promoted, demoted or no change?
self_status_change: NodeElderChange,
},
/// This node has started relocating to other section. Will be followed by
/// `Relocated` when the node finishes joining the destination section.
RelocationStarted {
/// Previous name before relocation
previous_name: XorName,
},
/// This node has completed relocation to other section.
Relocated {
/// Old name before the relocation.
previous_name: XorName,
/// New keypair to be used after relocation.
new_keypair: Arc<Keypair>,
},
/// Disconnected or failed to connect - restart required.
RestartRequired,
/// Received a message from a client node.
ClientMsgReceived {
/// The content of the message.
msg: Box<ClientMsg>,
/// The SocketAddr and PublicKey that sent the message.
/// (Note: socket_id will be a random hash, to map against the actual socketaddr)
user: EndUser,
},
/// Failed in sending a message to client, or connection to client is lost
ClientLost(SocketAddr),
/// Notify the current list of adult nodes, in case of churning.
AdultsChanged {
/// Remaining Adults in our section.
remaining: BTreeSet<XorName>,
/// New Adults in our section.
added: BTreeSet<XorName>,
/// Removed Adults in our section.
removed: BTreeSet<XorName>,
},
}
impl Debug for Event {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
match self {
Self::MessageReceived {
content, src, dst, ..
} => write!(
formatter,
"MessageReceived {{ content: \"{:<8}\", src: {:?}, dst: {:?} }}",
HexFmt(content),
src,
dst
),
Self::MemberJoined {
name,
previous_name,
age,
} => formatter
.debug_struct("MemberJoined")
.field("name", name)
.field("previous_name", previous_name)
.field("age", age)
.finish(),
Self::MemberLeft { name, age } => formatter
.debug_struct("MemberLeft")
.field("name", name)
.field("age", age)
.finish(),
Self::SectionSplit {
elders,
sibling_elders,
self_status_change,
} => formatter
.debug_struct("EldersChanged")
.field("elders", elders)
.field("sibling_elders", sibling_elders)
.field("self_status_change", self_status_change)
.finish(),
Self::EldersChanged {
elders,
self_status_change,
} => formatter
.debug_struct("EldersChanged")
.field("elders", elders)
.field("self_status_change", self_status_change)
.finish(),
Self::RelocationStarted { previous_name } => formatter
.debug_struct("RelocationStarted")
.field("previous_name", previous_name)
.finish(),
Self::Relocated {
previous_name,
new_keypair,
} => formatter
.debug_struct("Relocated")
.field("previous_name", previous_name)
.field("new_keypair", new_keypair)
.finish(),
Self::RestartRequired => write!(formatter, "RestartRequired"),
Self::ClientMsgReceived { msg, user, .. } => write!(
formatter,
"ClientMsgReceived {{ msg: {:?}, src: {:?} }}",
msg, user,
),
Self::ClientLost(addr) => write!(formatter, "ClientLost({:?})", addr),
Self::AdultsChanged {
remaining,
added,
removed,
} => formatter
.debug_struct("AdultsChanged")
.field("remaining", remaining)
.field("added", added)
.field("removed", removed)
.finish(),
}
}
}