mirror of https://github.com/ospab/ostp.git
gui, flutter: use server rtt for ping display
This commit is contained in:
parent
164c36ed3e
commit
87540166f6
|
|
@ -36,6 +36,7 @@ pub struct BridgeMetrics {
|
|||
pub bytes_sent: AtomicU64,
|
||||
pub bytes_recv: AtomicU64,
|
||||
pub connection_state: AtomicU8,
|
||||
pub rtt_ms: portable_atomic::AtomicU32,
|
||||
}
|
||||
|
||||
async fn send_datagram(socket: &crate::transport::Transport, frame: &Bytes, webrtc_masquerade: bool) -> std::io::Result<usize> {
|
||||
|
|
@ -210,6 +211,7 @@ impl Bridge {
|
|||
RelayMessage::Pong(ts) => {
|
||||
let now = SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap().as_millis() as u64;
|
||||
self.last_rtt_ms = now.saturating_sub(ts) as f64;
|
||||
self.metrics.rtt_ms.store(self.last_rtt_ms as u32, Ordering::Relaxed);
|
||||
}
|
||||
RelayMessage::KeepAlive | RelayMessage::Ping(_) | RelayMessage::Connect(_) => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ pub async fn run_client(config: crate::config::ClientConfig) -> Result<()> {
|
|||
bytes_sent: portable_atomic::AtomicU64::new(0),
|
||||
bytes_recv: portable_atomic::AtomicU64::new(0),
|
||||
connection_state: portable_atomic::AtomicU8::new(0),
|
||||
rtt_ms: portable_atomic::AtomicU32::new(0),
|
||||
});
|
||||
|
||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ struct MuxConfig {
|
|||
struct UIMetrics {
|
||||
bytes_sent: u64,
|
||||
bytes_recv: u64,
|
||||
rtt_ms: u32,
|
||||
}
|
||||
|
||||
// ── Messages exchanged with the privileged helper ────────────────────────────
|
||||
|
|
@ -87,7 +88,7 @@ struct UIMetrics {
|
|||
enum HelperMsg {
|
||||
Status { value: u8 },
|
||||
Log { message: String },
|
||||
Metrics { bytes_sent: u64, bytes_recv: u64 },
|
||||
Metrics { bytes_sent: u64, bytes_recv: u64, rtt_ms: u32 },
|
||||
Error { message: String },
|
||||
}
|
||||
|
||||
|
|
@ -262,12 +263,14 @@ async fn get_metrics(state: tauri::State<'_, AppState>) -> Result<Option<UIMetri
|
|||
Some(TunnelHandle::InProcess(s)) => Ok(Some(UIMetrics {
|
||||
bytes_sent: s.metrics.bytes_sent.load(Ordering::Relaxed),
|
||||
bytes_recv: s.metrics.bytes_recv.load(Ordering::Relaxed),
|
||||
rtt_ms: s.metrics.rtt_ms.load(Ordering::Relaxed),
|
||||
})),
|
||||
Some(TunnelHandle::Helper(h)) => {
|
||||
let ps = h.pipe_state.lock().await;
|
||||
Ok(Some(UIMetrics {
|
||||
bytes_sent: ps.bytes_sent,
|
||||
bytes_recv: ps.bytes_recv,
|
||||
rtt_ms: ps.rtt_ms,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -338,6 +341,7 @@ async fn start_proxy_in_process(
|
|||
// Start at 1 (connecting) so UI polling doesn't see 0 and flip back to disconnected
|
||||
// before the handshake task has had a chance to begin.
|
||||
connection_state: portable_atomic::AtomicU8::new(1),
|
||||
rtt_ms: portable_atomic::AtomicU32::new(0),
|
||||
});
|
||||
|
||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||
|
|
@ -383,7 +387,7 @@ async fn start_tun_via_helper(
|
|||
}).to_string();
|
||||
|
||||
let (cmd_tx, mut cmd_rx) = tokio::sync::mpsc::channel::<String>(16);
|
||||
let pipe_state = Arc::new(Mutex::new(HelperPipeState { connection_state: 1, bytes_sent: 0, bytes_recv: 0 }));
|
||||
let pipe_state = Arc::new(Mutex::new(HelperPipeState { connection_state: 1, bytes_sent: 0, bytes_recv: 0, rtt_ms: 0 }));
|
||||
let state_for_task = pipe_state.clone();
|
||||
|
||||
tokio::spawn(async move {
|
||||
|
|
@ -403,7 +407,7 @@ async fn start_tun_via_helper(
|
|||
let mut s = state_for_task.lock().await;
|
||||
match msg {
|
||||
HelperMsg::Status { value } => s.connection_state = value,
|
||||
HelperMsg::Metrics { bytes_sent, bytes_recv } => { s.bytes_sent = bytes_sent; s.bytes_recv = bytes_recv; }
|
||||
HelperMsg::Metrics { bytes_sent, bytes_recv, rtt_ms } => { s.bytes_sent = bytes_sent; s.bytes_recv = bytes_recv; s.rtt_ms = rtt_ms; }
|
||||
HelperMsg::Error { message } => { s.connection_state = 0; eprintln!("Helper error: {}", message); }
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -425,6 +429,7 @@ struct HelperPipeState {
|
|||
connection_state: u8,
|
||||
bytes_sent: u64,
|
||||
bytes_recv: u64,
|
||||
rtt_ms: u32,
|
||||
}
|
||||
|
||||
fn find_helper_exe() -> Option<PathBuf> {
|
||||
|
|
|
|||
|
|
@ -159,6 +159,11 @@ async function poll() {
|
|||
if (metrics) {
|
||||
metricDown.textContent = fmtBytes(metrics.bytes_recv);
|
||||
metricUp.textContent = fmtBytes(metrics.bytes_sent);
|
||||
|
||||
const isTun = rawConfig?.tun?.enable;
|
||||
const modeStr = isTun ? 'TUN' : 'SOCKS5';
|
||||
const pingStr = metrics.rtt_ms > 0 ? ` (${metrics.rtt_ms} ms)` : '';
|
||||
metricMode.textContent = modeStr + pingStr;
|
||||
}
|
||||
} catch {
|
||||
setState('disconnected');
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_startClient(
|
|||
bytes_sent: portable_atomic::AtomicU64::new(0),
|
||||
bytes_recv: portable_atomic::AtomicU64::new(0),
|
||||
connection_state: portable_atomic::AtomicU8::new(0),
|
||||
rtt_ms: portable_atomic::AtomicU32::new(0),
|
||||
});
|
||||
|
||||
let bridge = match Bridge::new(&config, Arc::clone(&metrics)) {
|
||||
|
|
@ -310,16 +311,17 @@ pub extern "system" fn Java_net_ostp_client_OstpClientSdk_getMetrics(
|
|||
let sent = m.bytes_sent.load(Ordering::Relaxed);
|
||||
let recv = m.bytes_recv.load(Ordering::Relaxed);
|
||||
let conn_state = m.connection_state.load(Ordering::Relaxed);
|
||||
let rtt = m.rtt_ms.load(Ordering::Relaxed);
|
||||
let json = format!(
|
||||
r#"{{"bytes_sent": {}, "bytes_recv": {}, "connection_state": {}}}"#,
|
||||
sent, recv, conn_state
|
||||
r#"{{"bytes_sent": {}, "bytes_recv": {}, "connection_state": {}, "rtt_ms": {}}}"#,
|
||||
sent, recv, conn_state, rtt
|
||||
);
|
||||
match env.new_string(json) {
|
||||
Ok(s) => s.into_raw(),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
} else {
|
||||
match env.new_string(r#"{"bytes_sent": 0, "bytes_recv": 0, "connection_state": 0}"#) {
|
||||
match env.new_string(r#"{"bytes_sent": 0, "bytes_recv": 0, "connection_state": 0, "rtt_ms": 0}"#) {
|
||||
Ok(s) => s.into_raw(),
|
||||
Err(_) => std::ptr::null_mut(),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ enum GuiCmd {
|
|||
enum HelperMsg {
|
||||
Status { value: u8 },
|
||||
Log { message: String },
|
||||
Metrics { bytes_sent: u64, bytes_recv: u64 },
|
||||
Metrics { bytes_sent: u64, bytes_recv: u64, rtt_ms: u32 },
|
||||
Error { message: String },
|
||||
}
|
||||
|
||||
|
|
@ -144,6 +144,7 @@ async fn run_server() -> Result<()> {
|
|||
bytes_sent: portable_atomic::AtomicU64::new(0),
|
||||
bytes_recv: portable_atomic::AtomicU64::new(0),
|
||||
connection_state: portable_atomic::AtomicU8::new(0),
|
||||
rtt_ms: portable_atomic::AtomicU32::new(0),
|
||||
});
|
||||
|
||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||
|
|
@ -179,13 +180,15 @@ async fn run_server() -> Result<()> {
|
|||
let sent = metrics_tick.bytes_sent.load(Ordering::Relaxed);
|
||||
let recv = metrics_tick.bytes_recv.load(Ordering::Relaxed);
|
||||
|
||||
let rtt = metrics_tick.rtt_ms.load(Ordering::Relaxed);
|
||||
|
||||
let mut w = writer_tick.lock().await;
|
||||
if cs != last_state {
|
||||
last_state = cs;
|
||||
let json = serde_json::to_string(&HelperMsg::Status { value: cs }).unwrap_or_default();
|
||||
if w.write_all(format!("{}\n", json).as_bytes()).await.is_err() { break; }
|
||||
}
|
||||
let json = serde_json::to_string(&HelperMsg::Metrics { bytes_sent: sent, bytes_recv: recv }).unwrap_or_default();
|
||||
let json = serde_json::to_string(&HelperMsg::Metrics { bytes_sent: sent, bytes_recv: recv, rtt_ms: rtt }).unwrap_or_default();
|
||||
if w.write_all(format!("{}\n", json).as_bytes()).await.is_err() { break; }
|
||||
drop(w);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue