Refactor proxy handling and update related UI flows
This commit is contained in:
@@ -219,6 +219,13 @@ pub struct PingSingBoxServerInputDto {
|
||||
pub tag: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PingProxyTargetInputDto {
|
||||
pub host: String,
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PingServerResponse {
|
||||
@@ -619,6 +626,11 @@ pub fn ping_all_singbox_servers(
|
||||
ping_all_singbox_servers_in_storage(&state.storage())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn ping_proxy_target(input: PingProxyTargetInputDto) -> Result<PingServerResponse, CommandError> {
|
||||
ping_proxy_target_endpoint(input)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn generate_singbox_config(
|
||||
state: tauri::State<'_, CommandState>,
|
||||
@@ -1115,6 +1127,20 @@ pub fn ping_all_singbox_servers_in_storage(
|
||||
Ok(cache.servers.iter().map(ping_subscription_server).collect())
|
||||
}
|
||||
|
||||
pub fn ping_proxy_target_endpoint(
|
||||
input: PingProxyTargetInputDto,
|
||||
) -> Result<PingServerResponse, CommandError> {
|
||||
let host = input.host.trim();
|
||||
if host.is_empty() {
|
||||
return Err(CommandError::new(
|
||||
"proxy_target_host_missing",
|
||||
"Хост внешнего прокси не указан.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ping_endpoint("external-proxy", host, input.port))
|
||||
}
|
||||
|
||||
pub fn generate_singbox_config_with_services<C>(
|
||||
storage: &JsonStorage,
|
||||
adapter: &SingBoxAdapter,
|
||||
@@ -1196,14 +1222,18 @@ fn validate_subscription_url(subscription_url: &str) -> Result<(), CommandError>
|
||||
}
|
||||
|
||||
fn ping_subscription_server(server: &SubscriptionServer) -> PingServerResponse {
|
||||
ping_endpoint(&server.tag, &server.server, server.server_port)
|
||||
}
|
||||
|
||||
fn ping_endpoint(tag: &str, server: &str, server_port: u16) -> PingServerResponse {
|
||||
let started = Instant::now();
|
||||
let addresses = match (server.server.as_str(), server.server_port).to_socket_addrs() {
|
||||
let addresses = match (server, server_port).to_socket_addrs() {
|
||||
Ok(addresses) => addresses.collect::<Vec<_>>(),
|
||||
Err(error) => {
|
||||
return PingServerResponse {
|
||||
tag: server.tag.clone(),
|
||||
server: server.server.clone(),
|
||||
server_port: server.server_port,
|
||||
tag: tag.to_string(),
|
||||
server: server.to_string(),
|
||||
server_port,
|
||||
ok: false,
|
||||
latency: None,
|
||||
error: Some(format!("DNS/адрес недоступен: {error}")),
|
||||
@@ -1213,9 +1243,9 @@ fn ping_subscription_server(server: &SubscriptionServer) -> PingServerResponse {
|
||||
|
||||
if addresses.is_empty() {
|
||||
return PingServerResponse {
|
||||
tag: server.tag.clone(),
|
||||
server: server.server.clone(),
|
||||
server_port: server.server_port,
|
||||
tag: tag.to_string(),
|
||||
server: server.to_string(),
|
||||
server_port,
|
||||
ok: false,
|
||||
latency: None,
|
||||
error: Some("DNS не вернул адреса".to_string()),
|
||||
@@ -1228,9 +1258,9 @@ fn ping_subscription_server(server: &SubscriptionServer) -> PingServerResponse {
|
||||
match TcpStream::connect_timeout(&address, timeout) {
|
||||
Ok(_) => {
|
||||
return PingServerResponse {
|
||||
tag: server.tag.clone(),
|
||||
server: server.server.clone(),
|
||||
server_port: server.server_port,
|
||||
tag: tag.to_string(),
|
||||
server: server.to_string(),
|
||||
server_port,
|
||||
ok: true,
|
||||
latency: Some(started.elapsed().as_millis()),
|
||||
error: None,
|
||||
@@ -1241,9 +1271,9 @@ fn ping_subscription_server(server: &SubscriptionServer) -> PingServerResponse {
|
||||
}
|
||||
|
||||
PingServerResponse {
|
||||
tag: server.tag.clone(),
|
||||
server: server.server.clone(),
|
||||
server_port: server.server_port,
|
||||
tag: tag.to_string(),
|
||||
server: server.to_string(),
|
||||
server_port,
|
||||
ok: false,
|
||||
latency: None,
|
||||
error: last_error,
|
||||
|
||||
@@ -52,6 +52,7 @@ fn main() {
|
||||
commands::select_singbox_server,
|
||||
commands::ping_singbox_server,
|
||||
commands::ping_all_singbox_servers,
|
||||
commands::ping_proxy_target,
|
||||
commands::generate_singbox_config,
|
||||
commands::apply_profiles,
|
||||
commands::get_logs,
|
||||
|
||||
@@ -37,6 +37,7 @@ use models::{
|
||||
use proxifyre::ProxiFyreAdapter;
|
||||
use std::collections::HashSet;
|
||||
use std::fs;
|
||||
use std::net::TcpListener;
|
||||
use std::path::{Path, PathBuf};
|
||||
#[cfg(windows)]
|
||||
use std::process::Command as ProcessCommand;
|
||||
@@ -127,6 +128,24 @@ fn resolve_preview_returns_structured_apps_without_filesystem_scan() {
|
||||
.any(|warning| warning.contains("Сканирование папок отложено")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ping_proxy_target_reports_open_tcp_endpoint() {
|
||||
let listener = TcpListener::bind("127.0.0.1:0").expect("bind local listener");
|
||||
let port = listener.local_addr().expect("read local addr").port();
|
||||
|
||||
let result = commands::ping_proxy_target_endpoint(commands::PingProxyTargetInputDto {
|
||||
host: "127.0.0.1".to_string(),
|
||||
port,
|
||||
})
|
||||
.expect("ping should return response");
|
||||
|
||||
assert_eq!(result.tag, "external-proxy");
|
||||
assert_eq!(result.server, "127.0.0.1");
|
||||
assert_eq!(result.server_port, port);
|
||||
assert!(result.ok);
|
||||
assert!(result.latency.is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(windows)]
|
||||
fn proxifyre_install_script_parses_as_powershell() {
|
||||
|
||||
@@ -184,6 +184,12 @@ export function pingAllSingBoxServers(): Promise<PingServerResponse[]> {
|
||||
return invoke<PingServerResponse[]>('ping_all_singbox_servers');
|
||||
}
|
||||
|
||||
export function pingProxyTarget(host: string, port: number): Promise<PingServerResponse> {
|
||||
return invoke<PingServerResponse>('ping_proxy_target', {
|
||||
input: { host, port },
|
||||
});
|
||||
}
|
||||
|
||||
export function generateSingBoxConfig(): Promise<GenerateSingBoxConfigResponse> {
|
||||
return invoke<GenerateSingBoxConfigResponse>('generate_singbox_config');
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user