use crate::{routing::Peer, section::SectionKeyShare, XorName};
use bytes::Bytes;
use hex_fmt::HexFmt;
use sn_messaging::{
node::{DkgFailureSignedSet, Proposal, RoutingMsg, Signed, SignedRelocateDetails},
section_info::SectionInfoMsg,
DestInfo, Itinerary, MessageType, SectionAuthorityProvider,
};
use std::{
fmt::{self, Debug, Formatter},
net::SocketAddr,
sync::atomic::{AtomicU64, Ordering},
time::Duration,
};
use tokio::sync::mpsc;
#[allow(clippy::large_enum_variant)]
pub(crate) enum Command {
HandleMessage {
sender: Option<SocketAddr>,
message: RoutingMsg,
dest_info: DestInfo,
},
HandleSectionInfoMsg {
sender: SocketAddr,
message: SectionInfoMsg,
dest_info: DestInfo,
},
HandleTimeout(u64),
HandleConnectionLost(SocketAddr),
HandlePeerLost(SocketAddr),
HandleAgreement { proposal: Proposal, signed: Signed },
HandleDkgOutcome {
section_auth: SectionAuthorityProvider,
outcome: SectionKeyShare,
},
HandleDkgFailure(DkgFailureSignedSet),
SendMessage {
recipients: Vec<(XorName, SocketAddr)>,
delivery_group_size: usize,
message: MessageType,
},
SendUserMessage {
itinerary: Itinerary,
content: Bytes,
additional_proof_chain_key: Option<bls::PublicKey>,
},
ScheduleTimeout { duration: Duration, token: u64 },
Relocate {
bootstrap_addrs: Vec<SocketAddr>,
details: SignedRelocateDetails,
message_rx: mpsc::Receiver<(RoutingMsg, SocketAddr)>,
},
SetJoinsAllowed(bool),
ProposeOnline {
peer: Peer,
previous_name: Option<XorName>,
destination_key: Option<bls::PublicKey>,
},
ProposeOffline(XorName),
StartConnectivityTest(XorName),
TestConnectivity(XorName),
}
impl Command {
pub fn send_message_to_node(
recipient: (XorName, SocketAddr),
routing_msg: RoutingMsg,
dest_info: DestInfo,
) -> Self {
Self::send_message_to_nodes(vec![recipient], 1, routing_msg, dest_info)
}
pub fn send_message_to_nodes(
recipients: Vec<(XorName, SocketAddr)>,
delivery_group_size: usize,
msg: RoutingMsg,
dest_info: DestInfo,
) -> Self {
Self::SendMessage {
recipients,
delivery_group_size,
message: MessageType::Routing { dest_info, msg },
}
}
}
impl Debug for Command {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Self::HandleMessage {
sender,
message,
dest_info,
} => f
.debug_struct("HandleMessage")
.field("sender", sender)
.field("message", message)
.field("dest_info", dest_info)
.finish(),
Self::HandleSectionInfoMsg {
sender,
message,
dest_info,
} => f
.debug_struct("HandleSectionInfoMsg")
.field("sender", sender)
.field("message", message)
.field("dest_info", dest_info)
.finish(),
Self::HandleTimeout(token) => f.debug_tuple("HandleTimeout").field(token).finish(),
Self::HandleConnectionLost(addr) => {
f.debug_tuple("HandleConnectionLost").field(addr).finish()
}
Self::HandlePeerLost(addr) => f.debug_tuple("HandlePeerLost").field(addr).finish(),
Self::HandleAgreement { proposal, signed } => f
.debug_struct("HandleAgreement")
.field("proposal", proposal)
.field("signed.public_key", &signed.public_key)
.finish(),
Self::HandleDkgOutcome {
section_auth,
outcome,
} => f
.debug_struct("HandleDkgOutcome")
.field("section_auth", section_auth)
.field("outcome", &outcome.public_key_set.public_key())
.finish(),
Self::HandleDkgFailure(signeds) => {
f.debug_tuple("HandleDkgFailure").field(signeds).finish()
}
Self::SendMessage {
recipients,
delivery_group_size,
message,
} => f
.debug_struct("SendMessage")
.field("recipients", recipients)
.field("delivery_group_size", delivery_group_size)
.field("message", message)
.finish(),
Self::SendUserMessage {
itinerary,
content,
additional_proof_chain_key,
} => f
.debug_struct("SendUserMessage")
.field("itinerary", itinerary)
.field("content", &format_args!("{:10}", HexFmt(content)))
.field("additional_proof_chain_key", additional_proof_chain_key)
.finish(),
Self::ScheduleTimeout { duration, token } => f
.debug_struct("ScheduleTimeout")
.field("duration", duration)
.field("token", token)
.finish(),
Self::Relocate {
bootstrap_addrs,
details,
..
} => f
.debug_struct("Relocate")
.field("bootstrap_addrs", bootstrap_addrs)
.field("details", details)
.finish(),
Self::SetJoinsAllowed(joins_allowed) => f
.debug_tuple("SetJoinsAllowed")
.field(joins_allowed)
.finish(),
Self::ProposeOnline {
peer,
previous_name,
..
} => f
.debug_struct("ProposeOnline")
.field("peer", peer)
.field("previous_name", previous_name)
.finish(),
Self::ProposeOffline(name) => f.debug_tuple("ProposeOffline").field(name).finish(),
Self::TestConnectivity(name) => f.debug_tuple("TestConnectivity").field(name).finish(),
Self::StartConnectivityTest(name) => {
f.debug_tuple("StartConnectivityTest").field(name).finish()
}
}
}
}
pub(crate) fn next_timer_token() -> u64 {
static NEXT: AtomicU64 = AtomicU64::new(0);
NEXT.fetch_add(1, Ordering::Relaxed)
}