From 2773d7598b8e48421da8765cbedc37372ab1577b Mon Sep 17 00:00:00 2001 From: pokamest Date: Fri, 19 Nov 2021 19:02:39 +0300 Subject: [PATCH] VPN connection routine fixed --- client/client.pro | 2 ++ client/core/ipcclient.cpp | 16 ++++++------ client/core/ipcclient.h | 14 +++-------- client/core/privileged_process.cpp | 27 ++++++++++++++++++++ client/core/privileged_process.h | 30 ++++++++++++++++++++++ client/protocols/ikev2_vpn_protocol.cpp | 12 ++++----- client/protocols/openvpnprotocol.cpp | 10 ++++---- client/protocols/openvpnprotocol.h | 2 +- client/protocols/wireguardprotocol.cpp | 33 ++++++++++++++++--------- client/protocols/wireguardprotocol.h | 4 +-- client/ui/pages_logic/VpnLogic.cpp | 18 +++++++++++--- client/ui/pages_logic/VpnLogic.h | 2 +- client/ui/qml/Pages/PageVPN.qml | 5 +--- client/vpnconnection.cpp | 8 +++++- 14 files changed, 131 insertions(+), 52 deletions(-) create mode 100644 client/core/privileged_process.cpp create mode 100644 client/core/privileged_process.h diff --git a/client/client.pro b/client/client.pro index 90381c787..69f081a21 100644 --- a/client/client.pro +++ b/client/client.pro @@ -30,6 +30,7 @@ HEADERS += \ core/errorstrings.h \ core/ipcclient.h \ configurators/openvpn_configurator.h \ + core/privileged_process.h \ core/scripts_registry.h \ core/server_defs.h \ core/servercontroller.h \ @@ -80,6 +81,7 @@ SOURCES += \ core/errorstrings.cpp \ core/ipcclient.cpp \ configurators/openvpn_configurator.cpp \ + core/privileged_process.cpp \ core/scripts_registry.cpp \ core/server_defs.cpp \ core/servercontroller.cpp \ diff --git a/client/core/ipcclient.cpp b/client/core/ipcclient.cpp index 475810a85..e40538782 100644 --- a/client/core/ipcclient.cpp +++ b/client/core/ipcclient.cpp @@ -63,7 +63,7 @@ bool IpcClient::init(IpcClient *instance) return Instance()->m_ipcClient->isReplicaValid(); } -QSharedPointer IpcClient::CreatePrivilegedProcess() +QSharedPointer IpcClient::CreatePrivilegedProcess() { #ifndef Q_OS_IOS if (! Instance()->m_ipcClient || ! Instance()->m_ipcClient->isReplicaValid()) { @@ -84,17 +84,19 @@ QSharedPointer IpcClient::CreatePrivilegedProcess() connect(pd->localSocket.data(), &QLocalSocket::connected, pd->replicaNode.data(), [pd]() { pd->replicaNode->addClientSideConnection(pd->localSocket.data()); - pd->ipcProcess.reset(pd->replicaNode->acquire()); + IpcProcessInterfaceReplica *repl = pd->replicaNode->acquire(); + PrivilegedProcess *priv = static_cast(repl); + pd->ipcProcess.reset(priv); if (!pd->ipcProcess) { - qWarning() << "Acquire IpcProcessInterfaceReplica failed"; + qWarning() << "Acquire PrivilegedProcess failed"; } else { pd->ipcProcess->waitForSource(1000); if (!pd->ipcProcess->isReplicaValid()) { - qWarning() << "IpcProcessInterfaceReplica replica is not connected!"; + qWarning() << "PrivilegedProcess replica is not connected!"; } - QObject::connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){ + QObject::connect(pd->ipcProcess.data(), &PrivilegedProcess::destroyed, pd->ipcProcess.data(), [pd](){ pd->replicaNode->deleteLater(); }); } @@ -103,10 +105,10 @@ QSharedPointer IpcClient::CreatePrivilegedProcess() pd->localSocket->connectToServer(amnezia::getIpcProcessUrl(pid)); pd->localSocket->waitForConnected(); - auto proccessReplica = QSharedPointer(pd->ipcProcess); + auto proccessReplica = QSharedPointer(pd->ipcProcess); return proccessReplica; #else - return QSharedPointer(); + return QSharedPointer(); #endif } diff --git a/client/core/ipcclient.h b/client/core/ipcclient.h index 1548a6cb8..ab5d750a8 100644 --- a/client/core/ipcclient.h +++ b/client/core/ipcclient.h @@ -7,13 +7,7 @@ #include "ipc.h" #include "rep_ipc_interface_replica.h" -#ifndef Q_OS_IOS -#include "rep_ipc_process_interface_replica.h" -#else -class IpcProcessInterfaceReplica { - -}; -#endif +#include "privileged_process.h" class IpcClient : public QObject { @@ -24,7 +18,7 @@ public: static IpcClient *Instance(); static bool init(IpcClient *instance); static QSharedPointer Interface(); - static QSharedPointer CreatePrivilegedProcess(); + static QSharedPointer CreatePrivilegedProcess(); bool isSocketConnected() const; @@ -40,10 +34,10 @@ private: struct ProcessDescriptor { ProcessDescriptor () { replicaNode = QSharedPointer(new QRemoteObjectNode()); - ipcProcess = QSharedPointer(); + ipcProcess = QSharedPointer(); localSocket = QSharedPointer(); } - QSharedPointer ipcProcess; + QSharedPointer ipcProcess; QSharedPointer replicaNode; QSharedPointer localSocket; }; diff --git a/client/core/privileged_process.cpp b/client/core/privileged_process.cpp new file mode 100644 index 000000000..3852236f6 --- /dev/null +++ b/client/core/privileged_process.cpp @@ -0,0 +1,27 @@ +#include "privileged_process.h" + +PrivilegedProcess::PrivilegedProcess() : + IpcProcessInterfaceReplica() +{ +} + +PrivilegedProcess::~PrivilegedProcess() +{ + qDebug() << "PrivilegedProcess::~PrivilegedProcess()"; +} + +void PrivilegedProcess::waitForFinished(int msecs) +{ + QSharedPointer loop(new QEventLoop); + connect(this, &PrivilegedProcess::finished, this, [this, loop](int exitCode, QProcess::ExitStatus exitStatus) mutable{ + loop->quit(); + loop.clear(); + }); + + QTimer::singleShot(msecs, this, [this, loop]() mutable { + loop->quit(); + loop.clear(); + }); + + loop->exec(); +} diff --git a/client/core/privileged_process.h b/client/core/privileged_process.h new file mode 100644 index 000000000..bf85fed18 --- /dev/null +++ b/client/core/privileged_process.h @@ -0,0 +1,30 @@ +#ifndef PRIVILEGED_PROCESS_H +#define PRIVILEGED_PROCESS_H + +#include + +#ifndef Q_OS_IOS +#include "rep_ipc_process_interface_replica.h" +// This class is dangerous - instance of this class casted from base class, +// so it support only functions +// Do not add any members into it +// +class PrivilegedProcess : public IpcProcessInterfaceReplica +{ + Q_OBJECT +public: + PrivilegedProcess(); + ~PrivilegedProcess() override; + + void waitForFinished(int msecs); + +}; + +#endif // PRIVILEGED_PROCESS_H + +#else // defined Q_OS_IOS +class IpcProcessInterfaceReplica {}; +class PrivilegedProcess {}; +#endif + + diff --git a/client/protocols/ikev2_vpn_protocol.cpp b/client/protocols/ikev2_vpn_protocol.cpp index ccb3c7ada..42e34ee80 100644 --- a/client/protocols/ikev2_vpn_protocol.cpp +++ b/client/protocols/ikev2_vpn_protocol.cpp @@ -278,18 +278,18 @@ ErrorCode Ikev2Protocol::start() certInstallProcess->setArguments(arguments); // qDebug() << arguments.join(" "); - // connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [certInstallProcess](QProcess::ProcessError error) { - // qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error; + // connect(certInstallProcess.data(), &PrivilegedProcess::errorOccurred, [certInstallProcess](QProcess::ProcessError error) { + // qDebug() << "PrivilegedProcess errorOccurred" << error; // }); - // connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [certInstallProcess](QProcess::ProcessState newState) { - // qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState; + // connect(certInstallProcess.data(), &PrivilegedProcess::stateChanged, [certInstallProcess](QProcess::ProcessState newState) { + // qDebug() << "PrivilegedProcess stateChanged" << newState; // }); - // connect(certInstallProcess.data(), &IpcProcessInterfaceReplica::readyRead, [certInstallProcess]() { + // connect(certInstallProcess.data(), &PrivilegedProcess::readyRead, [certInstallProcess]() { // auto req = certInstallProcess->readAll(); // req.waitForFinished(); - // qDebug() << "IpcProcessInterfaceReplica readyRead" << req.returnValue(); + // qDebug() << "PrivilegedProcess readyRead" << req.returnValue(); // }); diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index 074ea5843..df57e365a 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -192,15 +192,15 @@ ErrorCode OpenVpnProtocol::start() m_openVpnProcess->setArguments(arguments); qDebug() << arguments.join(" "); - connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [&](QProcess::ProcessError error) { - qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error; + connect(m_openVpnProcess.data(), &PrivilegedProcess::errorOccurred, [&](QProcess::ProcessError error) { + qDebug() << "PrivilegedProcess errorOccurred" << error; }); - connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [&](QProcess::ProcessState newState) { - qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState; + connect(m_openVpnProcess.data(), &PrivilegedProcess::stateChanged, [&](QProcess::ProcessState newState) { + qDebug() << "PrivilegedProcess stateChanged" << newState; }); - connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::finished, this, [&]() { + connect(m_openVpnProcess.data(), &PrivilegedProcess::finished, this, [&]() { setConnectionState(ConnectionState::Disconnected); }); diff --git a/client/protocols/openvpnprotocol.h b/client/protocols/openvpnprotocol.h index 5fbddd67a..34cff8f4a 100644 --- a/client/protocols/openvpnprotocol.h +++ b/client/protocols/openvpnprotocol.h @@ -51,7 +51,7 @@ private: void updateRouteGateway(QString line); void updateVpnGateway(const QString &line); - QSharedPointer m_openVpnProcess; + QSharedPointer m_openVpnProcess; }; #endif // OPENVPNPROTOCOL_H diff --git a/client/protocols/wireguardprotocol.cpp b/client/protocols/wireguardprotocol.cpp index a0f11618a..d08843e70 100644 --- a/client/protocols/wireguardprotocol.cpp +++ b/client/protocols/wireguardprotocol.cpp @@ -19,13 +19,16 @@ WireguardProtocol::WireguardProtocol(const QJsonObject &configuration, QObject* WireguardProtocol::~WireguardProtocol() { - qDebug() << "WireguardProtocol::~WireguardProtocol()"; + //qDebug() << "WireguardProtocol::~WireguardProtocol() 1"; WireguardProtocol::stop(); QThread::msleep(200); + //qDebug() << "WireguardProtocol::~WireguardProtocol() 2"; } void WireguardProtocol::stop() { + //qDebug() << "WireguardProtocol::stop() 1"; + #ifndef Q_OS_IOS if (!QFileInfo::exists(wireguardExecPath())) { qCritical() << "Wireguard executable missing!"; @@ -56,19 +59,22 @@ void WireguardProtocol::stop() qDebug() << arguments.join(" "); - connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) { - qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error; + connect(m_wireguardStopProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) { + qDebug() << "WireguardProtocol::WireguardProtocol Stop errorOccurred" << error; setConnectionState(ConnectionState::Disconnected); }); - connect(m_wireguardStopProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) { + connect(m_wireguardStopProcess.data(), &PrivilegedProcess::stateChanged, this, [this](QProcess::ProcessState newState) { qDebug() << "WireguardProtocol::WireguardProtocol Stop stateChanged" << newState; }); m_wireguardStopProcess->start(); + m_wireguardStopProcess->waitForFinished(10000); setConnectionState(VpnProtocol::Disconnected); #endif + + //qDebug() << "WireguardProtocol::stop() 2"; } void WireguardProtocol::readWireguardConfiguration(const QJsonObject &configuration) @@ -124,13 +130,15 @@ QString WireguardProtocol::wireguardExecPath() const ErrorCode WireguardProtocol::start() { + //qDebug() << "WireguardProtocol::start() 1"; + #ifndef Q_OS_IOS if (!m_isConfigLoaded) { setLastError(ErrorCode::ConfigMissing); return lastError(); } - //qDebug() << "Start OpenVPN connection"; + //qDebug() << "Start Wireguard connection"; WireguardProtocol::stop(); if (!QFileInfo::exists(wireguardExecPath())) { @@ -168,38 +176,41 @@ ErrorCode WireguardProtocol::start() qDebug() << arguments.join(" "); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, this, [this](QProcess::ProcessError error) { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::errorOccurred, this, [this](QProcess::ProcessError error) { qDebug() << "WireguardProtocol::WireguardProtocol errorOccurred" << error; setConnectionState(ConnectionState::Disconnected); }); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::stateChanged, this, [this](QProcess::ProcessState newState) { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::stateChanged, this, [this](QProcess::ProcessState newState) { qDebug() << "WireguardProtocol::WireguardProtocol stateChanged" << newState; }); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::finished, this, [this]() { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::finished, this, [this]() { setConnectionState(ConnectionState::Connected); }); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyRead, this, [this]() { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyRead, this, [this]() { QRemoteObjectPendingReply reply = m_wireguardStartProcess->readAll(); reply.waitForFinished(1000); qDebug() << "WireguardProtocol::WireguardProtocol readyRead" << reply.returnValue(); }); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardOutput, this, [this]() { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyReadStandardOutput, this, [this]() { QRemoteObjectPendingReply reply = m_wireguardStartProcess->readAllStandardOutput(); reply.waitForFinished(1000); qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardOutput" << reply.returnValue(); }); - connect(m_wireguardStartProcess.data(), &IpcProcessInterfaceReplica::readyReadStandardError, this, [this]() { + connect(m_wireguardStartProcess.data(), &PrivilegedProcess::readyReadStandardError, this, [this]() { QRemoteObjectPendingReply reply = m_wireguardStartProcess->readAllStandardError(); reply.waitForFinished(1000); qDebug() << "WireguardProtocol::WireguardProtocol readAllStandardError" << reply.returnValue(); }); m_wireguardStartProcess->start(); + m_wireguardStartProcess->waitForFinished(10000); + + //qDebug() << "WireguardProtocol::start() 2"; return ErrorCode::NoError; #else diff --git a/client/protocols/wireguardprotocol.h b/client/protocols/wireguardprotocol.h index ea205e1e2..8ed26c7d0 100644 --- a/client/protocols/wireguardprotocol.h +++ b/client/protocols/wireguardprotocol.h @@ -36,8 +36,8 @@ private: QString m_configFileName; QFile m_configFile; - QSharedPointer m_wireguardStartProcess; - QSharedPointer m_wireguardStopProcess; + QSharedPointer m_wireguardStartProcess; + QSharedPointer m_wireguardStopProcess; bool m_isConfigLoaded = false; diff --git a/client/ui/pages_logic/VpnLogic.cpp b/client/ui/pages_logic/VpnLogic.cpp index b9faad953..a83d4f8b0 100644 --- a/client/ui/pages_logic/VpnLogic.cpp +++ b/client/ui/pages_logic/VpnLogic.cpp @@ -81,6 +81,8 @@ void VpnLogic::onConnectionStateChanged(VpnProtocol::ConnectionState state) qDebug() << "VpnLogic::onConnectionStateChanged" << VpnProtocol::textConnectionState(state); bool pbConnectEnabled = false; + bool pbConnectChecked = false; + bool rbModeEnabled = false; bool pbConnectVisible = false; set_labelStateText(VpnProtocol::textConnectionState(state)); @@ -90,49 +92,57 @@ void VpnLogic::onConnectionStateChanged(VpnProtocol::ConnectionState state) switch (state) { case VpnProtocol::Disconnected: onBytesChanged(0,0); - set_pushButtonConnectChecked(false); + pbConnectChecked = false; pbConnectEnabled = true; pbConnectVisible = true; rbModeEnabled = true; break; case VpnProtocol::Preparing: + pbConnectChecked = true; pbConnectEnabled = false; pbConnectVisible = false; rbModeEnabled = false; break; case VpnProtocol::Connecting: + pbConnectChecked = true; pbConnectEnabled = false; pbConnectVisible = false; rbModeEnabled = false; break; case VpnProtocol::Connected: + pbConnectChecked = true; pbConnectEnabled = true; pbConnectVisible = true; rbModeEnabled = false; break; case VpnProtocol::Disconnecting: + pbConnectChecked = false; pbConnectEnabled = false; pbConnectVisible = false; rbModeEnabled = false; break; case VpnProtocol::Reconnecting: + pbConnectChecked = true; pbConnectEnabled = true; pbConnectVisible = false; rbModeEnabled = false; break; case VpnProtocol::Error: - set_pushButtonConnectEnabled(false); + pbConnectChecked = false; pbConnectEnabled = true; pbConnectVisible = true; rbModeEnabled = true; break; case VpnProtocol::Unknown: + pbConnectChecked = false; pbConnectEnabled = true; pbConnectVisible = true; rbModeEnabled = true; } set_pushButtonConnectEnabled(pbConnectEnabled); + set_pushButtonConnectChecked(pbConnectChecked); + set_pushButtonConnectVisible(pbConnectVisible); set_widgetVpnModeEnabled(rbModeEnabled); } @@ -142,9 +152,9 @@ void VpnLogic::onVpnProtocolError(ErrorCode errorCode) set_labelErrorText(errorString(errorCode)); } -void VpnLogic::onPushButtonConnectClicked(bool checked) +void VpnLogic::onPushButtonConnectClicked() { - if (checked) { + if (! pushButtonConnectChecked()) { onConnect(); } else { onDisconnect(); diff --git a/client/ui/pages_logic/VpnLogic.h b/client/ui/pages_logic/VpnLogic.h index 3a5d28119..95d39e1b0 100644 --- a/client/ui/pages_logic/VpnLogic.h +++ b/client/ui/pages_logic/VpnLogic.h @@ -33,7 +33,7 @@ public: Q_INVOKABLE void onRadioButtonVpnModeForwardSitesClicked(); Q_INVOKABLE void onRadioButtonVpnModeExceptSitesClicked(); - Q_INVOKABLE void onPushButtonConnectClicked(bool checked); + Q_INVOKABLE void onPushButtonConnectClicked(); public: explicit VpnLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/qml/Pages/PageVPN.qml b/client/ui/qml/Pages/PageVPN.qml index d4a178789..7dad8e256 100644 --- a/client/ui/qml/Pages/PageVPN.qml +++ b/client/ui/qml/Pages/PageVPN.qml @@ -53,10 +53,7 @@ PageBase { height: width checkable: true checked: VpnLogic.pushButtonConnectChecked - onCheckedChanged: { - VpnLogic.pushButtonConnectChecked = checked - VpnLogic.onPushButtonConnectClicked(checked) - } + onClicked: VpnLogic.onPushButtonConnectClicked() background: Image { anchors.fill: parent source: button_connect.checked ? "qrc:/images/connected.png" diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 456a85682..bd913dbb8 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -28,7 +28,9 @@ VpnConnection::VpnConnection(QObject* parent) : QObject(parent) VpnConnection::~VpnConnection() { + //qDebug() << "VpnConnection::~VpnConnection() 1"; m_vpnProtocol.clear(); + //qDebug() << "VpnConnection::~VpnConnection() 2"; } void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes) @@ -231,8 +233,11 @@ void VpnConnection::connectToVpn(int serverIndex, if (m_vpnProtocol) { disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); + //qDebug() << "VpnConnection::connectToVpn 1"; m_vpnProtocol->stop(); + //qDebug() << "VpnConnection::connectToVpn 2"; m_vpnProtocol.reset(); + //qDebug() << "VpnConnection::connectToVpn 3"; } ErrorCode e = ErrorCode::NoError; @@ -281,7 +286,7 @@ QString VpnConnection::bytesPerSecToText(quint64 bytes) void VpnConnection::disconnectFromVpn() { - qDebug() << "Disconnect from VPN"; + // qDebug() << "Disconnect from VPN 1"; if (IpcClient::Interface()) { IpcClient::Interface()->flushDns(); @@ -295,6 +300,7 @@ void VpnConnection::disconnectFromVpn() return; } m_vpnProtocol.data()->stop(); + // qDebug() << "Disconnect from VPN 2"; } VpnProtocol::ConnectionState VpnConnection::connectionState()