2 Commits

4 changed files with 20 additions and 4 deletions

View File

@@ -1,5 +1,11 @@
# Changelog
## 2026-03-30 - 1.10.2 - fix(client)
wait for the connection task to shut down cleanly before disconnecting and increase test timeout
- store the spawned client connection task handle and await it during disconnect with a 5 second timeout so the disconnect frame can be sent before closing
- increase the test script timeout from 60 seconds to 90 seconds to reduce flaky test runs
## 2026-03-29 - 1.10.1 - fix(test, docs, scripts)
correct test command verbosity, shorten load test timings, and document forwarding modes

View File

@@ -1,6 +1,6 @@
{
"name": "@push.rocks/smartvpn",
"version": "1.10.1",
"version": "1.10.2",
"private": false,
"description": "A VPN solution with TypeScript control plane and Rust data plane daemon",
"type": "module",
@@ -12,7 +12,7 @@
"scripts": {
"build": "(tsbuild tsfolders) && (tsrust)",
"test:before": "(tsrust)",
"test": "tstest test/ --verbose --logfile --timeout 60",
"test": "tstest test/ --verbose --logfile --timeout 90",
"buildDocs": "tsdoc"
},
"repository": {

View File

@@ -81,6 +81,7 @@ pub struct VpnClient {
connected_since: Arc<RwLock<Option<std::time::Instant>>>,
quality_rx: Option<watch::Receiver<ConnectionQuality>>,
link_health: Arc<RwLock<LinkHealth>>,
connection_handle: Option<tokio::task::JoinHandle<()>>,
}
impl VpnClient {
@@ -93,6 +94,7 @@ impl VpnClient {
connected_since: Arc::new(RwLock::new(None)),
quality_rx: None,
link_health: Arc::new(RwLock::new(LinkHealth::Degraded)),
connection_handle: None,
}
}
@@ -280,7 +282,7 @@ impl VpnClient {
// Spawn packet forwarding loop
let assigned_ip_clone = assigned_ip.clone();
tokio::spawn(client_loop(
let join_handle = tokio::spawn(client_loop(
sink,
stream,
noise_transport,
@@ -294,6 +296,7 @@ impl VpnClient {
tun_writer,
tun_subnet,
));
self.connection_handle = Some(join_handle);
Ok(assigned_ip_clone)
}
@@ -303,6 +306,13 @@ impl VpnClient {
if let Some(tx) = self.shutdown_tx.take() {
let _ = tx.send(()).await;
}
// Wait for the connection task to send the Disconnect frame and close
if let Some(handle) = self.connection_handle.take() {
let _ = tokio::time::timeout(
std::time::Duration::from_secs(5),
handle,
).await;
}
*self.assigned_ip.write().await = None;
*self.connected_since.write().await = None;
*self.state.write().await = ClientState::Disconnected;

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartvpn',
version: '1.10.1',
version: '1.10.2',
description: 'A VPN solution with TypeScript control plane and Rust data plane daemon'
}