mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-06-05 20:13:44 +02:00
Tetanus adam (#1906)
* Move some stuff around in prep for a VL2 rework and identity rework. * Mix ephemeral keys into "h" * More topology stuff for VL2. * Simplify key queue, fix macOS issues with bindings, and no need to cache PSK forever. * Some more merge fixes. * A bunch of ZSSP cleanup and optimization. Runs a bit faster now.
This commit is contained in:
parent
f2e2944658
commit
f66a2a7ef9
20 changed files with 610 additions and 407 deletions
|
@ -12,8 +12,9 @@ use zerotier_network_hypervisor::protocol::{PacketBuffer, DEFAULT_MULTICAST_LIMI
|
|||
use zerotier_network_hypervisor::vl1::*;
|
||||
use zerotier_network_hypervisor::vl2;
|
||||
use zerotier_network_hypervisor::vl2::multicastauthority::MulticastAuthority;
|
||||
use zerotier_network_hypervisor::vl2::networkconfig::*;
|
||||
use zerotier_network_hypervisor::vl2::{NetworkId, Revocation};
|
||||
use zerotier_network_hypervisor::vl2::v1::networkconfig::*;
|
||||
use zerotier_network_hypervisor::vl2::v1::Revocation;
|
||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||
use zerotier_utils::blob::Blob;
|
||||
use zerotier_utils::buffer::OutOfBoundsError;
|
||||
use zerotier_utils::error::InvalidParameterError;
|
||||
|
|
|
@ -11,7 +11,7 @@ use std::collections::HashMap;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use zerotier_network_hypervisor::vl1::{Address, Endpoint};
|
||||
use zerotier_network_hypervisor::vl2::networkconfig::NetworkConfig;
|
||||
use zerotier_network_hypervisor::vl2::v1::networkconfig::NetworkConfig;
|
||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||
use zerotier_utils::blob::Blob;
|
||||
|
||||
|
|
|
@ -6,9 +6,8 @@ use std::hash::Hash;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use zerotier_network_hypervisor::vl1::InetAddress;
|
||||
use zerotier_network_hypervisor::vl2::networkconfig::IpRoute;
|
||||
use zerotier_network_hypervisor::vl2::rule::Rule;
|
||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||
use zerotier_network_hypervisor::vl2::{IpRoute, NetworkId};
|
||||
|
||||
use crate::database::Database;
|
||||
use crate::model::Member;
|
||||
|
|
|
@ -13,9 +13,8 @@ use zerotier_crypto::secure_eq;
|
|||
use zerotier_crypto::typestate::Valid;
|
||||
|
||||
use zerotier_network_hypervisor::vl1::{Address, Identity, InetAddress};
|
||||
use zerotier_network_hypervisor::vl2::networkconfig::IpRoute;
|
||||
use zerotier_network_hypervisor::vl2::rule::Rule;
|
||||
use zerotier_network_hypervisor::vl2::NetworkId;
|
||||
use zerotier_network_hypervisor::vl2::{IpRoute, NetworkId};
|
||||
|
||||
use zerotier_utils::futures_util::{Stream, StreamExt};
|
||||
use zerotier_utils::tokio;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// MacOS implementation of AES primitives since CommonCrypto seems to be faster than OpenSSL, especially on ARM64.
|
||||
use std::os::raw::{c_int, c_void};
|
||||
use std::ptr::{null, null_mut};
|
||||
use std::sync::Mutex;
|
||||
use std::sync::atomic::AtomicPtr;
|
||||
|
||||
use crate::secret::Secret;
|
||||
use crate::secure_eq;
|
||||
|
@ -172,14 +172,26 @@ impl AesGcm<false> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct Aes(Mutex<*mut c_void>, Mutex<*mut c_void>);
|
||||
pub struct Aes(AtomicPtr<c_void>, AtomicPtr<c_void>);
|
||||
|
||||
impl Drop for Aes {
|
||||
#[inline(always)]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
CCCryptorRelease(*self.0.lock().unwrap());
|
||||
CCCryptorRelease(*self.1.lock().unwrap());
|
||||
loop {
|
||||
let p = self.0.load(std::sync::atomic::Ordering::Acquire);
|
||||
if !p.is_null() {
|
||||
CCCryptorRelease(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
loop {
|
||||
let p = self.1.load(std::sync::atomic::Ordering::Acquire);
|
||||
if !p.is_null() {
|
||||
CCCryptorRelease(p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +203,7 @@ impl Aes {
|
|||
KEY_SIZE == 32 || KEY_SIZE == 24 || KEY_SIZE == 16,
|
||||
"AES supports 128, 192, or 256 bits keys"
|
||||
);
|
||||
let aes: Self = std::mem::zeroed();
|
||||
let (mut p0, mut p1) = (null_mut(), null_mut());
|
||||
assert_eq!(
|
||||
CCCryptorCreateWithMode(
|
||||
kCCEncrypt,
|
||||
|
@ -205,7 +217,7 @@ impl Aes {
|
|||
0,
|
||||
0,
|
||||
kCCOptionECBMode,
|
||||
&mut *aes.0.lock().unwrap()
|
||||
&mut p0,
|
||||
),
|
||||
0
|
||||
);
|
||||
|
@ -222,11 +234,11 @@ impl Aes {
|
|||
0,
|
||||
0,
|
||||
kCCOptionECBMode,
|
||||
&mut *aes.1.lock().unwrap()
|
||||
&mut p1,
|
||||
),
|
||||
0
|
||||
);
|
||||
aes
|
||||
Self(AtomicPtr::new(p0), AtomicPtr::new(p1))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,8 +247,16 @@ impl Aes {
|
|||
assert_eq!(data.len(), 16);
|
||||
unsafe {
|
||||
let mut data_out_written = 0;
|
||||
let e = self.0.lock().unwrap();
|
||||
CCCryptorUpdate(*e, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
|
||||
loop {
|
||||
let p = self.0.load(std::sync::atomic::Ordering::Acquire);
|
||||
if !p.is_null() {
|
||||
CCCryptorUpdate(p, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
|
||||
self.0.store(p, std::sync::atomic::Ordering::Release);
|
||||
break;
|
||||
} else {
|
||||
std::thread::yield_now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,8 +265,16 @@ impl Aes {
|
|||
assert_eq!(data.len(), 16);
|
||||
unsafe {
|
||||
let mut data_out_written = 0;
|
||||
let d = self.1.lock().unwrap();
|
||||
CCCryptorUpdate(*d, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
|
||||
loop {
|
||||
let p = self.1.load(std::sync::atomic::Ordering::Acquire);
|
||||
if !p.is_null() {
|
||||
CCCryptorUpdate(p, data.as_ptr().cast(), 16, data.as_mut_ptr().cast(), 16, &mut data_out_written);
|
||||
self.1.store(p, std::sync::atomic::Ordering::Release);
|
||||
break;
|
||||
} else {
|
||||
std::thread::yield_now();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,6 +125,7 @@ impl Aes {
|
|||
let ptr = data.as_mut_ptr();
|
||||
unsafe { self.0.update::<true>(data, ptr).unwrap() }
|
||||
}
|
||||
|
||||
/// Do not ever encrypt the same plaintext twice. Make sure data is always different between calls.
|
||||
#[inline(always)]
|
||||
pub fn decrypt_block_in_place(&self, data: &mut [u8]) {
|
||||
|
|
|
@ -109,6 +109,7 @@ impl CipherCtxRef {
|
|||
}
|
||||
|
||||
/// Sets the authentication tag for verification during decryption.
|
||||
#[allow(unused)]
|
||||
pub fn set_tag(&self, tag: &[u8]) -> Result<(), ErrorStack> {
|
||||
unsafe {
|
||||
cvt(ffi::EVP_CIPHER_CTX_ctrl(
|
||||
|
|
|
@ -14,10 +14,13 @@ pub mod salsa;
|
|||
pub mod typestate;
|
||||
pub mod x25519;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod aes_fruity;
|
||||
pub mod aes_openssl;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use aes_fruity as aes;
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub mod aes_openssl;
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
pub use aes_openssl as aes;
|
||||
|
||||
|
|
17
network-hypervisor/src/vl2/iproute.rs
Normal file
17
network-hypervisor/src/vl2/iproute.rs
Normal file
|
@ -0,0 +1,17 @@
|
|||
use crate::vl1::InetAddress;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// ZeroTier-managed L3 route on a virtual network.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct IpRoute {
|
||||
pub target: InetAddress,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub via: Option<InetAddress>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub flags: Option<u16>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub metric: Option<u16>,
|
||||
}
|
|
@ -1,16 +1,16 @@
|
|||
// (c) 2020-2022 ZeroTier, Inc. -- currently proprietary pending actual release and licensing. See LICENSE.md.
|
||||
|
||||
mod iproute;
|
||||
mod multicastgroup;
|
||||
mod networkid;
|
||||
mod revocation;
|
||||
mod switch;
|
||||
mod topology;
|
||||
|
||||
pub mod multicastauthority;
|
||||
pub mod networkconfig;
|
||||
pub mod rule;
|
||||
pub mod v1;
|
||||
|
||||
pub use iproute::IpRoute;
|
||||
pub use multicastgroup::MulticastGroup;
|
||||
pub use networkid::NetworkId;
|
||||
pub use revocation::Revocation;
|
||||
pub use switch::{Switch, SwitchInterface};
|
||||
|
|
61
network-hypervisor/src/vl2/topology.rs
Normal file
61
network-hypervisor/src/vl2/topology.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use zerotier_utils::blob::Blob;
|
||||
use zerotier_utils::flatsortedmap::FlatSortedMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::vl1::identity::IDENTITY_FINGERPRINT_SIZE;
|
||||
use crate::vl1::inetaddress::InetAddress;
|
||||
use crate::vl2::rule::Rule;
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone)]
|
||||
pub struct Member<'a> {
|
||||
#[serde(skip_serializing_if = "u64_zero")]
|
||||
#[serde(default)]
|
||||
pub flags: u64,
|
||||
|
||||
#[serde(skip_serializing_if = "cow_str_is_empty")]
|
||||
#[serde(default)]
|
||||
pub name: Cow<'a, str>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Eq, PartialEq, Clone)]
|
||||
pub struct Topology<'a> {
|
||||
pub timestamp: i64,
|
||||
|
||||
#[serde(skip_serializing_if = "cow_str_is_empty")]
|
||||
#[serde(default)]
|
||||
pub name: Cow<'a, str>,
|
||||
|
||||
#[serde(skip_serializing_if = "slice_is_empty")]
|
||||
#[serde(default)]
|
||||
pub rules: Cow<'a, [Rule]>,
|
||||
|
||||
#[serde(skip_serializing_if = "FlatSortedMap::is_empty")]
|
||||
#[serde(default)]
|
||||
pub dns_resolvers: FlatSortedMap<'a, Cow<'a, str>, InetAddress>,
|
||||
|
||||
#[serde(skip_serializing_if = "FlatSortedMap::is_empty")]
|
||||
#[serde(default)]
|
||||
pub dns_names: FlatSortedMap<'a, Cow<'a, str>, InetAddress>,
|
||||
|
||||
#[serde(skip_serializing_if = "FlatSortedMap::is_empty")]
|
||||
#[serde(default)]
|
||||
pub members: FlatSortedMap<'a, Blob<IDENTITY_FINGERPRINT_SIZE>, Member<'a>>,
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn u64_zero(i: &u64) -> bool {
|
||||
*i == 0
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn cow_str_is_empty<'a>(s: &Cow<'a, str>) -> bool {
|
||||
s.is_empty()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn slice_is_empty<T, S: AsRef<[T]>>(x: &S) -> bool {
|
||||
x.as_ref().is_empty()
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
mod certificateofmembership;
|
||||
mod certificateofownership;
|
||||
pub mod networkconfig;
|
||||
mod revocation;
|
||||
mod tag;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
@ -15,4 +17,5 @@ pub enum CredentialType {
|
|||
|
||||
pub use certificateofmembership::CertificateOfMembership;
|
||||
pub use certificateofownership::{CertificateOfOwnership, Thing};
|
||||
pub use revocation::Revocation;
|
||||
pub use tag::Tag;
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::str::FromStr;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::vl1::{Address, Identity, InetAddress};
|
||||
use crate::vl2::iproute::IpRoute;
|
||||
use crate::vl2::rule::Rule;
|
||||
use crate::vl2::v1::{CertificateOfMembership, CertificateOfOwnership, Tag};
|
||||
use crate::vl2::NetworkId;
|
||||
|
@ -30,11 +31,6 @@ pub struct NetworkConfig {
|
|||
#[serde(default)]
|
||||
pub name: String,
|
||||
|
||||
/// A human-readable message for members of this network (V2 only)
|
||||
#[serde(skip_serializing_if = "String::is_empty")]
|
||||
#[serde(default)]
|
||||
pub motd: String,
|
||||
|
||||
/// True if network has access control (the default)
|
||||
pub private: bool,
|
||||
|
||||
|
@ -94,7 +90,6 @@ impl NetworkConfig {
|
|||
network_id,
|
||||
issued_to,
|
||||
name: String::new(),
|
||||
motd: String::new(),
|
||||
private: true,
|
||||
timestamp: 0,
|
||||
mtu: 0,
|
||||
|
@ -436,21 +431,6 @@ pub struct V1Credentials {
|
|||
pub tags: HashMap<u32, Tag>,
|
||||
}
|
||||
|
||||
/// Statically pushed L3 IP routes included with a network configuration.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct IpRoute {
|
||||
pub target: InetAddress,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub via: Option<InetAddress>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub flags: Option<u16>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
#[serde(default)]
|
||||
pub metric: Option<u16>,
|
||||
}
|
||||
|
||||
impl Marshalable for IpRoute {
|
||||
const MAX_MARSHAL_SIZE: usize = (InetAddress::MAX_MARSHAL_SIZE * 2) + 2 + 2;
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
use serde::ser::SerializeTuple;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
@ -72,6 +73,27 @@ impl<const L: usize> ToString for Blob<L> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> PartialOrd for Blob<L> {
|
||||
#[inline(always)]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
self.0.partial_cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> Ord for Blob<L> {
|
||||
#[inline(always)]
|
||||
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
|
||||
self.0.cmp(&other.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> Hash for Blob<L> {
|
||||
#[inline(always)]
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.0.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl<const L: usize> Debug for Blob<L> {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -118,7 +140,7 @@ impl<'de, const L: usize> serde::de::Visitor<'de> for BlobVisitor<L> {
|
|||
|
||||
impl<'de, const L: usize> Deserialize<'de> for Blob<L> {
|
||||
#[inline]
|
||||
fn deserialize<D>(deserializer: D) -> Result<Blob<L>, D::Error>
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
|
|
86
utils/src/flatsortedmap.rs
Normal file
86
utils/src/flatsortedmap.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
/* 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::borrow::Cow;
|
||||
use std::iter::{FromIterator, Iterator};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A simple flat sorted map backed by a vector and binary search.
|
||||
///
|
||||
/// This doesn't support gradual adding of keys or removal of keys, but only construction
|
||||
/// from an iterator of keys and values. It also implements Serialize and Deserialize and
|
||||
/// is mainly intended for memory and space efficient serializable lookup tables.
|
||||
///
|
||||
/// If the iterator supplies more than one key with different values, which of these is
|
||||
/// included is undefined.
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
#[repr(transparent)]
|
||||
pub struct FlatSortedMap<'a, K: Eq + Ord + Clone, V: Clone>(Cow<'a, [(K, V)]>);
|
||||
|
||||
impl<'a, K: Eq + Ord + Clone, V: Clone> FromIterator<(K, V)> for FlatSortedMap<'a, K, V> {
|
||||
#[inline]
|
||||
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
|
||||
let mut tmp = Vec::from_iter(iter);
|
||||
tmp.sort_unstable_by(|a, b| a.0.cmp(&b.0));
|
||||
tmp.dedup_by(|a, b| a.0.eq(&b.0));
|
||||
Self(Cow::Owned(tmp))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Eq + Ord + Clone, V: Clone> Default for FlatSortedMap<'a, K, V> {
|
||||
#[inline(always)]
|
||||
fn default() -> Self {
|
||||
Self(Cow::Owned(Vec::new()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Eq + Ord + Clone, V: Clone> FlatSortedMap<'a, K, V> {
|
||||
#[inline]
|
||||
pub fn get(&self, k: &K) -> Option<&V> {
|
||||
if let Ok(idx) = self.0.binary_search_by(|a| a.0.cmp(k)) {
|
||||
Some(unsafe { &self.0.get_unchecked(idx).1 })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains(&self, k: &K) -> bool {
|
||||
self.0.binary_search_by(|a| a.0.cmp(k)).is_ok()
|
||||
}
|
||||
|
||||
/// Returns true if this map is valid, meaning that it contains only one of each key and is sorted.
|
||||
#[inline]
|
||||
pub fn is_valid(&self) -> bool {
|
||||
let l = self.0.len();
|
||||
if l > 1 {
|
||||
for i in 1..l {
|
||||
if unsafe { !self.0.get_unchecked(i - 1).0.cmp(&self.0.get_unchecked(i).0).is_lt() } {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter(&self) -> impl Iterator<Item = &(K, V)> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.0.is_empty()
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ pub mod dictionary;
|
|||
pub mod error;
|
||||
#[allow(unused)]
|
||||
pub mod exitcode;
|
||||
pub mod flatsortedmap;
|
||||
pub mod gate;
|
||||
pub mod gatherarray;
|
||||
pub mod hex;
|
||||
|
|
|
@ -46,7 +46,7 @@ fn alice_main(
|
|||
alice_out: mpsc::SyncSender<Vec<u8>>,
|
||||
alice_in: mpsc::Receiver<Vec<u8>>,
|
||||
) {
|
||||
let context = zssp::Context::<TestApplication>::new(16);
|
||||
let context = zssp::Context::<TestApplication>::new(16, TEST_MTU);
|
||||
let mut data_buf = [0u8; 65536];
|
||||
let mut next_service = ms_monotonic() + 500;
|
||||
let mut last_ratchet_count = 0;
|
||||
|
@ -88,7 +88,6 @@ fn alice_main(
|
|||
&0,
|
||||
&mut data_buf,
|
||||
pkt,
|
||||
TEST_MTU,
|
||||
current_time,
|
||||
) {
|
||||
Ok(zssp::ReceiveResult::Ok(_)) => {
|
||||
|
@ -144,7 +143,6 @@ fn alice_main(
|
|||
|_, b| {
|
||||
let _ = alice_out.send(b.to_vec());
|
||||
},
|
||||
TEST_MTU,
|
||||
current_time,
|
||||
);
|
||||
}
|
||||
|
@ -159,7 +157,7 @@ fn bob_main(
|
|||
bob_out: mpsc::SyncSender<Vec<u8>>,
|
||||
bob_in: mpsc::Receiver<Vec<u8>>,
|
||||
) {
|
||||
let context = zssp::Context::<TestApplication>::new(16);
|
||||
let context = zssp::Context::<TestApplication>::new(16, TEST_MTU);
|
||||
let mut data_buf = [0u8; 65536];
|
||||
let mut data_buf_2 = [0u8; TEST_MTU];
|
||||
let mut last_ratchet_count = 0;
|
||||
|
@ -186,7 +184,6 @@ fn bob_main(
|
|||
&0,
|
||||
&mut data_buf,
|
||||
pkt,
|
||||
TEST_MTU,
|
||||
current_time,
|
||||
) {
|
||||
Ok(zssp::ReceiveResult::Ok(_)) => {
|
||||
|
@ -246,7 +243,6 @@ fn bob_main(
|
|||
|_, b| {
|
||||
let _ = bob_out.send(b.to_vec());
|
||||
},
|
||||
TEST_MTU,
|
||||
current_time,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use std::fmt::Display;
|
|||
use std::num::NonZeroU64;
|
||||
|
||||
use zerotier_crypto::random;
|
||||
use zerotier_utils::memory::{array_range, as_byte_array};
|
||||
|
||||
/// 48-bit session ID (most significant 16 bits of u64 are unused)
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
|
||||
|
@ -25,6 +24,7 @@ impl SessionId {
|
|||
pub const MAX: u64 = 0xffffffffffff;
|
||||
|
||||
/// Create a new session ID, panicing if 'i' is zero or exceeds MAX.
|
||||
#[inline(always)]
|
||||
pub fn new(i: u64) -> SessionId {
|
||||
assert!(i <= Self::MAX);
|
||||
Self(NonZeroU64::new(i.to_le()).unwrap())
|
||||
|
@ -35,22 +35,23 @@ impl SessionId {
|
|||
Self(NonZeroU64::new(((random::xorshift64_random() % (Self::MAX - 1)) + 1).to_le()).unwrap())
|
||||
}
|
||||
|
||||
pub(crate) fn new_from_bytes(b: &[u8; Self::SIZE]) -> Option<SessionId> {
|
||||
let mut tmp = [0u8; 8];
|
||||
#[inline(always)]
|
||||
pub fn to_bytes(&self) -> [u8; Self::SIZE] {
|
||||
self.0.get().to_ne_bytes()[..Self::SIZE].try_into().unwrap()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn new_from_bytes(b: &[u8]) -> Option<SessionId> {
|
||||
let mut tmp = 0u64.to_ne_bytes();
|
||||
tmp[..SESSION_ID_SIZE_BYTES].copy_from_slice(b);
|
||||
Self::new_from_u64_le(u64::from_ne_bytes(tmp))
|
||||
NonZeroU64::new(u64::from_ne_bytes(tmp)).map(|i| Self(i))
|
||||
}
|
||||
|
||||
/// Create from a u64 that is already in little-endian byte order.
|
||||
#[inline(always)]
|
||||
pub(crate) fn new_from_u64_le(i: u64) -> Option<SessionId> {
|
||||
NonZeroU64::new(i & Self::MAX.to_le()).map(|i| Self(i))
|
||||
}
|
||||
|
||||
/// Get this session ID as a little-endian byte array.
|
||||
#[inline(always)]
|
||||
pub(crate) fn as_bytes(&self) -> &[u8; Self::SIZE] {
|
||||
array_range::<u8, 8, 0, SESSION_ID_SIZE_BYTES>(as_byte_array(&self.0))
|
||||
pub fn new_from_array(b: &[u8; Self::SIZE]) -> Option<SessionId> {
|
||||
let mut tmp = 0u64.to_ne_bytes();
|
||||
tmp[..SESSION_ID_SIZE_BYTES].copy_from_slice(b);
|
||||
NonZeroU64::new(u64::from_ne_bytes(tmp)).map(|i| Self(i))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
690
zssp/src/zssp.rs
690
zssp/src/zssp.rs
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue