MOAR rust.

This commit is contained in:
Adam Ierymenko 2020-12-14 23:32:49 -05:00
parent 7fa7f6f07a
commit ab2870cbb7
No known key found for this signature in database
GPG key ID: C8877CF2D7A5D7F3
11 changed files with 297 additions and 53 deletions

View file

@ -445,10 +445,10 @@ int ZT_Locator_verify(const ZT_Locator *loc, const ZT_Identity *signer)
return reinterpret_cast<const ZeroTier::Locator *>(loc)->verify(*reinterpret_cast<const ZeroTier::Identity *>(signer)) ? 1 : 0;
}
void ZT_Locator_delete(ZT_Locator *loc)
void ZT_Locator_delete(const ZT_Locator *loc)
{
if (loc)
delete reinterpret_cast<ZeroTier::Locator *>(loc);
delete reinterpret_cast<const ZeroTier::Locator *>(loc);
}
/********************************************************************************************************************/
@ -466,6 +466,18 @@ ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type)
}
}
ZT_Identity *ZT_Identity_clone(const ZT_Identity *id)
{
if (id) {
try {
return reinterpret_cast<ZT_Identity *>(new ZeroTier::Identity(*reinterpret_cast<const ZeroTier::Identity *>(id)));
} catch ( ... ) {
return nullptr;
}
}
return nullptr;
}
ZT_Identity *ZT_Identity_fromString(const char *idStr)
{
if (!idStr)
@ -541,10 +553,10 @@ const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id)
return &(reinterpret_cast<const ZeroTier::Identity *>(id)->fingerprint());
}
void ZT_Identity_delete(ZT_Identity *id)
void ZT_Identity_delete(const ZT_Identity *id)
{
if (id)
delete reinterpret_cast<ZeroTier::Identity *>(id);
delete reinterpret_cast<const ZeroTier::Identity *>(id);
}
/********************************************************************************************************************/

View file

@ -2452,6 +2452,14 @@ ZT_SDK_API void ZT_Node_setController(
*/
ZT_SDK_API ZT_Identity *ZT_Identity_new(enum ZT_IdentityType type);
/**
* Make a copy of an identity
*
* @param id Identity to copy
* @return Copy, must be freed with ZT_Identity_delete.
*/
ZT_SDK_API ZT_Identity *ZT_Identity_clone(const ZT_Identity *id);
/**
* Create a new identity object from a string-serialized identity
*
@ -2560,7 +2568,7 @@ ZT_SDK_API const ZT_Fingerprint *ZT_Identity_fingerprint(const ZT_Identity *id);
*
* @param id Identity to delete
*/
ZT_SDK_API void ZT_Identity_delete(ZT_Identity *id);
ZT_SDK_API void ZT_Identity_delete(const ZT_Identity *id);
/* ---------------------------------------------------------------------------------------------------------------- */
@ -2712,7 +2720,7 @@ ZT_SDK_API int ZT_Locator_verify(
*
* @param loc Locator to delete
*/
ZT_SDK_API void ZT_Locator_delete(ZT_Locator *loc);
ZT_SDK_API void ZT_Locator_delete(const ZT_Locator *loc);
/* ---------------------------------------------------------------------------------------------------------------- */

View file

@ -1,23 +1,9 @@
pub struct Address(pub u64);
pub type Address = u64;
impl Address {
pub fn new_from_string(s: &str) -> Self {
Address(u64::from_str_radix(s, 16).unwrap_or(0))
pub fn address_to_string(a: Address) -> String {
format!("{:0>10x}", a as u64)
}
pub fn to_u64(&self) -> u64 {
self.0
}
}
impl ToString for Address {
fn to_string(&self) -> String {
format!("{:0>10x}", self.0)
}
}
impl From<String> for Address {
fn from(s: String) -> Self {
Address::new_from_string(s.as_str())
}
pub fn address_from_string(s: &str) -> Address {
return u64::from_str_radix(s, 16).unwrap_or(0) as Address;
}

View file

@ -0,0 +1,143 @@
use crate::*;
use crate::bindings::capi as ztcore;
use std::ffi::CStr;
use std::ptr::copy_nonoverlapping;
use std::os::raw::c_char;
pub struct CertificateName {
pub serial_no: String,
pub common_name: String,
pub country: String,
pub organization: String,
pub unit: String,
pub locality: String,
pub province: String,
pub street_address: String,
pub postal_code: String,
pub email: String,
pub url: String,
pub host: String
}
pub struct CertificateNetwork {
pub id: NetworkId,
pub controller: Fingerprint
}
pub struct CertificateIdentity {
pub identity: Identity,
pub locator: Locator
}
pub struct CertificateSubject {
pub timestamp: i64,
pub identities: Box<[CertificateIdentity]>,
pub networks: Box<[CertificateNetwork]>,
pub certificates: Box<[[u8; 48]]>,
pub update_urls: Box<[String]>,
pub name: CertificateName,
pub unique_id: Box<[u8]>,
pub unique_id_proof_signature: Box<[u8]>
}
pub struct Certificate {
pub serial_no: [u8; 48],
pub flags: u64,
pub timestamp: i64,
pub validity: [i64; 2],
pub subject: CertificateSubject,
pub issuer: Identity,
pub issuer_name: CertificateName,
pub extended_attributes: Box<[u8]>,
pub max_path_length: u32,
pub crl: Box<[u8; 48]>,
pub signature: Box<[u8]>
}
impl CertificateName {
pub(crate) fn new_from_capi(cn: &ztcore::ZT_Certificate_Name) -> CertificateName {
unsafe {
return CertificateName {
serial_no: String::from(CStr::from_ptr(cn.serialNo.as_ptr()).to_str().unwrap()),
common_name: String::from(CStr::from_ptr(cn.commonName.as_ptr()).to_str().unwrap()),
country: String::from(CStr::from_ptr(cn.country.as_ptr()).to_str().unwrap()),
organization: String::from(CStr::from_ptr(cn.organization.as_ptr()).to_str().unwrap()),
unit: String::from(CStr::from_ptr(cn.unit.as_ptr()).to_str().unwrap()),
locality: String::from(CStr::from_ptr(cn.locality.as_ptr()).to_str().unwrap()),
province: String::from(CStr::from_ptr(cn.province.as_ptr()).to_str().unwrap()),
street_address: String::from(CStr::from_ptr(cn.streetAddress.as_ptr()).to_str().unwrap()),
postal_code: String::from(CStr::from_ptr(cn.postalCode.as_ptr()).to_str().unwrap()),
email: String::from(CStr::from_ptr(cn.email.as_ptr()).to_str().unwrap()),
url: String::from(CStr::from_ptr(cn.url.as_ptr()).to_str().unwrap()),
host: String::from(CStr::from_ptr(cn.host.as_ptr()).to_str().unwrap())
};
}
}
}
impl CertificateNetwork {
pub(crate) fn new_from_capi(cn: &ztcore::ZT_Certificate_Network) -> CertificateNetwork {
CertificateNetwork{
id: cn.id as NetworkId,
controller: Fingerprint{
address: cn.controller.address as Address,
hash: cn.controller.hash
}
}
}
}
impl CertificateIdentity {
pub(crate) fn new_from_capi(ci: &ztcore::ZT_Certificate_Identity) -> CertificateIdentity {
CertificateIdentity{
identity: Identity::new_from_capi(ci.identity, false),
locator: Locator::new_from_capi(ci.locator, false)
}
}
}
impl CertificateSubject {
pub(crate) fn new_from_capi(cs: &ztcore::ZT_Certificate_Subject) -> CertificateSubject {
unsafe {
let cidentities: &[ztcore::ZT_Certificate_Identity] = std::slice::from_raw_parts(cs.identities, cs.identityCount as usize);
let mut identities: Vec<CertificateIdentity> = Vec::new();
for i in cidentities.iter() {
identities.push(CertificateIdentity::new_from_capi(i));
}
let cnetworks: &[ztcore::ZT_Certificate_Network] = std::slice::from_raw_parts(cs.networks, cs.networkCount as usize);
let mut networks: Vec<CertificateNetwork> = Vec::new();
for i in cnetworks.iter() {
networks.push(CertificateNetwork::new_from_capi(i));
}
let ccertificates: &[*const u8] = std::slice::from_raw_parts(cs.certificates, cs.certificateCount as usize);
let mut certificates: Vec<[u8; 48]> = Vec::new();
let mut ctmp: [u8; 48] = [0; 48];
for i in ccertificates.iter() {
copy_nonoverlapping(*i, ctmp.as_mut_ptr(), 48);
certificates.push(ctmp.clone());
}
let cupdate_urls: &[*const c_char] = std::slice::from_raw_parts(cs.updateURLs, cs.updateURLCount as usize);
let mut update_urls: Vec<String> = Vec::new();
for i in cupdate_urls.iter() {
update_urls.push(CStr::from_ptr(*i).to_str().unwrap().to_string());
}
return CertificateSubject{
timestamp: cs.timestamp,
identities: identities.into_boxed_slice(),
networks: networks.into_boxed_slice(),
certificates: certificates.into_boxed_slice(),
update_urls: update_urls.into_boxed_slice(),
name: CertificateName::new_from_capi(&cs.name),
unique_id: Box::from(std::slice::from_raw_parts(cs.uniqueId, cs.uniqueIdSize as usize).clone()),
unique_id_proof_signature: Box::from(std::slice::from_raw_parts(cs.uniqueIdProofSignature, cs.uniqueIdProofSignatureSize as usize).clone())
}
}
}
}
impl Certificate {
}

View file

@ -1,7 +1,7 @@
use crate::*;
use crate::bindings::capi as ztcore;
use num_traits::FromPrimitive;
use std::os::raw::c_char;
use std::os::raw::{c_char, c_int};
use std::ffi::CStr;
use std::mem::MaybeUninit;
@ -25,16 +25,25 @@ impl Endpoint {
return Err(ResultCode::from_i32(ec).unwrap());
}
}
pub(crate) fn new_from_capi(ep: *const ztcore::ZT_Endpoint) -> Endpoint {
unsafe {
return Endpoint{
ep_type: EndpointType::from_u32((*ep).type_ as u32).unwrap(),
intl: *ep
};
}
}
}
impl ToString for Endpoint {
fn to_string(&self) -> String {
let mut buf: [u8; 256] = [0; 256];
let mut buf: [u8; 1024] = [0; 1024];
unsafe {
if ztcore::ZT_Endpoint_toString(&(self.intl) as *const ztcore::ZT_Endpoint,buf.as_mut_ptr() as *mut c_char, 1024).is_null() {
if ztcore::ZT_Endpoint_toString(&(self.intl) as *const ztcore::ZT_Endpoint,buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
return String::from("(invalid)");
}
return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap());
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap());
}
}
}

View file

@ -16,7 +16,7 @@ impl Fingerprint {
if ztcore::ZT_Fingerprint_fromString(cfp.as_mut_ptr(), s.as_ptr() as *const c_char) != 0 {
let fp = cfp.assume_init();
return Ok(Fingerprint{
address: Address(fp.address),
address: fp.address as Address,
hash: fp.hash
});
}
@ -30,12 +30,12 @@ impl ToString for Fingerprint {
let mut buf: [u8; 256] = [0; 256];
unsafe {
if ztcore::ZT_Fingerprint_toString(&ztcore::ZT_Fingerprint {
address: self.address.to_u64(),
address: self.address,
hash: self.hash
}, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
return String::from("(invalid)");
}
return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap());
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap());
}
}
}

View file

@ -2,27 +2,36 @@ use crate::*;
use crate::bindings::capi as ztcore;
use std::os::raw::*;
use std::ffi::CStr;
use num_traits::ToPrimitive;
use num_traits::{ToPrimitive, FromPrimitive};
pub struct Identity {
pub id_type: IdentityType,
pub address: Address,
capi: *mut ztcore::ZT_Identity,
capi: *const ztcore::ZT_Identity,
requires_delete: bool
}
impl Identity {
pub(crate) fn new_from_capi(id: *const ztcore::ZT_Identity, requires_delete: bool) -> Identity {
unsafe {
let idt = ztcore::ZT_Identity_type(id);
let a = ztcore::ZT_Identity_address(id);
return Identity{
id_type: FromPrimitive::from_u32(idt as u32).unwrap(),
address: a as Address,
capi: id,
requires_delete: requires_delete
};
}
}
pub fn generate(id_type: IdentityType) -> Result<Identity, ResultCode> {
unsafe {
let id = ztcore::ZT_Identity_new(id_type.to_u32().unwrap());
if id.is_null() {
return Err(ResultCode::ErrorBadParameter); // this only really happens if type is invalid
}
let a = ztcore::ZT_Identity_address(id);
return Ok(Identity {
id_type: id_type,
address: Address(a as u64),
capi: id,
});
return Ok(Identity::new_from_capi(id, true));
}
}
@ -32,13 +41,7 @@ impl Identity {
if id.is_null() {
return Err(ResultCode::ErrorBadParameter);
}
let idt = ztcore::ZT_Identity_type(id);
let a = ztcore::ZT_Identity_address(id);
return Ok(Identity {
id_type: num_traits::FromPrimitive::from_u32(idt).unwrap(),
address: Address(a as u64),
capi: id
});
return Ok(Identity::new_from_capi(id, true));
}
}
@ -48,7 +51,7 @@ impl Identity {
if ztcore::ZT_Identity_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int, if include_private { 1 } else { 0 }).is_null() {
return String::from("(invalid)");
}
return String::from(CStr::from_bytes_with_nul(&buf).unwrap().to_str().unwrap());
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap());
}
}
@ -74,7 +77,7 @@ impl Identity {
unsafe {
let cfp = ztcore::ZT_Identity_fingerprint(self.capi);
return Fingerprint {
address: Address((*cfp).address),
address: (*cfp).address,
hash: (*cfp).hash
}
}
@ -107,11 +110,13 @@ impl Identity {
impl Drop for Identity {
fn drop(&mut self) {
if self.requires_delete && !self.capi.is_null() {
unsafe {
ztcore::ZT_Identity_delete(self.capi);
}
}
}
}
impl ToString for Identity {
fn to_string(&self) -> String {

View file

@ -3,12 +3,16 @@ mod identity;
mod address;
mod fingerprint;
mod endpoint;
mod inetaddress;
mod certificate;
mod networkid;
mod locator;
pub use identity::Identity;
pub use address::Address;
pub use address::*;
pub use fingerprint::Fingerprint;
pub use endpoint::Endpoint;
pub use networkid::*;
pub use locator::Locator;
use bindings::capi as ztcore;
use num_derive::FromPrimitive;

View file

@ -0,0 +1,68 @@
use crate::*;
use crate::bindings::capi as ztcore;
use std::os::raw::{c_char, c_int, c_uint};
use std::ffi::CStr;
pub struct Locator {
capi: *const ztcore::ZT_Locator,
requires_delete: bool
}
impl Locator {
pub(crate) fn new_from_capi(l: *const ztcore::ZT_Locator, requires_delete: bool) -> Locator {
Locator{
capi: l,
requires_delete: requires_delete
}
}
pub fn new_from_string(s: &str) -> Result<Locator, ResultCode> {
unsafe {
let l = ztcore::ZT_Locator_fromString(s.as_ptr() as *const c_char);
if l.is_null() {
return Err(ResultCode::ErrorBadParameter);
}
return Ok(Locator::new_from_capi(l, true));
}
}
pub fn timestamp(&self) -> i64 {
unsafe {
return ztcore::ZT_Locator_timestamp(self.capi) as i64;
}
}
pub fn endpoints(&self) -> Box<[Endpoint]> {
let mut eps: Vec<Endpoint> = Vec::new();
unsafe {
let ep_count = ztcore::ZT_Locator_endpointCount(self.capi) as usize;
eps.reserve(ep_count as usize);
for i in 0..ep_count {
eps.push(Endpoint::new_from_capi(ztcore::ZT_Locator_endpoint(self.capi, i as c_uint)));
}
}
eps.into_boxed_slice()
}
}
impl Drop for Locator {
fn drop(&mut self) {
if self.requires_delete && !self.capi.is_null() {
unsafe {
ztcore::ZT_Locator_delete(self.capi);
}
}
}
}
impl ToString for Locator {
fn to_string(&self) -> String {
let mut buf: [u8; 4096] = [0; 4096];
unsafe {
if ztcore::ZT_Locator_toString(self.capi, buf.as_mut_ptr() as *mut c_char, buf.len() as c_int).is_null() {
return String::from("(invalid)");
}
return String::from(CStr::from_bytes_with_nul(buf.as_ref()).unwrap().to_str().unwrap());
}
}
}

View file

@ -0,0 +1,9 @@
pub type NetworkId = u64;
pub fn network_id_to_string(n: NetworkId) -> String {
format!("{:0>16x}", n as u64)
}
pub fn network_id_from_string(s: &str) -> NetworkId {
return u64::from_str_radix(s, 16).unwrap_or(0) as NetworkId;
}