Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion wallguard-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wallguard-cli"
version = "1.1.11"
version = "1.3.0"
edition = "2024"
license = "AGPL-3.0-only"

Expand Down
2 changes: 1 addition & 1 deletion wallguard-common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wallguard-common"
version = "1.1.11"
version = "1.3.0"
edition = "2024"

[dependencies]
Expand Down
2 changes: 1 addition & 1 deletion wallguard-server/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wallguard-server"
version = "1.1.11"
version = "1.3.0"
edition = "2024"
authors = [
"Giuliano Bellini <gyulyvgc99@gmail.com>",
Expand Down
89 changes: 65 additions & 24 deletions wallguard-server/src/tunneling/timeout_controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use tokio::sync::Mutex;
pub struct TimeoutController {
idle_timeout: u64,
awake_interval: u64,
active_terminal_timeout: Option<u64>,
hard_timeout: Option<u64>,
tunnels: Arc<Mutex<HashMap<String, WallguardTunnel>>>,
}

impl TimeoutController {
pub fn new(tunnels: Arc<Mutex<HashMap<String, WallguardTunnel>>>) -> Self {
const DEFAULT_IDLE_TIMEOUT: u64 = 300; // 5 minutes
const DEFAULT_AWAKE_INTERVAL: u64 = 30; // 30 seconds
const DEFAULT_IDLE_TIMEOUT: u64 = 300;
const DEFAULT_AWAKE_INTERVAL: u64 = 30;

let idle_timeout = std::env::var("TUNNEL_CONTROLLER_IDLE_TIMEOUT")
.ok()
Expand All @@ -23,17 +25,23 @@ impl TimeoutController {
.and_then(|v| v.parse::<u64>().ok())
.unwrap_or(DEFAULT_AWAKE_INTERVAL);

let active_terminal_timeout = std::env::var("TUNNEL_CONTROLLER_ACTIVE_TERMINAL_TIMEOUT")
.ok()
.and_then(|v| v.parse::<u64>().ok());

let hard_timeout = std::env::var("TUNNEL_CONTROLLER_HARD_TIMEOUT")
.ok()
.and_then(|v| v.parse::<u64>().ok());

Self {
idle_timeout,
awake_interval,
active_terminal_timeout,
hard_timeout,
tunnels,
}
}

pub fn idle_timeout_duration(&self) -> Duration {
Duration::from_secs(self.idle_timeout)
}

pub fn awake_interval_duration(&self) -> Duration {
Duration::from_secs(self.awake_interval)
}
Expand Down Expand Up @@ -72,7 +80,9 @@ impl TimeoutController {
tun.data.created_at
};

if timestamp < Self::cutoff_timestamp(self.idle_timeout_duration()) {
if is_idle_expired(timestamp, self.idle_timeout)
|| is_lifetime_expired(tun.data.created_at, self.hard_timeout)
{
expired_ids.push(tun.data.tunnel_data.id.clone());
}
}
Expand Down Expand Up @@ -101,9 +111,17 @@ impl TimeoutController {
tun.data.created_at
};

if timestamp < Self::cutoff_timestamp(self.idle_timeout_duration())
&& !tun.has_active_terminals()
{
let expired = if tun.has_active_terminals() {
is_lifetime_expired(
tun.data.created_at,
self.active_terminal_timeout,
) || is_lifetime_expired(tun.data.created_at, self.hard_timeout)
} else {
is_idle_expired(timestamp, self.idle_timeout)
|| is_lifetime_expired(tun.data.created_at, self.hard_timeout)
};

if expired {
expired_ids.push(tun.data.tunnel_data.id.clone());
}
}
Expand Down Expand Up @@ -132,9 +150,17 @@ impl TimeoutController {
tun.data.created_at
};

if timestamp < Self::cutoff_timestamp(self.idle_timeout_duration())
&& !tun.has_active_terminals()
{
let expired = if tun.has_active_terminals() {
is_lifetime_expired(
tun.data.created_at,
self.active_terminal_timeout,
) || is_lifetime_expired(tun.data.created_at, self.hard_timeout)
} else {
is_idle_expired(timestamp, self.idle_timeout)
|| is_lifetime_expired(tun.data.created_at, self.hard_timeout)
};

if expired {
expired_ids.push(tun.data.tunnel_data.id.clone());
}
}
Expand Down Expand Up @@ -163,9 +189,17 @@ impl TimeoutController {
tun.data.created_at
};

if timestamp < Self::cutoff_timestamp(self.idle_timeout_duration())
&& !tun.has_active_viewers()
{
let expired = if tun.has_active_viewers() {
is_lifetime_expired(
tun.data.created_at,
self.active_terminal_timeout,
) || is_lifetime_expired(tun.data.created_at, self.hard_timeout)
} else {
is_idle_expired(timestamp, self.idle_timeout)
|| is_lifetime_expired(tun.data.created_at, self.hard_timeout)
};

if expired {
expired_ids.push(tun.data.tunnel_data.id.clone());
}
}
Expand All @@ -186,16 +220,23 @@ impl TimeoutController {
}
});
}
}

fn cutoff_timestamp(idle_timeout: Duration) -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};
fn cutoff_timestamp(timeout_secs: u64) -> u64 {
use std::time::{SystemTime, UNIX_EPOCH};

let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
now.checked_sub(Duration::from_secs(timeout_secs))
.unwrap_or(Duration::from_secs(0))
.as_secs()
}

let cutoff = now
.checked_sub(idle_timeout)
.unwrap_or(Duration::from_secs(0));
fn is_idle_expired(last_access: u64, idle_timeout_secs: u64) -> bool {
last_access < cutoff_timestamp(idle_timeout_secs)
}

cutoff.as_secs()
}
fn is_lifetime_expired(created_at: u64, timeout_secs: Option<u64>) -> bool {
timeout_secs
.map(|t| created_at < cutoff_timestamp(t))
.unwrap_or(false)
}
2 changes: 1 addition & 1 deletion wallguard/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "wallguard"
version = "1.1.11"
version = "1.3.0"
edition = "2024"
license = "AGPL-3.0-only"

Expand Down
Loading