support ohos (#974)
Some checks failed
EasyTier Core / pre_job (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier OHOS / pre_job (push) Has been cancelled
EasyTier OHOS / build-ohos (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Core / build_web (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier Core / magisk_build (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled

* 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

@@ -29,6 +29,30 @@ fn set_error_msg(msg: &str) {
msg_buf[..len].copy_from_slice(bytes);
}
#[no_mangle]
pub extern "C" fn set_tun_fd(
inst_name: *const std::ffi::c_char,
fd: std::ffi::c_int,
) -> std::ffi::c_int {
let inst_name = unsafe {
assert!(!inst_name.is_null());
std::ffi::CStr::from_ptr(inst_name)
.to_string_lossy()
.into_owned()
};
if !INSTANCE_NAME_ID_MAP.contains_key(&inst_name) {
return -1;
}
match INSTANCE_MANAGER.set_tun_fd(&INSTANCE_NAME_ID_MAP.get(&inst_name).unwrap().value(), fd) {
Ok(_) => {
0
}
Err(_) => {
-1
}
}
}
#[no_mangle]
pub extern "C" fn get_error_msg(out: *mut *const std::ffi::c_char) {
let msg_buf = ERROR_MSG.lock().unwrap();

View File

@@ -0,0 +1,46 @@
[package]
name = "easytier-ohrs"
version = "0.1.0"
edition = "2024"
[lib]
crate-type=["cdylib"]
[dependencies]
ohos-hilog-binding = {version = "*", features = ["redirect"]}
easytier = { path = "../../easytier" }
napi-derive-ohos = "1.0.4"
napi-ohos = { version = "1.0.4", default-features = false, features = [
"serde-json",
"latin1",
"chrono_date",
"object_indexmap",
"tokio",
"async",
"tokio_rt",
"tokio_macros",
"tokio_io_util",
"deferred_trace",
"napi8",
"node_version_detect",
"web_stream",
] }
once_cell = "1.21.3"
serde_json = "1.0.125"
tracing-subscriber = "0.3.19"
tracing-core = "0.1.33"
tracing = "0.1.41"
uuid = { version = "1.17.0", features = ["v4"] }
[build-dependencies]
napi-build-ohos = "1.0.4"
[profile.dev]
panic = "unwind"
debug = true
[profile.release]
panic = "abort"
lto = true
codegen-units = 1
opt-level = 3
strip = true

View File

@@ -0,0 +1,65 @@
# OpenHarmonyOS 项目构建说明
本项目需要 OpenHarmonyOS SDK 和多个基础库支持才能成功编译。请按照以下步骤准备构建环境。
如存在任何编译问题,请前往[Easytier for OHOS](https://github.com/FrankHan052176/EasyTier)
## 前置要求
### 1. 安装 OpenHarmonyOS SDK
**SDK 下载链接**
[OpenHarmony 每日构建版本](https://ci.openharmony.cn/workbench/cicd/dailybuild/dailylist)
**版本要求**
请选择版本号 **小于 OpenHarmony_5.1.0.58** 的 ohos-sdk-full 版本
下载后请解压到适当位置(如 `/usr/local/ohos-sdk`),并记下安装路径。
### 2. 编译依赖库
在编译本项目前,需要先自行编译以下四个基础库:
- glib
- libffi
- pcre2
- zlib
这些库需要使用 OpenHarmonyOS 的工具链进行交叉编译。
## 环境配置
### 1. 设置环境变量
创建并运行以下脚本设置环境变量(请根据您的实际 SDK 安装路径修改):
```bash
#!/bin/bash
# 请修改为您的实际 SDK 路径
export OHOS_SDK_PATH="/usr/local/ohos-sdk/linux"
export OHOS_TOOLCHAIN_DIR="${OHOS_SDK_PATH}/native/llvm"
export TARGET_ARCH="aarch64-linux-ohos"
export OHOS_SYSROOT="${OHOS_SDK_PATH}/native/sysroot"
export CC="${OHOS_TOOLCHAIN_DIR}/bin/aarch64-unknown-linux-ohos-clang"
export CXX="${OHOS_TOOLCHAIN_DIR}/bin/aarch64-unknown-linux-ohos-clang++"
export AS="${OHOS_TOOLCHAIN_DIR}/bin/llvm-as"
export AR="${OHOS_TOOLCHAIN_DIR}/bin/llvm-ar"
export LD="${OHOS_TOOLCHAIN_DIR}/bin/ld.lld"
export RANLIB="${OHOS_TOOLCHAIN_DIR}/bin/llvm-ranlib"
export STRIP="${OHOS_TOOLCHAIN_DIR}/bin/llvm-strip"
export OBJDUMP="${OHOS_TOOLCHAIN_DIR}/bin/llvm-objdump"
export OBJCOPY="${OHOS_TOOLCHAIN_DIR}/bin/llvm-objcopy"
export NM="${OHOS_TOOLCHAIN_DIR}/bin/llvm-nm"
export CFLAGS="-fPIC -D__MUSL__=1 -march=armv8-a --target=${TARGET_ARCH} -Wno-error --sysroot=${OHOS_SYSROOT} -I${OHOS_SYSROOT}/usr/include/${TARGET_ARCH}"
export CXXFLAGS="${CFLAGS}"
export LDFLAGS="--sysroot=${OHOS_SYSROOT} -L${OHOS_SYSROOT}/usr/lib/${TARGET_ARCH} -fuse-ld=${LD}"
export PKG_CONFIG_PATH="${OHOS_SYSROOT}/usr/lib/pkgconfig:${OHOS_SYSROOT}/usr/local/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="${OHOS_SYSROOT}/usr/lib:${OHOS_SYSROOT}/usr/local/lib"
export PKG_CONFIG_SYSROOT_DIR="${OHOS_SYSROOT}"
export HOST_TRIPLET="${TARGET_ARCH}"
export BUILD_TRIPLET="$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)"
export PATH="${OHOS_TOOLCHAIN_DIR}/bin:${PATH}"
echo "OpenHarmonyOS 环境变量已设置:"
echo "OHOS_SDK_PATH: ${OHOS_SDK_PATH}"
echo "OHOS_TOOLCHAIN_DIR: ${OHOS_TOOLCHAIN_DIR}"
echo "OHOS_SYSROOT: ${OHOS_SYSROOT}"
echo "PKG_CONFIG_PATH: ${PKG_CONFIG_PATH}"
echo "PATH: ${PATH}"

View File

@@ -0,0 +1,3 @@
fn main () {
napi_build_ohos::setup();
}

View File

@@ -0,0 +1,31 @@
#!/bin/bash
# 请修改为您的实际 SDK 路径
export OHOS_TOOLCHAIN_DIR="${OHOS_NDK_HOME}/native/llvm"
export TARGET_ARCH="aarch64-linux-ohos"
export OHOS_SYSROOT="${OHOS_NDK_HOME}/native/sysroot"
export CC="${OHOS_TOOLCHAIN_DIR}/bin/aarch64-unknown-linux-ohos-clang"
export CXX="${OHOS_TOOLCHAIN_DIR}/bin/aarch64-unknown-linux-ohos-clang++"
export AS="${OHOS_TOOLCHAIN_DIR}/bin/llvm-as"
export AR="${OHOS_TOOLCHAIN_DIR}/bin/llvm-ar"
export LD="${OHOS_TOOLCHAIN_DIR}/bin/ld.lld"
export RANLIB="${OHOS_TOOLCHAIN_DIR}/bin/llvm-ranlib"
export STRIP="${OHOS_TOOLCHAIN_DIR}/bin/llvm-strip"
export OBJDUMP="${OHOS_TOOLCHAIN_DIR}/bin/llvm-objdump"
export OBJCOPY="${OHOS_TOOLCHAIN_DIR}/bin/llvm-objcopy"
export NM="${OHOS_TOOLCHAIN_DIR}/bin/llvm-nm"
export CFLAGS="-fPIC -D__MUSL__=1 -march=armv8-a --target=${TARGET_ARCH} -Wno-error --sysroot=${OHOS_SYSROOT} -I${OHOS_SYSROOT}/usr/include/${TARGET_ARCH}"
export CXXFLAGS="${CFLAGS}"
export LDFLAGS="--sysroot=${OHOS_SYSROOT} -L${OHOS_SYSROOT}/usr/lib/${TARGET_ARCH} -fuse-ld=${LD}"
export PKG_CONFIG_PATH="${OHOS_SYSROOT}/usr/lib/pkgconfig:${OHOS_SYSROOT}/usr/local/lib/pkgconfig"
export PKG_CONFIG_LIBDIR="${OHOS_SYSROOT}/usr/lib:${OHOS_SYSROOT}/usr/local/lib"
export PKG_CONFIG_SYSROOT_DIR="${OHOS_SYSROOT}"
export HOST_TRIPLET="${TARGET_ARCH}"
export BUILD_TRIPLET="$(dpkg-architecture -qDEB_BUILD_GNU_TYPE)"
export PATH="${OHOS_TOOLCHAIN_DIR}/bin:${PATH}"
echo "OpenHarmonyOS 环境变量已设置:"
echo "OHOS_SDK_PATH: ${OHOS_NDK_HOME}"
echo "OHOS_TOOLCHAIN_DIR: ${OHOS_TOOLCHAIN_DIR}"
echo "OHOS_SYSROOT: ${OHOS_SYSROOT}"
echo "PKG_CONFIG_PATH: ${PKG_CONFIG_PATH}"
echo "PATH: ${PATH}"

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));
}
}