diff --git a/rust-zerotier-core/src/buffer.rs b/rust-zerotier-core/src/buffer.rs index 8ae984839..adb0b3e7b 100644 --- a/rust-zerotier-core/src/buffer.rs +++ b/rust-zerotier-core/src/buffer.rs @@ -44,13 +44,23 @@ impl Buffer { }; } - /// Get the current size of the data held by this buffer. Initially this is - /// equal to CAPACITY. + /// Get the current size of the data held by this buffer. + /// Initially this is equal to CAPACITY. #[inline(always)] pub fn len(&self) -> u32 { self.data_size } + #[inline(always)] + pub fn as_ptr(&self) -> *const u8 { + self.zt_core_buf + } + + #[inline(always)] + pub fn as_mut_ptr(&mut self) -> *mut u8 { + self.zt_core_buf + } + /// Set the size of the data held by this buffer. This is unsafe because /// setting it to a value larger than CAPACITY will place the buffer into /// an invalid state. diff --git a/rust-zerotier-core/src/endpoint.rs b/rust-zerotier-core/src/endpoint.rs index 05073fa80..3f14bfb70 100644 --- a/rust-zerotier-core/src/endpoint.rs +++ b/rust-zerotier-core/src/endpoint.rs @@ -21,7 +21,7 @@ use num_traits::FromPrimitive; use crate::*; use crate::bindings::capi as ztcore; -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum EndpointType { Nil = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_NIL as isize, ZeroTier = ztcore::ZT_EndpointType_ZT_ENDPOINT_TYPE_ZEROTIER as isize, diff --git a/rust-zerotier-core/src/inetaddress.rs b/rust-zerotier-core/src/inetaddress.rs index aa70a769a..f9d7c0736 100644 --- a/rust-zerotier-core/src/inetaddress.rs +++ b/rust-zerotier-core/src/inetaddress.rs @@ -29,7 +29,7 @@ use std::os::raw::{c_void, c_uint}; // blobs to be freely cast to one another. That the sizes are correct is // checked statically in the C++ code and in the tests in the Rust code. -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum IpScope { None = ztcore::ZT_InetAddress_IpScope_ZT_IP_SCOPE_NONE as isize, Multicast = ztcore::ZT_InetAddress_IpScope_ZT_IP_SCOPE_MULTICAST as isize, @@ -41,6 +41,7 @@ pub enum IpScope { Private = ztcore::ZT_InetAddress_IpScope_ZT_IP_SCOPE_PRIVATE as isize } +#[derive(PartialEq, Eq)] pub enum InetAddressFamily { Nil, IPv4, @@ -91,6 +92,10 @@ impl InetAddress { Some(a) } + /// Transmute a ZT_InetAddress from the core into a reference to a Rust + /// InetAddress containing exactly the same data. The returned reference + /// of course only remains valid so long as the ZT_InetAddress remains + /// valid. #[inline(always)] pub(crate) fn transmute_capi(a: &ztcore::ZT_InetAddress) -> &InetAddress { unsafe { @@ -98,6 +103,8 @@ impl InetAddress { } } + /// Create an InetAddress by copying a ZT_InetAddress instead of transmuting. + /// Returns None if the input is a nil address. pub(crate) fn new_from_capi(a: &ztcore::ZT_InetAddress) -> Option { if a.bits[0] != 0 { Some(InetAddress { diff --git a/rust-zerotier-core/src/lib.rs b/rust-zerotier-core/src/lib.rs index 690e07660..e5b6807f4 100644 --- a/rust-zerotier-core/src/lib.rs +++ b/rust-zerotier-core/src/lib.rs @@ -77,7 +77,7 @@ pub mod RulePacketCharacteristicFlags { pub const TcpFlagFIN: u64 = crate::bindings::capi::ZT_RULE_PACKET_CHARACTERISTICS_TCP_FIN as u64; } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum CredentialType { Null = ztcore::ZT_CredentialType_ZT_CREDENTIAL_TYPE_NULL as isize, CertificateOfMembership = ztcore::ZT_CredentialType_ZT_CREDENTIAL_TYPE_COM as isize, @@ -87,7 +87,7 @@ pub enum CredentialType { Revocation = ztcore::ZT_CredentialType_ZT_CREDENTIAL_TYPE_REVOCATION as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum TraceEventType { UnexpectedError = ztcore::ZT_TraceEventType_ZT_TRACE_UNEXPECTED_ERROR as isize, ResetingPathsInScope = ztcore::ZT_TraceEventType_ZT_TRACE_VL1_RESETTING_PATHS_IN_SCOPE as isize, @@ -100,7 +100,7 @@ pub enum TraceEventType { NetworkFilter = ztcore::ZT_TraceEventType_ZT_TRACE_VL2_NETWORK_FILTER as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum TracePacketDropReason { Unspecified = ztcore::ZT_TracePacketDropReason_ZT_TRACE_PACKET_DROP_REASON_UNSPECIFIED as isize, PeerTooOld = ztcore::ZT_TracePacketDropReason_ZT_TRACE_PACKET_DROP_REASON_PEER_TOO_OLD as isize, @@ -113,7 +113,7 @@ pub enum TracePacketDropReason { ReplyNotExpected = ztcore::ZT_TracePacketDropReason_ZT_TRACE_PACKET_DROP_REASON_REPLY_NOT_EXPECTED as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum TraceFrameDropReason { Unspecified = ztcore::ZT_TraceFrameDropReason_ZT_TRACE_FRAME_DROP_REASON_UNSPECIFIED as isize, BridgingNotAllowedRemote = ztcore::ZT_TraceFrameDropReason_ZT_TRACE_FRAME_DROP_REASON_BRIDGING_NOT_ALLOWED_REMOTE as isize, @@ -125,7 +125,7 @@ pub enum TraceFrameDropReason { PermissionDenied = ztcore::ZT_TraceFrameDropReason_ZT_TRACE_FRAME_DROP_REASON_PERMISSION_DENIED as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum TraceCredentialRejectionReason { SignatureVerificationFailed = ztcore::ZT_TraceCredentialRejectionReason_ZT_TRACE_CREDENTIAL_REJECTION_REASON_SIGNATURE_VERIFICATION_FAILED as isize, Revoked = ztcore::ZT_TraceCredentialRejectionReason_ZT_TRACE_CREDENTIAL_REJECTION_REASON_REVOKED as isize, @@ -133,7 +133,7 @@ pub enum TraceCredentialRejectionReason { Invalid = ztcore::ZT_TraceCredentialRejectionReason_ZT_TRACE_CREDENTIAL_REJECTION_REASON_INVALID as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum ResultCode { Ok = ztcore::ZT_ResultCode_ZT_RESULT_OK as isize, FatalErrorOutOfMemory = ztcore::ZT_ResultCode_ZT_RESULT_FATAL_ERROR_OUT_OF_MEMORY as isize, @@ -183,6 +183,7 @@ pub unsafe fn cstr_to_string(cstr: *const c_char, max_len: isize) -> String { String::new() } +/// Macro to implement to_json and new_from_json on types that are Serializable. #[macro_export(crate)] macro_rules! implement_to_from_json { ($struct_name:ident) => { diff --git a/rust-zerotier-core/src/node.rs b/rust-zerotier-core/src/node.rs index c433750f0..253f86283 100644 --- a/rust-zerotier-core/src/node.rs +++ b/rust-zerotier-core/src/node.rs @@ -30,10 +30,9 @@ use serde::{Deserialize, Serialize}; use crate::*; use crate::bindings::capi as ztcore; -/// Minimum delay between iterations of the background loop. -const NODE_BACKGROUND_MIN_DELAY: i64 = 250; +const NODE_BACKGROUND_MAX_DELAY: i64 = 250; -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum Event { Up = ztcore::ZT_Event_ZT_EVENT_UP as isize, Offline = ztcore::ZT_Event_ZT_EVENT_OFFLINE as isize, @@ -43,7 +42,7 @@ pub enum Event { UserMessage = ztcore::ZT_Event_ZT_EVENT_USER_MESSAGE as isize, } -#[derive(FromPrimitive,ToPrimitive)] +#[derive(FromPrimitive, ToPrimitive, PartialEq, Eq)] pub enum StateObjectType { IdentityPublic = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_IDENTITY_PUBLIC as isize, IdentitySecret = ztcore::ZT_StateObjectType_ZT_STATE_OBJECT_IDENTITY_SECRET as isize, @@ -55,6 +54,7 @@ pub enum StateObjectType { } impl StateObjectType { + /// Get the canonical file extension for this object type. pub fn to_file_ext(&self) -> &str { match *self { StateObjectType::IdentityPublic => "public", @@ -171,9 +171,14 @@ extern "C" fn zt_virtual_network_frame_function( ) { if !nptr.is_null() { let n = node_from_raw_ptr!(uptr); - let network_obj: &Arc = unsafe { &*((*nptr).cast::>()) }; - let data_slice = unsafe { &*slice_from_raw_parts(data.cast::(), data_size as usize) }; - n.event_handler.virtual_network_frame(NetworkId(nwid), network_obj, MAC(source_mac), MAC(dest_mac), ethertype as u16, vlan_id as u16, data_slice); + n.event_handler.virtual_network_frame( + NetworkId(nwid), + unsafe { &*((*nptr).cast::>()) }, + MAC(source_mac), + MAC(dest_mac), + ethertype as u16, + vlan_id as u16, + unsafe { &*slice_from_raw_parts(data.cast::(), data_size as usize) }); } } @@ -366,7 +371,7 @@ impl Node { let wn = Arc::downgrade(&n); let run = n.background_thread_run.clone(); n.background_thread.replace(Some(std::thread::spawn(move || { - let mut loop_delay = Duration::from_millis(500); + let mut loop_delay = Duration::from_millis(NODE_BACKGROUND_MAX_DELAY as u64); while run.load(Ordering::Relaxed) { std::thread::park_timeout(loop_delay); if run.load(Ordering::Relaxed) { @@ -386,7 +391,6 @@ impl Node { } /// This is called periodically from the background service thread. - #[inline(always)] fn process_background_tasks(&self) -> i64 { let current_time = now(); self.now.set(current_time); @@ -399,8 +403,8 @@ impl Node { if next_delay < 10 { next_delay = 10; - } else if next_delay > NODE_BACKGROUND_MIN_DELAY { - next_delay = NODE_BACKGROUND_MIN_DELAY; + } else if next_delay > NODE_BACKGROUND_MAX_DELAY { + next_delay = NODE_BACKGROUND_MAX_DELAY; } next_delay } @@ -450,7 +454,7 @@ impl Node { } #[inline(always)] - pub fn process_wire_packet(&self, local_socket: i64, remote_address: &InetAddress, data: Buffer) -> ResultCode { + pub fn process_wire_packet(&self, local_socket: i64, remote_address: &InetAddress, data: Buffer) -> ResultCode { let current_time = self.now.get(); let mut next_task_deadline: i64 = current_time; let rc = unsafe { ResultCode::from_i32(ztcore::ZT_Node_processWirePacket(self.capi.get(), null_mut(), current_time, local_socket, remote_address.as_capi_ptr(), data.zt_core_buf as *const c_void, data.data_size as u32, 1, &mut next_task_deadline as *mut i64) as i32).unwrap_or(ResultCode::ErrorInternalNonFatal) }; @@ -479,9 +483,17 @@ impl Node { } } + /// Get a copy of this node's identity. pub fn identity(&self) -> Identity { - let id = unsafe { ztcore::ZT_Node_identity(self.capi.get()) }; - return Identity::new_from_capi(id, false).clone(); + unsafe { self.identity_fast().clone() } + } + + /// Get an identity that simply holds a pointer to the underlying node's identity. + /// This is unsafe because the identity object becomes invalid if the node ceases + /// to exist the Identity becomes invalid. Use clone() on it to get a copy. + #[inline(always)] + pub(crate) unsafe fn identity_fast(&self) -> Identity { + Identity::new_from_capi(ztcore::ZT_Node_identity(self.capi.get()), false) } pub fn status(&self) -> NodeStatus { diff --git a/rust-zerotier-core/src/portableatomici64.rs b/rust-zerotier-core/src/portableatomici64.rs index 0d45c6313..e57d36cd1 100644 --- a/rust-zerotier-core/src/portableatomici64.rs +++ b/rust-zerotier-core/src/portableatomici64.rs @@ -18,7 +18,8 @@ use std::sync::Mutex; use std::sync::atomic::{AtomicI64, Ordering}; // This implements a basic atomic i64 that uses a mutex on 32-bit systems, -// since you can't atomically access something larger than word size. +// since you can't atomically access something larger than word size in most +// cases. #[cfg(all(target_pointer_width = "32"))] pub struct PortableAtomicI64 {