mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
fix: add network watcher back (#2240)
* feat: add reconnect in case of changing network * fix: reconnect to VPN on wakeup * fix: linux wakeup build
This commit is contained in:
@@ -72,9 +72,9 @@ void NetworkWatcher::initialize() {
|
|||||||
connect(m_impl, &NetworkWatcherImpl::unsecuredNetwork, this,
|
connect(m_impl, &NetworkWatcherImpl::unsecuredNetwork, this,
|
||||||
&NetworkWatcher::unsecuredNetwork);
|
&NetworkWatcher::unsecuredNetwork);
|
||||||
connect(m_impl, &NetworkWatcherImpl::networkChanged, this,
|
connect(m_impl, &NetworkWatcherImpl::networkChanged, this,
|
||||||
&NetworkWatcher::networkChange);
|
&NetworkWatcher::networkChanged);
|
||||||
connect(m_impl, &NetworkWatcherImpl::sleepMode, this,
|
connect(m_impl, &NetworkWatcherImpl::wakeup, this,
|
||||||
&NetworkWatcher::onSleepMode);
|
&NetworkWatcher::wakeup);
|
||||||
m_impl->initialize();
|
m_impl->initialize();
|
||||||
|
|
||||||
// Enable sleep/wake monitoring for VPN auto-reconnection
|
// Enable sleep/wake monitoring for VPN auto-reconnection
|
||||||
@@ -97,12 +97,6 @@ void NetworkWatcher::settingsChanged() {
|
|||||||
logger.debug() << "NetworkWatcher settings changed - keeping sleep monitoring active";
|
logger.debug() << "NetworkWatcher settings changed - keeping sleep monitoring active";
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkWatcher::onSleepMode()
|
|
||||||
{
|
|
||||||
logger.debug() << "Resumed from sleep mode";
|
|
||||||
emit sleepMode();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NetworkWatcher::unsecuredNetwork(const QString& networkName,
|
void NetworkWatcher::unsecuredNetwork(const QString& networkName,
|
||||||
const QString& networkId) {
|
const QString& networkId) {
|
||||||
logger.debug() << "Unsecured network:" << logger.sensitive(networkName)
|
logger.debug() << "Unsecured network:" << logger.sensitive(networkName)
|
||||||
|
|||||||
@@ -29,13 +29,11 @@ public:
|
|||||||
// false to restore.
|
// false to restore.
|
||||||
void simulateDisconnection(bool simulatedDisconnection);
|
void simulateDisconnection(bool simulatedDisconnection);
|
||||||
|
|
||||||
void onSleepMode();
|
|
||||||
|
|
||||||
QNetworkInformation::Reachability getReachability();
|
QNetworkInformation::Reachability getReachability();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void networkChange();
|
void networkChanged();
|
||||||
void sleepMode();
|
void wakeup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void settingsChanged();
|
void settingsChanged();
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ signals:
|
|||||||
// TODO: Only windows-networkwatcher has this, the other plattforms should
|
// TODO: Only windows-networkwatcher has this, the other plattforms should
|
||||||
// too.
|
// too.
|
||||||
void networkChanged(QString newBSSID);
|
void networkChanged(QString newBSSID);
|
||||||
void sleepMode();
|
void wakeup();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ void LinuxNetworkWatcher::initialize() {
|
|||||||
connect(m_worker, &LinuxNetworkWatcherWorker::unsecuredNetwork, this,
|
connect(m_worker, &LinuxNetworkWatcherWorker::unsecuredNetwork, this,
|
||||||
&LinuxNetworkWatcher::unsecuredNetwork);
|
&LinuxNetworkWatcher::unsecuredNetwork);
|
||||||
|
|
||||||
connect(m_worker, &LinuxNetworkWatcherWorker::sleepMode, this,
|
connect(m_worker, &LinuxNetworkWatcherWorker::wakeup, this,
|
||||||
&NetworkWatcherImpl::sleepMode);
|
&NetworkWatcherImpl::wakeup);
|
||||||
|
|
||||||
// Let's wait a few seconds to allow the UI to be fully loaded and shown.
|
// Let's wait a few seconds to allow the UI to be fully loaded and shown.
|
||||||
// This is not strictly needed, but it's better for user experience because
|
// This is not strictly needed, but it's better for user experience because
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ void LinuxNetworkWatcherWorker::checkDevices() {
|
|||||||
void LinuxNetworkWatcherWorker::NMStateChanged(quint32 state)
|
void LinuxNetworkWatcherWorker::NMStateChanged(quint32 state)
|
||||||
{
|
{
|
||||||
if (state == NM_STATE_ASLEEP) {
|
if (state == NM_STATE_ASLEEP) {
|
||||||
emit sleepMode();
|
emit wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug() << "NMStateChanged " << state;
|
logger.debug() << "NMStateChanged " << state;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class LinuxNetworkWatcherWorker final : public QObject {
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void unsecuredNetwork(const QString& networkName, const QString& networkId);
|
void unsecuredNetwork(const QString& networkName, const QString& networkId);
|
||||||
void sleepMode();
|
void wakeup();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void initialize();
|
void initialize();
|
||||||
|
|||||||
@@ -173,10 +173,10 @@ void PowerNotificationsListener::sleepWakeupCallBack(void *refParam, io_service_
|
|||||||
|
|
||||||
case kIOMessageSystemHasPoweredOn:
|
case kIOMessageSystemHasPoweredOn:
|
||||||
/* Announces that the system and its devices have woken up. */
|
/* Announces that the system and its devices have woken up. */
|
||||||
logger.debug() << "System has powered on - emitting sleepMode signal from dedicated CFRunLoop thread";
|
logger.debug() << "System has powered on - emitting wakeup signal from dedicated CFRunLoop thread";
|
||||||
if (listener->m_watcher) {
|
if (listener->m_watcher) {
|
||||||
// Use QMetaObject::invokeMethod for thread-safe signal emission
|
// Use QMetaObject::invokeMethod for thread-safe signal emission
|
||||||
QMetaObject::invokeMethod(listener->m_watcher, "sleepMode", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(listener->m_watcher, "wakeup", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ LRESULT WindowsNetworkWatcher::PowerWndProcCallback(HWND hwnd, UINT uMsg, WPARAM
|
|||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case WM_POWERBROADCAST:
|
case WM_POWERBROADCAST:
|
||||||
if (wParam == PBT_APMRESUMESUSPEND) {
|
if (wParam == PBT_APMRESUMESUSPEND) {
|
||||||
emit obj->sleepMode();
|
emit obj->wakeup();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject *
|
|||||||
m_impl.reset(new LocalSocketController());
|
m_impl.reset(new LocalSocketController());
|
||||||
connect(m_impl.get(), &ControllerImpl::connected, this,
|
connect(m_impl.get(), &ControllerImpl::connected, this,
|
||||||
[this](const QString &pubkey, const QDateTime &connectionTimestamp) {
|
[this](const QString &pubkey, const QDateTime &connectionTimestamp) {
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Connected);
|
setConnectionState(Vpn::ConnectionState::Connected);
|
||||||
});
|
});
|
||||||
connect(m_impl.get(), &ControllerImpl::statusUpdated, this,
|
connect(m_impl.get(), &ControllerImpl::statusUpdated, this,
|
||||||
[this](const QString& serverIpv4Gateway,
|
[this](const QString& serverIpv4Gateway,
|
||||||
@@ -38,7 +38,7 @@ WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject *
|
|||||||
});
|
});
|
||||||
|
|
||||||
connect(m_impl.get(), &ControllerImpl::disconnected, this,
|
connect(m_impl.get(), &ControllerImpl::disconnected, this,
|
||||||
[this]() { emit connectionStateChanged(Vpn::ConnectionState::Disconnected); });
|
[this]() { setConnectionState(Vpn::ConnectionState::Disconnected); });
|
||||||
m_impl->initialize(nullptr, nullptr);
|
m_impl->initialize(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ XrayProtocol::~XrayProtocol()
|
|||||||
ErrorCode XrayProtocol::start()
|
ErrorCode XrayProtocol::start()
|
||||||
{
|
{
|
||||||
qDebug() << "XrayProtocol::start()";
|
qDebug() << "XrayProtocol::start()";
|
||||||
setConnectionState(Vpn::ConnectionState::Connecting);
|
|
||||||
|
|
||||||
return IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
return IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
auto xrayStart = iface->xrayStart(QJsonDocument(m_xrayConfig).toJson());
|
auto xrayStart = iface->xrayStart(QJsonDocument(m_xrayConfig).toJson());
|
||||||
@@ -69,7 +68,6 @@ ErrorCode XrayProtocol::start()
|
|||||||
void XrayProtocol::stop()
|
void XrayProtocol::stop()
|
||||||
{
|
{
|
||||||
qDebug() << "XrayProtocol::stop()";
|
qDebug() << "XrayProtocol::stop()";
|
||||||
setConnectionState(Vpn::ConnectionState::Disconnecting);
|
|
||||||
|
|
||||||
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
|
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
auto disableKillSwitch = iface->disableKillSwitch();
|
auto disableKillSwitch = iface->disableKillSwitch();
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ VpnConnection::VpnConnection(std::shared_ptr<Settings> settings, QObject *parent
|
|||||||
m_checkTimer.setInterval(1000);
|
m_checkTimer.setInterval(1000);
|
||||||
connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged);
|
connect(IosController::Instance(), &IosController::connectionStateChanged, this, &VpnConnection::onConnectionStateChanged);
|
||||||
connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged);
|
connect(IosController::Instance(), &IosController::bytesChanged, this, &VpnConnection::onBytesChanged);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ void VpnConnection::onKillSwitchModeChanged(bool enabled)
|
|||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
IpcClient::withInterface([enabled](QSharedPointer<IpcInterfaceReplica> iface){
|
IpcClient::withInterface([enabled](QSharedPointer<IpcInterfaceReplica> iface){
|
||||||
QRemoteObjectPendingReply<bool> reply = iface->refreshKillSwitch(enabled);
|
QRemoteObjectPendingReply<bool> reply = iface->refreshKillSwitch(enabled);
|
||||||
if (reply.waitForFinished(1000) && reply.returnValue())
|
if (reply.waitForFinished() && reply.returnValue())
|
||||||
qDebug() << "VpnConnection::onKillSwitchModeChanged: Killswitch refreshed";
|
qDebug() << "VpnConnection::onKillSwitchModeChanged: Killswitch refreshed";
|
||||||
else
|
else
|
||||||
qWarning() << "VpnConnection::onKillSwitchModeChanged: Failed to execute remote refreshKillSwitch call";
|
qWarning() << "VpnConnection::onKillSwitchModeChanged: Failed to execute remote refreshKillSwitch call";
|
||||||
@@ -73,40 +72,57 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
|
|||||||
auto container = m_settings->defaultContainer(m_settings->defaultServerIndex());
|
auto container = m_settings->defaultContainer(m_settings->defaultServerIndex());
|
||||||
|
|
||||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
if (state == Vpn::ConnectionState::Connected) {
|
switch (state) {
|
||||||
iface->resetIpStack();
|
case Vpn::ConnectionState::Connected: {
|
||||||
iface->flushDns();
|
iface->resetIpStack();
|
||||||
|
|
||||||
if (!ContainerProps::isAwgContainer(container) &&
|
auto flushDns = iface->flushDns();
|
||||||
container != DockerContainer::WireGuard) {
|
if (flushDns.waitForFinished() && flushDns.returnValue())
|
||||||
QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString();
|
qDebug() << "VpnConnection::onConnectionStateChanged: Successfully flushed DNS";
|
||||||
QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString();
|
else
|
||||||
|
qWarning() << "VpnConnection::onConnectionStateChanged: Failed to clear saved routes";
|
||||||
|
|
||||||
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << dns1 << dns2);
|
|
||||||
|
|
||||||
if (m_settings->isSitesSplitTunnelingEnabled()) {
|
if (!ContainerProps::isAwgContainer(container) &&
|
||||||
iface->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
|
container != DockerContainer::WireGuard) {
|
||||||
// qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
|
QString dns1 = m_vpnConfiguration.value(config_key::dns1).toString();
|
||||||
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
QString dns2 = m_vpnConfiguration.value(config_key::dns2).toString();
|
||||||
QTimer::singleShot(1000, m_vpnProtocol.data(),
|
|
||||||
[this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); });
|
|
||||||
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
|
||||||
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1");
|
|
||||||
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1");
|
|
||||||
|
|
||||||
iface->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress());
|
// TODO: add error code handling for all routeAddList (or rework the code below)
|
||||||
addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings->routeMode());
|
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << dns1 << dns2);
|
||||||
|
|
||||||
|
if (m_settings->isSitesSplitTunnelingEnabled()) {
|
||||||
|
iface->routeDeleteList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0");
|
||||||
|
// qDebug() << "VpnConnection::onConnectionStateChanged :: adding custom routes, count:" << forwardIps.size();
|
||||||
|
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
||||||
|
QTimer::singleShot(1000, m_vpnProtocol.data(),
|
||||||
|
[this]() { addSitesRoutes(m_vpnProtocol->vpnGateway(), m_settings->routeMode()); });
|
||||||
|
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
||||||
|
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "0.0.0.0/1");
|
||||||
|
iface->routeAddList(m_vpnProtocol->vpnGateway(), QStringList() << "128.0.0.0/1");
|
||||||
|
|
||||||
|
iface->routeAddList(m_vpnProtocol->routeGateway(), QStringList() << remoteAddress());
|
||||||
|
addSitesRoutes(m_vpnProtocol->routeGateway(), m_settings->routeMode());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} break;
|
||||||
} else if (state == Vpn::ConnectionState::Error) {
|
case Vpn::ConnectionState::Disconnected:
|
||||||
iface->flushDns();
|
case Vpn::ConnectionState::Error: {
|
||||||
|
auto flushDns = iface->flushDns();
|
||||||
|
if (flushDns.waitForFinished() && flushDns.returnValue())
|
||||||
|
qDebug() << "VpnConnection::onConnectionStateChanged: Successfully flushed DNS";
|
||||||
|
else
|
||||||
|
qWarning() << "VpnConnection::onConnectionStateChanged: Failed to flush DNS";
|
||||||
|
|
||||||
if (m_settings->isSitesSplitTunnelingEnabled()) {
|
auto clearSavedRoutes = iface->clearSavedRoutes();
|
||||||
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
if (clearSavedRoutes.waitForFinished() && clearSavedRoutes.returnValue())
|
||||||
iface->clearSavedRoutes();
|
qDebug() << "VpnConnection::onConnectionStateChanged: Successfully cleared saved routes";
|
||||||
}
|
else
|
||||||
}
|
qWarning() << "VpnConnection::onConnectionStateChanged: Failed to clear saved routes";
|
||||||
|
} break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
@@ -120,7 +136,6 @@ void VpnConnection::onConnectionStateChanged(Vpn::ConnectionState state)
|
|||||||
m_checkTimer.stop();
|
m_checkTimer.stop();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
emit connectionStateChanged(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString &VpnConnection::remoteAddress() const
|
const QString &VpnConnection::remoteAddress() const
|
||||||
@@ -165,7 +180,11 @@ void VpnConnection::addSitesRoutes(const QString &gw, Settings::RouteMode mode)
|
|||||||
});
|
});
|
||||||
m_settings->addVpnSite(mode, site, ip);
|
m_settings->addVpnSite(mode, site, ip);
|
||||||
}
|
}
|
||||||
flushDns();
|
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
|
||||||
|
auto reply = iface->flushDns();
|
||||||
|
if (reply.waitForFinished() || !reply.returnValue())
|
||||||
|
qWarning() << "VpnConnection::addSitesRoutes: Failed to flush DNS";
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,48 +199,6 @@ QSharedPointer<VpnProtocol> VpnConnection::vpnProtocol() const
|
|||||||
return m_vpnProtocol;
|
return m_vpnProtocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnConnection::addRoutes(const QStringList &ips)
|
|
||||||
{
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
|
||||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
|
||||||
if (connectionState() == Vpn::ConnectionState::Connected) {
|
|
||||||
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
|
||||||
iface->routeAddList(m_vpnProtocol->vpnGateway(), ips);
|
|
||||||
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
|
||||||
iface->routeAddList(m_vpnProtocol->routeGateway(), ips);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VpnConnection::deleteRoutes(const QStringList &ips)
|
|
||||||
{
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
|
||||||
IpcClient::withInterface([&](QSharedPointer<IpcInterfaceReplica> iface) {
|
|
||||||
if (connectionState() == Vpn::ConnectionState::Connected) {
|
|
||||||
if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
|
|
||||||
iface->routeDeleteList(vpnProtocol()->vpnGateway(), ips);
|
|
||||||
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
|
|
||||||
iface->routeDeleteList(m_vpnProtocol->routeGateway(), ips);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VpnConnection::flushDns()
|
|
||||||
{
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
|
||||||
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
|
|
||||||
auto reply = iface->flushDns();
|
|
||||||
if (reply.waitForFinished(1000) || !reply.returnValue()) {
|
|
||||||
qWarning() << "VpnConnection::flushDns(): Failed to flush DNS";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void VpnConnection::disconnectSlots()
|
void VpnConnection::disconnectSlots()
|
||||||
{
|
{
|
||||||
if (m_vpnProtocol) {
|
if (m_vpnProtocol) {
|
||||||
@@ -251,7 +228,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
|
|||||||
<< m_settings->routeMode();
|
<< m_settings->routeMode();
|
||||||
|
|
||||||
m_remoteAddress = NetworkUtilities::getIPAddress(credentials.hostName);
|
m_remoteAddress = NetworkUtilities::getIPAddress(credentials.hostName);
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Connecting);
|
setConnectionState(Vpn::ConnectionState::Connecting);
|
||||||
|
|
||||||
m_vpnConfiguration = vpnConfiguration;
|
m_vpnConfiguration = vpnConfiguration;
|
||||||
|
|
||||||
@@ -269,7 +246,7 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
|
|||||||
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
|
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS) && !defined(MACOS_NE)
|
||||||
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
|
m_vpnProtocol.reset(VpnProtocol::factory(container, m_vpnConfiguration));
|
||||||
if (!m_vpnProtocol) {
|
if (!m_vpnProtocol) {
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
setConnectionState(Vpn::ConnectionState::Error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_vpnProtocol->prepare();
|
m_vpnProtocol->prepare();
|
||||||
@@ -287,17 +264,24 @@ void VpnConnection::connectToVpn(int serverIndex, const ServerCredentials &crede
|
|||||||
|
|
||||||
createProtocolConnections();
|
createProtocolConnections();
|
||||||
|
|
||||||
ErrorCode errorCode = m_vpnProtocol->start();
|
if (ErrorCode err = m_vpnProtocol->start(); err != ErrorCode::NoError) {
|
||||||
if (errorCode != ErrorCode::NoError)
|
setConnectionState(Vpn::ConnectionState::Error);
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Error);
|
emit vpnProtocolError(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnConnection::createProtocolConnections()
|
void VpnConnection::createProtocolConnections()
|
||||||
{
|
{
|
||||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||||
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(Vpn::ConnectionState)), this,
|
connect(m_vpnProtocol.data(), &VpnProtocol::connectionStateChanged, this, &VpnConnection::setConnectionState);
|
||||||
SLOT(onConnectionStateChanged(Vpn::ConnectionState)));
|
|
||||||
connect(m_vpnProtocol.data(), SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64)));
|
connect(m_vpnProtocol.data(), SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64)));
|
||||||
|
|
||||||
|
#ifdef AMNEZIA_DESKTOP
|
||||||
|
IpcClient::withInterface([this](QSharedPointer<IpcInterfaceReplica> rep) {
|
||||||
|
connect(rep.data(), &IpcInterfaceReplica::networkChanged, this, &VpnConnection::reconnectToVpn, Qt::QueuedConnection);
|
||||||
|
connect(rep.data(), &IpcInterfaceReplica::wakeup, this, &VpnConnection::reconnectToVpn, Qt::QueuedConnection);
|
||||||
|
});
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void VpnConnection::appendKillSwitchConfig()
|
void VpnConnection::appendKillSwitchConfig()
|
||||||
@@ -439,6 +423,27 @@ QString VpnConnection::bytesPerSecToText(quint64 bytes)
|
|||||||
return QString("%1 %2").arg(QString::number(mbps, 'f', 2)).arg(tr("Mbps")); // Mbit/s
|
return QString("%1 %2").arg(QString::number(mbps, 'f', 2)).arg(tr("Mbps")); // Mbit/s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VpnConnection::reconnectToVpn() {
|
||||||
|
if (m_vpnProtocol.isNull())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_connectionState != Vpn::ConnectionState::Connected) {
|
||||||
|
qWarning() << QString("Reconnect triggered on %1 during inappropriate state: %2; ignoring slot")
|
||||||
|
.arg(QMetaEnum::fromType<Vpn::ConnectionState>().valueToKey(m_connectionState));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Reconnect triggered. Reconnecting to the server";
|
||||||
|
|
||||||
|
setConnectionState(Vpn::ConnectionState::Reconnecting);
|
||||||
|
|
||||||
|
m_vpnProtocol->stop();
|
||||||
|
if (ErrorCode err = m_vpnProtocol->start(); err != ErrorCode::NoError) {
|
||||||
|
setConnectionState(Vpn::ConnectionState::Error);
|
||||||
|
emit vpnProtocolError(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VpnConnection::disconnectFromVpn()
|
void VpnConnection::disconnectFromVpn()
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
#if defined(Q_OS_IOS) || defined(MACOS_NE)
|
||||||
@@ -448,27 +453,11 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (m_vpnProtocol.isNull()) {
|
if (m_vpnProtocol.isNull()) {
|
||||||
emit connectionStateChanged(Vpn::ConnectionState::Disconnected);
|
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_vpnProtocol->stop();
|
setConnectionState(Vpn::ConnectionState::Disconnecting);
|
||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
|
||||||
IpcClient::withInterface([](QSharedPointer<IpcInterfaceReplica> iface) {
|
|
||||||
QRemoteObjectPendingReply<bool> flushReply = iface->flushDns();
|
|
||||||
if (flushReply.waitForFinished(5000) && flushReply.returnValue())
|
|
||||||
qDebug() << "VpnConnection::disconnectFromVpn(): Successfully flushed DNS";
|
|
||||||
else
|
|
||||||
qWarning() << "VpnConnection::disconnectFromVpn(): Failed to flush DNS";
|
|
||||||
|
|
||||||
QRemoteObjectPendingReply<bool> clearSavedRoutesReply = iface->clearSavedRoutes();
|
|
||||||
if (clearSavedRoutesReply.waitForFinished(5000) && clearSavedRoutesReply.returnValue())
|
|
||||||
qDebug() << "VpnConnection::disconnectFromVpn(): Successfully cleared saved routes";
|
|
||||||
else
|
|
||||||
qWarning() << "VpnConnection::disconnectFromVpn(): Failed to clear saved routes";
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
auto *const connection = new QMetaObject::Connection;
|
auto *const connection = new QMetaObject::Connection;
|
||||||
@@ -480,9 +469,10 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
delete connection;
|
delete connection;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_vpnProtocol->stop();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_vpnProtocol->stop();
|
||||||
|
|
||||||
#if !defined(Q_OS_ANDROID) && !defined(AMNEZIA_DESKTOP)
|
#if !defined(Q_OS_ANDROID) && !defined(AMNEZIA_DESKTOP)
|
||||||
m_vpnProtocol->deleteLater();
|
m_vpnProtocol->deleteLater();
|
||||||
#endif
|
#endif
|
||||||
@@ -490,27 +480,12 @@ void VpnConnection::disconnectFromVpn()
|
|||||||
m_vpnProtocol = nullptr;
|
m_vpnProtocol = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vpn::ConnectionState VpnConnection::connectionState()
|
void VpnConnection::setConnectionState(Vpn::ConnectionState state) {
|
||||||
{
|
onConnectionStateChanged(state);
|
||||||
if (!m_vpnProtocol)
|
|
||||||
return Vpn::ConnectionState::Disconnected;
|
if (state == Vpn::Disconnected && m_connectionState == Vpn::Reconnecting)
|
||||||
return m_vpnProtocol->connectionState();
|
return;
|
||||||
}
|
|
||||||
|
m_connectionState = state;
|
||||||
bool VpnConnection::isConnected() const
|
emit connectionStateChanged(state);
|
||||||
{
|
|
||||||
if (m_vpnProtocol.isNull()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_vpnProtocol->isConnected();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VpnConnection::isDisconnected() const
|
|
||||||
{
|
|
||||||
if (m_vpnProtocol.isNull()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m_vpnProtocol->isDisconnected();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,10 +34,6 @@ public:
|
|||||||
|
|
||||||
ErrorCode lastError() const;
|
ErrorCode lastError() const;
|
||||||
|
|
||||||
bool isConnected() const;
|
|
||||||
bool isDisconnected() const;
|
|
||||||
|
|
||||||
Vpn::ConnectionState connectionState();
|
|
||||||
QSharedPointer<VpnProtocol> vpnProtocol() const;
|
QSharedPointer<VpnProtocol> vpnProtocol() const;
|
||||||
|
|
||||||
const QString &remoteAddress() const;
|
const QString &remoteAddress() const;
|
||||||
@@ -48,14 +44,10 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void connectToVpn(int serverIndex,
|
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &vpnConfiguration);
|
||||||
const ServerCredentials &credentials, DockerContainer container, const QJsonObject &vpnConfiguration);
|
void reconnectToVpn();
|
||||||
|
|
||||||
void disconnectFromVpn();
|
void disconnectFromVpn();
|
||||||
|
|
||||||
void addRoutes(const QStringList &ips);
|
|
||||||
void deleteRoutes(const QStringList &ips);
|
|
||||||
void flushDns();
|
|
||||||
void onKillSwitchModeChanged(bool enabled);
|
void onKillSwitchModeChanged(bool enabled);
|
||||||
void disconnectSlots();
|
void disconnectSlots();
|
||||||
|
|
||||||
@@ -70,6 +62,8 @@ protected slots:
|
|||||||
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||||
void onConnectionStateChanged(Vpn::ConnectionState state);
|
void onConnectionStateChanged(Vpn::ConnectionState state);
|
||||||
|
|
||||||
|
void setConnectionState(Vpn::ConnectionState state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<VpnProtocol> m_vpnProtocol;
|
QSharedPointer<VpnProtocol> m_vpnProtocol;
|
||||||
|
|
||||||
@@ -89,6 +83,8 @@ private:
|
|||||||
void createAndroidConnections();
|
void createAndroidConnections();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Vpn::ConnectionState m_connectionState;
|
||||||
|
|
||||||
void createProtocolConnections();
|
void createProtocolConnections();
|
||||||
|
|
||||||
void appendSplitTunnelingConfig();
|
void appendSplitTunnelingConfig();
|
||||||
|
|||||||
@@ -45,5 +45,6 @@ class IpcInterface
|
|||||||
SLOT( bool stopNetworkCheck() );
|
SLOT( bool stopNetworkCheck() );
|
||||||
|
|
||||||
SIGNAL( connectionLose() );
|
SIGNAL( connectionLose() );
|
||||||
SIGNAL( networkChange() );
|
SIGNAL( wakeup() );
|
||||||
|
SIGNAL( networkChanged() );
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,8 +50,8 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_networkWatcher.initialize();
|
m_networkWatcher.initialize();
|
||||||
connect(&m_networkWatcher, &NetworkWatcher::sleepMode, &m_ipcServer, &IpcServer::networkChange);
|
connect(&m_networkWatcher, &NetworkWatcher::networkChanged, &m_ipcServer, &IpcServer::networkChanged);
|
||||||
connect(&m_networkWatcher, &NetworkWatcher::networkChange, &m_ipcServer, &IpcServer::networkChange);
|
connect(&m_networkWatcher, &NetworkWatcher::wakeup, &m_ipcServer, &IpcServer::wakeup);
|
||||||
KillSwitch::instance()->init();
|
KillSwitch::instance()->init();
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
|||||||
Reference in New Issue
Block a user