use crate::edge::credentials;
use crate::{access, helpers, Error, Result};
use std::ffi::CString;
use std::os::raw::c_char;
use std::ptr;
use uplink_sys as ulksys;
pub struct Config {
inner: ulksys::EdgeConfig,
}
impl Config {
pub fn new(auth_service_addr: &str) -> Result<Self> {
let parts: Vec<&str> = auth_service_addr.split(':').collect();
if parts.len() != 2 {
return Err(Error::new_invalid_arguments(
"auth_service_addr",
"invalid address, missing port or it contains more than one colon",
));
}
if let Err(err) = parts[1].parse::<u16>() {
return Err(Error::new_invalid_arguments(
"auth_service_addr",
&format!("invalid port. {}", err),
));
}
let addr = helpers::cstring_from_str_fn_arg("auth_service_addr", auth_service_addr)?;
Ok(Self {
inner: ulksys::EdgeConfig {
auth_service_address: addr.into_raw(),
certificate_pem: ptr::null_mut(),
insecure_unencrypted_connection: false,
},
})
}
pub fn new_insecure(auth_service_addr: &str) -> Result<Self> {
let mut config = Self::new(auth_service_addr)?;
config.inner.insecure_unencrypted_connection = true;
Ok(config)
}
pub fn with_certificate(auth_service_addr: &str, cert_pem: &[u8]) -> Result<Self> {
let mut this = Self::new(auth_service_addr)?;
match CString::new(cert_pem) {
Err(e) => Err(Error::new_invalid_arguments(
"cert_pem",
&format!(
"cannot contains null bytes (0 byte). Null byte found at {}",
e.nul_position()
),
)),
Ok(cert) => {
this.inner.certificate_pem = cert.into_raw();
Ok(this)
}
}
}
pub fn register_gateway_access(
&self,
access: &access::Grant,
opts: Option<&OptionsRegisterAccess>,
) -> Result<credentials::Gateway> {
let mut uc_opts = opts.map(|o| o.as_ffi_options_register_access());
let uc_opts_ptr = uc_opts.as_mut().map_or(ptr::null_mut(), |o| {
o as *mut ulksys::EdgeRegisterAccessOptions
});
let uc_res = unsafe {
ulksys::edge_register_access(self.inner, access.as_ffi_access(), uc_opts_ptr)
};
credentials::Gateway::from_ffi_credentials_result(uc_res)
}
}
impl Drop for Config {
fn drop(&mut self) {
unsafe {
drop(CString::from_raw(
self.inner.auth_service_address as *mut c_char,
));
if !self.inner.certificate_pem.is_null() {
drop(CString::from_raw(self.inner.certificate_pem as *mut c_char));
}
};
}
}
pub struct OptionsRegisterAccess {
pub public: bool,
}
impl OptionsRegisterAccess {
pub(crate) fn as_ffi_options_register_access(&self) -> ulksys::EdgeRegisterAccessOptions {
ulksys::EdgeRegisterAccessOptions {
is_public: self.public,
}
}
}