[WIP] seamless protocol switching without leaving the app

This commit is contained in:
Alex Kh 2021-12-08 19:40:43 +04:00
parent 1a333f7968
commit b6bab0c723
2 changed files with 56 additions and 25 deletions

View file

@ -46,7 +46,7 @@ public class IOSVpnProtocolImpl : NSObject {
stateChangeCallback = callback stateChangeCallback = callback
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, NotificationCenter.default.addObserver(self,
selector: #selector(self.vpnStatusDidChange(notification:)), selector: #selector(self.vpnStatusDidChange(notification:)),
name: Notification.Name.NEVPNStatusDidChange, name: Notification.Name.NEVPNStatusDidChange,
@ -70,15 +70,15 @@ public class IOSVpnProtocolImpl : NSObject {
let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:)) let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:))
if let name = tunnel?.localizedDescription, name == vpnName { // if let name = tunnel?.localizedDescription, name == vpnName {
tunnel?.removeFromPreferences(completionHandler: { removeError in // tunnel?.removeFromPreferences(completionHandler: { removeError in
if let error = removeError { // if let error = removeError {
Logger.global?.log(message: "WireguardVPN Tunnel Remove from Prefs Error: \(error)") // Logger.global?.log(message: "WireguardVPN Tunnel Remove from Prefs Error: \(error)")
closure(ConnectionState.Error, nil) // closure(ConnectionState.Error, nil)
return // return
} // }
}) // })
} // }
if tunnel == nil { if tunnel == nil {
Logger.global?.log(message: "Creating the tunnel") Logger.global?.log(message: "Creating the tunnel")
@ -117,6 +117,8 @@ public class IOSVpnProtocolImpl : NSObject {
self.privateKey = PrivateKey(rawValue: privateKey) self.privateKey = PrivateKey(rawValue: privateKey)
self.deviceIpv4Address = deviceIpv4Address self.deviceIpv4Address = deviceIpv4Address
self.deviceIpv6Address = deviceIpv6Address self.deviceIpv6Address = deviceIpv6Address
NotificationCenter.default.removeObserver(self)
NotificationCenter.default.addObserver(self, selector: #selector(self.vpnStatusDidChange(notification:)), name: Notification.Name.NEVPNStatusDidChange, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(self.vpnStatusDidChange(notification:)), name: Notification.Name.NEVPNStatusDidChange, object: nil)
@ -138,15 +140,15 @@ public class IOSVpnProtocolImpl : NSObject {
let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:)) let tunnel = nsManagers.first(where: IOSVpnProtocolImpl.isOurManager(_:))
if let name = tunnel?.localizedDescription, name != vpnName { // if let name = tunnel?.localizedDescription, name != vpnName {
tunnel?.removeFromPreferences(completionHandler: { removeError in // tunnel?.removeFromPreferences(completionHandler: { removeError in
if let error = removeError { // if let error = removeError {
Logger.global?.log(message: "OpenVpn Tunnel Remove from Prefs Error: \(error)") // Logger.global?.log(message: "OpenVpn Tunnel Remove from Prefs Error: \(error)")
closure(ConnectionState.Error, nil) // closure(ConnectionState.Error, nil)
return // return
} // }
}) // })
} // }
if tunnel == nil { if tunnel == nil {
Logger.global?.log(message: "Creating the tunnel") Logger.global?.log(message: "Creating the tunnel")

View file

@ -19,6 +19,7 @@ namespace
{ {
IOSVpnProtocol* s_instance = nullptr; IOSVpnProtocol* s_instance = nullptr;
IOSVpnProtocolImpl* m_controller = nullptr; IOSVpnProtocolImpl* m_controller = nullptr;
Proto currentProto = amnezia::Proto::Any;
} }
IOSVpnProtocol::IOSVpnProtocol(Proto proto, const QJsonObject &configuration, QObject* parent) IOSVpnProtocol::IOSVpnProtocol(Proto proto, const QJsonObject &configuration, QObject* parent)
@ -51,8 +52,10 @@ bool IOSVpnProtocol::initialize()
if (protoName == "wireguard") { if (protoName == "wireguard") {
setupWireguardProtocol(result); setupWireguardProtocol(result);
currentProto = amnezia::Proto::WireGuard;
} else if (protoName == "openvpn") { } else if (protoName == "openvpn") {
setupOpenVPNProtocol(result); setupOpenVPNProtocol(result);
currentProto = amnezia::Proto::OpenVpn;
} else { } else {
return false; return false;
} }
@ -65,20 +68,38 @@ ErrorCode IOSVpnProtocol::start()
{ {
bool ok; bool ok;
QtJson::JsonObject result = QtJson::parse(QJsonDocument(m_rawConfig).toJson(), ok).toMap(); QtJson::JsonObject result = QtJson::parse(QJsonDocument(m_rawConfig).toJson(), ok).toMap();
qDebug() << "current protocol: " << currentProto;
qDebug() << "new protocol: " << m_protocol;
qDebug() << "config: " << result; qDebug() << "config: " << result;
if(!ok) { if(!ok) {
qDebug() << QString("An error occurred during config parsing"); qDebug() << QString("An error occurred during config parsing");
return InternalError; return InternalError;
} }
QString protocol = result["protocol"].toString(); QString protocol = result["protocol"].toString();
if (protocol == "wireguard") { switch (m_protocol) {
launchWireguardTunnel(result); case amnezia::Proto::OpenVpn:
} else if (protocol == "openvpn") { if (currentProto == amnezia::Proto::WireGuard) {
launchOpenVPNTunnel(result); setupOpenVPNProtocol(result);
} else { launchOpenVPNTunnel(result);
return InternalError; currentProto = amnezia::Proto::OpenVpn;
return NoError;
}
launchOpenVPNTunnel(result);
break;
case amnezia::Proto::WireGuard:
if (currentProto == amnezia::Proto::OpenVpn) {
setupWireguardProtocol(result);
launchWireguardTunnel(result);
currentProto = amnezia::Proto::WireGuard;
return NoError;
}
launchWireguardTunnel(result);
break;
default:
break;
} }
return NoError; return NoError;
@ -270,6 +291,10 @@ void IOSVpnProtocol::setupWireguardProtocol(const QtJson::JsonObject &result)
} }
} }
callback:^(BOOL a_connected) { callback:^(BOOL a_connected) {
if (currentProto != m_protocol) {
qDebug() << "Protocols switched: " << a_connected;
return;
}
qDebug() << "State changed: " << a_connected; qDebug() << "State changed: " << a_connected;
if (a_connected) { if (a_connected) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
@ -327,6 +352,10 @@ void IOSVpnProtocol::setupOpenVPNProtocol(const QtJson::JsonObject &result)
} }
} }
callback:^(BOOL a_connected) { callback:^(BOOL a_connected) {
if (currentProto != m_protocol) {
qDebug() << "Protocols switched: " << a_connected;
return;
}
qDebug() << "OVPN State changed: " << a_connected; qDebug() << "OVPN State changed: " << a_connected;
if (a_connected) { if (a_connected) {
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{