mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-13 17:35:37 +00:00
294 lines
9.0 KiB
Rust
294 lines
9.0 KiB
Rust
use easytier::proto::{api, common};
|
|
use napi_derive_ohos::napi;
|
|
use serde::Serialize;
|
|
use std::collections::HashSet;
|
|
use std::sync::Mutex;
|
|
|
|
static ATTACHED_TUN_INSTANCE_IDS: once_cell::sync::Lazy<Mutex<HashSet<String>>> =
|
|
once_cell::sync::Lazy::new(|| Mutex::new(HashSet::new()));
|
|
|
|
pub fn mark_tun_attached(instance_id: &str) {
|
|
if let Ok(mut guard) = ATTACHED_TUN_INSTANCE_IDS.lock() {
|
|
guard.insert(instance_id.to_string());
|
|
}
|
|
}
|
|
|
|
pub fn clear_tun_attached(instance_id: &str) {
|
|
if let Ok(mut guard) = ATTACHED_TUN_INSTANCE_IDS.lock() {
|
|
guard.remove(instance_id);
|
|
}
|
|
}
|
|
|
|
pub fn is_tun_attached(instance_id: &str) -> bool {
|
|
ATTACHED_TUN_INSTANCE_IDS
|
|
.lock()
|
|
.map(|guard| guard.contains(instance_id))
|
|
.unwrap_or(false)
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct PeerConnStats {
|
|
pub rx_bytes: i64,
|
|
pub tx_bytes: i64,
|
|
pub rx_packets: i64,
|
|
pub tx_packets: i64,
|
|
pub latency_us: i64,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct PeerConnInfo {
|
|
pub conn_id: String,
|
|
pub my_peer_id: i64,
|
|
pub peer_id: i64,
|
|
pub features: Vec<String>,
|
|
pub tunnel_type: Option<String>,
|
|
pub local_addr: Option<String>,
|
|
pub remote_addr: Option<String>,
|
|
pub resolved_remote_addr: Option<String>,
|
|
pub stats: Option<PeerConnStats>,
|
|
pub loss_rate: Option<f64>,
|
|
pub is_client: bool,
|
|
pub network_name: Option<String>,
|
|
pub is_closed: bool,
|
|
pub secure_auth_level: Option<i32>,
|
|
pub peer_identity_type: Option<i32>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct PeerInfo {
|
|
pub peer_id: i64,
|
|
pub default_conn_id: Option<String>,
|
|
pub directly_connected_conns: Vec<String>,
|
|
pub conns: Vec<PeerConnInfo>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct RouteView {
|
|
pub peer_id: i64,
|
|
pub hostname: Option<String>,
|
|
pub ipv4: Option<String>,
|
|
pub ipv4_cidr: Option<String>,
|
|
pub ipv6_cidr: Option<String>,
|
|
pub proxy_cidrs: Vec<String>,
|
|
pub next_hop_peer_id: Option<i64>,
|
|
pub cost: Option<i32>,
|
|
pub path_latency: Option<i64>,
|
|
pub udp_nat_type: Option<i32>,
|
|
pub tcp_nat_type: Option<i32>,
|
|
pub inst_id: Option<String>,
|
|
pub version: Option<String>,
|
|
pub is_public_server: Option<bool>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct MyNodeInfo {
|
|
pub virtual_ipv4: Option<String>,
|
|
pub virtual_ipv4_cidr: Option<String>,
|
|
pub hostname: Option<String>,
|
|
pub version: Option<String>,
|
|
pub peer_id: Option<i64>,
|
|
pub listeners: Vec<String>,
|
|
pub vpn_portal_cfg: Option<String>,
|
|
pub udp_nat_type: Option<i32>,
|
|
pub tcp_nat_type: Option<i32>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct RuntimeInstanceState {
|
|
pub config_id: String,
|
|
pub instance_id: String,
|
|
pub display_name: String,
|
|
pub running: bool,
|
|
pub tun_required: bool,
|
|
pub tun_attached: bool,
|
|
pub magic_dns_enabled: bool,
|
|
pub need_exit_node: bool,
|
|
pub error_message: Option<String>,
|
|
pub my_node_info: Option<MyNodeInfo>,
|
|
pub events: Vec<String>,
|
|
pub routes: Vec<RouteView>,
|
|
pub peers: Vec<PeerInfo>,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct TunAggregateState {
|
|
pub active: bool,
|
|
pub attached_instance_ids: Vec<String>,
|
|
pub aggregated_routes: Vec<String>,
|
|
pub dns_servers: Vec<String>,
|
|
pub need_rebuild: bool,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
#[serde(rename_all = "camelCase")]
|
|
#[napi(object)]
|
|
pub struct RuntimeAggregateState {
|
|
pub instances: Vec<RuntimeInstanceState>,
|
|
pub tun: TunAggregateState,
|
|
pub running_instance_count: i32,
|
|
}
|
|
|
|
fn stringify_ipv4_inet(value: Option<common::Ipv4Inet>) -> Option<String> {
|
|
value.map(|v| v.to_string())
|
|
}
|
|
|
|
fn stringify_ipv6_inet(value: Option<common::Ipv6Inet>) -> Option<String> {
|
|
value.map(|v| v.to_string())
|
|
}
|
|
|
|
fn stringify_url(value: Option<common::Url>) -> Option<String> {
|
|
value.map(|v| v.to_string())
|
|
}
|
|
|
|
fn stringify_uuid(value: Option<common::Uuid>) -> Option<String> {
|
|
value.map(|v| v.to_string())
|
|
}
|
|
|
|
fn optional_u32_to_i64(value: Option<u32>) -> Option<i64> {
|
|
value.map(|v| v as i64)
|
|
}
|
|
|
|
fn optional_i32_to_i64(value: Option<i32>) -> Option<i64> {
|
|
value.map(|v| v as i64)
|
|
}
|
|
|
|
fn route_to_view(route: api::instance::Route) -> RouteView {
|
|
let stun = route.stun_info;
|
|
let feature_flag = route.feature_flag;
|
|
RouteView {
|
|
peer_id: route.peer_id as i64,
|
|
hostname: (!route.hostname.is_empty()).then_some(route.hostname),
|
|
ipv4: route
|
|
.ipv4_addr
|
|
.as_ref()
|
|
.and_then(|inet| inet.address.as_ref())
|
|
.map(|addr| addr.to_string()),
|
|
ipv4_cidr: stringify_ipv4_inet(route.ipv4_addr),
|
|
ipv6_cidr: stringify_ipv6_inet(route.ipv6_addr),
|
|
proxy_cidrs: route.proxy_cidrs,
|
|
next_hop_peer_id: optional_u32_to_i64(route.next_hop_peer_id_latency_first)
|
|
.or_else(|| Some(route.next_hop_peer_id as i64)),
|
|
cost: Some(route.cost),
|
|
path_latency: optional_i32_to_i64(route.path_latency_latency_first)
|
|
.or_else(|| Some(route.path_latency as i64)),
|
|
udp_nat_type: stun.as_ref().map(|info| info.udp_nat_type),
|
|
tcp_nat_type: stun.as_ref().map(|info| info.tcp_nat_type),
|
|
inst_id: (!route.inst_id.is_empty()).then_some(route.inst_id),
|
|
version: (!route.version.is_empty()).then_some(route.version),
|
|
is_public_server: feature_flag.map(|flag| flag.is_public_server),
|
|
}
|
|
}
|
|
|
|
fn peer_conn_to_view(conn: api::instance::PeerConnInfo) -> PeerConnInfo {
|
|
let stats = conn.stats.map(|stats| PeerConnStats {
|
|
rx_bytes: stats.rx_bytes as i64,
|
|
tx_bytes: stats.tx_bytes as i64,
|
|
rx_packets: stats.rx_packets as i64,
|
|
tx_packets: stats.tx_packets as i64,
|
|
latency_us: stats.latency_us as i64,
|
|
});
|
|
|
|
PeerConnInfo {
|
|
conn_id: conn.conn_id,
|
|
my_peer_id: conn.my_peer_id as i64,
|
|
peer_id: conn.peer_id as i64,
|
|
features: conn.features,
|
|
tunnel_type: conn.tunnel.as_ref().map(|t| t.tunnel_type.clone()),
|
|
local_addr: conn
|
|
.tunnel
|
|
.as_ref()
|
|
.and_then(|t| stringify_url(t.local_addr.clone())),
|
|
remote_addr: conn
|
|
.tunnel
|
|
.as_ref()
|
|
.and_then(|t| stringify_url(t.remote_addr.clone())),
|
|
resolved_remote_addr: conn
|
|
.tunnel
|
|
.as_ref()
|
|
.and_then(|t| stringify_url(t.resolved_remote_addr.clone())),
|
|
stats,
|
|
loss_rate: Some(conn.loss_rate as f64),
|
|
is_client: conn.is_client,
|
|
network_name: (!conn.network_name.is_empty()).then_some(conn.network_name),
|
|
is_closed: conn.is_closed,
|
|
secure_auth_level: Some(conn.secure_auth_level),
|
|
peer_identity_type: Some(conn.peer_identity_type),
|
|
}
|
|
}
|
|
|
|
fn peer_to_view(peer: api::instance::PeerInfo) -> PeerInfo {
|
|
PeerInfo {
|
|
peer_id: peer.peer_id as i64,
|
|
default_conn_id: stringify_uuid(peer.default_conn_id),
|
|
directly_connected_conns: peer
|
|
.directly_connected_conns
|
|
.into_iter()
|
|
.map(|id| id.to_string())
|
|
.collect(),
|
|
conns: peer.conns.into_iter().map(peer_conn_to_view).collect(),
|
|
}
|
|
}
|
|
|
|
fn my_node_info_to_view(info: api::manage::MyNodeInfo) -> MyNodeInfo {
|
|
MyNodeInfo {
|
|
virtual_ipv4: info
|
|
.virtual_ipv4
|
|
.as_ref()
|
|
.and_then(|inet| inet.address.as_ref())
|
|
.map(|addr| addr.to_string()),
|
|
virtual_ipv4_cidr: stringify_ipv4_inet(info.virtual_ipv4),
|
|
hostname: (!info.hostname.is_empty()).then_some(info.hostname),
|
|
version: (!info.version.is_empty()).then_some(info.version),
|
|
peer_id: Some(info.peer_id as i64),
|
|
listeners: info
|
|
.listeners
|
|
.into_iter()
|
|
.map(|url| url.to_string())
|
|
.collect(),
|
|
vpn_portal_cfg: info.vpn_portal_cfg,
|
|
udp_nat_type: info.stun_info.as_ref().map(|stun| stun.udp_nat_type),
|
|
tcp_nat_type: info.stun_info.as_ref().map(|stun| stun.tcp_nat_type),
|
|
}
|
|
}
|
|
|
|
pub fn runtime_instance_from_running_info(
|
|
config_id: String,
|
|
display_name: String,
|
|
magic_dns_enabled: bool,
|
|
need_exit_node: bool,
|
|
info: api::manage::NetworkInstanceRunningInfo,
|
|
) -> RuntimeInstanceState {
|
|
let tun_attached = info.running && is_tun_attached(&config_id);
|
|
let tun_required = info.running && (info.dev_name != "no_tun" || tun_attached);
|
|
|
|
RuntimeInstanceState {
|
|
config_id: config_id.clone(),
|
|
instance_id: config_id,
|
|
display_name,
|
|
running: info.running,
|
|
tun_required,
|
|
tun_attached,
|
|
magic_dns_enabled,
|
|
need_exit_node,
|
|
error_message: info.error_msg,
|
|
my_node_info: info.my_node_info.map(my_node_info_to_view),
|
|
events: info.events,
|
|
routes: info.routes.into_iter().map(route_to_view).collect(),
|
|
peers: info.peers.into_iter().map(peer_to_view).collect(),
|
|
}
|
|
}
|