parent
f588fe29db
commit
151e662027
11 changed files with 149 additions and 35 deletions
|
@ -108,6 +108,7 @@ target_sources(${PROJECT} PRIVATE
|
|||
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/ScreenProtection.swift
|
||||
${CLIENT_ROOT_DIR}/platforms/ios/VPNCController.swift
|
||||
)
|
||||
|
||||
target_sources(${PROJECT} PRIVATE
|
||||
|
|
|
@ -16,6 +16,11 @@ struct Log {
|
|||
|
||||
private static let appGroupID = "group.org.amnezia.AmneziaVPN"
|
||||
|
||||
static let appLogURL = {
|
||||
let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)!
|
||||
return sharedContainerURL.appendingPathComponent("app.log", isDirectory: false)
|
||||
}()
|
||||
|
||||
static let neLogURL = {
|
||||
let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)!
|
||||
return sharedContainerURL.appendingPathComponent("ne.log", isDirectory: false)
|
||||
|
@ -70,8 +75,12 @@ struct Log {
|
|||
}
|
||||
|
||||
static func log(_ type: OSLogType, title: String = "", message: String, url: URL = neLogURL) {
|
||||
NSLog("\(title) \(message)")
|
||||
|
||||
guard isLoggingEnabled else { return }
|
||||
|
||||
osLog.log(level: type, "\(title) \(message)")
|
||||
|
||||
let date = Date()
|
||||
let level = Record.Level(from: type)
|
||||
let messages = message.split(whereSeparator: \.isNewline)
|
||||
|
@ -107,3 +116,7 @@ extension Log: CustomStringConvertible {
|
|||
.joined(separator: "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func log(_ type: OSLogType, title: String = "", message: String) {
|
||||
Log.log(type, title: "App: \(title)", message: message, url: Log.appLogURL)
|
||||
}
|
||||
|
|
|
@ -1,50 +1,33 @@
|
|||
import Foundation
|
||||
import NetworkExtension
|
||||
|
||||
public func swiftUpdateLogData(_ qtString: std.string) -> std.string {
|
||||
let qtLog = Log(String(describing: qtString))
|
||||
var log = qtLog
|
||||
|
||||
if let appLog = Log(at: Log.appLogURL) {
|
||||
appLog.records.forEach {
|
||||
log.records.append($0)
|
||||
}
|
||||
}
|
||||
|
||||
if let neLog = Log(at: Log.neLogURL) {
|
||||
neLog.records.forEach {
|
||||
log.records.append($0)
|
||||
}
|
||||
}
|
||||
|
||||
log.records.sort {
|
||||
$0.date < $1.date
|
||||
}
|
||||
}
|
||||
|
||||
return std.string(log.description)
|
||||
}
|
||||
|
||||
public func swiftDeleteLog() {
|
||||
Log.clear(at: Log.appLogURL)
|
||||
Log.clear(at: Log.neLogURL)
|
||||
}
|
||||
|
||||
public func toggleLogging(_ isEnabled: Bool) {
|
||||
Log.isLoggingEnabled = isEnabled
|
||||
}
|
||||
|
||||
public func clearSettings() {
|
||||
NETunnelProviderManager.loadAllFromPreferences { managers, error in
|
||||
if let error {
|
||||
NSLog("clearSettings removeFromPreferences error: \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
|
||||
managers?.forEach { manager in
|
||||
manager.removeFromPreferences { error in
|
||||
if let error {
|
||||
NSLog("NE removeFromPreferences error: \(error.localizedDescription)")
|
||||
} else {
|
||||
manager.loadFromPreferences { error in
|
||||
if let error {
|
||||
NSLog("NE loadFromPreferences after remove error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ extension PacketTunnelProvider {
|
|||
}
|
||||
|
||||
func stopOpenVPN(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
ovpnLog(.info, message: "Stopping tunnel: reason: \(reason.description)")
|
||||
|
||||
stopHandler = completionHandler
|
||||
if vpnReachability.isTracking {
|
||||
vpnReachability.stopTracking()
|
||||
|
|
|
@ -200,7 +200,7 @@ extension PacketTunnelProvider {
|
|||
// }
|
||||
|
||||
func stopWireguard(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
wg_log(.info, staticMessage: "Stopping tunnel")
|
||||
wg_log(.info, message: "Stopping tunnel: reason: \(reason.description)")
|
||||
|
||||
wgAdapter.stop { error in
|
||||
ErrorNotifier.removeLastErrorFile()
|
||||
|
|
|
@ -200,3 +200,46 @@ extension WireGuardLogLevel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NEProviderStopReason: CustomStringConvertible {
|
||||
public var description: String {
|
||||
switch self {
|
||||
case .none:
|
||||
return "No specific reason"
|
||||
case .userInitiated:
|
||||
return "The user stopped the NE"
|
||||
case .providerFailed:
|
||||
return "The NE failed to function correctly"
|
||||
case .noNetworkAvailable:
|
||||
return "No network connectivity is currently available"
|
||||
case .unrecoverableNetworkChange:
|
||||
return "The device’s network connectivity changed"
|
||||
case .providerDisabled:
|
||||
return "The NE was disabled"
|
||||
case .authenticationCanceled:
|
||||
return "The authentication process was canceled"
|
||||
case .configurationFailed:
|
||||
return "The VPNC is invalid"
|
||||
case .idleTimeout:
|
||||
return "The session timed out"
|
||||
case .configurationDisabled:
|
||||
return "The VPNC was disabled"
|
||||
case .configurationRemoved:
|
||||
return "The VPNC was removed"
|
||||
case .superceded:
|
||||
return "VPNC was superceded by a higher-priority VPNC"
|
||||
case .userLogout:
|
||||
return "The user logged out"
|
||||
case .userSwitch:
|
||||
return "The current console user changed"
|
||||
case .connectionFailed:
|
||||
return "The connection failed"
|
||||
case .sleep:
|
||||
return "A stop reason indicating the VPNC enabled disconnect on sleep and the device went to sleep"
|
||||
case .appUpdate:
|
||||
return "appUpdat"
|
||||
@unknown default:
|
||||
return "@unknown default"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
50
client/platforms/ios/VPNCController.swift
Normal file
50
client/platforms/ios/VPNCController.swift
Normal file
|
@ -0,0 +1,50 @@
|
|||
import Foundation
|
||||
import NetworkExtension
|
||||
|
||||
public func removeVPNC(_ vpncName: std.string) {
|
||||
let vpncName = String(describing: vpncName)
|
||||
|
||||
Task {
|
||||
await getManagers()?.first { manager in
|
||||
if let name = manager.localizedDescription, name == vpncName {
|
||||
Task {
|
||||
await remove(manager)
|
||||
}
|
||||
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func clearSettings() {
|
||||
Task {
|
||||
await getManagers()?.forEach { manager in
|
||||
Task {
|
||||
await remove(manager)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getManagers() async -> [NETunnelProviderManager]? {
|
||||
do {
|
||||
return try await NETunnelProviderManager.loadAllFromPreferences()
|
||||
} catch {
|
||||
log(.error, title: "VPNC: ", message: "loadAllFromPreferences error: \(error.localizedDescription)")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func remove(_ manager: NETunnelProviderManager) async {
|
||||
let vpncName = manager.localizedDescription ?? "Unknown"
|
||||
do {
|
||||
try await manager.removeFromPreferences()
|
||||
try await manager.loadFromPreferences()
|
||||
log(.info, title: "VPNC: ", message: "Remove \(vpncName)")
|
||||
} catch {
|
||||
log(.error, title: "VPNC: ", message: "Failed to remove \(vpncName) (\(error.localizedDescription))")
|
||||
}
|
||||
}
|
|
@ -86,6 +86,9 @@ struct WGConfig: Decodable {
|
|||
AllowedIPs = \(allowedIPs.joined(separator: ", "))
|
||||
Endpoint = \(hostName):\(port)
|
||||
PersistentKeepalive = \(persistentKeepAlive)
|
||||
|
||||
SplitTunnelType = \(splitTunnelType)
|
||||
SplitTunnelSites = \(splitTunnelSites.joined(separator: ", "))
|
||||
"""
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,9 +89,11 @@ bool IosController::initialize()
|
|||
|
||||
|
||||
for (NETunnelProviderManager *manager in managers) {
|
||||
qDebug() << "IosController::initialize : VPNC: " << manager.localizedDescription;
|
||||
|
||||
if (manager.connection.status == NEVPNStatusConnected) {
|
||||
m_currentTunnel = manager;
|
||||
qDebug() << "IosController::initialize : VPN already connected";
|
||||
qDebug() << "IosController::initialize : VPN already connected with" << manager.localizedDescription;
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Connected);
|
||||
break;
|
||||
|
||||
|
@ -138,7 +140,7 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
|||
[NETunnelProviderManager loadAllFromPreferencesWithCompletionHandler:^(NSArray<NETunnelProviderManager *> * _Nullable managers, NSError * _Nullable error) {
|
||||
@try {
|
||||
if (error) {
|
||||
qDebug() << "IosController::connectVpn : Error:" << [error.localizedDescription UTF8String];
|
||||
qDebug() << "IosController::connectVpn : VPNC: loadAllFromPreferences error:" << [error.localizedDescription UTF8String];
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
||||
ok = false;
|
||||
return;
|
||||
|
@ -151,7 +153,7 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
|||
for (NETunnelProviderManager *manager in managers) {
|
||||
if ([manager.localizedDescription isEqualToString:tunnelName.toNSString()]) {
|
||||
m_currentTunnel = manager;
|
||||
qDebug() << "IosController::connectVpn : Using existing tunnel";
|
||||
qDebug() << "IosController::connectVpn : Using existing tunnel:" << manager.localizedDescription;
|
||||
if (manager.connection.status == NEVPNStatusConnected) {
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Connected);
|
||||
return;
|
||||
|
@ -162,10 +164,10 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
|
|||
}
|
||||
|
||||
if (!m_currentTunnel) {
|
||||
qDebug() << "IosController::connectVpn : Creating new tunnel";
|
||||
isNewTunnelCreated = true;
|
||||
m_currentTunnel = [[NETunnelProviderManager alloc] init];
|
||||
m_currentTunnel.localizedDescription = [NSString stringWithUTF8String:tunnelName.toStdString().c_str()];
|
||||
qDebug() << "IosController::connectVpn : Creating new tunnel" << m_currentTunnel.localizedDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -598,13 +600,14 @@ void IosController::startTunnel()
|
|||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
if (saveError) {
|
||||
qDebug().nospace() << "IosController::startTunnel" << protocolName << ": Connect " << protocolName << " Tunnel Save Error" << saveError.localizedDescription.UTF8String;
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
||||
return;
|
||||
}
|
||||
|
||||
[m_currentTunnel loadFromPreferencesWithCompletionHandler:^(NSError *loadError) {
|
||||
if (loadError) {
|
||||
qDebug().nospace() << "IosController::start" << protocolName << ": Connect " << protocolName << " Tunnel Load Error" << loadError.localizedDescription.UTF8String;
|
||||
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << ": Connect " << protocolName << " Tunnel Load Error" << loadError.localizedDescription.UTF8String;
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
||||
return;
|
||||
}
|
||||
|
@ -615,11 +618,11 @@ void IosController::startTunnel()
|
|||
BOOL started = [m_currentTunnel.connection startVPNTunnelWithOptions:nil andReturnError:&startError];
|
||||
|
||||
if (!started || startError) {
|
||||
qDebug().nospace() << "IosController::start" << protocolName << " : Connect " << protocolName << " Tunnel Start Error"
|
||||
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << " : Connect " << protocolName << " Tunnel Start Error"
|
||||
<< (startError ? startError.localizedDescription.UTF8String : "");
|
||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
||||
} else {
|
||||
qDebug().nospace() << "IosController::start" << protocolName << " : Starting the tunnel succeeded";
|
||||
qDebug().nospace() << "IosController::startTunnel :" << m_currentTunnel.localizedDescription << protocolName << " : Starting the tunnel succeeded";
|
||||
}
|
||||
}];
|
||||
});
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
#include "ui/models/protocols/awgConfigModel.h"
|
||||
#include "ui/models/protocols/wireguardConfigModel.h"
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
#include <AmneziaVPN-Swift.h>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
Logger logger("ServerController");
|
||||
|
@ -564,6 +568,15 @@ void InstallController::removeApiConfig()
|
|||
{
|
||||
auto serverConfig = m_serversModel->getServerConfig(m_serversModel->getDefaultServerIndex());
|
||||
|
||||
#ifdef Q_OS_IOS
|
||||
QString vpncName = QString("%1 (%2) %3")
|
||||
.arg(serverConfig[config_key::description].toString())
|
||||
.arg(serverConfig[config_key::hostName].toString())
|
||||
.arg(serverConfig[config_key::vpnproto].toString());
|
||||
|
||||
AmneziaVPN::removeVPNC(vpncName.toStdString());
|
||||
#endif
|
||||
|
||||
serverConfig.remove(config_key::dns1);
|
||||
serverConfig.remove(config_key::dns2);
|
||||
serverConfig.remove(config_key::containers);
|
||||
|
|
|
@ -78,6 +78,9 @@ void SettingsController::toggleLogging(bool enable)
|
|||
#endif
|
||||
if (enable == true) {
|
||||
checkIfNeedDisableLogs();
|
||||
|
||||
qInfo().noquote() << QString("Logging has enabled on %1 version %2 %3").arg(APPLICATION_NAME, APP_VERSION, GIT_COMMIT_HASH);
|
||||
qInfo().noquote() << QString("%1 (%2)").arg(QSysInfo::prettyProductName(), QSysInfo::currentCpuArchitecture());
|
||||
}
|
||||
emit loggingStateChanged();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue