diff --git a/client/communicator.cpp b/client/communicator.cpp index 0dd3ca3c5..04a4e811d 100644 --- a/client/communicator.cpp +++ b/client/communicator.cpp @@ -45,7 +45,7 @@ void Communicator::onLineAvailable(const QString& line) emit messageReceived(message); } -bool Communicator::connected() const +bool Communicator::isConnected() const { if (!m_localClient) { return false; @@ -66,7 +66,7 @@ bool Communicator::writeData(const QString& data) void Communicator::sendMessage(const Message& message) { - if (!connected()) { + if (!isConnected()) { return; } const QString data = message.toString(); diff --git a/client/communicator.h b/client/communicator.h index 8546bd59f..3c4f1628d 100644 --- a/client/communicator.h +++ b/client/communicator.h @@ -16,7 +16,7 @@ public: explicit Communicator(QObject* parent = nullptr); ~Communicator(); - bool connected() const; + bool isConnected() const; void sendMessage(const Message& message); signals: diff --git a/client/core/defs.h b/client/core/defs.h index 83c75ff0e..99fc9e754 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -47,9 +47,13 @@ enum ErrorCode EasyRsaError, // Distro errors - AmneziaServiceConnectionFailed, OpenVpnExecutableMissing, - EasyRsaExecutableMissing + EasyRsaExecutableMissing, + AmneziaServiceConnectionFailed, + + // VPN errors + OpenVpnAdaptersInUseError, + OpenVpnUnknownError }; } // namespace amnezia diff --git a/client/core/errorstrings.h b/client/core/errorstrings.h index e3933ae69..0e9659121 100644 --- a/client/core/errorstrings.h +++ b/client/core/errorstrings.h @@ -31,12 +31,17 @@ QString errorString(ErrorCode code){ // Local errors case (FailedToSaveConfigData): return QObject::tr("Failed to save config to disk"); case (OpenVpnConfigMissing): return QObject::tr("OpenVPN config missing"); - case (OpenVpnManagementServerError): return QObject::tr("OpenVpn management server error"); + case (OpenVpnManagementServerError): return QObject::tr("OpenVPN management server error"); + case (EasyRsaError): return QObject::tr("EasyRSA runtime error"); + // Distro errors case (OpenVpnExecutableMissing): return QObject::tr("OpenVPN executable missing"); case (EasyRsaExecutableMissing): return QObject::tr("EasyRsa executable missing"); case (AmneziaServiceConnectionFailed): return QObject::tr("Amnezia helper service error"); + // VPN errors + case (OpenVpnAdaptersInUseError): return QObject::tr("Can't connect: another VPN connection is active"); + case(InternalError): default: return QObject::tr("Internal error"); diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index d4e92a049..19d25a757 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -119,7 +119,7 @@ ErrorCode OpenVpnProtocol::start() m_openVpnStateSigTermHandlerTimer.stop(); stop(); - if (communicator() && !communicator()->connected()) { + if (communicator() && !communicator()->isConnected()) { setLastError(ErrorCode::AmneziaServiceConnectionFailed); return lastError(); } @@ -213,6 +213,16 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer() } } + if (line.contains("FATAL")) { + if (line.contains("tap-windows6 adapters on this system are currently in use or disabled")) { + emit protocolError(ErrorCode::OpenVpnAdaptersInUseError); + } + else { + emit protocolError(ErrorCode::OpenVpnUnknownError); + } + } + + QByteArray data(line.toStdString().c_str()); if (data.contains(">BYTECOUNT:")) { int beg = data.lastIndexOf(">BYTECOUNT:"); diff --git a/client/protocols/vpnprotocol.cpp b/client/protocols/vpnprotocol.cpp index 5e9c35ba4..eb81e02f6 100644 --- a/client/protocols/vpnprotocol.cpp +++ b/client/protocols/vpnprotocol.cpp @@ -93,14 +93,14 @@ void VpnProtocol::setConnectionState(VpnProtocol::ConnectionState state) QString VpnProtocol::textConnectionState(ConnectionState connectionState) { switch (connectionState) { - case ConnectionState::Unknown: return "Unknown"; - case ConnectionState::Disconnected: return "Disconnected"; - case ConnectionState::Preparing: return "Preparing"; - case ConnectionState::Connecting: return "Connecting"; - case ConnectionState::Connected: return "Connected"; - case ConnectionState::Disconnecting: return "Disconnecting"; - case ConnectionState::TunnelReconnecting: return "TunnelReconnecting"; - case ConnectionState::Error: return "Error"; + case ConnectionState::Unknown: return tr("Unknown"); + case ConnectionState::Disconnected: return tr("Disconnected"); + case ConnectionState::Preparing: return tr("Preparing"); + case ConnectionState::Connecting: return tr("Connecting"); + case ConnectionState::Connected: return tr("Connected"); + case ConnectionState::Disconnecting: return tr("Disconnecting"); + case ConnectionState::TunnelReconnecting: return tr("TunnelReconnecting"); + case ConnectionState::Error: return tr("Error"); default: ; } @@ -113,12 +113,12 @@ QString VpnProtocol::textConnectionState() const return textConnectionState(m_connectionState); } -bool VpnProtocol::connected() const +bool VpnProtocol::onConnected() const { return m_connectionState == ConnectionState::Connected; } -bool VpnProtocol::disconnected() const +bool VpnProtocol::onDisconnected() const { return m_connectionState == ConnectionState::Disconnected; } diff --git a/client/protocols/vpnprotocol.h b/client/protocols/vpnprotocol.h index 3472afdf8..fa1fc9a9a 100644 --- a/client/protocols/vpnprotocol.h +++ b/client/protocols/vpnprotocol.h @@ -25,8 +25,8 @@ public: static void initializeCommunicator(QObject* parent = nullptr); - virtual bool connected() const; - virtual bool disconnected() const; + virtual bool onConnected() const; + virtual bool onDisconnected() const; virtual ErrorCode start() = 0; virtual void stop() = 0; @@ -39,6 +39,7 @@ signals: void bytesChanged(quint64 receivedBytes, quint64 sentBytes); void connectionStateChanged(VpnProtocol::ConnectionState state); void timeoutTimerEvent(); + void protocolError(amnezia::ErrorCode e); protected slots: virtual void onTimeout(); diff --git a/client/ui/mainwindow.cpp b/client/ui/mainwindow.cpp index db995c679..a4deede92 100644 --- a/client/ui/mainwindow.cpp +++ b/client/ui/mainwindow.cpp @@ -76,6 +76,7 @@ MainWindow::MainWindow(QWidget *parent) : m_vpnConnection = new VpnConnection(this); connect(m_vpnConnection, SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64))); connect(m_vpnConnection, SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState))); + connect(m_vpnConnection, SIGNAL(vpnProtocolError(amnezia::ErrorCode)), this, SLOT(onVpnProtocolError(amnezia::ErrorCode))); onConnectionStateChanged(VpnProtocol::ConnectionState::Disconnected); @@ -90,7 +91,7 @@ MainWindow::~MainWindow() for (int i = 0; i < 50; i++) { qApp->processEvents(QEventLoop::ExcludeUserInputEvents); QThread::msleep(100); - if (m_vpnConnection->disconnected()) { + if (m_vpnConnection->onDisconnected()) { break; } } @@ -297,6 +298,11 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state) ui->pushButton_connect->setEnabled(pushButtonConnectEnabled); } +void MainWindow::onVpnProtocolError(ErrorCode errorCode) +{ + QMessageBox::critical(this, APPLICATION_NAME, errorString(errorCode)); +} + void MainWindow::onPushButtonConnectToggled(bool checked) { if (checked) { diff --git a/client/ui/mainwindow.h b/client/ui/mainwindow.h index 6d02c8626..de5889eef 100644 --- a/client/ui/mainwindow.h +++ b/client/ui/mainwindow.h @@ -34,6 +34,8 @@ public: private slots: void onBytesChanged(quint64 receivedBytes, quint64 sentBytes); void onConnectionStateChanged(VpnProtocol::ConnectionState state); + void onVpnProtocolError(amnezia::ErrorCode errorCode); + void onPushButtonBackFromNewServerClicked(bool clicked); void onPushButtonBackFromSettingsClicked(bool clicked); void onPushButtonBackFromSitesClicked(bool clicked); diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 1ed8f4449..ef75f4e91 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -69,7 +69,11 @@ ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Prot if (e) { return e; } + if (m_vpnProtocol) { + disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); + } m_vpnProtocol.reset(new OpenVpnProtocol()); + connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError); } else if (protocol == Protocol::ShadowSocks) { return ErrorCode::NotImplementedError; @@ -96,20 +100,20 @@ void VpnConnection::disconnectFromVpn() m_vpnProtocol.data()->stop(); } -bool VpnConnection::connected() const +bool VpnConnection::onConnected() const { if (!m_vpnProtocol.data()) { return false; } - return m_vpnProtocol.data()->connected(); + return m_vpnProtocol.data()->onConnected(); } -bool VpnConnection::disconnected() const +bool VpnConnection::onDisconnected() const { if (!m_vpnProtocol.data()) { return true; } - return m_vpnProtocol.data()->disconnected(); + return m_vpnProtocol.data()->onDisconnected(); } diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 0bf81851c..9eb58ab30 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -23,13 +23,14 @@ public: ErrorCode lastError() const; ErrorCode requestVpnConfig(const ServerCredentials &credentials, Protocol protocol); ErrorCode connectToVpn(const ServerCredentials &credentials, Protocol protocol = Protocol::Any); - bool connected() const; - bool disconnected() const; + bool onConnected() const; + bool onDisconnected() const; void disconnectFromVpn(); signals: void bytesChanged(quint64 receivedBytes, quint64 sentBytes); void connectionStateChanged(VpnProtocol::ConnectionState state); + void vpnProtocolError(amnezia::ErrorCode error); protected slots: void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);