mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-05-02 11:53: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::{Address, MAC};
|
||||||
use crate::vl1::inetaddress::InetAddress;
|
use crate::vl1::inetaddress::InetAddress;
|
||||||
use crate::vl1::buffer::Buffer;
|
use crate::vl1::buffer::Buffer;
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
const TYPE_NIL: u8 = 0;
|
const TYPE_NIL: u8 = 0;
|
||||||
const TYPE_ZEROTIER: u8 = 1;
|
const TYPE_ZEROTIER: u8 = 1;
|
||||||
|
@ -15,6 +16,7 @@ const TYPE_IPTCP: u8 = 7;
|
||||||
const TYPE_HTTP: u8 = 8;
|
const TYPE_HTTP: u8 = 8;
|
||||||
const TYPE_WEBRTC: u8 = 9;
|
const TYPE_WEBRTC: u8 = 9;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
Nil = TYPE_NIL,
|
Nil = TYPE_NIL,
|
||||||
|
@ -29,7 +31,7 @@ pub enum Type {
|
||||||
WebRTC = TYPE_WEBRTC,
|
WebRTC = TYPE_WEBRTC,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub enum Endpoint {
|
pub enum Endpoint {
|
||||||
Nil,
|
Nil,
|
||||||
ZeroTier(Address),
|
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 {
|
impl ToString for Endpoint {
|
||||||
fn to_string(&self) -> String {
|
fn to_string(&self) -> String {
|
||||||
match self {
|
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