mirror of
https://github.com/ZeroTier/ZeroTierOne
synced 2025-08-14 02:27:38 -07:00
add smee client
This commit is contained in:
parent
a6b764bf7c
commit
4674bb5c8b
13 changed files with 1901 additions and 1737 deletions
104
rustybits/smeeclient/src/ext.rs
Normal file
104
rustybits/smeeclient/src/ext.rs
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (c)2021 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2025-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
|
||||
use std::ffi::CStr;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use crate::NetworkJoinedParams;
|
||||
use crate::SmeeClient;
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn smee_client_new(
|
||||
temporal_url: *const c_char,
|
||||
namespace: *const c_char,
|
||||
task_queue: *const c_char,
|
||||
) -> *mut SmeeClient {
|
||||
let url = unsafe {
|
||||
assert!(!temporal_url.is_null());
|
||||
CStr::from_ptr(temporal_url).to_str().unwrap()
|
||||
};
|
||||
|
||||
let ns = unsafe {
|
||||
assert!(!namespace.is_null());
|
||||
CStr::from_ptr(namespace).to_str().unwrap()
|
||||
};
|
||||
|
||||
let tq = unsafe {
|
||||
assert!(!task_queue.is_null());
|
||||
CStr::from_ptr(task_queue).to_str().unwrap()
|
||||
};
|
||||
|
||||
match SmeeClient::new(url, ns, tq) {
|
||||
Ok(c) => Box::into_raw(Box::new(c)),
|
||||
Err(e) => {
|
||||
println!("error creating smee client instance: {}", e);
|
||||
std::ptr::null_mut()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn smee_client_delete(ptr: *mut SmeeClient) {
|
||||
if ptr.is_null() {
|
||||
return;
|
||||
}
|
||||
let smee = unsafe {
|
||||
assert!(!ptr.is_null());
|
||||
Box::from_raw(&mut *ptr)
|
||||
};
|
||||
|
||||
smee.shutdown();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn smee_client_notify_netowrk_joined(
|
||||
smee_instance: *mut SmeeClient,
|
||||
network_id: *const c_char,
|
||||
member_id: *const c_char,
|
||||
hook_url: *const c_char,
|
||||
src_ip: *const c_char,
|
||||
) -> bool {
|
||||
let nwid = unsafe {
|
||||
assert!(!network_id.is_null());
|
||||
CStr::from_ptr(network_id).to_str().unwrap()
|
||||
};
|
||||
|
||||
let mem_id = unsafe {
|
||||
assert!(!member_id.is_null());
|
||||
CStr::from_ptr(member_id).to_str().unwrap()
|
||||
};
|
||||
|
||||
let url = unsafe {
|
||||
assert!(!hook_url.is_null());
|
||||
CStr::from_ptr(hook_url).to_str().unwrap()
|
||||
};
|
||||
|
||||
let src = unsafe {
|
||||
if src_ip.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(src_ip).to_str().unwrap())
|
||||
}
|
||||
};
|
||||
|
||||
let smee = unsafe {
|
||||
assert!(!smee_instance.is_null());
|
||||
&mut *smee_instance
|
||||
};
|
||||
|
||||
let params = NetworkJoinedParams::new(nwid, mem_id, url, src);
|
||||
|
||||
match smee.notify_network_joined(params) {
|
||||
Ok(()) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
115
rustybits/smeeclient/src/lib.rs
Normal file
115
rustybits/smeeclient/src/lib.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c)2023 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2025-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
|
||||
pub mod ext;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
use temporal_client::{Client, ClientOptionsBuilder, RetryClient, WorkflowClientTrait, WorkflowOptions};
|
||||
use temporal_sdk_core_protos::{coresdk::AsJsonPayloadExt, temporal::api::enums::v1::WorkflowIdReusePolicy};
|
||||
use url::Url;
|
||||
use uuid::Uuid;
|
||||
|
||||
const CLIENT_NAME: &str = "SmeeClient-Rust";
|
||||
const CLIENT_VERSION: &str = "0.1";
|
||||
const NETWORK_JOINED_WORKFLOW: &str = "NetworkJoinedWorkflow";
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
pub struct NetworkJoinedParams {
|
||||
#[serde(rename = "NetworkID")]
|
||||
pub network_id: String,
|
||||
|
||||
#[serde(rename = "MemberID")]
|
||||
pub member_id: String,
|
||||
|
||||
#[serde(rename = "HookURL")]
|
||||
pub hook_url: String,
|
||||
|
||||
#[serde(rename = "SrcIP")]
|
||||
pub src_ip: Option<String>,
|
||||
}
|
||||
|
||||
impl NetworkJoinedParams {
|
||||
fn new(network_id: &str, member_id: &str, hook_url: &str, src_ip: Option<&str>) -> Self {
|
||||
Self {
|
||||
network_id: network_id.to_string(),
|
||||
member_id: member_id.to_string(),
|
||||
hook_url: hook_url.to_string(),
|
||||
src_ip: match src_ip {
|
||||
Some(x) => Some(x.to_string()),
|
||||
None => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SmeeClient {
|
||||
tokio_rt: tokio::runtime::Runtime,
|
||||
client: RetryClient<Client>,
|
||||
task_queue: String,
|
||||
}
|
||||
|
||||
impl SmeeClient {
|
||||
pub fn new(temporal_url: &str, namespace: &str, task_queue: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
// start tokio runtime. Required by temporal
|
||||
let rt = tokio::runtime::Runtime::new()?;
|
||||
|
||||
let c = ClientOptionsBuilder::default()
|
||||
.target_url(Url::from_str(temporal_url).unwrap())
|
||||
.client_name(CLIENT_NAME)
|
||||
.client_version(CLIENT_VERSION)
|
||||
.build()?;
|
||||
|
||||
let con = rt.block_on(async { c.connect(namespace.to_string(), None, None).await })?;
|
||||
|
||||
Ok(Self {
|
||||
tokio_rt: rt,
|
||||
client: con,
|
||||
task_queue: task_queue.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn notify_network_joined(&self, params: NetworkJoinedParams) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let options = WorkflowOptions {
|
||||
id_reuse_policy: WorkflowIdReusePolicy::RejectDuplicate,
|
||||
execution_timeout: None,
|
||||
run_timeout: None,
|
||||
task_timeout: None,
|
||||
cron_schedule: None,
|
||||
search_attributes: None,
|
||||
};
|
||||
|
||||
let payload = vec![params.as_json_payload()?];
|
||||
|
||||
let workflow_id = Uuid::new_v4();
|
||||
|
||||
self.tokio_rt.block_on(async {
|
||||
self.client
|
||||
.start_workflow(
|
||||
payload,
|
||||
self.task_queue.clone(),
|
||||
workflow_id.hyphenated().to_string(),
|
||||
String::from(NETWORK_JOINED_WORKFLOW),
|
||||
None,
|
||||
options,
|
||||
)
|
||||
.await
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn shutdown(self) {
|
||||
self.tokio_rt.shutdown_timeout(Duration::from_secs(5))
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue