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:
Yaroslav Gurov
2026-02-19 13:21:49 +01:00
committed by GitHub
parent 9bd1e6a0f5
commit cd1e561fd4
14 changed files with 122 additions and 160 deletions

View File

@@ -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)

View File

@@ -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();

View File

@@ -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:

View File

@@ -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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;

View File

@@ -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:

View File

@@ -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);
} }

View File

@@ -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();

View File

@@ -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();
} }

View File

@@ -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();

View File

@@ -45,5 +45,6 @@ class IpcInterface
SLOT( bool stopNetworkCheck() ); SLOT( bool stopNetworkCheck() );
SIGNAL( connectionLose() ); SIGNAL( connectionLose() );
SIGNAL( networkChange() ); SIGNAL( wakeup() );
SIGNAL( networkChanged() );
}; };

View File

@@ -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