mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-07 21:13:44 +02:00
Simplify some Rust generic madness.
This commit is contained in:
parent
dd9f1cffe5
commit
f0158ee8ae
11 changed files with 228 additions and 303 deletions
|
@ -17,6 +17,7 @@ use zerotier_network_hypervisor::vl2::v1::Revocation;
|
||||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||||
use zerotier_utils::blob::Blob;
|
use zerotier_utils::blob::Blob;
|
||||||
use zerotier_utils::buffer::OutOfBoundsError;
|
use zerotier_utils::buffer::OutOfBoundsError;
|
||||||
|
use zerotier_utils::cast::cast_ref;
|
||||||
use zerotier_utils::error::InvalidParameterError;
|
use zerotier_utils::error::InvalidParameterError;
|
||||||
use zerotier_utils::reaper::Reaper;
|
use zerotier_utils::reaper::Reaper;
|
||||||
use zerotier_utils::tokio;
|
use zerotier_utils::tokio;
|
||||||
|
@ -139,62 +140,56 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compose and send network configuration packet (either V1 or V2)
|
/// Compose and send network configuration packet (either V1 or V2)
|
||||||
fn send_network_config(
|
fn send_network_config<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
peer: &Peer,
|
app: &Application,
|
||||||
|
node: &Node<Application>,
|
||||||
|
peer: &Peer<Application>,
|
||||||
config: &NetworkConfig,
|
config: &NetworkConfig,
|
||||||
in_re_message_id: Option<u64>, // None for unsolicited push
|
in_re_message_id: Option<u64>, // None for unsolicited push
|
||||||
) {
|
) {
|
||||||
if let Some(host_system) = self.service.read().unwrap().upgrade() {
|
peer.send(app, node, None, ms_monotonic(), |packet| -> Result<(), OutOfBoundsError> {
|
||||||
peer.send(
|
let payload_start = packet.len();
|
||||||
host_system.as_ref(),
|
|
||||||
host_system.node(),
|
|
||||||
None,
|
|
||||||
ms_monotonic(),
|
|
||||||
|packet| -> Result<(), OutOfBoundsError> {
|
|
||||||
let payload_start = packet.len();
|
|
||||||
|
|
||||||
if let Some(in_re_message_id) = in_re_message_id {
|
if let Some(in_re_message_id) = in_re_message_id {
|
||||||
let ok_header = packet.append_struct_get_mut::<protocol::OkHeader>()?;
|
let ok_header = packet.append_struct_get_mut::<protocol::OkHeader>()?;
|
||||||
ok_header.verb = protocol::message_type::VL1_OK;
|
ok_header.verb = protocol::message_type::VL1_OK;
|
||||||
ok_header.in_re_verb = protocol::message_type::VL2_NETWORK_CONFIG_REQUEST;
|
ok_header.in_re_verb = protocol::message_type::VL2_NETWORK_CONFIG_REQUEST;
|
||||||
ok_header.in_re_message_id = in_re_message_id.to_be_bytes();
|
ok_header.in_re_message_id = in_re_message_id.to_be_bytes();
|
||||||
} else {
|
} else {
|
||||||
packet.append_u8(protocol::message_type::VL2_NETWORK_CONFIG)?;
|
packet.append_u8(protocol::message_type::VL2_NETWORK_CONFIG)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if peer.is_v2() {
|
if peer.is_v2() {
|
||||||
todo!()
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
let config_data = if let Some(config_dict) = config.v1_proto_to_dictionary(&self.local_identity) {
|
let config_data = if let Some(config_dict) = config.v1_proto_to_dictionary(&self.local_identity) {
|
||||||
config_dict.to_bytes()
|
config_dict.to_bytes()
|
||||||
} else {
|
} else {
|
||||||
eprintln!("WARNING: unexpected error serializing network config into V1 format dictionary");
|
eprintln!("WARNING: unexpected error serializing network config into V1 format dictionary");
|
||||||
return Err(OutOfBoundsError); // abort
|
return Err(OutOfBoundsError); // abort
|
||||||
};
|
};
|
||||||
if config_data.len() > (u16::MAX as usize) {
|
if config_data.len() > (u16::MAX as usize) {
|
||||||
eprintln!("WARNING: network config is larger than 65536 bytes!");
|
eprintln!("WARNING: network config is larger than 65536 bytes!");
|
||||||
return Err(OutOfBoundsError); // abort
|
return Err(OutOfBoundsError); // abort
|
||||||
}
|
}
|
||||||
|
|
||||||
packet.append_u64(config.network_id.into())?;
|
packet.append_u64(config.network_id.into())?;
|
||||||
packet.append_u16(config_data.len() as u16)?;
|
packet.append_u16(config_data.len() as u16)?;
|
||||||
packet.append_bytes(config_data.as_slice())?;
|
packet.append_bytes(config_data.as_slice())?;
|
||||||
|
|
||||||
// TODO: for V1 we may need to introduce use of the chunking mechanism for large configs.
|
// TODO: for V1 we may need to introduce use of the chunking mechanism for large configs.
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_payload_len = protocol::compress(&mut packet.as_bytes_mut()[payload_start..]);
|
let new_payload_len = protocol::compress(&mut packet.as_bytes_mut()[payload_start..]);
|
||||||
packet.set_size(payload_start + new_payload_len);
|
packet.set_size(payload_start + new_payload_len);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send one or more revocation object(s) to a peer. The provided vector is drained.
|
/// Send one or more revocation object(s) to a peer. The provided vector is drained.
|
||||||
fn send_revocations(&self, peer: &Peer, revocations: &mut Vec<Revocation>) {
|
fn send_revocations(&self, peer: &Peer<VL1Service<Self>>, revocations: &mut Vec<Revocation>) {
|
||||||
if let Some(host_system) = self.service.read().unwrap().upgrade() {
|
if let Some(host_system) = self.service.read().unwrap().upgrade() {
|
||||||
let time_ticks = ms_monotonic();
|
let time_ticks = ms_monotonic();
|
||||||
while !revocations.is_empty() {
|
while !revocations.is_empty() {
|
||||||
|
@ -496,20 +491,12 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InnerProtocolLayer for Controller {
|
impl InnerProtocolLayer for Controller {
|
||||||
#[inline(always)]
|
fn handle_packet<Application: ApplicationLayer + ?Sized>(
|
||||||
fn should_respond_to(&self, _: &Valid<Identity>) -> bool {
|
|
||||||
// Controllers always have to establish sessions to process requests. We don't really know if
|
|
||||||
// a member is relevant until we have looked up both the network and the member, since whether
|
|
||||||
// or not to "learn" unknown members is a network level option.
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_packet<HostSystemImpl: ApplicationLayer + ?Sized>(
|
|
||||||
&self,
|
&self,
|
||||||
host_system: &HostSystemImpl,
|
app: &Application,
|
||||||
_: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
verb: u8,
|
verb: u8,
|
||||||
|
@ -518,10 +505,6 @@ impl InnerProtocolLayer for Controller {
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
match verb {
|
match verb {
|
||||||
protocol::message_type::VL2_NETWORK_CONFIG_REQUEST => {
|
protocol::message_type::VL2_NETWORK_CONFIG_REQUEST => {
|
||||||
if !self.should_respond_to(&source.identity) {
|
|
||||||
return PacketHandlerResult::Ok; // handled and ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
let network_id = payload.read_u64(&mut cursor);
|
let network_id = payload.read_u64(&mut cursor);
|
||||||
if network_id.is_err() {
|
if network_id.is_err() {
|
||||||
return PacketHandlerResult::Error;
|
return PacketHandlerResult::Error;
|
||||||
|
@ -533,7 +516,7 @@ impl InnerProtocolLayer for Controller {
|
||||||
let network_id = network_id.unwrap();
|
let network_id = network_id.unwrap();
|
||||||
|
|
||||||
debug_event!(
|
debug_event!(
|
||||||
host_system,
|
app,
|
||||||
"[vl2] NETWORK_CONFIG_REQUEST from {}({}) for {:0>16x}",
|
"[vl2] NETWORK_CONFIG_REQUEST from {}({}) for {:0>16x}",
|
||||||
source.identity.address.to_string(),
|
source.identity.address.to_string(),
|
||||||
source_path.endpoint.to_string(),
|
source_path.endpoint.to_string(),
|
||||||
|
@ -565,7 +548,8 @@ impl InnerProtocolLayer for Controller {
|
||||||
let (result, config) = match self2.authorize(&source.identity, network_id, now).await {
|
let (result, config) = match self2.authorize(&source.identity, network_id, now).await {
|
||||||
Result::Ok((result, Some(config))) => {
|
Result::Ok((result, Some(config))) => {
|
||||||
//println!("{}", serde_yaml::to_string(&config).unwrap());
|
//println!("{}", serde_yaml::to_string(&config).unwrap());
|
||||||
self2.send_network_config(source.as_ref(), &config, Some(message_id));
|
let app = self2.service.read().unwrap().upgrade().unwrap();
|
||||||
|
self2.send_network_config(app.as_ref(), app.node(), cast_ref(source.as_ref()).unwrap(), &config, Some(message_id));
|
||||||
(result, Some(config))
|
(result, Some(config))
|
||||||
}
|
}
|
||||||
Result::Ok((result, None)) => (result, None),
|
Result::Ok((result, None)) => (result, None),
|
||||||
|
@ -618,23 +602,21 @@ impl InnerProtocolLayer for Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
protocol::message_type::VL2_MULTICAST_GATHER => {
|
protocol::message_type::VL2_MULTICAST_GATHER => {
|
||||||
if let Some(service) = self.service.read().unwrap().upgrade() {
|
let auth = self.recently_authorized.read().unwrap();
|
||||||
let auth = self.recently_authorized.read().unwrap();
|
let time_ticks = ms_monotonic();
|
||||||
let time_ticks = ms_monotonic();
|
self.multicast_authority.handle_vl2_multicast_gather(
|
||||||
self.multicast_authority.handle_vl2_multicast_gather(
|
|network_id, identity| {
|
||||||
|network_id, identity| {
|
auth.get(&identity.fingerprint)
|
||||||
auth.get(&identity.fingerprint)
|
.map_or(false, |t| t.get(&network_id).map_or(false, |t| *t > time_ticks))
|
||||||
.map_or(false, |t| t.get(&network_id).map_or(false, |t| *t > time_ticks))
|
},
|
||||||
},
|
time_ticks,
|
||||||
time_ticks,
|
app,
|
||||||
service.as_ref(),
|
node,
|
||||||
service.node(),
|
source,
|
||||||
source,
|
message_id,
|
||||||
message_id,
|
payload,
|
||||||
payload,
|
cursor,
|
||||||
cursor,
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
PacketHandlerResult::Ok
|
PacketHandlerResult::Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,12 @@ use zerotier_utils::gate::IntervalGate;
|
||||||
use zerotier_utils::hex;
|
use zerotier_utils::hex;
|
||||||
use zerotier_utils::marshalable::Marshalable;
|
use zerotier_utils::marshalable::Marshalable;
|
||||||
use zerotier_utils::ringbuffer::RingBuffer;
|
use zerotier_utils::ringbuffer::RingBuffer;
|
||||||
use zerotier_utils::thing::Thing;
|
|
||||||
|
|
||||||
/// Interface trait to be implemented by code that's using the ZeroTier network hypervisor.
|
/// Interface trait to be implemented by code that's using the ZeroTier network hypervisor.
|
||||||
///
|
///
|
||||||
/// This is analogous to a C struct full of function pointers to callbacks along with some
|
/// This is analogous to a C struct full of function pointers to callbacks along with some
|
||||||
/// associated type definitions.
|
/// associated type definitions.
|
||||||
pub trait ApplicationLayer: Sync + Send {
|
pub trait ApplicationLayer: Sync + Send + 'static {
|
||||||
/// Type for local system sockets.
|
/// Type for local system sockets.
|
||||||
type LocalSocket: Sync + Send + Hash + PartialEq + Eq + Clone + ToString + Sized + 'static;
|
type LocalSocket: Sync + Send + Hash + PartialEq + Eq + Clone + ToString + Sized + 'static;
|
||||||
|
|
||||||
|
@ -56,6 +55,9 @@ pub trait ApplicationLayer: Sync + Send {
|
||||||
/// unbound, etc.
|
/// unbound, etc.
|
||||||
fn local_socket_is_valid(&self, socket: &Self::LocalSocket) -> bool;
|
fn local_socket_is_valid(&self, socket: &Self::LocalSocket) -> bool;
|
||||||
|
|
||||||
|
/// Check if this node should respond to messages from a given peer at all.
|
||||||
|
fn should_respond_to(&self, id: &Valid<Identity>) -> bool;
|
||||||
|
|
||||||
/// Called to send a packet over the physical network (virtual -> physical).
|
/// Called to send a packet over the physical network (virtual -> physical).
|
||||||
///
|
///
|
||||||
/// This sends with UDP-like semantics. It should do whatever best effort it can and return.
|
/// This sends with UDP-like semantics. It should do whatever best effort it can and return.
|
||||||
|
@ -130,13 +132,6 @@ pub enum PacketHandlerResult {
|
||||||
/// it could also be implemented for testing or "off label" use of VL1 to carry different protocols.
|
/// it could also be implemented for testing or "off label" use of VL1 to carry different protocols.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub trait InnerProtocolLayer: Sync + Send {
|
pub trait InnerProtocolLayer: Sync + Send {
|
||||||
/// Check if this node should respond to messages from a given peer at all.
|
|
||||||
///
|
|
||||||
/// The default implementation always returns true.
|
|
||||||
fn should_respond_to(&self, id: &Valid<Identity>) -> bool {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle a packet, returning true if it was handled by the next layer.
|
/// Handle a packet, returning true if it was handled by the next layer.
|
||||||
///
|
///
|
||||||
/// Do not attempt to handle OK or ERROR. Instead implement handle_ok() and handle_error().
|
/// Do not attempt to handle OK or ERROR. Instead implement handle_ok() and handle_error().
|
||||||
|
@ -144,9 +139,9 @@ pub trait InnerProtocolLayer: Sync + Send {
|
||||||
fn handle_packet<Application: ApplicationLayer + ?Sized>(
|
fn handle_packet<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
verb: u8,
|
verb: u8,
|
||||||
|
@ -161,9 +156,9 @@ pub trait InnerProtocolLayer: Sync + Send {
|
||||||
fn handle_error<Application: ApplicationLayer + ?Sized>(
|
fn handle_error<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
in_re_verb: u8,
|
in_re_verb: u8,
|
||||||
|
@ -180,9 +175,9 @@ pub trait InnerProtocolLayer: Sync + Send {
|
||||||
fn handle_ok<Application: ApplicationLayer + ?Sized>(
|
fn handle_ok<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
in_re_verb: u8,
|
in_re_verb: u8,
|
||||||
|
@ -194,12 +189,12 @@ pub trait InnerProtocolLayer: Sync + Send {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RootInfo {
|
struct RootInfo<Application: ApplicationLayer + ?Sized> {
|
||||||
/// Root sets to which we are a member.
|
/// Root sets to which we are a member.
|
||||||
sets: HashMap<String, Verified<RootSet>>,
|
sets: HashMap<String, Verified<RootSet>>,
|
||||||
|
|
||||||
/// Root peers and their statically defined endpoints (from root sets).
|
/// Root peers and their statically defined endpoints (from root sets).
|
||||||
roots: HashMap<Arc<Peer>, Vec<Endpoint>>,
|
roots: HashMap<Arc<Peer<Application>>, Vec<Endpoint>>,
|
||||||
|
|
||||||
/// If this node is a root, these are the root sets to which it's a member in binary serialized form.
|
/// If this node is a root, these are the root sets to which it's a member in binary serialized form.
|
||||||
/// Set to None if this node is not a root, meaning it doesn't appear in any of its root sets.
|
/// Set to None if this node is not a root, meaning it doesn't appear in any of its root sets.
|
||||||
|
@ -225,17 +220,15 @@ struct BackgroundTaskIntervals {
|
||||||
whois_queue_retry: IntervalGate<{ WHOIS_RETRY_INTERVAL }>,
|
whois_queue_retry: IntervalGate<{ WHOIS_RETRY_INTERVAL }>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct WhoisQueueItem {
|
struct WhoisQueueItem<Application: ApplicationLayer + ?Sized> {
|
||||||
v1_proto_waiting_packets: RingBuffer<(Weak<Path>, PooledPacketBuffer), WHOIS_MAX_WAITING_PACKETS>,
|
v1_proto_waiting_packets:
|
||||||
|
RingBuffer<(Weak<Path<Application::LocalSocket, Application::LocalInterface>>, PooledPacketBuffer), WHOIS_MAX_WAITING_PACKETS>,
|
||||||
last_retry_time: i64,
|
last_retry_time: i64,
|
||||||
retry_count: u16,
|
retry_count: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
const PATH_MAP_SIZE: usize = std::mem::size_of::<HashMap<[u8; std::mem::size_of::<Endpoint>() + 128], Arc<Path>>>();
|
|
||||||
type PathMap<LocalSocket> = HashMap<PathKey<'static, 'static, LocalSocket>, Arc<Path>>;
|
|
||||||
|
|
||||||
/// A ZeroTier VL1 node that can communicate securely with the ZeroTier peer-to-peer network.
|
/// A ZeroTier VL1 node that can communicate securely with the ZeroTier peer-to-peer network.
|
||||||
pub struct Node {
|
pub struct Node<Application: ApplicationLayer + ?Sized> {
|
||||||
/// A random ID generated to identify this particular running instance.
|
/// A random ID generated to identify this particular running instance.
|
||||||
pub instance_id: [u8; 16],
|
pub instance_id: [u8; 16],
|
||||||
|
|
||||||
|
@ -246,27 +239,23 @@ pub struct Node {
|
||||||
intervals: Mutex<BackgroundTaskIntervals>,
|
intervals: Mutex<BackgroundTaskIntervals>,
|
||||||
|
|
||||||
/// Canonicalized network paths, held as Weak<> to be automatically cleaned when no longer in use.
|
/// Canonicalized network paths, held as Weak<> to be automatically cleaned when no longer in use.
|
||||||
paths: RwLock<Thing<PATH_MAP_SIZE>>, // holds a PathMap<> but as a Thing<> to hide ApplicationLayer template parameter
|
paths: RwLock<HashMap<PathKey<'static, 'static, Application::LocalSocket>, Arc<Path<Application::LocalSocket, Application::LocalInterface>>>>,
|
||||||
|
|
||||||
/// Peers with which we are currently communicating.
|
/// Peers with which we are currently communicating.
|
||||||
peers: RwLock<HashMap<Address, Arc<Peer>>>,
|
peers: RwLock<HashMap<Address, Arc<Peer<Application>>>>,
|
||||||
|
|
||||||
/// This node's trusted roots, sorted in ascending order of quality/preference, and cluster definitions.
|
/// This node's trusted roots, sorted in ascending order of quality/preference, and cluster definitions.
|
||||||
roots: RwLock<RootInfo>,
|
roots: RwLock<RootInfo<Application>>,
|
||||||
|
|
||||||
/// Current best root.
|
/// Current best root.
|
||||||
best_root: RwLock<Option<Arc<Peer>>>,
|
best_root: RwLock<Option<Arc<Peer<Application>>>>,
|
||||||
|
|
||||||
/// Queue of identities being looked up.
|
/// Queue of identities being looked up.
|
||||||
whois_queue: Mutex<HashMap<Address, WhoisQueueItem>>,
|
whois_queue: Mutex<HashMap<Address, WhoisQueueItem<Application>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl<Application: ApplicationLayer + ?Sized> Node<Application> {
|
||||||
pub fn new<Application: ApplicationLayer + ?Sized>(
|
pub fn new(app: &Application, auto_generate_identity: bool, auto_upgrade_identity: bool) -> Result<Self, InvalidParameterError> {
|
||||||
app: &Application,
|
|
||||||
auto_generate_identity: bool,
|
|
||||||
auto_upgrade_identity: bool,
|
|
||||||
) -> Result<Self, InvalidParameterError> {
|
|
||||||
let mut id = {
|
let mut id = {
|
||||||
let id = app.load_node_identity();
|
let id = app.load_node_identity();
|
||||||
if id.is_none() {
|
if id.is_none() {
|
||||||
|
@ -297,7 +286,7 @@ impl Node {
|
||||||
instance_id: random::get_bytes_secure(),
|
instance_id: random::get_bytes_secure(),
|
||||||
identity: id,
|
identity: id,
|
||||||
intervals: Mutex::new(BackgroundTaskIntervals::default()),
|
intervals: Mutex::new(BackgroundTaskIntervals::default()),
|
||||||
paths: RwLock::new(Thing::new(PathMap::<Application::LocalSocket>::new())),
|
paths: RwLock::new(HashMap::new()),
|
||||||
peers: RwLock::new(HashMap::new()),
|
peers: RwLock::new(HashMap::new()),
|
||||||
roots: RwLock::new(RootInfo {
|
roots: RwLock::new(RootInfo {
|
||||||
sets: HashMap::new(),
|
sets: HashMap::new(),
|
||||||
|
@ -312,7 +301,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn peer(&self, a: Address) -> Option<Arc<Peer>> {
|
pub fn peer(&self, a: Address) -> Option<Arc<Peer<Application>>> {
|
||||||
self.peers.read().unwrap().get(&a).cloned()
|
self.peers.read().unwrap().get(&a).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,13 +312,13 @@ impl Node {
|
||||||
|
|
||||||
/// Get the current "best" root from among this node's trusted roots.
|
/// Get the current "best" root from among this node's trusted roots.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn best_root(&self) -> Option<Arc<Peer>> {
|
pub fn best_root(&self) -> Option<Arc<Peer<Application>>> {
|
||||||
self.best_root.read().unwrap().clone()
|
self.best_root.read().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether a peer is a root according to any root set trusted by this node.
|
/// Check whether a peer is a root according to any root set trusted by this node.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn is_peer_root(&self, peer: &Peer) -> bool {
|
pub fn is_peer_root(&self, peer: &Peer<Application>) -> bool {
|
||||||
self.roots.read().unwrap().roots.keys().any(|p| p.identity.eq(&peer.identity))
|
self.roots.read().unwrap().roots.keys().any(|p| p.identity.eq(&peer.identity))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +369,7 @@ impl Node {
|
||||||
self.roots.read().unwrap().sets.values().cloned().map(|s| s.remove_typestate()).collect()
|
self.roots.read().unwrap().sets.values().cloned().map(|s| s.remove_typestate()).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_background_tasks<Application: ApplicationLayer + ?Sized>(&self, app: &Application) -> Duration {
|
pub fn do_background_tasks(&self, app: &Application) -> Duration {
|
||||||
const INTERVAL_MS: i64 = 1000;
|
const INTERVAL_MS: i64 = 1000;
|
||||||
const INTERVAL: Duration = Duration::from_millis(INTERVAL_MS as u64);
|
const INTERVAL: Duration = Duration::from_millis(INTERVAL_MS as u64);
|
||||||
let time_ticks = app.time_ticks();
|
let time_ticks = app.time_ticks();
|
||||||
|
@ -611,7 +600,7 @@ impl Node {
|
||||||
let mut need_keepalive = Vec::new();
|
let mut need_keepalive = Vec::new();
|
||||||
|
|
||||||
// First check all paths in read mode to avoid blocking the entire node.
|
// First check all paths in read mode to avoid blocking the entire node.
|
||||||
for (k, path) in self.paths.read().unwrap().get::<PathMap<Application::LocalSocket>>().iter() {
|
for (k, path) in self.paths.read().unwrap().iter() {
|
||||||
if app.local_socket_is_valid(k.local_socket()) {
|
if app.local_socket_is_valid(k.local_socket()) {
|
||||||
match path.service(time_ticks) {
|
match path.service(time_ticks) {
|
||||||
PathServiceResult::Ok => {}
|
PathServiceResult::Ok => {}
|
||||||
|
@ -625,19 +614,13 @@ impl Node {
|
||||||
|
|
||||||
// Lock in write mode and remove dead paths, doing so piecemeal to again avoid blocking.
|
// Lock in write mode and remove dead paths, doing so piecemeal to again avoid blocking.
|
||||||
for dp in dead_paths.iter() {
|
for dp in dead_paths.iter() {
|
||||||
self.paths.write().unwrap().get_mut::<PathMap<Application::LocalSocket>>().remove(dp);
|
self.paths.write().unwrap().remove(dp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally run keepalive sends as a batch.
|
// Finally run keepalive sends as a batch.
|
||||||
let keepalive_buf = [time_ticks as u8]; // just an arbitrary byte, no significance
|
let keepalive_buf = [time_ticks as u8]; // just an arbitrary byte, no significance
|
||||||
for p in need_keepalive.iter() {
|
for p in need_keepalive.iter() {
|
||||||
app.wire_send(
|
app.wire_send(&p.endpoint, Some(&p.local_socket), Some(&p.local_interface), &keepalive_buf, 0);
|
||||||
&p.endpoint,
|
|
||||||
Some(p.local_socket::<Application>()),
|
|
||||||
Some(p.local_interface::<Application>()),
|
|
||||||
&keepalive_buf,
|
|
||||||
0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +646,7 @@ impl Node {
|
||||||
INTERVAL
|
INTERVAL
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_incoming_physical_packet<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
pub fn handle_incoming_physical_packet<Inner: InnerProtocolLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
inner: &Inner,
|
||||||
|
@ -685,14 +668,7 @@ impl Node {
|
||||||
source_local_interface.to_string()
|
source_local_interface.to_string()
|
||||||
);
|
);
|
||||||
|
|
||||||
// An 0xff value at byte [8] means this is a ZSSP packet. This is accomplished via the
|
// TODO: detect inbound ZSSP sessions, handle ZSSP mode.
|
||||||
// backward compatibility hack of always having 0xff at byte [4] of 6-byte session IDs
|
|
||||||
// and by having 0xffffffffffff be the "nil" session ID for session init packets. ZSSP
|
|
||||||
// is the new V2 Noise-based forward-secure transport protocol. What follows below this
|
|
||||||
// is legacy handling of the old v1 protocol.
|
|
||||||
if packet.u8_at(8).map_or(false, |x| x == 0xff) {
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy ZeroTier V1 packet handling
|
// Legacy ZeroTier V1 packet handling
|
||||||
if let Ok(fragment_header) = packet.struct_mut_at::<v1::FragmentHeader>(0) {
|
if let Ok(fragment_header) = packet.struct_mut_at::<v1::FragmentHeader>(0) {
|
||||||
|
@ -701,7 +677,7 @@ impl Node {
|
||||||
|
|
||||||
if dest == self.identity.address {
|
if dest == self.identity.address {
|
||||||
let fragment_header = &*fragment_header; // discard mut
|
let fragment_header = &*fragment_header; // discard mut
|
||||||
let path = self.canonical_path::<Application>(source_endpoint, source_local_socket, source_local_interface, time_ticks);
|
let path = self.canonical_path(source_endpoint, source_local_socket, source_local_interface, time_ticks);
|
||||||
path.log_receive_anything(time_ticks);
|
path.log_receive_anything(time_ticks);
|
||||||
|
|
||||||
if fragment_header.is_fragment() {
|
if fragment_header.is_fragment() {
|
||||||
|
@ -816,8 +792,8 @@ impl Node {
|
||||||
if let Some(forward_path) = peer.direct_path() {
|
if let Some(forward_path) = peer.direct_path() {
|
||||||
app.wire_send(
|
app.wire_send(
|
||||||
&forward_path.endpoint,
|
&forward_path.endpoint,
|
||||||
Some(forward_path.local_socket::<Application>()),
|
Some(&forward_path.local_socket),
|
||||||
Some(forward_path.local_interface::<Application>()),
|
Some(&forward_path.local_interface),
|
||||||
packet.as_bytes(),
|
packet.as_bytes(),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
|
@ -834,11 +810,11 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Enqueue and send a WHOIS query for a given address, adding the supplied packet (if any) to the list to be processed on reply.
|
/// Enqueue and send a WHOIS query for a given address, adding the supplied packet (if any) to the list to be processed on reply.
|
||||||
fn whois<Application: ApplicationLayer + ?Sized>(
|
fn whois(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
address: Address,
|
address: Address,
|
||||||
waiting_packet: Option<(Weak<Path>, PooledPacketBuffer)>,
|
waiting_packet: Option<(Weak<Path<Application::LocalSocket, Application::LocalInterface>>, PooledPacketBuffer)>,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
) {
|
) {
|
||||||
{
|
{
|
||||||
|
@ -862,7 +838,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a WHOIS query to the current best root.
|
/// Send a WHOIS query to the current best root.
|
||||||
fn send_whois<Application: ApplicationLayer + ?Sized>(&self, app: &Application, mut addresses: &[Address], time_ticks: i64) {
|
fn send_whois(&self, app: &Application, mut addresses: &[Address], time_ticks: i64) {
|
||||||
debug_assert!(!addresses.is_empty());
|
debug_assert!(!addresses.is_empty());
|
||||||
debug_event!(app, "[vl1] [v1] sending WHOIS for {}", {
|
debug_event!(app, "[vl1] [v1] sending WHOIS for {}", {
|
||||||
let mut tmp = String::new();
|
let mut tmp = String::new();
|
||||||
|
@ -894,7 +870,7 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called by Peer when an identity is received from another node, e.g. via OK(WHOIS).
|
/// Called by Peer when an identity is received from another node, e.g. via OK(WHOIS).
|
||||||
pub(crate) fn handle_incoming_identity<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
pub(crate) fn handle_incoming_identity<Inner: InnerProtocolLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
inner: &Inner,
|
||||||
|
@ -907,7 +883,7 @@ impl Node {
|
||||||
let mut whois_queue = self.whois_queue.lock().unwrap();
|
let mut whois_queue = self.whois_queue.lock().unwrap();
|
||||||
if let Some(qi) = whois_queue.get_mut(&received_identity.address) {
|
if let Some(qi) = whois_queue.get_mut(&received_identity.address) {
|
||||||
let address = received_identity.address;
|
let address = received_identity.address;
|
||||||
if inner.should_respond_to(&received_identity) {
|
if app.should_respond_to(&received_identity) {
|
||||||
let mut peers = self.peers.write().unwrap();
|
let mut peers = self.peers.write().unwrap();
|
||||||
if let Some(peer) = peers.get(&address).cloned().or_else(|| {
|
if let Some(peer) = peers.get(&address).cloned().or_else(|| {
|
||||||
Peer::new(&self.identity, received_identity, time_ticks)
|
Peer::new(&self.identity, received_identity, time_ticks)
|
||||||
|
@ -946,31 +922,23 @@ impl Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the canonical Path object corresponding to an endpoint.
|
/// Get the canonical Path object corresponding to an endpoint.
|
||||||
pub(crate) fn canonical_path<Application: ApplicationLayer + ?Sized>(
|
pub(crate) fn canonical_path(
|
||||||
&self,
|
&self,
|
||||||
ep: &Endpoint,
|
ep: &Endpoint,
|
||||||
local_socket: &Application::LocalSocket,
|
local_socket: &Application::LocalSocket,
|
||||||
local_interface: &Application::LocalInterface,
|
local_interface: &Application::LocalInterface,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
) -> Arc<Path> {
|
) -> Arc<Path<Application::LocalSocket, Application::LocalInterface>> {
|
||||||
let paths = self.paths.read().unwrap();
|
let paths = self.paths.read().unwrap();
|
||||||
if let Some(path) = paths.get::<PathMap<Application::LocalSocket>>().get(&PathKey::Ref(ep, local_socket)) {
|
if let Some(path) = paths.get(&PathKey::Ref(ep, local_socket)) {
|
||||||
path.clone()
|
path.clone()
|
||||||
} else {
|
} else {
|
||||||
drop(paths);
|
drop(paths);
|
||||||
self.paths
|
self.paths
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_mut::<PathMap<Application::LocalSocket>>()
|
|
||||||
.entry(PathKey::Copied(ep.clone(), local_socket.clone()))
|
.entry(PathKey::Copied(ep.clone(), local_socket.clone()))
|
||||||
.or_insert_with(|| {
|
.or_insert_with(|| Arc::new(Path::new(ep.clone(), local_socket.clone(), local_interface.clone(), time_ticks)))
|
||||||
Arc::new(Path::new::<Application>(
|
|
||||||
ep.clone(),
|
|
||||||
local_socket.clone(),
|
|
||||||
local_interface.clone(),
|
|
||||||
time_ticks,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.clone()
|
.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,8 @@ use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::vl1::endpoint::Endpoint;
|
use crate::vl1::endpoint::Endpoint;
|
||||||
use crate::vl1::node::*;
|
|
||||||
|
|
||||||
use zerotier_crypto::random;
|
use zerotier_crypto::random;
|
||||||
use zerotier_utils::thing::Thing;
|
|
||||||
use zerotier_utils::NEVER_HAPPENED_TICKS;
|
use zerotier_utils::NEVER_HAPPENED_TICKS;
|
||||||
|
|
||||||
pub(crate) const SERVICE_INTERVAL_MS: i64 = protocol::PATH_KEEPALIVE_INTERVAL;
|
pub(crate) const SERVICE_INTERVAL_MS: i64 = protocol::PATH_KEEPALIVE_INTERVAL;
|
||||||
|
@ -26,27 +24,22 @@ pub(crate) enum PathServiceResult {
|
||||||
/// These are maintained in Node and canonicalized so that all unique paths have
|
/// These are maintained in Node and canonicalized so that all unique paths have
|
||||||
/// one and only one unique path object. That enables statistics to be tracked
|
/// one and only one unique path object. That enables statistics to be tracked
|
||||||
/// for them and uniform application of things like keepalives.
|
/// for them and uniform application of things like keepalives.
|
||||||
pub struct Path {
|
pub struct Path<LocalSocket, LocalInterface> {
|
||||||
pub endpoint: Endpoint,
|
pub endpoint: Endpoint,
|
||||||
local_socket: Thing<64>,
|
pub local_socket: LocalSocket,
|
||||||
local_interface: Thing<64>,
|
pub local_interface: LocalInterface,
|
||||||
last_send_time_ticks: AtomicI64,
|
last_send_time_ticks: AtomicI64,
|
||||||
last_receive_time_ticks: AtomicI64,
|
last_receive_time_ticks: AtomicI64,
|
||||||
create_time_ticks: i64,
|
create_time_ticks: i64,
|
||||||
fragmented_packets: Mutex<HashMap<u64, protocol::v1::FragmentedPacket, PacketIdHasher>>,
|
fragmented_packets: Mutex<HashMap<u64, protocol::v1::FragmentedPacket, PacketIdHasher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Path {
|
impl<LocalSocket, LocalInterface> Path<LocalSocket, LocalInterface> {
|
||||||
pub(crate) fn new<Application: ApplicationLayer + ?Sized>(
|
pub(crate) fn new(endpoint: Endpoint, local_socket: LocalSocket, local_interface: LocalInterface, time_ticks: i64) -> Self {
|
||||||
endpoint: Endpoint,
|
|
||||||
local_socket: Application::LocalSocket,
|
|
||||||
local_interface: Application::LocalInterface,
|
|
||||||
time_ticks: i64,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
endpoint,
|
endpoint,
|
||||||
local_socket: Thing::new(local_socket), // enlarge Thing<> if this panics
|
local_socket,
|
||||||
local_interface: Thing::new(local_interface), // enlarge Thing<> if this panics
|
local_interface,
|
||||||
last_send_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
last_send_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
||||||
last_receive_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
last_receive_time_ticks: AtomicI64::new(NEVER_HAPPENED_TICKS),
|
||||||
create_time_ticks: time_ticks,
|
create_time_ticks: time_ticks,
|
||||||
|
@ -54,16 +47,6 @@ impl Path {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn local_socket<Application: ApplicationLayer + ?Sized>(&self) -> &Application::LocalSocket {
|
|
||||||
self.local_socket.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
pub(crate) fn local_interface<Application: ApplicationLayer + ?Sized>(&self) -> &Application::LocalInterface {
|
|
||||||
self.local_interface.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Receive a fragment and return a FragmentedPacket if the entire packet was assembled.
|
/// Receive a fragment and return a FragmentedPacket if the entire packet was assembled.
|
||||||
/// This returns None if more fragments are needed to assemble the packet.
|
/// This returns None if more fragments are needed to assemble the packet.
|
||||||
pub(crate) fn v1_proto_receive_fragment(
|
pub(crate) fn v1_proto_receive_fragment(
|
||||||
|
|
|
@ -24,11 +24,11 @@ use crate::{VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION};
|
||||||
|
|
||||||
pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000;
|
pub(crate) const SERVICE_INTERVAL_MS: i64 = 10000;
|
||||||
|
|
||||||
pub struct Peer {
|
pub struct Peer<Application: ApplicationLayer + ?Sized> {
|
||||||
pub identity: Valid<Identity>,
|
pub identity: Valid<Identity>,
|
||||||
|
|
||||||
v1_proto_static_secret: v1::SymmetricSecret,
|
v1_proto_static_secret: v1::SymmetricSecret,
|
||||||
paths: Mutex<Vec<PeerPath>>,
|
paths: Mutex<Vec<PeerPath<Application>>>,
|
||||||
|
|
||||||
pub(crate) last_send_time_ticks: AtomicI64,
|
pub(crate) last_send_time_ticks: AtomicI64,
|
||||||
pub(crate) last_receive_time_ticks: AtomicI64,
|
pub(crate) last_receive_time_ticks: AtomicI64,
|
||||||
|
@ -41,8 +41,8 @@ pub struct Peer {
|
||||||
remote_node_info: RwLock<RemoteNodeInfo>,
|
remote_node_info: RwLock<RemoteNodeInfo>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeerPath {
|
struct PeerPath<Application: ApplicationLayer + ?Sized> {
|
||||||
path: Weak<Path>,
|
path: Weak<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
last_receive_time_ticks: i64,
|
last_receive_time_ticks: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,11 +53,11 @@ struct RemoteNodeInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sort a list of paths by quality or priority, with best paths first.
|
/// Sort a list of paths by quality or priority, with best paths first.
|
||||||
fn prioritize_paths<Application: ApplicationLayer + ?Sized>(paths: &mut Vec<PeerPath>) {
|
fn prioritize_paths<Application: ApplicationLayer + ?Sized>(paths: &mut Vec<PeerPath<Application>>) {
|
||||||
paths.sort_unstable_by(|a, b| a.last_receive_time_ticks.cmp(&b.last_receive_time_ticks).reverse());
|
paths.sort_unstable_by(|a, b| a.last_receive_time_ticks.cmp(&b.last_receive_time_ticks).reverse());
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Peer {
|
impl<Application: ApplicationLayer + ?Sized> Peer<Application> {
|
||||||
/// Create a new peer.
|
/// Create a new peer.
|
||||||
///
|
///
|
||||||
/// This only returns None if this_node_identity does not have its secrets or if some
|
/// This only returns None if this_node_identity does not have its secrets or if some
|
||||||
|
@ -113,7 +113,7 @@ impl Peer {
|
||||||
|
|
||||||
/// Get current best path or None if there are no direct paths to this peer.
|
/// Get current best path or None if there are no direct paths to this peer.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn direct_path(&self) -> Option<Arc<Path>> {
|
pub fn direct_path(&self) -> Option<Arc<Path<Application::LocalSocket, Application::LocalInterface>>> {
|
||||||
for p in self.paths.lock().unwrap().iter() {
|
for p in self.paths.lock().unwrap().iter() {
|
||||||
let pp = p.path.upgrade();
|
let pp = p.path.upgrade();
|
||||||
if pp.is_some() {
|
if pp.is_some() {
|
||||||
|
@ -125,7 +125,7 @@ impl Peer {
|
||||||
|
|
||||||
/// Get either the current best direct path or an indirect path via e.g. a root.
|
/// Get either the current best direct path or an indirect path via e.g. a root.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn path(&self, node: &Node) -> Option<Arc<Path>> {
|
pub fn path(&self, node: &Node<Application>) -> Option<Arc<Path<Application::LocalSocket, Application::LocalInterface>>> {
|
||||||
let direct_path = self.direct_path();
|
let direct_path = self.direct_path();
|
||||||
if direct_path.is_some() {
|
if direct_path.is_some() {
|
||||||
return direct_path;
|
return direct_path;
|
||||||
|
@ -136,7 +136,7 @@ impl Peer {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn learn_path<Application: ApplicationLayer + ?Sized>(&self, app: &Application, new_path: &Arc<Path>, time_ticks: i64) {
|
fn learn_path(&self, app: &Application, new_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>, time_ticks: i64) {
|
||||||
let mut paths = self.paths.lock().unwrap();
|
let mut paths = self.paths.lock().unwrap();
|
||||||
|
|
||||||
// TODO: check path filter
|
// TODO: check path filter
|
||||||
|
@ -202,7 +202,7 @@ impl Peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called every SERVICE_INTERVAL_MS by the background service loop in Node.
|
/// Called every SERVICE_INTERVAL_MS by the background service loop in Node.
|
||||||
pub(crate) fn service<Application: ApplicationLayer + ?Sized>(&self, _: &Application, _: &Node, time_ticks: i64) -> bool {
|
pub(crate) fn service(&self, _: &Application, _: &Node<Application>, time_ticks: i64) -> bool {
|
||||||
// Prune dead paths and sort in descending order of quality.
|
// Prune dead paths and sort in descending order of quality.
|
||||||
{
|
{
|
||||||
let mut paths = self.paths.lock().unwrap();
|
let mut paths = self.paths.lock().unwrap();
|
||||||
|
@ -223,7 +223,7 @@ impl Peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a prepared and encrypted packet using the V1 protocol with fragmentation if needed.
|
/// Send a prepared and encrypted packet using the V1 protocol with fragmentation if needed.
|
||||||
fn v1_proto_internal_send<Application: ApplicationLayer + ?Sized>(
|
fn v1_proto_internal_send(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
endpoint: &Endpoint,
|
endpoint: &Endpoint,
|
||||||
|
@ -281,11 +281,11 @@ impl Peer {
|
||||||
/// The builder function must append the verb (with any verb flags) and packet payload. If it returns
|
/// The builder function must append the verb (with any verb flags) and packet payload. If it returns
|
||||||
/// an error, the error is returned immediately and the send is aborted. None is returned if the send
|
/// an error, the error is returned immediately and the send is aborted. None is returned if the send
|
||||||
/// function itself fails for some reason such as no paths being available.
|
/// function itself fails for some reason such as no paths being available.
|
||||||
pub fn send<Application: ApplicationLayer + ?Sized, R, E, BuilderFunction: FnOnce(&mut PacketBuffer) -> Result<R, E>>(
|
pub fn send<R, E, BuilderFunction: FnOnce(&mut PacketBuffer) -> Result<R, E>>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
path: Option<&Arc<Path>>,
|
path: Option<&Arc<Path<Application::LocalSocket, Application::LocalInterface>>>,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
builder_function: BuilderFunction,
|
builder_function: BuilderFunction,
|
||||||
) -> Option<Result<R, E>> {
|
) -> Option<Result<R, E>> {
|
||||||
|
@ -369,8 +369,8 @@ impl Peer {
|
||||||
self.v1_proto_internal_send(
|
self.v1_proto_internal_send(
|
||||||
app,
|
app,
|
||||||
&path.endpoint,
|
&path.endpoint,
|
||||||
Some(path.local_socket::<Application>()),
|
Some(&path.local_socket),
|
||||||
Some(path.local_interface::<Application>()),
|
Some(&path.local_interface),
|
||||||
max_fragment_size,
|
max_fragment_size,
|
||||||
packet,
|
packet,
|
||||||
);
|
);
|
||||||
|
@ -389,12 +389,7 @@ impl Peer {
|
||||||
/// Unlike other messages HELLO is sent partially in the clear and always with the long-lived
|
/// Unlike other messages HELLO is sent partially in the clear and always with the long-lived
|
||||||
/// static identity key. Authentication in old versions is via Poly1305 and in new versions
|
/// static identity key. Authentication in old versions is via Poly1305 and in new versions
|
||||||
/// via HMAC-SHA512.
|
/// via HMAC-SHA512.
|
||||||
pub(crate) fn send_hello<Application: ApplicationLayer + ?Sized>(
|
pub(crate) fn send_hello(&self, app: &Application, node: &Node<Application>, explicit_endpoint: Option<&Endpoint>) -> bool {
|
||||||
&self,
|
|
||||||
app: &Application,
|
|
||||||
node: &Node,
|
|
||||||
explicit_endpoint: Option<&Endpoint>,
|
|
||||||
) -> bool {
|
|
||||||
let mut path = None;
|
let mut path = None;
|
||||||
let destination = if let Some(explicit_endpoint) = explicit_endpoint {
|
let destination = if let Some(explicit_endpoint) = explicit_endpoint {
|
||||||
explicit_endpoint
|
explicit_endpoint
|
||||||
|
@ -454,8 +449,8 @@ impl Peer {
|
||||||
self.v1_proto_internal_send(
|
self.v1_proto_internal_send(
|
||||||
app,
|
app,
|
||||||
destination,
|
destination,
|
||||||
Some(p.local_socket::<Application>()),
|
Some(&p.local_socket),
|
||||||
Some(p.local_interface::<Application>()),
|
Some(&p.local_interface),
|
||||||
max_fragment_size,
|
max_fragment_size,
|
||||||
packet,
|
packet,
|
||||||
);
|
);
|
||||||
|
@ -473,13 +468,13 @@ impl Peer {
|
||||||
/// those fragments after the main packet header and first chunk.
|
/// those fragments after the main packet header and first chunk.
|
||||||
///
|
///
|
||||||
/// This returns true if the packet decrypted and passed authentication.
|
/// This returns true if the packet decrypted and passed authentication.
|
||||||
pub(crate) fn v1_proto_receive<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
pub(crate) fn v1_proto_receive<Inner: InnerProtocolLayer + ?Sized>(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
inner: &Inner,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
packet_header: &v1::PacketHeader,
|
packet_header: &v1::PacketHeader,
|
||||||
frag0: &PacketBuffer,
|
frag0: &PacketBuffer,
|
||||||
fragments: &[Option<PooledPacketBuffer>],
|
fragments: &[Option<PooledPacketBuffer>],
|
||||||
|
@ -539,7 +534,7 @@ impl Peer {
|
||||||
|
|
||||||
return match verb {
|
return match verb {
|
||||||
message_type::VL1_NOP => PacketHandlerResult::Ok,
|
message_type::VL1_NOP => PacketHandlerResult::Ok,
|
||||||
message_type::VL1_HELLO => self.handle_incoming_hello(app, inner, node, time_ticks, message_id, source_path, &payload),
|
message_type::VL1_HELLO => self.handle_incoming_hello(app, node, time_ticks, message_id, source_path, &payload),
|
||||||
message_type::VL1_ERROR => {
|
message_type::VL1_ERROR => {
|
||||||
self.handle_incoming_error(app, inner, node, time_ticks, source_path, packet_header.hops(), message_id, &payload)
|
self.handle_incoming_error(app, inner, node, time_ticks, source_path, packet_header.hops(), message_id, &payload)
|
||||||
}
|
}
|
||||||
|
@ -554,9 +549,9 @@ impl Peer {
|
||||||
path_is_known,
|
path_is_known,
|
||||||
&payload,
|
&payload,
|
||||||
),
|
),
|
||||||
message_type::VL1_WHOIS => self.handle_incoming_whois(app, inner, node, time_ticks, message_id, &payload),
|
message_type::VL1_WHOIS => self.handle_incoming_whois(app, node, time_ticks, message_id, &payload),
|
||||||
message_type::VL1_RENDEZVOUS => self.handle_incoming_rendezvous(app, node, time_ticks, message_id, source_path, &payload),
|
message_type::VL1_RENDEZVOUS => self.handle_incoming_rendezvous(app, node, time_ticks, message_id, source_path, &payload),
|
||||||
message_type::VL1_ECHO => self.handle_incoming_echo(app, inner, node, time_ticks, message_id, &payload),
|
message_type::VL1_ECHO => self.handle_incoming_echo(app, node, time_ticks, message_id, &payload),
|
||||||
message_type::VL1_PUSH_DIRECT_PATHS => self.handle_incoming_push_direct_paths(app, node, time_ticks, source_path, &payload),
|
message_type::VL1_PUSH_DIRECT_PATHS => self.handle_incoming_push_direct_paths(app, node, time_ticks, source_path, &payload),
|
||||||
message_type::VL1_USER_MESSAGE => self.handle_incoming_user_message(app, node, time_ticks, source_path, &payload),
|
message_type::VL1_USER_MESSAGE => self.handle_incoming_user_message(app, node, time_ticks, source_path, &payload),
|
||||||
_ => inner.handle_packet(app, node, self, &source_path, packet_header.hops(), message_id, verb, &payload, 1),
|
_ => inner.handle_packet(app, node, self, &source_path, packet_header.hops(), message_id, verb, &payload, 1),
|
||||||
|
@ -567,17 +562,16 @@ impl Peer {
|
||||||
return PacketHandlerResult::Error;
|
return PacketHandlerResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_hello<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
fn handle_incoming_hello(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
node: &Node<Application>,
|
||||||
node: &Node,
|
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
message_id: MessageId,
|
message_id: MessageId,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
if !(inner.should_respond_to(&self.identity) || node.this_node_is_root() || node.is_peer_root(self)) {
|
if !(app.should_respond_to(&self.identity) || node.this_node_is_root() || node.is_peer_root(self)) {
|
||||||
debug_event!(
|
debug_event!(
|
||||||
app,
|
app,
|
||||||
"[vl1] dropping HELLO from {} due to lack of trust relationship",
|
"[vl1] dropping HELLO from {} due to lack of trust relationship",
|
||||||
|
@ -621,13 +615,13 @@ impl Peer {
|
||||||
return PacketHandlerResult::Error;
|
return PacketHandlerResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_error<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
fn handle_incoming_error<Inner: InnerProtocolLayer + ?Sized>(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
inner: &Inner,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
_time_ticks: i64,
|
_time_ticks: i64,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
|
@ -659,13 +653,13 @@ impl Peer {
|
||||||
return PacketHandlerResult::Error;
|
return PacketHandlerResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_ok<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
fn handle_incoming_ok<Inner: InnerProtocolLayer + ?Sized>(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
inner: &Inner,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
path_is_known: bool,
|
path_is_known: bool,
|
||||||
|
@ -761,16 +755,15 @@ impl Peer {
|
||||||
return PacketHandlerResult::Error;
|
return PacketHandlerResult::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_whois<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
fn handle_incoming_whois(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
node: &Node<Application>,
|
||||||
node: &Node,
|
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
_message_id: MessageId,
|
_message_id: MessageId,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
if node.this_node_is_root() || inner.should_respond_to(&self.identity) {
|
if node.this_node_is_root() || app.should_respond_to(&self.identity) {
|
||||||
let mut addresses = payload.as_bytes();
|
let mut addresses = payload.as_bytes();
|
||||||
while addresses.len() >= ADDRESS_SIZE {
|
while addresses.len() >= ADDRESS_SIZE {
|
||||||
if !self
|
if !self
|
||||||
|
@ -794,29 +787,28 @@ impl Peer {
|
||||||
return PacketHandlerResult::Ok;
|
return PacketHandlerResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_rendezvous<Application: ApplicationLayer + ?Sized>(
|
fn handle_incoming_rendezvous(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
_app: &Application,
|
_app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
_time_ticks: i64,
|
_time_ticks: i64,
|
||||||
_message_id: MessageId,
|
_message_id: MessageId,
|
||||||
_source_path: &Arc<Path>,
|
_source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
_payload: &PacketBuffer,
|
_payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
if node.is_peer_root(self) {}
|
if node.is_peer_root(self) {}
|
||||||
return PacketHandlerResult::Ok;
|
return PacketHandlerResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_echo<Application: ApplicationLayer + ?Sized, Inner: InnerProtocolLayer + ?Sized>(
|
fn handle_incoming_echo(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
inner: &Inner,
|
node: &Node<Application>,
|
||||||
node: &Node,
|
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
message_id: MessageId,
|
message_id: MessageId,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
if inner.should_respond_to(&self.identity) || node.is_peer_root(self) {
|
if app.should_respond_to(&self.identity) || node.is_peer_root(self) {
|
||||||
self.send(app, node, None, time_ticks, |packet| {
|
self.send(app, node, None, time_ticks, |packet| {
|
||||||
let mut f: &mut OkHeader = packet.append_struct_get_mut().unwrap();
|
let mut f: &mut OkHeader = packet.append_struct_get_mut().unwrap();
|
||||||
f.verb = message_type::VL1_OK;
|
f.verb = message_type::VL1_OK;
|
||||||
|
@ -834,44 +826,44 @@ impl Peer {
|
||||||
return PacketHandlerResult::Ok;
|
return PacketHandlerResult::Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_push_direct_paths<Application: ApplicationLayer + ?Sized>(
|
fn handle_incoming_push_direct_paths(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
_app: &Application,
|
_app: &Application,
|
||||||
_node: &Node,
|
_node: &Node<Application>,
|
||||||
_time_ticks: i64,
|
_time_ticks: i64,
|
||||||
_source_path: &Arc<Path>,
|
_source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
_payload: &PacketBuffer,
|
_payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
PacketHandlerResult::Ok
|
PacketHandlerResult::Ok
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_incoming_user_message<Application: ApplicationLayer + ?Sized>(
|
fn handle_incoming_user_message(
|
||||||
self: &Arc<Self>,
|
self: &Arc<Self>,
|
||||||
_app: &Application,
|
_app: &Application,
|
||||||
_node: &Node,
|
_node: &Node<Application>,
|
||||||
_time_ticks: i64,
|
_time_ticks: i64,
|
||||||
_source_path: &Arc<Path>,
|
_source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
_payload: &PacketBuffer,
|
_payload: &PacketBuffer,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
PacketHandlerResult::Ok
|
PacketHandlerResult::Ok
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash for Peer {
|
impl<Application: ApplicationLayer + ?Sized> Hash for Peer<Application> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
state.write_u64(self.identity.address.into());
|
state.write_u64(self.identity.address.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialEq for Peer {
|
impl<Application: ApplicationLayer + ?Sized> PartialEq for Peer<Application> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.identity.fingerprint.eq(&other.identity.fingerprint)
|
self.identity.fingerprint.eq(&other.identity.fingerprint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Eq for Peer {}
|
impl<Application: ApplicationLayer + ?Sized> Eq for Peer<Application> {}
|
||||||
|
|
||||||
fn v1_proto_try_aead_decrypt(
|
fn v1_proto_try_aead_decrypt(
|
||||||
secret: &v1::SymmetricSecret,
|
secret: &v1::SymmetricSecret,
|
||||||
|
|
|
@ -3,19 +3,13 @@ use std::sync::{Arc, Mutex, RwLock};
|
||||||
|
|
||||||
use crate::protocol;
|
use crate::protocol;
|
||||||
use crate::protocol::PacketBuffer;
|
use crate::protocol::PacketBuffer;
|
||||||
use crate::vl1::{Address, ApplicationLayer, Identity, Node, PacketHandlerResult, Peer, MAC};
|
use crate::vl1::*;
|
||||||
use crate::vl2::{MulticastGroup, NetworkId};
|
use crate::vl2::{MulticastGroup, NetworkId};
|
||||||
|
|
||||||
use zerotier_utils::buffer::OutOfBoundsError;
|
use zerotier_utils::buffer::OutOfBoundsError;
|
||||||
use zerotier_utils::sync::RMaybeWLockGuard;
|
use zerotier_utils::sync::RMaybeWLockGuard;
|
||||||
|
|
||||||
/// Handler implementations for VL2_MULTICAST_LIKE and VL2_MULTICAST_GATHER.
|
/// Handler implementations for VL2_MULTICAST_LIKE and VL2_MULTICAST_GATHER.
|
||||||
///
|
|
||||||
/// Both controllers and roots will want to handle these, with the latter supporting them for legacy
|
|
||||||
/// reasons only. Regular nodes may also want to handle them in the future. So, break this out to allow
|
|
||||||
/// easy code reuse. To integrate call the appropriate method when the appropriate message type is
|
|
||||||
/// received and pass in a function to check whether specific network/identity combinations should be
|
|
||||||
/// processed. The GATHER implementation will send reply packets to the source peer.
|
|
||||||
pub struct MulticastAuthority {
|
pub struct MulticastAuthority {
|
||||||
subscriptions: RwLock<HashMap<(NetworkId, MulticastGroup), Mutex<HashMap<Address, i64>>>>,
|
subscriptions: RwLock<HashMap<(NetworkId, MulticastGroup), Mutex<HashMap<Address, i64>>>>,
|
||||||
}
|
}
|
||||||
|
@ -47,11 +41,11 @@ impl MulticastAuthority {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call for VL2_MULTICAST_LIKE packets.
|
/// Call for VL2_MULTICAST_LIKE packets.
|
||||||
pub fn handle_vl2_multicast_like<Authenticator: Fn(NetworkId, &Identity) -> bool>(
|
pub fn handle_vl2_multicast_like<Application: ApplicationLayer + ?Sized, Authenticator: Fn(NetworkId, &Identity) -> bool>(
|
||||||
&self,
|
&self,
|
||||||
auth: Authenticator,
|
auth: Authenticator,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
mut cursor: usize,
|
mut cursor: usize,
|
||||||
) -> PacketHandlerResult {
|
) -> PacketHandlerResult {
|
||||||
|
@ -84,13 +78,13 @@ impl MulticastAuthority {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call for VL2_MULTICAST_GATHER packets.
|
/// Call for VL2_MULTICAST_GATHER packets.
|
||||||
pub fn handle_vl2_multicast_gather<HostSystemImpl: ApplicationLayer + ?Sized, Authenticator: Fn(NetworkId, &Identity) -> bool>(
|
pub fn handle_vl2_multicast_gather<Application: ApplicationLayer + ?Sized, Authenticator: Fn(NetworkId, &Identity) -> bool>(
|
||||||
&self,
|
&self,
|
||||||
auth: Authenticator,
|
auth: Authenticator,
|
||||||
time_ticks: i64,
|
time_ticks: i64,
|
||||||
host_system: &HostSystemImpl,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
payload: &PacketBuffer,
|
payload: &PacketBuffer,
|
||||||
mut cursor: usize,
|
mut cursor: usize,
|
||||||
|
@ -114,7 +108,7 @@ impl MulticastAuthority {
|
||||||
}
|
}
|
||||||
|
|
||||||
while !gathered.is_empty() {
|
while !gathered.is_empty() {
|
||||||
source.send(host_system, node, None, time_ticks, |packet| -> Result<(), OutOfBoundsError> {
|
source.send(app, node, None, time_ticks, |packet| -> Result<(), OutOfBoundsError> {
|
||||||
let ok_header = packet.append_struct_get_mut::<protocol::OkHeader>()?;
|
let ok_header = packet.append_struct_get_mut::<protocol::OkHeader>()?;
|
||||||
ok_header.verb = protocol::message_type::VL1_OK;
|
ok_header.verb = protocol::message_type::VL1_OK;
|
||||||
ok_header.in_re_verb = protocol::message_type::VL2_MULTICAST_GATHER;
|
ok_header.in_re_verb = protocol::message_type::VL2_MULTICAST_GATHER;
|
||||||
|
|
|
@ -14,9 +14,9 @@ impl InnerProtocolLayer for Switch {
|
||||||
fn handle_packet<Application: ApplicationLayer + ?Sized>(
|
fn handle_packet<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
verb: u8,
|
verb: u8,
|
||||||
|
@ -29,9 +29,9 @@ impl InnerProtocolLayer for Switch {
|
||||||
fn handle_error<Application: ApplicationLayer + ?Sized>(
|
fn handle_error<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
in_re_verb: u8,
|
in_re_verb: u8,
|
||||||
|
@ -46,9 +46,9 @@ impl InnerProtocolLayer for Switch {
|
||||||
fn handle_ok<Application: ApplicationLayer + ?Sized>(
|
fn handle_ok<Application: ApplicationLayer + ?Sized>(
|
||||||
&self,
|
&self,
|
||||||
app: &Application,
|
app: &Application,
|
||||||
node: &Node,
|
node: &Node<Application>,
|
||||||
source: &Arc<Peer>,
|
source: &Arc<Peer<Application>>,
|
||||||
source_path: &Arc<Path>,
|
source_path: &Arc<Path<Application::LocalSocket, Application::LocalInterface>>,
|
||||||
source_hops: u8,
|
source_hops: u8,
|
||||||
message_id: u64,
|
message_id: u64,
|
||||||
in_re_verb: u8,
|
in_re_verb: u8,
|
||||||
|
|
33
utils/src/cast.rs
Normal file
33
utils/src/cast.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* (c) ZeroTier, Inc.
|
||||||
|
* https://www.zerotier.com/
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::any::TypeId;
|
||||||
|
use std::mem::size_of;
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn same_type<U: 'static, V: 'static>() -> bool {
|
||||||
|
TypeId::of::<U>() == TypeId::of::<V>() && size_of::<U>() == size_of::<V>()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn cast_ref<U: 'static, V: 'static>(u: &U) -> Option<&V> {
|
||||||
|
if same_type::<U, V>() {
|
||||||
|
Some(unsafe { std::mem::transmute::<&U, &V>(u) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn cast_mut<U: 'static, V: 'static>(u: &mut U) -> Option<&mut V> {
|
||||||
|
if same_type::<U, V>() {
|
||||||
|
Some(unsafe { std::mem::transmute::<&mut U, &mut V>(u) })
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
|
@ -33,36 +33,3 @@ impl<const FREQ: i64> IntervalGate<FREQ> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Boolean rate limiter with atomic semantics.
|
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct AtomicIntervalGate<const FREQ: i64>(AtomicI64);
|
|
||||||
|
|
||||||
impl<const FREQ: i64> Default for AtomicIntervalGate<FREQ> {
|
|
||||||
#[inline(always)]
|
|
||||||
fn default() -> Self {
|
|
||||||
Self(AtomicI64::new(crate::util::NEVER_HAPPENED_TICKS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<const FREQ: i64> AtomicIntervalGate<FREQ> {
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn new(initial_ts: i64) -> Self {
|
|
||||||
Self(AtomicI64::new(initial_ts))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
#[allow(unused)]
|
|
||||||
pub fn gate(&self, mut time: i64) -> bool {
|
|
||||||
let prev_time = self.0.load(Ordering::Acquire);
|
|
||||||
if (time - prev_time) < FREQ {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
self.0.store(time, Ordering::Release);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
pub mod arrayvec;
|
pub mod arrayvec;
|
||||||
pub mod blob;
|
pub mod blob;
|
||||||
pub mod buffer;
|
pub mod buffer;
|
||||||
|
pub mod cast;
|
||||||
pub mod defer;
|
pub mod defer;
|
||||||
pub mod dictionary;
|
pub mod dictionary;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
@ -26,7 +27,6 @@ pub mod pool;
|
||||||
pub mod reaper;
|
pub mod reaper;
|
||||||
pub mod ringbuffer;
|
pub mod ringbuffer;
|
||||||
pub mod sync;
|
pub mod sync;
|
||||||
pub mod thing;
|
|
||||||
pub mod varint;
|
pub mod varint;
|
||||||
|
|
||||||
#[cfg(feature = "tokio")]
|
#[cfg(feature = "tokio")]
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub struct VL1Service<Inner: InnerProtocolLayer + ?Sized + 'static> {
|
||||||
vl1_data_storage: Arc<dyn VL1DataStorage>,
|
vl1_data_storage: Arc<dyn VL1DataStorage>,
|
||||||
inner: Arc<Inner>,
|
inner: Arc<Inner>,
|
||||||
buffer_pool: Arc<PacketBufferPool>,
|
buffer_pool: Arc<PacketBufferPool>,
|
||||||
node_container: Option<Node>, // never None, set in new()
|
node_container: Option<Node<Self>>, // never None, set in new()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VL1ServiceMutableState {
|
struct VL1ServiceMutableState {
|
||||||
|
@ -79,7 +79,7 @@ impl<Inner: InnerProtocolLayer + ?Sized + 'static> VL1Service<Inner> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn node(&self) -> &Node {
|
pub fn node(&self) -> &Node<Self> {
|
||||||
debug_assert!(self.node_container.is_some());
|
debug_assert!(self.node_container.is_some());
|
||||||
unsafe { self.node_container.as_ref().unwrap_unchecked() }
|
unsafe { self.node_container.as_ref().unwrap_unchecked() }
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,12 @@ impl<Inner: InnerProtocolLayer + ?Sized + 'static> ApplicationLayer for VL1Servi
|
||||||
socket.is_valid()
|
socket.is_valid()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn should_respond_to(&self, _: &Valid<Identity>) -> bool {
|
||||||
|
// TODO: provide a way for the user of VL1Service to control this
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn load_node_identity(&self) -> Option<Valid<Identity>> {
|
fn load_node_identity(&self) -> Option<Valid<Identity>> {
|
||||||
self.vl1_data_storage.load_node_identity()
|
self.vl1_data_storage.load_node_identity()
|
||||||
|
|
Loading…
Add table
Reference in a new issue