From 67281d311a59f2ac27c9327675753544dd23b55b Mon Sep 17 00:00:00 2001 From: nullchinchilla Date: Fri, 19 Apr 2024 19:38:08 -0400 Subject: [PATCH] Reduce GUI repaint interval, display MB used in dashboard, optimize imports, add byte tracking to socks5 loop, introduce stats module --- binaries/geph5-client-gui/src/main.rs | 2 +- .../geph5-client-gui/src/tabs/dashboard.rs | 4 +- binaries/geph5-client/src/client.rs | 19 ++++++---- binaries/geph5-client/src/lib.rs | 1 + binaries/geph5-client/src/socks5.rs | 38 ++++++++++++++++--- binaries/geph5-client/src/stats.rs | 5 +++ 6 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 binaries/geph5-client/src/stats.rs diff --git a/binaries/geph5-client-gui/src/main.rs b/binaries/geph5-client-gui/src/main.rs index be647d99..e31df8e8 100644 --- a/binaries/geph5-client-gui/src/main.rs +++ b/binaries/geph5-client-gui/src/main.rs @@ -110,7 +110,7 @@ impl App { impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { - ctx.request_repaint_after(Duration::from_millis(1000)); + ctx.request_repaint_after(Duration::from_millis(100)); egui::TopBottomPanel::top("top").show(ctx, |ui| { ui.horizontal(|ui| { diff --git a/binaries/geph5-client-gui/src/tabs/dashboard.rs b/binaries/geph5-client-gui/src/tabs/dashboard.rs index eb60c17e..ffedae92 100644 --- a/binaries/geph5-client-gui/src/tabs/dashboard.rs +++ b/binaries/geph5-client-gui/src/tabs/dashboard.rs @@ -1,4 +1,4 @@ -use std::time::{Duration, Instant}; +use std::time::Duration; use crate::{daemon::DAEMON, l10n::l10n, settings::get_config}; @@ -19,6 +19,8 @@ impl Dashboard { let start_time = daemon.start_time().elapsed().as_secs() + 1; let start_time = Duration::from_secs(1) * start_time as _; columns[1].label(format!("{:?}", start_time)); + let mb_used = (daemon.bytes_used() as f64) / 1_000_000.0; + columns[1].label(format!("{:.2} MB", mb_used)); } None => { columns[1].colored_label(egui::Color32::DARK_RED, l10n("disconnected")); diff --git a/binaries/geph5-client/src/client.rs b/binaries/geph5-client/src/client.rs index 2face9dc..4edb28e4 100644 --- a/binaries/geph5-client/src/client.rs +++ b/binaries/geph5-client/src/client.rs @@ -1,16 +1,12 @@ use anyctx::AnyCtx; use clone_macro::clone; -use futures_util::{ - future::{FusedFuture, Shared}, - task::noop_waker, - FutureExt, TryFutureExt, -}; +use futures_util::{future::Shared, task::noop_waker, FutureExt, TryFutureExt}; use geph5_broker_protocol::{Credential, ExitList}; use smol::future::FutureExt as _; use std::{ net::SocketAddr, path::PathBuf, - sync::Arc, + sync::{atomic::Ordering, Arc}, task::Context, time::{Duration, Instant}, }; @@ -25,6 +21,7 @@ use crate::{ database::db_read_or_wait, route::ExitConstraint, socks5::socks5_loop, + stats::STAT_TOTAL_BYTES, }; #[derive(Serialize, Deserialize, Clone)] @@ -41,6 +38,7 @@ pub struct Config { pub struct Client { task: Shared>>>, + ctx: AnyCtx, start_time: Instant, } @@ -48,10 +46,10 @@ impl Client { /// Starts the client logic in the loop, returnign the handle. pub fn start(cfg: Config) -> Self { let ctx = AnyCtx::new(cfg); - let task = smolscale::spawn(client_main(ctx).map_err(Arc::new)); + let task = smolscale::spawn(client_main(ctx.clone()).map_err(Arc::new)); Client { task: task.shared(), - + ctx, start_time: Instant::now(), } } @@ -79,6 +77,11 @@ impl Client { pub fn start_time(&self) -> Instant { self.start_time } + + /// Returns the count of all bytes used. + pub fn bytes_used(&self) -> u64 { + self.ctx.get(STAT_TOTAL_BYTES).load(Ordering::Relaxed) + } } pub type CtxField = fn(&AnyCtx) -> T; diff --git a/binaries/geph5-client/src/lib.rs b/binaries/geph5-client/src/lib.rs index 2f2b2e10..bbafc656 100644 --- a/binaries/geph5-client/src/lib.rs +++ b/binaries/geph5-client/src/lib.rs @@ -9,3 +9,4 @@ mod client_inner; mod database; mod route; mod socks5; +mod stats; diff --git a/binaries/geph5-client/src/socks5.rs b/binaries/geph5-client/src/socks5.rs index d6e03552..2840a9d7 100644 --- a/binaries/geph5-client/src/socks5.rs +++ b/binaries/geph5-client/src/socks5.rs @@ -1,6 +1,8 @@ use crate::client_inner::open_conn; +use crate::stats::STAT_TOTAL_BYTES; use anyctx::AnyCtx; -use futures_util::AsyncReadExt as _; +use futures_util::AsyncWriteExt; +use futures_util::{AsyncRead, AsyncReadExt as _, AsyncWrite}; use nursery_macro::nursery; use sillad::listener::Listener as _; use smol::future::FutureExt as _; @@ -8,7 +10,7 @@ use socksv5::v5::{ read_handshake, read_request, write_auth_method, write_request_status, SocksV5AuthMethod, SocksV5Host, SocksV5RequestStatus, }; -use std::net::Ipv4Addr; +use std::{net::Ipv4Addr, sync::atomic::Ordering}; use super::Config; @@ -48,12 +50,38 @@ pub async fn socks5_loop(ctx: &AnyCtx) -> anyhow::Result<()> { .await?; tracing::trace!(remote_addr = display(&remote_addr), "connection opened"); let (read_stream, write_stream) = stream.split(); - smol::io::copy(read_stream, write_client) - .race(smol::io::copy(read_client, write_stream)) - .await?; + io_copy_with(read_stream, write_client, |n| { + ctx.get(STAT_TOTAL_BYTES) + .fetch_add(n as u64, Ordering::Relaxed); + }) + .race(io_copy_with(read_client, write_stream, |n| { + ctx.get(STAT_TOTAL_BYTES) + .fetch_add(n as u64, Ordering::Relaxed); + })) + .await?; anyhow::Ok(()) }) .detach(); } }) } + +async fn io_copy_with( + mut read: impl AsyncRead + Unpin, + mut write: impl AsyncWrite + Unpin, + mut on_copy: impl FnMut(usize), +) -> anyhow::Result<()> { + let mut buffer = vec![0; 8192]; // Buffer size can be adjusted based on expected data sizes or performance testing + + loop { + let bytes_read = read.read(&mut buffer).await?; + + if bytes_read == 0 { + break; // End of input stream + } + + write.write_all(&buffer[..bytes_read]).await?; + on_copy(bytes_read); // Invoke the callback + } + Ok(()) +} diff --git a/binaries/geph5-client/src/stats.rs b/binaries/geph5-client/src/stats.rs new file mode 100644 index 00000000..7c9caf39 --- /dev/null +++ b/binaries/geph5-client/src/stats.rs @@ -0,0 +1,5 @@ +use std::sync::atomic::AtomicU64; + +use crate::client::CtxField; + +pub static STAT_TOTAL_BYTES: CtxField = |_| AtomicU64::new(0);