Skip to content

Commit

Permalink
store profile and fake ip
Browse files Browse the repository at this point in the history
  • Loading branch information
ibigbug committed Sep 12, 2023
1 parent baa958f commit b851a8d
Show file tree
Hide file tree
Showing 13 changed files with 309 additions and 101 deletions.
5 changes: 5 additions & 0 deletions clash/tests/data/config/rules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ external-ui: "public"
experimental:
ignore-resolve-fail: true

profile:
store-selected: true
store-fake-ip: false


proxy-groups:
- name: "relay"
type: relay
Expand Down
25 changes: 18 additions & 7 deletions clash_lib/src/app/api/handlers/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,25 @@ use http::StatusCode;
use serde::Deserialize;

use crate::{
app::{api::AppState, outbound::manager::ThreadSafeOutboundManager},
app::{
api::AppState, outbound::manager::ThreadSafeOutboundManager, profile::ThreadSafeCacheFile,
},
proxy::AnyOutboundHandler,
};

#[derive(Clone)]
pub struct ProxyState {
outbound_manager: ThreadSafeOutboundManager,
cache_store: ThreadSafeCacheFile,
}

pub fn routes(outbound_manager: ThreadSafeOutboundManager) -> Router<Arc<AppState>> {
pub fn routes(
outbound_manager: ThreadSafeOutboundManager,
cache_store: ThreadSafeCacheFile,
) -> Router<Arc<AppState>> {
let state = ProxyState {
outbound_manager: outbound_manager.clone(),
outbound_manager,
cache_store,
};
Router::new()
.route("/", get(get_proxies))
Expand Down Expand Up @@ -87,10 +94,14 @@ async fn update_proxy(
let outbound_manager = state.outbound_manager.read().await;
if let Some(ctrl) = outbound_manager.get_selector_control(proxy.name()) {
match ctrl.lock().await.select(&payload.name).await {
Ok(_) => (
StatusCode::ACCEPTED,
format!("selected proxy {} for {}", payload.name, proxy.name()),
),
Ok(_) => {
let cache_store = state.cache_store;
cache_store.set_selected(proxy.name(), &payload.name).await;
(
StatusCode::ACCEPTED,
format!("selected proxy {} for {}", payload.name, proxy.name()),
)
}
Err(err) => (
StatusCode::BAD_REQUEST,
format!(
Expand Down
4 changes: 3 additions & 1 deletion clash_lib/src/app/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::{config::internal::config::Controller, GlobalState, Runner};
use super::dispatcher::StatisticsManager;
use super::dns::ThreadSafeDNSResolver;
use super::logging::LogEvent;
use super::profile::ThreadSafeCacheFile;
use super::{
dispatcher, inbound::manager::ThreadSafeInboundManager,
outbound::manager::ThreadSafeOutboundManager, router::ThreadSafeRouter,
Expand All @@ -36,6 +37,7 @@ pub fn get_api_runner(
dns_resolver: ThreadSafeDNSResolver,
outbound_manager: ThreadSafeOutboundManager,
statistics_manager: Arc<StatisticsManager>,
cache_store: ThreadSafeCacheFile,
router: ThreadSafeRouter,
) -> Option<Runner> {
if let Some(bind_addr) = controller_cfg.external_controller {
Expand Down Expand Up @@ -70,7 +72,7 @@ pub fn get_api_runner(
.nest("/rules", handlers::rule::routes(router))
.nest(
"/proxies",
handlers::proxy::routes(outbound_manager.clone()),
handlers::proxy::routes(outbound_manager.clone(), cache_store),
)
.nest(
"/connections",
Expand Down
44 changes: 27 additions & 17 deletions clash_lib/src/app/dns/fakeip/file_store.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,49 @@
use async_trait::async_trait;

use crate::app::profile::ThreadSafeCacheFile;

use super::Store;

pub struct FileStore;
pub struct FileStore(ThreadSafeCacheFile);

impl FileStore {
pub fn new() -> Self {
Self
pub fn new(store: ThreadSafeCacheFile) -> Self {
Self(store)
}
}

#[async_trait]
impl Store for FileStore {
fn get_by_host(&mut self, _host: &str) -> Option<std::net::IpAddr> {
todo!()
async fn get_by_host(&mut self, host: &str) -> Option<std::net::IpAddr> {
self.0
.get_fake_ip(host)
.await
.map(|ip| ip.parse().ok())
.flatten()
}

fn pub_by_host(&mut self, _host: &str, _ip: std::net::IpAddr) {
todo!()
async fn pub_by_host(&mut self, host: &str, ip: std::net::IpAddr) {
self.0.set_host_to_ip(host, &ip.to_string()).await;
}

fn get_by_ip(&mut self, _ip: std::net::IpAddr) -> Option<String> {
todo!()
async fn get_by_ip(&mut self, ip: std::net::IpAddr) -> Option<String> {
self.0.get_fake_ip(&ip.to_string()).await
}

fn put_by_ip(&mut self, _ip: std::net::IpAddr, _host: &str) {
todo!()
async fn put_by_ip(&mut self, ip: std::net::IpAddr, host: &str) {
self.0.set_ip_to_host(&ip.to_string(), host).await;
}

fn del_by_ip(&mut self, _ip: std::net::IpAddr) {
todo!()
async fn del_by_ip(&mut self, ip: std::net::IpAddr) {
let host = self.get_by_ip(ip).await.unwrap_or_default();
self.0.delete_fake_ip_pair(&ip.to_string(), &host).await;
}

fn exist(&mut self, _ip: std::net::IpAddr) -> bool {
todo!()
async fn exist(&mut self, ip: std::net::IpAddr) -> bool {
self.0.get_fake_ip(&ip.to_string()).await.is_some()
}

fn copy_to(&self, _store: &mut Box<dyn Store>) {
todo!()
async fn copy_to(&self, #[allow(unused)] store: &mut Box<dyn Store>) {
//NO-OP
}
}
20 changes: 12 additions & 8 deletions clash_lib/src/app/dns/fakeip/mem_store.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::net::IpAddr;

use async_trait::async_trait;

use super::Store;

pub struct InMemStore {
Expand All @@ -16,40 +18,42 @@ impl InMemStore {
}
}

#[async_trait]
impl Store for InMemStore {
fn get_by_host(&mut self, host: &str) -> Option<std::net::IpAddr> {
async fn get_by_host(&mut self, host: &str) -> Option<std::net::IpAddr> {
self.htoi.get_mut(host).map(|ip| {
self.itoh.get_mut(ip);
*ip
})
}

fn pub_by_host(&mut self, host: &str, ip: std::net::IpAddr) {
async fn pub_by_host(&mut self, host: &str, ip: std::net::IpAddr) {
self.htoi.insert(host.into(), ip);
}

fn get_by_ip(&mut self, ip: std::net::IpAddr) -> Option<String> {
async fn get_by_ip(&mut self, ip: std::net::IpAddr) -> Option<String> {
self.itoh.get_mut(&ip).map(|h| {
self.htoi.get_mut(h);
h.to_string()
})
}

fn put_by_ip(&mut self, ip: std::net::IpAddr, host: &str) {
async fn put_by_ip(&mut self, ip: std::net::IpAddr, host: &str) {
self.itoh.insert(ip, host.into());
}

fn del_by_ip(&mut self, ip: std::net::IpAddr) {
async fn del_by_ip(&mut self, ip: std::net::IpAddr) {
if let Some(host) = self.itoh.remove(&ip) {
self.htoi.remove(&host);
}
}

fn exist(&mut self, ip: std::net::IpAddr) -> bool {
async fn exist(&mut self, ip: std::net::IpAddr) -> bool {
self.itoh.contains_key(&ip)
}

fn copy_to(&self, _store: &mut Box<dyn Store>) {
todo!("not implemented yet")
async fn copy_to(&self, #[allow(unused)] store: &mut Box<dyn Store>) {
// TODO: copy
// NOTE: use file based persistence store
}
}
Loading

0 comments on commit b851a8d

Please sign in to comment.