mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-16 12:52:24 +02:00
renamed config log active_clientto log_active_user
This commit is contained in:
@@ -70,6 +70,7 @@ url: ['http://localhost:3001/xmltv.php?epg_id=1', 'http://localhost:3001/xmltv.p
|
||||
When no matching epg_id is found, the display name is used to match a channel name. The given strings are stripped to get a better match.
|
||||
- fixed chno assignment issue
|
||||
- Added `method` attribute to input config. It can be set to `GET` or `POST`.
|
||||
- !BREAKING_CHANGE! `log` config `active_clients` renamed to `log_active_user`
|
||||
|
||||
# 2.2.5 (2025-03-27)
|
||||
- fixed web ui playlist regexp search
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ async fn create_shared_data(cfg: &Arc<Config>) -> AppState {
|
||||
}
|
||||
});
|
||||
|
||||
let active_users = Arc::new(ActiveUserManager::new(cfg.log.as_ref().is_some_and(|l| l.active_clients)));
|
||||
let active_users = Arc::new(ActiveUserManager::new(cfg.log.as_ref().is_some_and(|l| l.log_active_user)));
|
||||
let active_provider = Arc::new(ActiveProviderManager::new(cfg).await);
|
||||
|
||||
let client = if cfg.connect_timeout_secs > 0 {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use jsonwebtoken::get_current_timestamp;
|
||||
use log::{info, trace};
|
||||
use tokio::sync::RwLock;
|
||||
use crate::model::api_proxy::UserConnectionPermission;
|
||||
|
||||
// TODO this should be bound to grace_period, because grace_period can be more than 2 secs
|
||||
const GRACE_TIME_CHECK: u64 = 2;
|
||||
|
||||
pub struct UserConnectionGuard {
|
||||
manager: Arc<ActiveUserManager>,
|
||||
username: String,
|
||||
@@ -19,9 +22,25 @@ impl Drop for UserConnectionGuard {
|
||||
}
|
||||
}
|
||||
|
||||
struct UserConnectionData {
|
||||
connections: u32,
|
||||
granted_grace: u32,
|
||||
grace_ts: u64,
|
||||
}
|
||||
|
||||
impl UserConnectionData {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
connections: 1,
|
||||
granted_grace: 0,
|
||||
grace_ts: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ActiveUserManager {
|
||||
log_active_clients: bool,
|
||||
pub user: Arc<RwLock<HashMap<String, AtomicU32>>>,
|
||||
log_active_user: bool,
|
||||
user: Arc<RwLock<HashMap<String, UserConnectionData>>>,
|
||||
}
|
||||
|
||||
impl Default for ActiveUserManager {
|
||||
@@ -31,38 +50,45 @@ impl Default for ActiveUserManager {
|
||||
}
|
||||
|
||||
impl ActiveUserManager {
|
||||
pub fn new(log_active_clients: bool) -> Self {
|
||||
pub fn new(log_active_user: bool) -> Self {
|
||||
Self {
|
||||
log_active_clients,
|
||||
log_active_user,
|
||||
user: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
fn clone_inner(&self) -> Self {
|
||||
Self {
|
||||
log_active_clients: self.log_active_clients,
|
||||
log_active_user: self.log_active_user,
|
||||
user: Arc::clone(&self.user),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn user_connections(&self, username: &str) -> u32 {
|
||||
if let Some(counter) = self.user.read().await.get(username) {
|
||||
return counter.load(Ordering::SeqCst);
|
||||
if let Some(connection_data) = self.user.read().await.get(username) {
|
||||
return connection_data.connections;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
pub async fn connection_permission(&self, username: &str, max_connections: u32, grace_period: bool) -> UserConnectionPermission {
|
||||
if let Some(counter) = self.user.read().await.get(username) {
|
||||
let current_connections = counter.load(Ordering::SeqCst);
|
||||
if let Some(connection_data) = self.user.write().await.get_mut(username) {
|
||||
let current_connections = connection_data.connections;
|
||||
if connection_data.granted_grace > 0 && (get_current_timestamp() - connection_data.grace_ts) > GRACE_TIME_CHECK {
|
||||
trace!("User access denied, grace exhausted, too many connections: {username}");
|
||||
return UserConnectionPermission::Exhausted;
|
||||
}
|
||||
let extra_con = u32::from(grace_period);
|
||||
if current_connections < max_connections + extra_con {
|
||||
connection_data.granted_grace += 1;
|
||||
connection_data.grace_ts = get_current_timestamp();
|
||||
return UserConnectionPermission::GracePeriod;
|
||||
}
|
||||
if current_connections >= max_connections {
|
||||
trace!("User access denied, too many connections: {username}");
|
||||
return UserConnectionPermission::Exhausted;
|
||||
}
|
||||
connection_data.granted_grace = 0;
|
||||
}
|
||||
UserConnectionPermission::Allowed
|
||||
}
|
||||
@@ -72,15 +98,15 @@ impl ActiveUserManager {
|
||||
}
|
||||
|
||||
pub async fn active_connections(&self) -> usize {
|
||||
self.user.read().await.values().map(|c| c.load(Ordering::SeqCst) as usize).sum()
|
||||
self.user.read().await.values().map(|c| c.connections as usize).sum()
|
||||
}
|
||||
|
||||
pub async fn add_connection(&self, username: &str) -> UserConnectionGuard {
|
||||
let mut lock = self.user.write().await;
|
||||
if let Some(counter) = lock.get(username) {
|
||||
counter.fetch_add(1, Ordering::SeqCst);
|
||||
if let Some(connection_data) = lock.get_mut(username) {
|
||||
connection_data.connections += 1;
|
||||
} else {
|
||||
lock.insert(username.to_string(), AtomicU32::new(1));
|
||||
lock.insert(username.to_string(), UserConnectionData::new());
|
||||
}
|
||||
drop(lock);
|
||||
|
||||
@@ -94,9 +120,9 @@ impl ActiveUserManager {
|
||||
|
||||
async fn remove_connection(&self, username: &str) {
|
||||
let mut lock = self.user.write().await;
|
||||
if let Some(counter) = lock.get(username) {
|
||||
let new_count = counter.fetch_sub(1, Ordering::SeqCst) - 1;
|
||||
if new_count == 0 {
|
||||
if let Some(connection_data) = lock.get_mut(username) {
|
||||
connection_data.connections -= 1;
|
||||
if connection_data.connections == 0 {
|
||||
lock.remove(username);
|
||||
}
|
||||
}
|
||||
@@ -106,7 +132,7 @@ impl ActiveUserManager {
|
||||
}
|
||||
|
||||
async fn log_active_user(&self) {
|
||||
if self.log_active_clients {
|
||||
if self.log_active_user {
|
||||
let user_count = self.active_users().await;
|
||||
let user_connection_count = self.active_connections().await;
|
||||
info!("Active Users: {user_count}, Active User Connections: {user_connection_count}");
|
||||
|
||||
+1
-1
@@ -1120,7 +1120,7 @@ pub struct LogConfig {
|
||||
#[serde(default = "default_as_true")]
|
||||
pub sanitize_sensitive_info: bool,
|
||||
#[serde(default)]
|
||||
pub active_clients: bool,
|
||||
pub log_active_user: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub log_level: Option<String>,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user