mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-04-13 05:20:28 +08:00
148 lines
4.6 KiB
Rust
148 lines
4.6 KiB
Rust
use serde_yaml_ng::{Mapping, Value};
|
||
use smartstring::alias::String;
|
||
use std::collections::{HashMap, HashSet};
|
||
|
||
use crate::enhance::field::use_keys;
|
||
|
||
const PATCH_CONFIG_INNER: [&str; 4] = ["allow-lan", "ipv6", "log-level", "unified-delay"];
|
||
|
||
#[derive(Default, Clone)]
|
||
pub struct IRuntime {
|
||
pub config: Option<Mapping>,
|
||
// 记录在订阅中(包括merge和script生成的)出现过的keys
|
||
// 这些keys不一定都生效
|
||
pub exists_keys: HashSet<String>,
|
||
// TODO 或许可以用 FixMap 来存储以提升效率
|
||
pub chain_logs: HashMap<String, Vec<(String, String)>>,
|
||
}
|
||
|
||
impl IRuntime {
|
||
#[inline]
|
||
pub fn new() -> Self {
|
||
Self::default()
|
||
}
|
||
|
||
#[inline]
|
||
pub fn clean_all(&mut self) {
|
||
self.config = None;
|
||
self.exists_keys.clear();
|
||
self.chain_logs.clear();
|
||
}
|
||
|
||
// 这里只更改 allow-lan | ipv6 | log-level | tun
|
||
#[inline]
|
||
pub fn patch_config(&mut self, patch: &Mapping) {
|
||
let config = if let Some(config) = self.config.as_mut() {
|
||
config
|
||
} else {
|
||
return;
|
||
};
|
||
|
||
for key in PATCH_CONFIG_INNER.iter() {
|
||
if let Some(value) = patch.get(key) {
|
||
config.insert((*key).into(), value.clone());
|
||
}
|
||
}
|
||
|
||
let patch_tun = patch.get("tun");
|
||
if let Some(patch_tun_value) = patch_tun {
|
||
let mut tun = config
|
||
.get("tun")
|
||
.and_then(|val| val.as_mapping())
|
||
.cloned()
|
||
.unwrap_or_else(Mapping::new);
|
||
|
||
if let Some(patch_tun_mapping) = patch_tun_value.as_mapping() {
|
||
for key in use_keys(patch_tun_mapping) {
|
||
if let Some(value) = patch_tun_mapping.get(key.as_str()) {
|
||
tun.insert(Value::from(key.as_str()), value.clone());
|
||
}
|
||
}
|
||
}
|
||
|
||
config.insert("tun".into(), Value::from(tun));
|
||
}
|
||
}
|
||
|
||
/// 更新链式代理配置
|
||
///
|
||
/// 该函数更新 `proxies` 和 `proxy-groups` 配置,并处理链式代理的修改或(传入 None )删除。
|
||
///
|
||
/// 配置示例:
|
||
///
|
||
/// ```json
|
||
/// {
|
||
/// "proxies": [
|
||
/// {
|
||
/// "name": "入口节点",
|
||
/// "type": "xxx",
|
||
/// "server": "xxx",
|
||
/// "port": "xxx",
|
||
/// "ports": "xxx",
|
||
/// "password": "xxx",
|
||
/// "skip-cert-verify": "xxx"
|
||
/// },
|
||
/// {
|
||
/// "name": "hop_node_1_xxxx",
|
||
/// "type": "xxx",
|
||
/// "server": "xxx",
|
||
/// "port": "xxx",
|
||
/// "ports": "xxx",
|
||
/// "password": "xxx",
|
||
/// "skip-cert-verify": "xxx",
|
||
/// "dialer-proxy": "入口节点"
|
||
/// },
|
||
/// {
|
||
/// "name": "出口节点",
|
||
/// "type": "xxx",
|
||
/// "server": "xxx",
|
||
/// "port": "xxx",
|
||
/// "ports": "xxx",
|
||
/// "password": "xxx",
|
||
/// "skip-cert-verify": "xxx",
|
||
/// "dialer-proxy": "hop_node_1_xxxx"
|
||
/// }
|
||
/// ],
|
||
/// "proxy-groups": [
|
||
/// {
|
||
/// "name": "proxy_chain",
|
||
/// "type": "select",
|
||
/// "proxies": ["出口节点"]
|
||
/// }
|
||
/// ]
|
||
/// }
|
||
/// ```
|
||
#[inline]
|
||
pub fn update_proxy_chain_config(&mut self, proxy_chain_config: Option<Value>) {
|
||
let config = if let Some(config) = self.config.as_mut() {
|
||
config
|
||
} else {
|
||
return;
|
||
};
|
||
|
||
if let Some(Value::Sequence(proxies)) = config.get_mut("proxies") {
|
||
proxies.iter_mut().for_each(|proxy| {
|
||
if let Some(proxy) = proxy.as_mapping_mut()
|
||
&& proxy.get("dialer-proxy").is_some()
|
||
{
|
||
proxy.remove("dialer-proxy");
|
||
}
|
||
});
|
||
}
|
||
|
||
if let Some(Value::Sequence(dialer_proxies)) = proxy_chain_config
|
||
&& let Some(Value::Sequence(proxies)) = config.get_mut("proxies")
|
||
{
|
||
for (i, dialer_proxy) in dialer_proxies.iter().enumerate() {
|
||
if let Some(Value::Mapping(proxy)) =
|
||
proxies.iter_mut().find(|proxy| proxy.get("name") == Some(dialer_proxy))
|
||
&& i != 0
|
||
&& let Some(dialer_proxy) = dialer_proxies.get(i - 1)
|
||
{
|
||
proxy.insert("dialer-proxy".into(), dialer_proxy.to_owned());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|