Network ID object and some more cleanup.

This commit is contained in:
Adam Ierymenko 2022-04-27 16:02:10 -04:00
parent 6e55419581
commit 85b5f0c5e0
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
5 changed files with 148 additions and 13 deletions

View file

@ -6,9 +6,6 @@
* https://www.zerotier.com/
*/
#[macro_use]
extern crate lazy_static;
pub const VERSION_MAJOR: u8 = 1;
pub const VERSION_MINOR: u8 = 99;
pub const VERSION_REVISION: u8 = 1;

View file

@ -406,17 +406,8 @@ impl InetAddress {
}
/// Get the address family of this InetAddress: AF_INET, AF_INET6, or 0 if uninitialized.
#[inline(always)]
#[cfg(not(target_os = "linux"))]
pub fn family(&self) -> u8 {
unsafe { self.sa.sa_family }
}
/// Get the address family of this InetAddress: AF_INET, AF_INET6, or 0 if uninitialized.
#[inline(always)]
#[cfg(target_os = "linux")]
pub fn family(&self) -> u16 {
unsafe { self.sa.sa_family }
unsafe { self.sa.sa_family as u8 }
}
/// Get a pointer to the C "sockaddr" structure and the size of the returned structure in bytes.

View file

@ -12,6 +12,7 @@ use std::num::NonZeroI64;
use std::sync::atomic::{AtomicI64, Ordering};
use std::sync::Arc;
use lazy_static::lazy_static;
use parking_lot::Mutex;
use zerotier_core_crypto::hash::SHA384_HASH_SIZE;

View file

@ -7,7 +7,9 @@
*/
mod multicastgroup;
mod networkid;
mod switch;
pub use multicastgroup::MulticastGroup;
pub use networkid::NetworkId;
pub use switch::{Switch, SwitchInterface};

View file

@ -0,0 +1,144 @@
/* 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)2021 ZeroTier, Inc.
* https://www.zerotier.com/
*/
use std::hash::{Hash, Hasher};
use std::num::NonZeroU64;
use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::error::InvalidFormatError;
use crate::util::buffer::Buffer;
use crate::util::hex::HEX_CHARS;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct NetworkId(NonZeroU64);
impl NetworkId {
/// Get an address from a 64-bit integer or return None if it is zero or reserved.
#[inline(always)]
pub fn from_u64(i: u64) -> Option<NetworkId> {
NonZeroU64::new(i).map(|i| Self(i))
}
#[inline(always)]
pub fn from_bytes(b: &[u8]) -> Option<NetworkId> {
if b.len() >= 8 {
Self::from_bytes_fixed(b[0..8].try_into().unwrap())
} else {
None
}
}
#[inline(always)]
pub fn from_bytes_fixed(b: &[u8; 8]) -> Option<NetworkId> {
Self::from_u64(u64::from_be_bytes(*b))
}
#[inline(always)]
pub fn to_bytes(&self) -> [u8; 8] {
self.0.get().to_be_bytes()
}
#[inline(always)]
pub fn to_u64(&self) -> u64 {
self.0.get()
}
#[inline(always)]
pub(crate) fn marshal<const BL: usize>(&self, buf: &mut Buffer<BL>) -> std::io::Result<()> {
buf.append_u64(self.0.get())
}
#[inline(always)]
pub(crate) fn unmarshal<const BL: usize>(buf: &Buffer<BL>, cursor: &mut usize) -> std::io::Result<Option<Self>> {
Ok(Self::from_u64(buf.read_u64(cursor)?))
}
}
impl ToString for NetworkId {
fn to_string(&self) -> String {
let mut v = self.0.get();
let mut s = String::with_capacity(16);
for _ in 0..16 {
s.push(HEX_CHARS[(v >> 60) as usize] as char);
v <<= 4;
}
s
}
}
impl FromStr for NetworkId {
type Err = InvalidFormatError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
NetworkId::from_bytes(crate::util::hex::from_string(s).as_slice()).map_or_else(|| Err(InvalidFormatError), |a| Ok(a))
}
}
impl Hash for NetworkId {
#[inline(always)]
fn hash<H: Hasher>(&self, state: &mut H) {
state.write_u64(self.0.get());
}
}
impl Serialize for NetworkId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if serializer.is_human_readable() {
serializer.serialize_str(self.to_string().as_str())
} else {
serializer.serialize_bytes(&self.to_bytes())
}
}
}
struct NetworkIdVisitor;
impl<'de> serde::de::Visitor<'de> for NetworkIdVisitor {
type Value = NetworkId;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a ZeroTier network ID")
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
if v.len() == 8 {
NetworkId::from_bytes(v).map_or_else(|| Err(E::custom("object too large")), |a| Ok(a))
} else {
Err(E::custom("object too large"))
}
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
NetworkId::from_str(v).map_err(|e| E::custom(e.to_string()))
}
}
impl<'de> Deserialize<'de> for NetworkId {
fn deserialize<D>(deserializer: D) -> Result<NetworkId, D::Error>
where
D: Deserializer<'de>,
{
if deserializer.is_human_readable() {
deserializer.deserialize_str(NetworkIdVisitor)
} else {
deserializer.deserialize_bytes(NetworkIdVisitor)
}
}
}