mirror of
https://github.com/clash-verge-rev/clash-verge-rev
synced 2025-05-05 07:03:45 +08:00
refactor: use of Mihomo API with socket-based communication
This commit is contained in:
parent
2fa90ef29e
commit
a58020fb52
@ -18,6 +18,9 @@
|
|||||||
- 外部控制的开关
|
- 外部控制的开关
|
||||||
- 使用 socks 进行内核通信,以解决各种潜在的内核通信异常
|
- 使用 socks 进行内核通信,以解决各种潜在的内核通信异常
|
||||||
|
|
||||||
|
#### 重构了:
|
||||||
|
- Mihomo 内核不再使用 http 交互,而是使用 socket 进行通信
|
||||||
|
|
||||||
|
|
||||||
## v2.2.3
|
## v2.2.3
|
||||||
|
|
||||||
|
53
src-tauri/Cargo.lock
generated
53
src-tauri/Cargo.lock
generated
@ -1824,6 +1824,12 @@ dependencies = [
|
|||||||
"litrs",
|
"litrs",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dotenv"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
@ -2913,7 +2919,7 @@ dependencies = [
|
|||||||
"httpdate",
|
"httpdate",
|
||||||
"itoa 1.0.15",
|
"itoa 1.0.15",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.8",
|
"socket2 0.4.10",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -2933,6 +2939,7 @@ dependencies = [
|
|||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"httparse",
|
"httparse",
|
||||||
|
"httpdate",
|
||||||
"itoa 1.0.15",
|
"itoa 1.0.15",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
@ -2988,9 +2995,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.10"
|
version = "0.1.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
|
checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@ -2998,13 +3005,29 @@ dependencies = [
|
|||||||
"http 1.3.1",
|
"http 1.3.1",
|
||||||
"http-body 1.0.1",
|
"http-body 1.0.1",
|
||||||
"hyper 1.6.0",
|
"hyper 1.6.0",
|
||||||
|
"libc",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2 0.5.8",
|
"socket2 0.5.9",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyperlocal"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
|
||||||
|
dependencies = [
|
||||||
|
"hex",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper 1.6.0",
|
||||||
|
"hyper-util",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iana-time-zone"
|
name = "iana-time-zone"
|
||||||
version = "0.1.62"
|
version = "0.1.62"
|
||||||
@ -3852,10 +3875,18 @@ dependencies = [
|
|||||||
name = "mihomo_api"
|
name = "mihomo_api"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"async-trait",
|
||||||
"serde",
|
"dotenv",
|
||||||
|
"futures",
|
||||||
|
"http-body-util",
|
||||||
|
"hyper 1.6.0",
|
||||||
|
"hyper-util",
|
||||||
|
"hyperlocal",
|
||||||
|
"lazy_static",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -5344,7 +5375,7 @@ dependencies = [
|
|||||||
"quinn-udp",
|
"quinn-udp",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
"rustls",
|
"rustls",
|
||||||
"socket2 0.5.8",
|
"socket2 0.5.9",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -5380,7 +5411,7 @@ dependencies = [
|
|||||||
"cfg_aliases 0.2.1",
|
"cfg_aliases 0.2.1",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2 0.5.8",
|
"socket2 0.5.9",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
@ -6484,9 +6515,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.5.8"
|
version = "0.5.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
@ -7484,7 +7515,7 @@ dependencies = [
|
|||||||
"parking_lot",
|
"parking_lot",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"socket2 0.5.8",
|
"socket2 0.5.9",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"tracing",
|
"tracing",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
|
@ -2,6 +2,7 @@ use super::CmdResult;
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::*, core::*, feat, module::mihomo::MihomoManager, process::AsyncHandler, wrap_err,
|
config::*, core::*, feat, module::mihomo::MihomoManager, process::AsyncHandler, wrap_err,
|
||||||
};
|
};
|
||||||
|
use mihomo_api::model::MihomoClient;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
|
|
||||||
/// 复制Clash环境变量
|
/// 复制Clash环境变量
|
||||||
@ -70,6 +71,7 @@ pub async fn clash_api_get_proxy_delay(
|
|||||||
MihomoManager::global()
|
MihomoManager::global()
|
||||||
.test_proxy_delay(&name, url, timeout)
|
.test_proxy_delay(&name, url, timeout)
|
||||||
.await
|
.await
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 测试URL延迟
|
/// 测试URL延迟
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
|
use mihomo_api::model::MihomoClient;
|
||||||
|
|
||||||
use super::CmdResult;
|
use super::CmdResult;
|
||||||
use crate::module::mihomo::MihomoManager;
|
use crate::module::mihomo::MihomoManager;
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_proxies() -> CmdResult<serde_json::Value> {
|
pub async fn get_proxies() -> CmdResult<serde_json::Value> {
|
||||||
let mannager = MihomoManager::global();
|
let manager = MihomoManager::global();
|
||||||
|
manager.refresh_proxies().await.map_err(|e| e.to_string())?;
|
||||||
mannager
|
let data = manager.get_data_proxies().await;
|
||||||
.refresh_proxies()
|
Ok(data)
|
||||||
.await
|
|
||||||
.map(|_| mannager.get_proxies())
|
|
||||||
.or_else(|_| Ok(mannager.get_proxies()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn get_providers_proxies() -> CmdResult<serde_json::Value> {
|
pub async fn get_providers_proxies() -> CmdResult<serde_json::Value> {
|
||||||
let mannager = MihomoManager::global();
|
let manager = MihomoManager::global();
|
||||||
|
manager
|
||||||
mannager
|
|
||||||
.refresh_providers_proxies()
|
.refresh_providers_proxies()
|
||||||
.await
|
.await
|
||||||
.map(|_| mannager.get_providers_proxies())
|
.map_err(|e| e.to_string())?;
|
||||||
.or_else(|_| Ok(mannager.get_providers_proxies()))
|
let data = manager.get_data_providers_proxies().await;
|
||||||
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,10 @@ impl IClashTemp {
|
|||||||
map.insert("ipv6".into(), true.into());
|
map.insert("ipv6".into(), true.into());
|
||||||
map.insert("mode".into(), "rule".into());
|
map.insert("mode".into(), "rule".into());
|
||||||
map.insert("external-controller".into(), "127.0.0.1:9097".into());
|
map.insert("external-controller".into(), "127.0.0.1:9097".into());
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
map.insert("external-controller-unix".into(), "mihomo.sock".into());
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
map.insert("external-controller-pipe".into(), r"\\.\pipe\mihomo".into());
|
||||||
let mut cors_map = Mapping::new();
|
let mut cors_map = Mapping::new();
|
||||||
cors_map.insert("allow-private-network".into(), true.into());
|
cors_map.insert("allow-private-network".into(), true.into());
|
||||||
cors_map.insert("allow-origins".into(), vec!["*"].into());
|
cors_map.insert("allow-origins".into(), vec!["*"].into());
|
||||||
|
@ -15,6 +15,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use mihomo_api::model::MihomoClient;
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::{fmt, path::PathBuf, sync::Arc};
|
use std::{fmt, path::PathBuf, sync::Arc};
|
||||||
use tauri_plugin_shell::{process::CommandChild, ShellExt};
|
use tauri_plugin_shell::{process::CommandChild, ShellExt};
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
process::AsyncHandler,
|
process::AsyncHandler,
|
||||||
utils::{logging::Type, resolve},
|
utils::{logging::Type, resolve},
|
||||||
};
|
};
|
||||||
|
use mihomo_api::model::MihomoClient;
|
||||||
use serde_yaml::{Mapping, Value};
|
use serde_yaml::{Mapping, Value};
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use mihomo_api::model::MihomoClient;
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use crate::AppHandleManager;
|
use crate::AppHandleManager;
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -74,12 +76,11 @@ pub fn quit() {
|
|||||||
"enable": false
|
"enable": false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
timeout(
|
|
||||||
Duration::from_secs(1),
|
let patch_future =
|
||||||
MihomoManager::global().patch_configs(disable_tun),
|
async { MihomoManager::global().patch_configs(disable_tun).await };
|
||||||
)
|
|
||||||
.await
|
timeout(Duration::from_secs(1), patch_future).await.is_ok()
|
||||||
.is_ok()
|
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::config::Config;
|
use crate::{config::Config, utils::dirs::app_socket_path};
|
||||||
use mihomo_api;
|
use mihomo_api;
|
||||||
use once_cell::sync::{Lazy, OnceCell};
|
use once_cell::sync::{Lazy, OnceCell};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
@ -24,20 +24,18 @@ impl MihomoManager {
|
|||||||
&INSTANCE
|
&INSTANCE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn global() -> mihomo_api::MihomoManager {
|
pub fn global() -> &'static mihomo_api::MihomoManager {
|
||||||
let instance = MihomoManager::__global();
|
let instance = MihomoManager::__global();
|
||||||
let (current_server, headers) = MihomoManager::get_clash_client_info().unwrap();
|
|
||||||
|
|
||||||
let lock = instance.mihomo.lock().unwrap();
|
let mihomo = &instance.mihomo;
|
||||||
if let Some(mihomo) = lock.get() {
|
let lock = mihomo.lock().unwrap();
|
||||||
if mihomo.get_mihomo_server() == current_server {
|
|
||||||
return mihomo.clone();
|
if lock.get().is_none() {
|
||||||
}
|
let socket_path = MihomoManager::get_socket_path();
|
||||||
|
lock.set(mihomo_api::MihomoManager::new(socket_path)).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.set(mihomo_api::MihomoManager::new(current_server, headers))
|
unsafe { std::mem::transmute(lock.get().unwrap()) }
|
||||||
.ok();
|
|
||||||
lock.get().unwrap().clone()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,4 +65,12 @@ impl MihomoManager {
|
|||||||
let token = http::header::HeaderValue::from_str(&auth).unwrap();
|
let token = http::header::HeaderValue::from_str(&auth).unwrap();
|
||||||
(ws_url, token)
|
(ws_url, token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_socket_path() -> String {
|
||||||
|
#[cfg(unix)]
|
||||||
|
let socket_path = app_socket_path().unwrap();
|
||||||
|
#[cfg(windows)]
|
||||||
|
let socket_path = r"\\.\pipe\mihomo";
|
||||||
|
socket_path
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,3 +179,10 @@ pub fn get_encryption_key() -> Result<Vec<u8>> {
|
|||||||
Ok(key)
|
Ok(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn app_socket_path() -> Result<String> {
|
||||||
|
let app_dir = app_home_dir()?;
|
||||||
|
let socket_path = app_dir.join("mihomo.sock");
|
||||||
|
let socket_path = path_to_str(&socket_path)?;
|
||||||
|
Ok(socket_path.to_string())
|
||||||
|
}
|
||||||
|
@ -15,8 +15,7 @@ use parking_lot::RwLock;
|
|||||||
use percent_encoding::percent_decode_str;
|
use percent_encoding::percent_decode_str;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_yaml::Mapping;
|
use serde_yaml::Mapping;
|
||||||
use std::net::TcpListener;
|
use std::{net::TcpListener, sync::Arc};
|
||||||
use std::sync::Arc;
|
|
||||||
use tauri::{App, Manager};
|
use tauri::{App, Manager};
|
||||||
|
|
||||||
use tauri::Url;
|
use tauri::Url;
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
$pipeName = "\\.\pipe\mihomo"
|
|
||||||
$pipe = new-object System.IO.Pipes.NamedPipeClientStream(".", "mihomo", [System.IO.Pipes.PipeDirection]::InOut)
|
|
||||||
$pipe.Connect(1000) # 尝试连接 1 秒
|
|
||||||
if ($pipe.IsConnected) {
|
|
||||||
Write-Host "成功连接到管道"
|
|
||||||
# 示例写入或读取可以加上如下内容
|
|
||||||
# $writer = new-object System.IO.StreamWriter($pipe)
|
|
||||||
# $writer.WriteLine("hello pipe")
|
|
||||||
# $writer.Flush()
|
|
||||||
$pipe.Close()
|
|
||||||
} else {
|
|
||||||
Write-Host "连接失败"
|
|
||||||
}
|
|
@ -42,8 +42,7 @@
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub use model::E;
|
pub use model::{E, MihomoData, MihomoManager};
|
||||||
pub use model::MihomoData;
|
pub mod platform;
|
||||||
pub use model::MihomoManager;
|
|
||||||
pub mod sock;
|
pub mod sock;
|
||||||
pub mod platform;
|
pub use platform::Client;
|
||||||
|
@ -40,7 +40,7 @@ pub trait MihomoClient: Sized {
|
|||||||
async fn refresh_proxies(&self) -> Result<&Self, E>;
|
async fn refresh_proxies(&self) -> Result<&Self, E>;
|
||||||
async fn refresh_providers_proxies(&self) -> Result<&Self, E>;
|
async fn refresh_providers_proxies(&self) -> Result<&Self, E>;
|
||||||
async fn get_connections(&self) -> Result<Value, E>;
|
async fn get_connections(&self) -> Result<Value, E>;
|
||||||
async fn delete_connections(&self, id: &str) -> Result<(), E>;
|
async fn delete_connection(&self, id: &str) -> Result<(), E>;
|
||||||
async fn test_proxy_delay(
|
async fn test_proxy_delay(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
use crate::model::E;
|
use crate::{model::E, platform::Client};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use hyper::Method;
|
use hyper::Method;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use crate::platform::Client;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
MihomoData,
|
MihomoData,
|
||||||
@ -47,7 +46,9 @@ impl MihomoClient for MihomoManager {
|
|||||||
body: Option<Value>,
|
body: Option<Value>,
|
||||||
) -> Result<Value, E> {
|
) -> Result<Value, E> {
|
||||||
let client = self.client.lock().await;
|
let client = self.client.lock().await;
|
||||||
client.send_request(self.socket_path.clone(), path, method, body).await
|
client
|
||||||
|
.send_request(self.socket_path.clone(), path, method, body)
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_version(&self) -> Result<Value, E> {
|
async fn get_version(&self) -> Result<Value, E> {
|
||||||
@ -96,7 +97,7 @@ impl MihomoClient for MihomoManager {
|
|||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn delete_connections(&self, id: &str) -> Result<(), E> {
|
async fn delete_connection(&self, id: &str) -> Result<(), E> {
|
||||||
let _ = self
|
let _ = self
|
||||||
.send_request(&format!("/connections/{}", id), Method::DELETE, None)
|
.send_request(&format!("/connections/{}", id), Method::DELETE, None)
|
||||||
.await?;
|
.await?;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user