mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-26 17:03:43 +02:00
Make sure endpoint sorting is stable forever, and some Locator stuff.
This commit is contained in:
parent
653a6dcf3c
commit
faecf04dd5
2 changed files with 159 additions and 2 deletions
|
@ -3,6 +3,7 @@ use std::hash::{Hash, Hasher};
|
|||
use crate::vl1::{Address, MAC};
|
||||
use crate::vl1::inetaddress::InetAddress;
|
||||
use crate::vl1::buffer::Buffer;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
const TYPE_NIL: u8 = 0;
|
||||
const TYPE_ZEROTIER: u8 = 1;
|
||||
|
@ -15,6 +16,7 @@ const TYPE_IPTCP: u8 = 7;
|
|||
const TYPE_HTTP: u8 = 8;
|
||||
const TYPE_WEBRTC: u8 = 9;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[repr(u8)]
|
||||
pub enum Type {
|
||||
Nil = TYPE_NIL,
|
||||
|
@ -29,7 +31,7 @@ pub enum Type {
|
|||
WebRTC = TYPE_WEBRTC,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub enum Endpoint {
|
||||
Nil,
|
||||
ZeroTier(Address),
|
||||
|
@ -206,6 +208,119 @@ impl Hash for Endpoint {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Endpoint {
|
||||
#[inline(always)]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Endpoint {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
// This ordering is done explicitly instead of using derive() so it will be certain
|
||||
// to be consistent with the integer order in the Type enum. Make sure it stays this
|
||||
// way if new types are added in future revisions.
|
||||
match self {
|
||||
Endpoint::Nil => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Equal,
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::ZeroTier(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::Ethernet(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::WifiDirect(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::Bluetooth(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(_) => Ordering::Less,
|
||||
Endpoint::Bluetooth(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::Ip(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(_) => Ordering::Less,
|
||||
Endpoint::Bluetooth(_) => Ordering::Less,
|
||||
Endpoint::Ip(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::IpUdp(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(_) => Ordering::Less,
|
||||
Endpoint::Bluetooth(_) => Ordering::Less,
|
||||
Endpoint::Ip(_) => Ordering::Less,
|
||||
Endpoint::IpUdp(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::IpTcp(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(_) => Ordering::Less,
|
||||
Endpoint::Bluetooth(_) => Ordering::Less,
|
||||
Endpoint::Ip(_) => Ordering::Less,
|
||||
Endpoint::IpUdp(_) => Ordering::Less,
|
||||
Endpoint::IpTcp(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::Http(a) => {
|
||||
match other {
|
||||
Endpoint::Nil => Ordering::Less,
|
||||
Endpoint::ZeroTier(_) => Ordering::Less,
|
||||
Endpoint::Ethernet(_) => Ordering::Less,
|
||||
Endpoint::WifiDirect(_) => Ordering::Less,
|
||||
Endpoint::Bluetooth(_) => Ordering::Less,
|
||||
Endpoint::Ip(_) => Ordering::Less,
|
||||
Endpoint::IpUdp(_) => Ordering::Less,
|
||||
Endpoint::IpTcp(_) => Ordering::Less,
|
||||
Endpoint::Http(b) => a.cmp(b),
|
||||
_ => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
Endpoint::WebRTC(a) => {
|
||||
match other {
|
||||
Endpoint::WebRTC(b) => a.cmp(b),
|
||||
_ => Ordering::Less,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToString for Endpoint {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
|
|
|
@ -1 +1,43 @@
|
|||
pub struct Locator;
|
||||
use crate::vl1::{Endpoint, Address, Identity};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
/// A signed object generated by nodes to inform the network where they may be found.
|
||||
///
|
||||
/// By default this will just enumerate the roots used by this node, but nodes with
|
||||
/// static IPs can also list physical IP/port addresses where they can be reached with
|
||||
/// no involvement from a root at all.
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Locator {
|
||||
pub(crate) signer: Address,
|
||||
pub(crate) timestamp: i64,
|
||||
pub(crate) endpoints: Vec<Endpoint>,
|
||||
pub(crate) signature: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Locator {
|
||||
pub fn create(id: &Identity, ts: i64, endpoints: &[Endpoint]) -> Option<Locator> {
|
||||
let mut loc = Locator {
|
||||
signer: id.address(),
|
||||
timestamp: ts,
|
||||
endpoints: endpoints.to_vec(),
|
||||
signature: Vec::new()
|
||||
};
|
||||
loc.endpoints.sort_unstable();
|
||||
loc.endpoints.dedup();
|
||||
Some(loc)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Locator {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
if !self.signature.is_empty() {
|
||||
state.write(self.signature.as_slice());
|
||||
} else {
|
||||
state.write_u64(self.signer.to_u64());
|
||||
state.write_i64(self.timestamp);
|
||||
for e in self.endpoints.iter() {
|
||||
e.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue