Refactor proxy routing and session management

This commit is contained in:
2026-07-08 00:09:38 +03:00
parent c5bdb10445
commit b45dd2ae05
26 changed files with 5193 additions and 307 deletions

View File

@@ -1,5 +1,10 @@
use serde::{Deserialize, Serialize};
pub const DEFAULT_LOCAL_SINGBOX_LISTEN_HOST: &str = "127.0.0.1";
pub const DEFAULT_LOCAL_SINGBOX_LISTEN_PORT: u16 = 1080;
pub const DEFAULT_LOCAL_SINGBOX_SERVICE_NAME: &str = "VpnProxySingBox";
pub const DEFAULT_LOCAL_SINGBOX_INSTALL_ROOT: &str = r"C:\Program Files\VpnProxy\sing-box";
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum Protocol {
@@ -128,6 +133,65 @@ pub struct ComponentStatus {
pub actions: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct LocalSingBoxConfig {
#[serde(default)]
pub subscription_url: Option<String>,
#[serde(default)]
pub selected_server_tag: Option<String>,
#[serde(default = "default_local_singbox_listen_host")]
pub listen_host: String,
#[serde(default = "default_local_singbox_listen_port")]
pub listen_port: u16,
#[serde(default = "default_local_singbox_service_name")]
pub service_name: String,
#[serde(default = "default_local_singbox_install_root")]
pub install_root: String,
#[serde(default)]
pub updated_at: Option<String>,
}
impl LocalSingBoxConfig {
pub fn subscription_display_url(&self) -> Option<String> {
self.subscription_url
.as_deref()
.map(redact_subscription_url)
}
}
impl Default for LocalSingBoxConfig {
fn default() -> Self {
Self {
subscription_url: None,
selected_server_tag: None,
listen_host: default_local_singbox_listen_host(),
listen_port: default_local_singbox_listen_port(),
service_name: default_local_singbox_service_name(),
install_root: default_local_singbox_install_root(),
updated_at: None,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SubscriptionCache {
pub config: serde_json::Value,
#[serde(default)]
pub servers: Vec<SubscriptionServer>,
#[serde(default)]
pub user_info: serde_json::Map<String, serde_json::Value>,
pub fetched_at: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SubscriptionServer {
pub tag: String,
#[serde(rename = "type")]
pub server_type: String,
pub server: String,
pub server_port: u16,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ActivityEntry {
pub id: String,
@@ -165,3 +229,45 @@ fn default_target_kind() -> String {
fn default_proxy_protocol() -> String {
"socks5".to_string()
}
fn default_local_singbox_listen_host() -> String {
DEFAULT_LOCAL_SINGBOX_LISTEN_HOST.to_string()
}
fn default_local_singbox_listen_port() -> u16 {
DEFAULT_LOCAL_SINGBOX_LISTEN_PORT
}
fn default_local_singbox_service_name() -> String {
DEFAULT_LOCAL_SINGBOX_SERVICE_NAME.to_string()
}
fn default_local_singbox_install_root() -> String {
DEFAULT_LOCAL_SINGBOX_INSTALL_ROOT.to_string()
}
pub fn redact_subscription_url(raw_url: &str) -> String {
let trimmed = raw_url.trim();
if trimmed.is_empty() {
return String::new();
}
match trimmed.split_once("://") {
Some((scheme, rest)) => {
let host = rest
.split(['/', '?', '#'])
.next()
.filter(|value| !value.is_empty())
.unwrap_or("subscription");
format!("{scheme}://{host}/...")
}
None => {
let visible = trimmed.chars().take(18).collect::<String>();
if trimmed.chars().count() <= 18 {
"***".to_string()
} else {
format!("{visible}...")
}
}
}
}