diff --git a/src/main.rs b/src/main.rs index ea46d41..9e7e815 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,12 +72,12 @@ pub fn generate_unique_id() -> u64 { } pub mod global_state { - use std::sync::{atomic::AtomicU64, Arc}; - + use std::{sync::{atomic::AtomicU64, Arc}, time::SystemTimeError}; use crate::{certs::DynamicCertResolver, tcp_proxy::{ReverseTcpProxy, ReverseTcpProxyTarget}, types::odd_box_event::Event}; #[derive(Debug)] pub struct GlobalState { + pub started_at_time_stamp : std::time::SystemTime, pub log_handle : crate::OddLogHandle, pub app_state: std::sync::Arc, pub config: std::sync::Arc>, @@ -88,7 +88,9 @@ pub mod global_state { pub global_broadcast_channel: tokio::sync::broadcast::Sender } impl GlobalState { - + pub fn uptime(&self) -> Result { + self.started_at_time_stamp.elapsed() + } pub fn new( app_state: std::sync::Arc, config: std::sync::Arc>, @@ -99,6 +101,7 @@ pub mod global_state { ) -> Self { Self { + started_at_time_stamp: std::time::SystemTime::now(), log_handle, app_state, config, diff --git a/src/proxy.rs b/src/proxy.rs index b870549..a2a195f 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -34,6 +34,9 @@ use crate::types::proxy_state::ProxyActiveTCPConnection; use tokio_util::sync::CancellationToken; use tokio::task::JoinHandle; +// This is the main entrypoint of the reverse proxy listener... +// It sets up the two tcp sockets and routes traffic either to the terminating proxy service (hyper) +// or thru the managed tunnel mode where we do not terminate http traffic (but possibly do terminate tls depending on config). pub async fn listen( cfg: Arc>, initial_bind_addr: SocketAddr, @@ -209,6 +212,11 @@ async fn listen_http( Ok(_) => {}, Err(e) => tracing::trace!("Failed to set_only_vs: {e:?}") }; + + // note: we reuse here as we want to be able to run multiple instances of odd-box at the same time. + // if nothing else it lets us launch a newer version of the server without stopping the old, so that we can upgrade + // to a later version without downtime. + match socket.set_reuse_port(true) { Ok(_) => {}, Err(e) => { @@ -301,6 +309,11 @@ async fn listen_https( Ok(_) => {}, Err(e) => tracing::trace!("Failed to set_only_vs: {e:?}") }; + + // note: we reuse here as we want to be able to run multiple instances of odd-box at the same time. + // if nothing else it lets us launch a newer version of the server without stopping the old, so that we can upgrade + // to a later version without downtime. + match socket.set_reuse_address(true) { // annoying as hell otherwise for quick resets Ok(_) => {}, Err(e) => tracing::warn!("Failed to set_reuse_address: {e:?}") diff --git a/src/tui/mod.rs b/src/tui/mod.rs index afd88ce..96778eb 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -917,6 +917,11 @@ fn draw_ui( // help_bar_text.push(ratatui::text::Span::raw(format!("| DBG: {}", // app_state.dbg // ))); + let uptime = if let Ok(d) = global_state.uptime() { + format_duration(d) + } else { + String::new() + }; let current_version = self_update::cargo_crate_version!(); let help_bar = Paragraph::new(Line::from(help_bar_text)) .style(Style::default().fg(Color::DarkGray)) @@ -924,7 +929,7 @@ fn draw_ui( .block(Block::default().borders(Borders::ALL) .border_type(BorderType::Rounded) .border_style(Style::default().fg(Color::DarkGray)) - .title(format!(" ODD-BOX v{current_version}")).title_style( + .title(format!(" ODD-BOX v{current_version} {uptime} ")).title_style( if is_dark_theme { Style::default().fg(Color::LightYellow) } else { @@ -936,7 +941,24 @@ fn draw_ui( } +fn format_duration(d: std::time::Duration) -> String { + let total_secs = d.as_secs(); + let days = total_secs / 86400; // 1 day = 86_400 seconds + let hours = (total_secs % 86400) / 3600; + let minutes = (total_secs % 3600) / 60; + let seconds = total_secs % 60; + + if days > 0 { + format!(" - uptime: {} days, {} hours, {} minutes", days, hours, minutes) + } else if hours > 0 { + format!(" - uptime: {} hours, {} minutes", hours, minutes) + } else if minutes > 0 { + format!(" - uptime: {} minutes, {} seconds", minutes,seconds) + } else { + format!(" - uptime: {} seconds", seconds) + } +} fn wrap_string(input: &str, max_length: usize) -> Vec { let words = input.split_whitespace(); let mut wrapped_lines = Vec::new();