Skip to content

Commit 5823399

Browse files
authored
Fix "object not found" during disconnect after system settings connect, other small fixes (#697)
* fix * fixes * remove println * bump versions
1 parent c507c35 commit 5823399

8 files changed

Lines changed: 201 additions & 134 deletions

File tree

src-tauri/Cargo.lock

Lines changed: 93 additions & 94 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/src/apple.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use objc2_network_extension::{
3131
use serde::{Deserialize, Serialize};
3232
use sqlx::SqliteExecutor;
3333
use tauri::{AppHandle, Emitter, Manager};
34+
use tracing::Level;
3435

3536
use crate::{
3637
active_connections::find_connection,
@@ -41,6 +42,7 @@ use crate::{
4142
},
4243
error::Error,
4344
events::EventKey,
45+
log_watcher::service_log_watcher::spawn_log_watcher_task,
4446
utils::{DEFAULT_ROUTE_IPV4, DEFAULT_ROUTE_IPV6},
4547
ConnectionType,
4648
};
@@ -62,6 +64,8 @@ static VPN_STATE_UPDATE_COMMS: LazyLock<(
6264
(Mutex::new(tx), Mutex::new(Some(rx)))
6365
});
6466

67+
const SYSTEM_SYNC_DELAY_MS: u64 = 500;
68+
6569
/// Thread responsible for handling VPN status update requests.
6670
/// This is an async function.
6771
/// It has access to the `AppHandle` to be able to emit events.
@@ -78,6 +82,7 @@ pub async fn connection_state_update_thread(app_handle: &AppHandle) {
7882
debug!("Waiting for status update message from channel...");
7983

8084
debug!("Status update message received, synchronizing state...");
85+
tokio::time::sleep(Duration::from_millis(SYSTEM_SYNC_DELAY_MS)).await;
8186
sync_connections_with_system(app_handle).await;
8287

8388
debug!("Processed status update message.");
@@ -128,6 +133,26 @@ pub async fn sync_connections_with_system(app_handle: &AppHandle) {
128133
app_handle
129134
.emit(EventKey::ConnectionChanged.into(), ())
130135
.unwrap();
136+
137+
debug!(
138+
"Spawning log watcher for location {} (started from system settings)",
139+
location.name
140+
);
141+
if let Err(e) = spawn_log_watcher_task(
142+
app_handle.clone(),
143+
location.id,
144+
location.name.clone(),
145+
ConnectionType::Location,
146+
Level::DEBUG,
147+
None,
148+
)
149+
.await
150+
{
151+
warn!(
152+
"Failed to spawn log watcher for location {}: {e}",
153+
location.name
154+
);
155+
}
131156
}
132157
}
133158
Some(NEVPNStatus::Disconnected) => {
@@ -197,6 +222,27 @@ pub async fn sync_connections_with_system(app_handle: &AppHandle) {
197222
app_handle
198223
.emit(EventKey::ConnectionChanged.into(), ())
199224
.unwrap();
225+
226+
// Spawn log watcher for this tunnel (VPN was started from system settings)
227+
debug!(
228+
"Spawning log watcher for tunnel {} (started from system settings)",
229+
tunnel.name
230+
);
231+
if let Err(e) = spawn_log_watcher_task(
232+
app_handle.clone(),
233+
tunnel.id,
234+
tunnel.name.clone(),
235+
ConnectionType::Tunnel,
236+
Level::DEBUG,
237+
None,
238+
)
239+
.await
240+
{
241+
warn!(
242+
"Failed to spawn log watcher for tunnel {}: {e}",
243+
tunnel.name
244+
);
245+
}
200246
}
201247
}
202248
Some(NEVPNStatus::Disconnected) => {
@@ -676,7 +722,7 @@ impl TunnelConfiguration {
676722
info!("VPN started");
677723
}
678724
} else {
679-
error!(
725+
debug!(
680726
"Couldn't find configuration from system settings for {}",
681727
self.name
682728
);
@@ -691,7 +737,7 @@ pub(crate) fn remove_config_for_location(location: &Location<Id>) {
691737
provider_manager.removeFromPreferencesWithCompletionHandler(None);
692738
}
693739
} else {
694-
error!(
740+
debug!(
695741
"Couldn't find configuration in system settings for location {}",
696742
location.name
697743
);
@@ -705,7 +751,7 @@ pub(crate) fn remove_config_for_tunnel(tunnel: &Tunnel<Id>) {
705751
provider_manager.removeFromPreferencesWithCompletionHandler(None);
706752
}
707753
} else {
708-
error!(
754+
debug!(
709755
"Couldn't find configuration in system settings for tunnel {}",
710756
tunnel.name
711757
);
@@ -716,7 +762,7 @@ pub(crate) fn remove_config_for_tunnel(tunnel: &Tunnel<Id>) {
716762
pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
717763
manager_for_key_and_value("locationId", location.id).map_or_else(
718764
|| {
719-
error!(
765+
debug!(
720766
"Couldn't find configuration in system settings for location {}",
721767
location.name
722768
);
@@ -726,6 +772,7 @@ pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
726772
unsafe {
727773
provider_manager.connection().stopVPNTunnel();
728774
}
775+
729776
info!("VPN stopped");
730777
true
731778
},
@@ -736,7 +783,7 @@ pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
736783
pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
737784
manager_for_key_and_value("tunnelId", tunnel.id).map_or_else(
738785
|| {
739-
error!(
786+
debug!(
740787
"Couldn't find configuration in system settings for location {}",
741788
tunnel.name
742789
);
@@ -746,6 +793,7 @@ pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
746793
unsafe {
747794
provider_manager.connection().stopVPNTunnel();
748795
}
796+
749797
info!("VPN stopped");
750798
true
751799
},
@@ -756,7 +804,7 @@ pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
756804
pub(crate) fn get_location_status(location: &Location<Id>) -> Option<NEVPNStatus> {
757805
manager_for_key_and_value("locationId", location.id).map_or_else(
758806
|| {
759-
error!(
807+
debug!(
760808
"Couldn't find configuration in system settings for location {}",
761809
location.name
762810
);
@@ -773,7 +821,7 @@ pub(crate) fn get_location_status(location: &Location<Id>) -> Option<NEVPNStatus
773821
pub(crate) fn get_tunnel_status(tunnel: &Tunnel<Id>) -> Option<NEVPNStatus> {
774822
manager_for_key_and_value("tunnelId", tunnel.id).map_or_else(
775823
|| {
776-
error!(
824+
debug!(
777825
"Couldn't find configuration in system settings for tunnel {}",
778826
tunnel.name
779827
);

src-tauri/src/log_watcher/global_log_watcher.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use tokio_util::sync::CancellationToken;
2121
use tracing::Level;
2222

2323
#[cfg(target_os = "macos")]
24-
use crate::log_watcher::get_vpn_extension_log_path;
24+
use crate::log_watcher::get_vpn_extension_log_dir_path;
2525
use crate::{
2626
appstate::AppState,
2727
error::Error,
@@ -31,7 +31,7 @@ use crate::{
3131
use crate::{log_watcher::extract_timestamp, utils::get_service_log_dir};
3232

3333
#[cfg(target_os = "macos")]
34-
const VPN_EXTENSION_LOG_FILENAME: &str = "vpn-extension.log";
34+
pub(crate) const VPN_EXTENSION_LOG_FILENAME: &str = "vpn-extension.log";
3535

3636
/// Helper struct to handle log directory logic
3737
#[derive(Debug)]
@@ -60,7 +60,7 @@ impl LogDirs {
6060
})?;
6161

6262
#[cfg(target_os = "macos")]
63-
let vpn_extension_log_dir = get_vpn_extension_log_path()?;
63+
let vpn_extension_log_dir = get_vpn_extension_log_dir_path()?;
6464

6565
#[cfg(not(target_os = "macos"))]
6666
debug!(

src-tauri/src/log_watcher/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static LOG_LINE_REGEX: LazyLock<Regex> = LazyLock::new(|| {
8282

8383
/// Get the VPN extension log file path on macOS
8484
#[cfg(target_os = "macos")]
85-
fn get_vpn_extension_log_path() -> Result<PathBuf, LogWatcherError> {
85+
fn get_vpn_extension_log_dir_path() -> Result<PathBuf, LogWatcherError> {
8686
use objc2_foundation::{ns_string, NSFileManager};
8787

8888
let manager = NSFileManager::defaultManager();

src-tauri/src/log_watcher/service_log_watcher.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ pub async fn spawn_log_watcher_task(
490490
log_level: Level,
491491
from: Option<String>,
492492
) -> Result<String, Error> {
493-
use crate::log_watcher::get_vpn_extension_log_path;
493+
use crate::log_watcher::{
494+
get_vpn_extension_log_dir_path, global_log_watcher::VPN_EXTENSION_LOG_FILENAME,
495+
};
494496

495497
debug!(
496498
"Spawning VPN extension log watcher task for location ID {location_id}, interface {interface_name}"
@@ -507,7 +509,9 @@ pub async fn spawn_log_watcher_task(
507509
let event_topic = format!("log-update-{connection_type_str}-{location_id}");
508510
debug!("Using the following event topic for the VPN extension log watcher: {event_topic}");
509511

510-
let log_file = get_vpn_extension_log_path().map_err(|e| Error::InternalError(e.to_string()))?;
512+
let log_dir =
513+
get_vpn_extension_log_dir_path().map_err(|e| Error::InternalError(e.to_string()))?;
514+
let log_file = log_dir.join(VPN_EXTENSION_LOG_FILENAME);
511515
debug!("VPN extension log file path: {}", log_file.display());
512516

513517
let topic_clone = event_topic.clone();
@@ -566,15 +570,20 @@ pub fn stop_log_watcher_task(handle: &AppHandle, interface_name: &str) -> Result
566570
.lock()
567571
.expect("Failed to lock log watchers mutex");
568572

569-
if let Some(token) = log_watchers.remove(interface_name) {
570-
debug!("Using cancellation token for service log watcher on interface {interface_name}");
571-
token.cancel();
572-
debug!("Service log watcher for interface {interface_name} stopped");
573-
Ok(())
574-
} else {
575-
debug!(
576-
"Service log watcher for interface {interface_name} couldn't be found, nothing to stop"
577-
);
578-
Err(Error::NotFound)
579-
}
573+
log_watchers.remove(interface_name).map_or_else(
574+
|| {
575+
warn!(
576+
"Service log watcher for interface {interface_name} couldn't be found, nothing to stop"
577+
);
578+
Ok(())
579+
},
580+
|token| {
581+
debug!(
582+
"Using cancellation token for service log watcher on interface {interface_name}"
583+
);
584+
token.cancel();
585+
debug!("Service log watcher for interface {interface_name} stopped");
586+
Ok(())
587+
},
588+
)
580589
}

src/pages/client/pages/ClientInstancePage/components/LocationsList/components/LocationsDetailView/components/LocationLogs/LocationLogs.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,11 @@ export const LocationLogs = ({ locationId, connectionType }: Props) => {
6262
logsContainerElement.current &&
6363
filterLogByLevel(locationLogLevelRef.current, item.level)
6464
) {
65-
const messageString = `${item.timestamp} ${item.level} ${item.fields.message}`;
65+
const utcTimestamp = item.timestamp.endsWith('Z')
66+
? item.timestamp
67+
: `${item.timestamp}Z`;
68+
const dateTime = new Date(utcTimestamp).toLocaleString();
69+
const messageString = `${dateTime} ${item.level} ${item.fields.message}`;
6670
const element = createLogLineElement(messageString);
6771
const scrollAfterAppend =
6872
logsContainerElement.current.scrollHeight -

src/pages/client/pages/ClientSettingsPage/components/GlobalLogs/GlobalLogs.tsx

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,24 @@ export const GlobalLogs = () => {
3030
const { startGlobalLogWatcher, stopGlobalLogWatcher } = clientApi;
3131

3232
const handleLogsDownload = async () => {
33-
const path = await save({
34-
filters: [
35-
{
36-
name: 'Logs',
37-
extensions: ['txt', 'log'],
38-
},
39-
],
40-
});
33+
try {
34+
const path = await save({
35+
filters: [
36+
{
37+
name: 'Logs',
38+
extensions: ['txt', 'log'],
39+
},
40+
],
41+
});
4142

42-
if (path) {
43-
const logs = getAllLogs();
44-
await writeTextFile(path, logs);
45-
} else {
46-
error('Failed to save logs! Path was null');
43+
if (path) {
44+
const logs = getAllLogs();
45+
await writeTextFile(path, logs);
46+
} else {
47+
throw new Error('No path selected');
48+
}
49+
} catch (e) {
50+
error(`Failed to save logs: ${e}`);
4751
}
4852
};
4953

@@ -72,7 +76,10 @@ export const GlobalLogs = () => {
7276
filterLogByLevel(globalLogLevelRef.current, item.level) &&
7377
filterLogBySource(logSourceRef.current, item.source)
7478
) {
75-
const dateTime = new Date(item.timestamp).toLocaleString();
79+
const utcTimestamp = item.timestamp.endsWith('Z')
80+
? item.timestamp
81+
: `${item.timestamp}Z`;
82+
const dateTime = new Date(utcTimestamp).toLocaleString();
7683
const messageString = `[${dateTime}][${item.level}][${item.source}] ${item.fields.message}`;
7784
const element = createLogLineElement(messageString);
7885
const scrollAfterAppend =

swift/boringtun

0 commit comments

Comments
 (0)