support ohos (#974)

* support ohos

---------

Co-authored-by: FrankHan <2777926911@qq.com>
This commit is contained in:
韩嘉乐
2025-07-02 09:44:45 +08:00
committed by GitHub
parent bf021a9ead
commit 01e491ec07
22 changed files with 668 additions and 21 deletions

View File

@@ -0,0 +1,148 @@
mod native_log;
use easytier::common::config::{ConfigLoader, TomlConfigLoader};
use easytier::instance_manager::NetworkInstanceManager;
use easytier::launcher::ConfigSource;
use napi_derive_ohos::napi;
use ohos_hilog_binding::{hilog_debug, hilog_error};
use std::format;
use uuid::Uuid;
static INSTANCE_MANAGER: once_cell::sync::Lazy<NetworkInstanceManager> =
once_cell::sync::Lazy::new(NetworkInstanceManager::new);
#[napi(object)]
pub struct KeyValuePair {
pub key: String,
pub value: String,
}
#[napi]
pub fn set_tun_fd(
inst_id: String,
fd: i32,
) -> bool {
match Uuid::try_parse(&inst_id) {
Ok(uuid) => {
match INSTANCE_MANAGER.set_tun_fd(&uuid, fd) {
Ok(_) => {
hilog_debug!("[Rust] set tun fd {} to {}.", fd, inst_id);
true
}
Err(e) => {
hilog_error!("[Rust] cant set tun fd {} to {}. {}", fd, inst_id, e);
false
}
}
}
Err(e) => {
hilog_error!("[Rust] cant covert {} to uuid. {}", inst_id, e);
false
}
}
}
#[napi]
pub fn parse_config(cfg_str: String) -> bool {
match TomlConfigLoader::new_from_str(&cfg_str) {
Ok(_) => {
true
}
Err(e) => {
hilog_error!("[Rust] parse config failed {}", e);
false
}
}
}
#[napi]
pub fn run_network_instance(cfg_str: String) -> bool {
let cfg = match TomlConfigLoader::new_from_str(&cfg_str) {
Ok(cfg) => cfg,
Err(e) => {
hilog_error!("[Rust] parse config failed {}", e);
return false;
}
};
if INSTANCE_MANAGER.list_network_instance_ids().len() > 0 {
hilog_error!("[Rust] there is a running instance!");
return false;
}
let inst_id = cfg.get_id();
if INSTANCE_MANAGER
.list_network_instance_ids()
.contains(&inst_id)
{
return false;
}
INSTANCE_MANAGER
.run_network_instance(cfg, ConfigSource::FFI)
.unwrap();
true
}
#[napi]
pub fn stop_network_instance(inst_names: Vec<String>) {
INSTANCE_MANAGER
.delete_network_instance(
inst_names
.into_iter()
.filter_map(|s| Uuid::parse_str(&s).ok())
.collect(),
)
.unwrap();
hilog_debug!("[Rust] stop_network_instance");
}
#[napi]
pub fn collect_network_infos() -> Vec<KeyValuePair> {
let mut result = Vec::new();
match INSTANCE_MANAGER.collect_network_infos() {
Ok(map) => {
for (uuid, info) in map.iter() {
// convert value to json string
let value = match serde_json::to_string(&info) {
Ok(value) => value,
Err(e) => {
hilog_error!("[Rust] failed to serialize instance {} info: {}", uuid, e);
continue;
}
};
result.push(KeyValuePair {
key: uuid.clone().to_string(),
value: value.clone(),
});
}
}
Err(_) => {}
}
result
}
#[napi]
pub fn collect_running_network() -> Vec<String> {
INSTANCE_MANAGER
.list_network_instance_ids()
.clone()
.into_iter()
.map(|id| id.to_string())
.collect()
}
#[napi]
pub fn is_running_network(inst_id: String) -> bool {
match Uuid::try_parse(&inst_id) {
Ok(uuid) => {
INSTANCE_MANAGER
.list_network_instance_ids()
.contains(&uuid)
}
Err(e) => {
hilog_error!("[Rust] cant covert {} to uuid. {}", inst_id, e);
false
}
}
}

View File

@@ -0,0 +1,98 @@
use std::collections::HashMap;
use std::panic;
use napi_derive_ohos::napi;
use ohos_hilog_binding::{hilog_debug, hilog_error, hilog_info, hilog_warn, set_global_options, LogOptions};
use tracing::{Event, Subscriber};
use tracing_core::Level;
use tracing_subscriber::layer::{Context, Layer};
use tracing_subscriber::prelude::*;
static INITIALIZED: std::sync::Once = std::sync::Once::new();
fn panic_hook(info: &panic::PanicHookInfo) {
hilog_error!("RUST PANIC: {}", info);
}
#[napi]
pub fn init_panic_hook() {
INITIALIZED.call_once(|| {
panic::set_hook(Box::new(panic_hook));
});
}
#[napi]
pub fn hilog_global_options(
domain: u32,
tag: String,
) {
ohos_hilog_binding::forward_stdio_to_hilog();
set_global_options(LogOptions{
domain,
tag: Box::leak(tag.clone().into_boxed_str()),
})
}
#[napi]
pub fn init_tracing_subscriber() {
tracing_subscriber::registry()
.with(
CallbackLayer {
callback: Box::new(tracing_callback),
}
)
.init();
}
fn tracing_callback(event: &Event, fields: HashMap<String, String>) {
let metadata = event.metadata();
#[cfg(target_env = "ohos")]
{
let loc = metadata.target().split("::").last().unwrap();
match *metadata.level() {
Level::TRACE => {
hilog_debug!("[{}] {:?}", loc, fields.values().collect::<Vec<_>>());
}
Level::DEBUG => {
hilog_debug!("[{}] {:?}", loc, fields.values().collect::<Vec<_>>());
}
Level::INFO => {
hilog_info!("[{}] {:?}", loc, fields.values().collect::<Vec<_>>());
}
Level::WARN => {
hilog_warn!("[{}] {:?}", loc, fields.values().collect::<Vec<_>>());
}
Level::ERROR => {
hilog_error!("[{}] {:?}", loc, fields.values().collect::<Vec<_>>());
}
}
}
}
struct CallbackLayer {
callback: Box<dyn Fn(&Event, HashMap<String, String>) + Send + Sync>,
}
impl<S: Subscriber> Layer<S> for CallbackLayer {
fn on_event(&self, event: &Event, _ctx: Context<S>) {
// 使用 fmt::format::FmtSpan 提取字段值
let mut fields = HashMap::new();
let mut visitor = FieldCollector(&mut fields);
event.record(&mut visitor);
(self.callback)(event, fields);
}
}
struct FieldCollector<'a>(&'a mut HashMap<String, String>);
impl<'a> tracing::field::Visit for FieldCollector<'a> {
fn record_i64(&mut self, field: &tracing::field::Field, value: i64) {
self.0.insert(field.name().to_string(), value.to_string());
}
fn record_str(&mut self, field: &tracing::field::Field, value: &str) {
self.0.insert(field.name().to_string(), value.to_string());
}
fn record_debug(&mut self, field: &tracing::field::Field, value: &dyn std::fmt::Debug) {
self.0.insert(field.name().to_string(), format!("{:?}", value));
}
}