mirror of
https://codeberg.org/YGGverse/psocks.git
synced 2026-04-01 00:45:27 +00:00
rename list to rules, change api to free list control namespace
This commit is contained in:
parent
949a8a3b2c
commit
c821fa7492
5 changed files with 43 additions and 41 deletions
117
src/list.rs
117
src/list.rs
|
|
@ -1,117 +0,0 @@
|
|||
mod cache;
|
||||
mod item;
|
||||
|
||||
use anyhow::Result;
|
||||
use cache::Cache;
|
||||
use item::Item;
|
||||
use log::*;
|
||||
use std::{collections::HashSet, path::PathBuf};
|
||||
use tokio::{fs, sync::RwLock};
|
||||
|
||||
pub struct List {
|
||||
/// In-memory registry, based on `--allow-list` + `--cache`
|
||||
index: RwLock<HashSet<Item>>,
|
||||
/// FS cache for JSON/API changes, based on `--cache` value
|
||||
cache: Cache,
|
||||
}
|
||||
|
||||
impl List {
|
||||
/// Build new List object
|
||||
pub async fn from_opt(list: &Vec<String>, cache: Option<PathBuf>) -> Result<Self> {
|
||||
fn handle(this: &mut HashSet<Item>, line: &str) -> Option<bool> {
|
||||
if line.starts_with("/") || line.starts_with("#") || line.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(this.insert(Item::from_line(line)))
|
||||
}
|
||||
|
||||
let mut index = HashSet::new();
|
||||
|
||||
let mut list_rules_total = 0;
|
||||
|
||||
for i in list {
|
||||
for line in if i.contains("://") {
|
||||
let response = reqwest::get(i).await?;
|
||||
let status = response.status();
|
||||
if status.is_success() {
|
||||
response.text().await?
|
||||
} else {
|
||||
warn!("Could not receive remote list `{i}`: `{status}`");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
fs::read_to_string(i).await?
|
||||
}
|
||||
.lines()
|
||||
{
|
||||
if handle(&mut index, line).is_some_and(|status| !status) {
|
||||
warn!("List `{i}` contains duplicated entry: `{line}`")
|
||||
}
|
||||
list_rules_total += 1
|
||||
}
|
||||
}
|
||||
|
||||
let cache = Cache::from_path(cache).await?;
|
||||
|
||||
let cache_rules_total = cache.read().await?.map(|data| {
|
||||
let mut t = 0;
|
||||
for line in data.lines() {
|
||||
if handle(&mut index, line).is_some_and(|status| !status) {
|
||||
warn!("Cache file contains duplicated entry: `{line}`")
|
||||
}
|
||||
t += 1
|
||||
}
|
||||
t
|
||||
});
|
||||
|
||||
let len = index.len();
|
||||
info!(
|
||||
"Total rules parsed: {len} (lists: {list_rules_total} / cache: {cache_rules_total:?})",
|
||||
);
|
||||
|
||||
Ok(Self {
|
||||
index: RwLock::new(index),
|
||||
cache,
|
||||
})
|
||||
}
|
||||
/// Check if rule is exist in the (allow) index
|
||||
pub async fn any(&self, value: &str) -> bool {
|
||||
self.index.read().await.iter().any(|item| match item {
|
||||
Item::Exact(v) => v == value,
|
||||
Item::Ending(v) => value.ends_with(v),
|
||||
})
|
||||
}
|
||||
/// Get total rules from the current session
|
||||
pub async fn rules(&self) -> u64 {
|
||||
self.index.read().await.len() as u64
|
||||
}
|
||||
/// Allow given `rule`
|
||||
/// * return `false` if the `rule` is exist
|
||||
pub async fn allow(&self, rule: &str) -> Result<bool> {
|
||||
self.cache.allow(rule).await?;
|
||||
Ok(self.index.write().await.insert(Item::from_line(rule)))
|
||||
}
|
||||
/// Block given `rule`
|
||||
/// * return `false` if the `rule` is not exist
|
||||
pub async fn block(&self, rule: &str) -> Result<bool> {
|
||||
self.cache.block(rule).await?;
|
||||
Ok(self.index.write().await.remove(&Item::from_line(rule)))
|
||||
}
|
||||
/// Privately clean `--cache` file collected, return deleted rules
|
||||
/// * we can implement `self.index` update at this step @TODO
|
||||
pub async fn cache_clean(&self) -> Result<Option<Vec<String>>> {
|
||||
self.cache.clean().await
|
||||
}
|
||||
/// Return active rules (from server memory)
|
||||
pub async fn list(&self) -> Vec<String> {
|
||||
let mut list: Vec<String> = self
|
||||
.index
|
||||
.read()
|
||||
.await
|
||||
.iter()
|
||||
.map(|item| item.to_string())
|
||||
.collect();
|
||||
list.sort(); // HashSet does not keep the order
|
||||
list
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue