Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 93 additions & 94 deletions src-tauri/Cargo.lock

Large diffs are not rendered by default.

62 changes: 55 additions & 7 deletions src-tauri/src/apple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ use objc2_network_extension::{
use serde::{Deserialize, Serialize};
use sqlx::SqliteExecutor;
use tauri::{AppHandle, Emitter, Manager};
use tracing::Level;

use crate::{
active_connections::find_connection,
Expand All @@ -41,6 +42,7 @@ use crate::{
},
error::Error,
events::EventKey,
log_watcher::service_log_watcher::spawn_log_watcher_task,
utils::{DEFAULT_ROUTE_IPV4, DEFAULT_ROUTE_IPV6},
ConnectionType,
};
Expand All @@ -62,6 +64,8 @@ static VPN_STATE_UPDATE_COMMS: LazyLock<(
(Mutex::new(tx), Mutex::new(Some(rx)))
});

const SYSTEM_SYNC_DELAY_MS: u64 = 500;

/// Thread responsible for handling VPN status update requests.
/// This is an async function.
/// It has access to the `AppHandle` to be able to emit events.
Expand All @@ -78,6 +82,7 @@ pub async fn connection_state_update_thread(app_handle: &AppHandle) {
debug!("Waiting for status update message from channel...");

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

debug!("Processed status update message.");
Expand Down Expand Up @@ -128,6 +133,26 @@ pub async fn sync_connections_with_system(app_handle: &AppHandle) {
app_handle
.emit(EventKey::ConnectionChanged.into(), ())
.unwrap();

debug!(
"Spawning log watcher for location {} (started from system settings)",
location.name
);
if let Err(e) = spawn_log_watcher_task(
app_handle.clone(),
location.id,
location.name.clone(),
ConnectionType::Location,
Level::DEBUG,
None,
)
.await
{
warn!(
"Failed to spawn log watcher for location {}: {e}",
location.name
);
}
}
}
Some(NEVPNStatus::Disconnected) => {
Expand Down Expand Up @@ -197,6 +222,27 @@ pub async fn sync_connections_with_system(app_handle: &AppHandle) {
app_handle
.emit(EventKey::ConnectionChanged.into(), ())
.unwrap();

// Spawn log watcher for this tunnel (VPN was started from system settings)
debug!(
"Spawning log watcher for tunnel {} (started from system settings)",
tunnel.name
);
if let Err(e) = spawn_log_watcher_task(
app_handle.clone(),
tunnel.id,
tunnel.name.clone(),
ConnectionType::Tunnel,
Level::DEBUG,
None,
)
.await
{
warn!(
"Failed to spawn log watcher for tunnel {}: {e}",
tunnel.name
);
}
}
}
Some(NEVPNStatus::Disconnected) => {
Expand Down Expand Up @@ -676,7 +722,7 @@ impl TunnelConfiguration {
info!("VPN started");
}
} else {
error!(
debug!(
"Couldn't find configuration from system settings for {}",
self.name
);
Expand All @@ -691,7 +737,7 @@ pub(crate) fn remove_config_for_location(location: &Location<Id>) {
provider_manager.removeFromPreferencesWithCompletionHandler(None);
}
} else {
error!(
debug!(
"Couldn't find configuration in system settings for location {}",
location.name
);
Expand All @@ -705,7 +751,7 @@ pub(crate) fn remove_config_for_tunnel(tunnel: &Tunnel<Id>) {
provider_manager.removeFromPreferencesWithCompletionHandler(None);
}
} else {
error!(
debug!(
"Couldn't find configuration in system settings for tunnel {}",
tunnel.name
);
Expand All @@ -716,7 +762,7 @@ pub(crate) fn remove_config_for_tunnel(tunnel: &Tunnel<Id>) {
pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
manager_for_key_and_value("locationId", location.id).map_or_else(
|| {
error!(
debug!(
"Couldn't find configuration in system settings for location {}",
location.name
);
Expand All @@ -726,6 +772,7 @@ pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
unsafe {
provider_manager.connection().stopVPNTunnel();
}

info!("VPN stopped");
true
},
Expand All @@ -736,7 +783,7 @@ pub(crate) fn stop_tunnel_for_location(location: &Location<Id>) -> bool {
pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
manager_for_key_and_value("tunnelId", tunnel.id).map_or_else(
|| {
error!(
debug!(
"Couldn't find configuration in system settings for location {}",
tunnel.name
);
Expand All @@ -746,6 +793,7 @@ pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
unsafe {
provider_manager.connection().stopVPNTunnel();
}

info!("VPN stopped");
true
},
Expand All @@ -756,7 +804,7 @@ pub(crate) fn stop_tunnel_for_tunnel(tunnel: &Tunnel<Id>) -> bool {
pub(crate) fn get_location_status(location: &Location<Id>) -> Option<NEVPNStatus> {
manager_for_key_and_value("locationId", location.id).map_or_else(
|| {
error!(
debug!(
"Couldn't find configuration in system settings for location {}",
location.name
);
Expand All @@ -773,7 +821,7 @@ pub(crate) fn get_location_status(location: &Location<Id>) -> Option<NEVPNStatus
pub(crate) fn get_tunnel_status(tunnel: &Tunnel<Id>) -> Option<NEVPNStatus> {
manager_for_key_and_value("tunnelId", tunnel.id).map_or_else(
|| {
error!(
debug!(
"Couldn't find configuration in system settings for tunnel {}",
tunnel.name
);
Expand Down
6 changes: 3 additions & 3 deletions src-tauri/src/log_watcher/global_log_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use tokio_util::sync::CancellationToken;
use tracing::Level;

#[cfg(target_os = "macos")]
use crate::log_watcher::get_vpn_extension_log_path;
use crate::log_watcher::get_vpn_extension_log_dir_path;
use crate::{
appstate::AppState,
error::Error,
Expand All @@ -31,7 +31,7 @@ use crate::{
use crate::{log_watcher::extract_timestamp, utils::get_service_log_dir};

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

/// Helper struct to handle log directory logic
#[derive(Debug)]
Expand Down Expand Up @@ -60,7 +60,7 @@ impl LogDirs {
})?;

#[cfg(target_os = "macos")]
let vpn_extension_log_dir = get_vpn_extension_log_path()?;
let vpn_extension_log_dir = get_vpn_extension_log_dir_path()?;

#[cfg(not(target_os = "macos"))]
debug!(
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/log_watcher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static LOG_LINE_REGEX: LazyLock<Regex> = LazyLock::new(|| {

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

let manager = NSFileManager::defaultManager();
Expand Down
35 changes: 22 additions & 13 deletions src-tauri/src/log_watcher/service_log_watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,9 @@ pub async fn spawn_log_watcher_task(
log_level: Level,
from: Option<String>,
) -> Result<String, Error> {
use crate::log_watcher::get_vpn_extension_log_path;
use crate::log_watcher::{
get_vpn_extension_log_dir_path, global_log_watcher::VPN_EXTENSION_LOG_FILENAME,
};

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

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

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

if let Some(token) = log_watchers.remove(interface_name) {
debug!("Using cancellation token for service log watcher on interface {interface_name}");
token.cancel();
debug!("Service log watcher for interface {interface_name} stopped");
Ok(())
} else {
debug!(
"Service log watcher for interface {interface_name} couldn't be found, nothing to stop"
);
Err(Error::NotFound)
}
log_watchers.remove(interface_name).map_or_else(
|| {
warn!(
"Service log watcher for interface {interface_name} couldn't be found, nothing to stop"
);
Ok(())
},
|token| {
debug!(
"Using cancellation token for service log watcher on interface {interface_name}"
);
token.cancel();
debug!("Service log watcher for interface {interface_name} stopped");
Ok(())
},
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,11 @@ export const LocationLogs = ({ locationId, connectionType }: Props) => {
logsContainerElement.current &&
filterLogByLevel(locationLogLevelRef.current, item.level)
) {
const messageString = `${item.timestamp} ${item.level} ${item.fields.message}`;
const utcTimestamp = item.timestamp.endsWith('Z')
? item.timestamp
: `${item.timestamp}Z`;
const dateTime = new Date(utcTimestamp).toLocaleString();
const messageString = `${dateTime} ${item.level} ${item.fields.message}`;
const element = createLogLineElement(messageString);
const scrollAfterAppend =
logsContainerElement.current.scrollHeight -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,24 @@ export const GlobalLogs = () => {
const { startGlobalLogWatcher, stopGlobalLogWatcher } = clientApi;

const handleLogsDownload = async () => {
const path = await save({
filters: [
{
name: 'Logs',
extensions: ['txt', 'log'],
},
],
});
try {
const path = await save({
filters: [
{
name: 'Logs',
extensions: ['txt', 'log'],
},
],
});

if (path) {
const logs = getAllLogs();
await writeTextFile(path, logs);
} else {
error('Failed to save logs! Path was null');
if (path) {
const logs = getAllLogs();
await writeTextFile(path, logs);
} else {
throw new Error('No path selected');
}
} catch (e) {
error(`Failed to save logs: ${e}`);
}
};

Expand Down Expand Up @@ -72,7 +76,10 @@ export const GlobalLogs = () => {
filterLogByLevel(globalLogLevelRef.current, item.level) &&
filterLogBySource(logSourceRef.current, item.source)
) {
const dateTime = new Date(item.timestamp).toLocaleString();
const utcTimestamp = item.timestamp.endsWith('Z')
? item.timestamp
: `${item.timestamp}Z`;
const dateTime = new Date(utcTimestamp).toLocaleString();
const messageString = `[${dateTime}][${item.level}][${item.source}] ${item.fields.message}`;
const element = createLogLineElement(messageString);
const scrollAfterAppend =
Expand Down
2 changes: 1 addition & 1 deletion swift/boringtun
Submodule boringtun updated 1 files
+48 −68 Cargo.lock