allow open rpc port in gui normal mode (#1795)

* allow open rpc port for gui normal mode
* downgrade dev tool console
This commit is contained in:
KKRainbow
2026-01-16 11:12:32 +08:00
committed by GitHub
parent 53264f67bf
commit 005b321f62
11 changed files with 295 additions and 117 deletions
+2
View File
@@ -57,6 +57,8 @@ tauri-plugin-os = "2.3.0"
uuid = "1.17.0"
async-trait = "0.1.89"
url = { version = "2.5", features = ["serde"] }
[target.'cfg(target_os = "windows")'.dependencies]
windows = { version = "0.52", features = ["Win32_Foundation", "Win32_UI_Shell", "Win32_UI_WindowsAndMessaging"] }
winapi = { version = "0.3.9", features = ["securitybaseapi", "processthreadsapi"] }
+88 -25
View File
@@ -19,11 +19,13 @@ use easytier::{
launcher::NetworkConfig,
rpc_service::ApiRpcServer,
tunnel::ring::RingTunnelListener,
tunnel::tcp::TcpTunnelListener,
tunnel::TunnelListener,
utils::{self},
};
use std::ops::Deref;
use std::sync::Arc;
use tokio::sync::{RwLock, RwLockReadGuard};
use tokio::sync::{Mutex, RwLock, RwLockReadGuard};
use uuid::Uuid;
use tauri::{AppHandle, Emitter, Manager as _};
@@ -40,8 +42,21 @@ static RPC_RING_UUID: once_cell::sync::Lazy<uuid::Uuid> =
static CLIENT_MANAGER: once_cell::sync::Lazy<RwLock<Option<manager::GUIClientManager>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
static RING_RPC_SERVER: once_cell::sync::Lazy<RwLock<Option<ApiRpcServer<RingTunnelListener>>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
type BoxedTunnelListener = Box<dyn TunnelListener>;
#[derive(Clone, Copy, PartialEq, Eq)]
enum RpcServerKind {
Ring,
Tcp,
}
struct RpcServer {
kind: RpcServerKind,
_server: ApiRpcServer<BoxedTunnelListener>,
bind_url: Option<url::Url>,
}
static RPC_SERVER: once_cell::sync::Lazy<Mutex<Option<RpcServer>>> =
once_cell::sync::Lazy::new(|| Mutex::new(None));
static WEB_CLIENT: once_cell::sync::Lazy<RwLock<Option<WebClient>>> =
once_cell::sync::Lazy::new(|| RwLock::new(None));
@@ -322,8 +337,25 @@ fn get_service_status() -> Result<&'static str, String> {
}
}
fn normalize_normal_mode_rpc_portal(portal: &str) -> Result<(url::Url, url::Url), String> {
let portal_url: url::Url = portal
.parse()
.map_err(|e| format!("invalid rpc portal: {:#}", e))?;
let bind_url = portal_url.clone();
let mut connect_url = portal_url.clone();
// if bind addr is 0.0.0.0, should convert to 127.0.0.1
if connect_url.host_str() == Some("0.0.0.0") {
connect_url.set_host(Some("127.0.0.1")).unwrap();
}
Ok((bind_url, connect_url))
}
#[tauri::command]
async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(), String> {
async fn init_rpc_connection(
_app: AppHandle,
is_normal_mode: bool,
url: Option<String>,
) -> Result<(), String> {
let mut client_manager_guard =
tokio::time::timeout(std::time::Duration::from_secs(5), CLIENT_MANAGER.write())
.await
@@ -331,41 +363,72 @@ async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(),
let mut instance_manager_guard = INSTANCE_MANAGER
.try_write()
.map_err(|_| "Failed to acquire write lock for instance manager")?;
let mut ring_rpc_server_guard = RING_RPC_SERVER
.try_write()
.map_err(|_| "Failed to acquire write lock for ring rpc server")?;
let mut rpc_server_guard = RPC_SERVER
.try_lock()
.map_err(|_| "Failed to acquire lock for rpc server")?;
let normal_mode = url.is_none();
if normal_mode {
let mut client_url = url.clone();
if is_normal_mode {
let instance_manager = if let Some(im) = instance_manager_guard.take() {
im
} else {
Arc::new(NetworkInstanceManager::new())
};
let rpc_server = if let Some(rpc_server) = ring_rpc_server_guard.take() {
rpc_server
let portal = url.and_then(|s| {
let trimmed = s.trim().to_string();
if trimmed.is_empty() {
None
} else {
Some(trimmed)
}
});
let (desired_kind, bind_url, connect_url) = if let Some(portal) = portal {
let (bind_url, connect_url) = normalize_normal_mode_rpc_portal(&portal)?;
(RpcServerKind::Tcp, Some(bind_url), Some(connect_url))
} else {
ApiRpcServer::from_tunnel(
RingTunnelListener::new(
format!("ring://{}", RPC_RING_UUID.deref()).parse().unwrap(),
),
instance_manager.clone(),
)
.with_rx_timeout(None)
.serve()
.await
.map_err(|e| e.to_string())?
(RpcServerKind::Ring, None, None)
};
let need_restart = rpc_server_guard
.as_ref()
.map(|x| x.kind != desired_kind || x.bind_url != bind_url)
.unwrap_or(true);
if need_restart {
*rpc_server_guard = None;
let tunnel: BoxedTunnelListener = match desired_kind {
RpcServerKind::Ring => Box::new(RingTunnelListener::new(
format!("ring://{}", RPC_RING_UUID.deref()).parse().unwrap(),
)),
RpcServerKind::Tcp => Box::new(TcpTunnelListener::new(
bind_url.clone().expect("tcp rpc must have bind url"),
)),
};
let rpc_server = ApiRpcServer::from_tunnel(tunnel, instance_manager.clone())
.with_rx_timeout(None)
.serve()
.await
.map_err(|e| e.to_string())?;
*rpc_server_guard = Some(RpcServer {
kind: desired_kind,
_server: rpc_server,
bind_url,
});
}
*instance_manager_guard = Some(instance_manager);
*ring_rpc_server_guard = Some(rpc_server);
client_url = connect_url.map(|u| u.to_string());
} else {
*ring_rpc_server_guard = None;
*rpc_server_guard = None;
}
let client_manager = tokio::time::timeout(
std::time::Duration::from_millis(1000),
manager::GUIClientManager::new(url),
manager::GUIClientManager::new(client_url),
)
.await
.map_err(|_| "connect remote rpc timed out".to_string())?
@@ -373,7 +436,7 @@ async fn init_rpc_connection(_app: AppHandle, url: Option<String>) -> Result<(),
.map_err(|e| format!("{:#}", e))?;
*client_manager_guard = Some(client_manager);
if !normal_mode {
if !is_normal_mode {
drop(WEB_CLIENT.write().await.take());
if let Some(instance_manager) = instance_manager_guard.take() {
instance_manager