OMG Rust links! On MacOS only so far.

This commit is contained in:
Adam Ierymenko 2021-01-05 17:23:33 -05:00
parent f677a7408e
commit 36f9dd54d9
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
7 changed files with 114 additions and 35 deletions

View file

@ -3,6 +3,7 @@ name = "rust-zerotier-core"
version = "0.1.0"
authors = ["Adam Ierymenko <adam.ierymenko@zerotier.com>"]
edition = "2018"
build = "build.rs"
[dependencies]
num-traits = "0.2.14"

View file

@ -0,0 +1,6 @@
fn main() {
let d = env!("CARGO_MANIFEST_DIR");
println!("cargo:rustc-link-search=native={}/../build/core", d);
println!("cargo:rustc-link-lib=static=zt_core");
println!("cargo:rustc-link-lib=c++");
}

View file

@ -1,16 +1,21 @@
pub struct Address(pub u64);
impl Address {
#[inline]
pub fn new_from_string(s: &str) -> Address {
return Address(u64::from_str_radix(s, 16).unwrap_or(0));
impl ToString for Address {
fn to_string(&self) -> String {
format!("{:0>10x}", self.0)
}
}
impl ToString for Address {
#[inline]
fn to_string(&self) -> String {
format!("{:0>10x}", self.0)
impl From<u64> for Address {
#[inline(always)]
fn from(i: u64) -> Address {
Address(i)
}
}
impl From<&str> for Address {
fn from(s: &str) -> Address {
Address(u64::from_str_radix(s, 16).unwrap_or(0))
}
}
@ -30,7 +35,7 @@ impl<'de> serde::de::Visitor<'de> for AddressVisitor {
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
Ok(Address::new_from_string(s))
Ok(Address::from(s))
}
}

View file

@ -1,17 +1,24 @@
use std::os::raw::c_void;
use std::ptr::null_mut;
use std::slice::{from_raw_parts, from_raw_parts_mut};
use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
use crate::bindings::capi as ztcore;
/// A reusable buffer for I/O to/from the ZeroTier core.
/// The core allocates and manages a pool of these. This provides a Rust
/// interface to that pool. ZT core buffers are used to reduce the need for
/// memory copying by passing buffers around instead of memcpy'ing when
/// packet data is passed into and out of the core.
pub struct Buffer {
pub(crate) zt_core_buf: *mut u8,
pub(crate) data_size: u32
}
impl Buffer {
pub const CAPACITY: u32 = ztcore::ZT_BUF_SIZE;
/// Maximum capacity of a ZeroTier reusable buffer.
pub const CAPACITY: u32 = ztcore::ZT_BUF_SIZE as u32;
/// Obtain a new buffer from the core and set the size of its data to CAPACITY.
/// The contents of the buffer are not defined.
#[inline(always)]
pub fn new() -> Buffer {
let b = unsafe { ztcore::ZT_getBuffer() as *mut u8 };
@ -24,6 +31,8 @@ impl Buffer {
};
}
/// 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
@ -36,10 +45,29 @@ impl Buffer {
pub unsafe fn set_len(&mut self, s: u32) {
self.data_size = s;
}
/// Get a slice that points to this buffer's data. This is unsafe because
/// the returned slice will be invalid if set_len() has been called with a
/// value higher than CAPACITY or if this has been consumed by the ZeroTier
/// core. The latter case is handled automatically in node.rs though, so it
/// is not something you generally have to worry about.
#[inline(always)]
pub unsafe fn as_mut_slice(&mut self) -> &mut [u8] {
return &mut *slice_from_raw_parts_mut(self.zt_core_buf, self.data_size as usize);
}
/// Get a slice that points to this buffer's data. This is unsafe because
/// the returned slice will be invalid if set_len() has been called with a
/// value higher than CAPACITY or if this has been consumed by the ZeroTier
/// core. The latter case is handled automatically in node.rs though, so it
/// is not something you generally have to worry about.
#[inline(always)]
pub unsafe fn as_slice(&mut self) -> &[u8] {
return &*slice_from_raw_parts(self.zt_core_buf, self.data_size as usize);
}
}
impl Drop for Buffer {
#[inline(always)]
fn drop(&mut self) {
// NOTE: in node.rs std::mem::forget() is used to prevent this from
// being called on buffers that have been returned via one of the

View file

@ -6,6 +6,7 @@ use std::os::raw::{c_char, c_uint, c_void};
use std::ptr::{copy_nonoverlapping, null, null_mut};
use std::sync::Mutex;
use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive;
use serde::{Deserialize, Serialize};
@ -173,7 +174,7 @@ pub struct CertificateSubjectUniqueIdSecret {
pub public: Vec<u8>,
pub private: Vec<u8>,
#[serde(rename = "type")]
pub type_: CertificateUniqueIdType
pub type_: CertificateUniqueIdType,
}
const CERTIFICATE_UNIQUE_ID_CREATE_BUF_SIZE: usize = 128;
@ -236,6 +237,49 @@ impl ToString for CertificateError {
}
}
impl From<&str> for CertificateError {
fn from(s: &str) -> CertificateError {
match s.to_ascii_lowercase().as_str() {
"havenewercert" => CertificateError::HaveNewerCert,
"invalidformat" => CertificateError::InvalidFormat,
"invalididentity" => CertificateError::InvalidIdentity,
"invalidprimarysignature" => CertificateError::InvalidPrimarySignature,
"invalidchain" => CertificateError::InvalidChain,
"invalidcomponentsignature" => CertificateError::InvalidComponentSignature,
"invaliduniqueidproof" => CertificateError::InvalidUniqueIdProof,
"missingrequiredfields" => CertificateError::MissingRequiredFields,
"outofvalidtimewindow" => CertificateError::OutOfValidTimeWindow,
_ => CertificateError::None // also "none"
}
}
}
impl serde::Serialize for CertificateError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
serializer.serialize_str(self.to_string().as_str())
}
}
struct CertificateErrorVisitor;
impl<'de> serde::de::Visitor<'de> for CertificateErrorVisitor {
type Value = CertificateError;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("CertificateError value in string form")
}
fn visit_str<E>(self, s: &str) -> Result<Self::Value, E> where E: serde::de::Error {
return Ok(CertificateError::from(s));
}
}
impl<'de> serde::Deserialize<'de> for CertificateError {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: serde::Deserializer<'de> {
deserializer.deserialize_str(CertificateErrorVisitor)
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#[derive(Serialize, Deserialize)]
@ -272,7 +316,7 @@ impl CertificateName {
postal_code: String::new(),
email: String::new(),
url: String::new(),
host: String::new()
host: String::new(),
}
}
@ -289,7 +333,7 @@ impl CertificateName {
postal_code: cstr_to_string(cn.postalCode.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
email: cstr_to_string(cn.email.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
url: cstr_to_string(cn.url.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
host: cstr_to_string(cn.host.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1)
host: cstr_to_string(cn.host.as_ptr(), CERTIFICATE_MAX_STRING_LENGTH - 1),
};
}
@ -425,7 +469,7 @@ impl CertificateSubject {
update_urls: Vec::new(),
name: CertificateName::new(),
unique_id: Vec::new(),
unique_id_proof_signature: Vec::new()
unique_id_proof_signature: Vec::new(),
}
}
@ -582,7 +626,7 @@ pub struct Certificate {
pub extended_attributes: Vec<u8>,
#[serde(rename = "maxPathLength")]
pub max_path_length: u32,
pub signature: Vec<u8>
pub signature: Vec<u8>,
}
pub(crate) struct CertificateCAPIContainer {
@ -602,7 +646,7 @@ impl Certificate {
issuer_name: CertificateName::new(),
extended_attributes: Vec::new(),
max_path_length: 0,
signature: Vec::new()
signature: Vec::new(),
}
}
@ -712,4 +756,11 @@ mod tests {
let sn = CertificateSerialNo::from(&test[0..48]);
assert!(test.eq(&sn.0));
}
#[test]
fn generate_certificate_unique_id() {
let uid = CertificateSubjectUniqueIdSecret::new(CertificateUniqueIdType::NistP384);
println!("certificate unique ID public: {}", hex::encode(uid.public).as_str());
println!("certificate unique ID private: {}", hex::encode(uid.private).as_str());
}
}

View file

@ -1,5 +1,3 @@
#[link(name = ":../../build/core/libzt_core.a")]
use std::os::raw::{c_char, c_int};
use num_derive::{FromPrimitive, ToPrimitive};
@ -49,7 +47,7 @@ pub const DEFAULT_UDP_MTU: u32 = ztcore::ZT_DEFAULT_UDP_MTU;
pub const MAX_UDP_MTU: u32 = ztcore::ZT_MAX_UDP_MTU;
#[allow(non_snake_case,non_upper_case_globals)]
pub mod RulePacketCharacteristics {
pub mod RulePacketCharacteristicFlags {
pub const Inbound: u64 = crate::bindings::capi::ZT_RULE_PACKET_CHARACTERISTICS_INBOUND as u64;
pub const Multicast: u64 = crate::bindings::capi::ZT_RULE_PACKET_CHARACTERISTICS_MULTICAST as u64;
pub const Broadcast: u64 = crate::bindings::capi::ZT_RULE_PACKET_CHARACTERISTICS_BROADCAST as u64;
@ -183,7 +181,7 @@ pub unsafe fn cstr_to_string(cstr: *const c_char, max_len: isize) -> String {
if !cstr.is_null() {
let mut cstr_len: isize = 0;
while max_len < 0 || cstr_len < max_len {
if (*cstr.offset(cstr_len) == 0) {
if *cstr.offset(cstr_len) == 0 {
break;
}
cstr_len += 1;

View file

@ -56,7 +56,6 @@ macro_rules! node_from_raw_ptr {
}
}
#[no_mangle]
extern "C" fn zt_virtual_network_config_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -70,7 +69,6 @@ extern "C" fn zt_virtual_network_config_function<T: NodeEventHandler + 'static>(
n.event_handler.virtual_network_config();
}
#[no_mangle]
extern "C" fn zt_virtual_network_frame_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -88,7 +86,6 @@ extern "C" fn zt_virtual_network_frame_function<T: NodeEventHandler + 'static>(
n.event_handler.virtual_network_frame();
}
#[no_mangle]
extern "C" fn zt_event_callback<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -100,7 +97,6 @@ extern "C" fn zt_event_callback<T: NodeEventHandler + 'static>(
n.event_handler.event();
}
#[no_mangle]
extern "C" fn zt_state_put_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -114,7 +110,6 @@ extern "C" fn zt_state_put_function<T: NodeEventHandler + 'static>(
n.event_handler.state_put();
}
#[no_mangle]
extern "C" fn zt_state_get_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -128,7 +123,6 @@ extern "C" fn zt_state_get_function<T: NodeEventHandler + 'static>(
n.event_handler.state_get();
}
#[no_mangle]
extern "C" fn zt_wire_packet_send_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -143,7 +137,6 @@ extern "C" fn zt_wire_packet_send_function<T: NodeEventHandler + 'static>(
n.event_handler.wire_packet_send();
}
#[no_mangle]
extern "C" fn zt_path_check_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -157,7 +150,6 @@ extern "C" fn zt_path_check_function<T: NodeEventHandler + 'static>(
n.event_handler.path_check();
}
#[no_mangle]
extern "C" fn zt_path_lookup_function<T: NodeEventHandler + 'static>(
capi: *mut ztcore::ZT_Node,
uptr: *mut c_void,
@ -309,10 +301,8 @@ impl<T: NodeEventHandler + 'static> Node<T> {
}
pub fn identity(&self) -> Identity {
unsafe {
let mut id = ztcore::ZT_Node_identity(self.capi.get());
return Identity::new_from_capi(id, false).clone();
}
let id = unsafe { ztcore::ZT_Node_identity(self.capi.get()) };
return Identity::new_from_capi(id, false).clone();
}
pub fn status(&self) -> NodeStatus {