Compare commits

..

3 Commits

Author SHA1 Message Date
vladimir.kuznetsov 4911aa5eaa Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into HEAD 2024-01-10 20:51:34 +07:00
vladimir.kuznetsov f18dbc1e15 remove unnecessary mutexes 2024-01-10 20:50:35 +07:00
vladimir.kuznetsov 9753c3feb6 Now value and setValue of secureQSettings are always called in the main thread 2024-01-06 10:48:29 +07:00
20 changed files with 415 additions and 232 deletions
+1 -1
View File
@@ -361,7 +361,7 @@ void AmneziaApplication::initControllers()
m_settings, m_configurator));
m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_settings));
m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_settings));
m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
+112
View File
@@ -0,0 +1,112 @@
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
#include "managementserver.h"
ManagementServer::ManagementServer(QObject *parent) : QObject(parent),
m_tcpServer(nullptr)
{
}
ManagementServer::~ManagementServer()
{
}
bool ManagementServer::isOpen() const
{
return (m_socket && m_socket->isOpen());
}
void ManagementServer::stop()
{
if (m_tcpServer) m_tcpServer->close();
}
void ManagementServer::onAcceptError(QAbstractSocket::SocketError socketError)
{
qDebug().noquote() << QString("Accept error: %1").arg(socketError);
}
qint64 ManagementServer::writeCommand(const QString& message)
{
if (!isOpen()) {
return 0;
}
const QString command = message + "\n";
qint64 bytesWritten = m_socket->write(command.toStdString().c_str());
m_socket->flush();
return bytesWritten;
}
void ManagementServer::onNewConnection()
{
qDebug() << "New incoming connection";
m_socket = QPointer<QTcpSocket>(m_tcpServer->nextPendingConnection());
if (m_tcpServer) m_tcpServer->close();
QObject::connect(m_socket.data(), &QTcpSocket::disconnected, this, &ManagementServer::onSocketDisconnected);
QObject::connect(m_socket.data(), &QTcpSocket::errorOccurred, this, &ManagementServer::onSocketError);
QObject::connect(m_socket.data(), &QTcpSocket::readyRead, this, &ManagementServer::onReadyRead);
}
void ManagementServer::onSocketError(QAbstractSocket::SocketError socketError)
{
Q_UNUSED(socketError)
qDebug().noquote() << QString("Management server error: %1").arg(m_socket->errorString());
}
void ManagementServer::onSocketDisconnected()
{
if (m_socket) m_socket->deleteLater();
}
QPointer<QTcpSocket> ManagementServer::socket() const
{
if (!isOpen()) {
return nullptr;
}
return m_socket;
}
void ManagementServer::onReadyRead()
{
emit readyRead();
}
bool ManagementServer::start(const QString& host, unsigned int port)
{
if (m_tcpServer) m_tcpServer->close();
m_tcpServer = QSharedPointer<QTcpServer>(new QTcpServer(this), [](QTcpServer *s){
if (s) s->deleteLater();
});
m_tcpServer->setMaxPendingConnections(1);
connect(m_tcpServer.data(), SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(onAcceptError(QAbstractSocket::SocketError)));
connect(m_tcpServer.data(), SIGNAL(newConnection()), this, SLOT(onNewConnection()));
if (m_tcpServer->listen(QHostAddress(host), port)) {
emit serverStarted();
return true;
}
qDebug().noquote() << QString("Can't start TCP server, %1,%2")
.arg(m_tcpServer->serverError())
.arg(m_tcpServer->errorString());
return false;
}
QString ManagementServer::readLine()
{
if (!isOpen()) {
qDebug() << "Socket is not opened";
return QString();
}
return m_socket->readLine();
}
+45
View File
@@ -0,0 +1,45 @@
#ifndef MANAGEMENTSERVER_H
#define MANAGEMENTSERVER_H
#include <QAbstractSocket>
#include <QPointer>
#include <QSharedPointer>
#include <QString>
class QTcpServer;
class QTcpSocket;
class ManagementServer : public QObject
{
Q_OBJECT
public:
explicit ManagementServer(QObject *parent = nullptr);
~ManagementServer();
bool start(const QString& host, unsigned int port);
void stop();
bool isOpen() const;
QString readLine();
qint64 writeCommand(const QString& message);
QPointer<QTcpSocket> socket() const;
signals:
void readyRead();
void serverStarted();
protected slots:
void onAcceptError(QAbstractSocket::SocketError socketError);
void onNewConnection();
void onReadyRead();
void onSocketDisconnected();
void onSocketError(QAbstractSocket::SocketError socketError);
protected:
QSharedPointer<QTcpServer> m_tcpServer;
QPointer<QTcpSocket> m_socket;
};
#endif // MANAGEMENTSERVER_H
+11 -5
View File
@@ -22,8 +22,6 @@ OpenVpnOverCloakProtocol::~OpenVpnOverCloakProtocol()
ErrorCode OpenVpnOverCloakProtocol::start()
{
#if 0
if (!QFileInfo::exists(cloakExecPath())) {
setLastError(ErrorCode::CloakExecutableMissing);
return lastError();
@@ -79,12 +77,10 @@ ErrorCode OpenVpnOverCloakProtocol::start()
if (m_ckProcess.state() == QProcess::ProcessState::Running) {
setConnectionState(Vpn::ConnectionState::Connecting);
#endif
return OpenVpnProtocol::start();
#if 0
}
else return ErrorCode::CloakExecutableMissing;
#endif
}
void OpenVpnOverCloakProtocol::stop()
@@ -94,6 +90,16 @@ void OpenVpnOverCloakProtocol::stop()
qDebug() << "OpenVpnOverCloakProtocol::stop()";
#ifdef Q_OS_WIN
Utils::signalCtrl(m_ckProcess.processId(), CTRL_C_EVENT);
#endif
m_ckProcess.terminate();
if (Utils::processIsRunning(Utils::executable("ck-client", false))) {
QThread::msleep(1000);
Utils::killProcessByName(Utils::executable("ck-client", false));
}
}
QString OpenVpnOverCloakProtocol::cloakExecPath()
+156 -145
View File
@@ -10,10 +10,11 @@
#include "utilities.h"
#include "version.h"
OpenVpnProtocol::OpenVpnProtocol(const QJsonObject &configuration, QObject *parent) : VpnProtocol(configuration, parent)
{
readOpenVpnConfiguration(configuration);
connect(&m_managementServer, &ManagementServer::readyRead, this,
&OpenVpnProtocol::onReadyReadDataFromManagementServer);
}
OpenVpnProtocol::~OpenVpnProtocol()
@@ -24,6 +25,7 @@ OpenVpnProtocol::~OpenVpnProtocol()
QString OpenVpnProtocol::defaultConfigFileName()
{
// qDebug() << "OpenVpnProtocol::defaultConfigFileName" << defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
return defaultConfigPath() + QString("/%1.ovpn").arg(APPLICATION_NAME);
}
@@ -31,20 +33,25 @@ QString OpenVpnProtocol::defaultConfigPath()
{
QString p = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/config";
Utils::initializePath(p);
return p;
}
void OpenVpnProtocol::stop()
{
qDebug() << "OpenVpnProtocol::stop()";
setConnectionState(Vpn::ConnectionState::Disconnecting);
// TODO: need refactoring
// sendTermSignal() will even return true while server connected ???
if ((m_connectionState == Vpn::ConnectionState::Preparing) || (m_connectionState == Vpn::ConnectionState::Connecting)
|| (m_connectionState == Vpn::ConnectionState::Connected)
|| (m_connectionState == Vpn::ConnectionState::Reconnecting)) {
if (!sendTermSignal()) {
killOpenVpnProcess();
QThread::msleep(10);
}
QThread::msleep(10);
m_managementServer.stop();
}
setConnectionState(Vpn::ConnectionState::Disconnected);
}
@@ -79,30 +86,9 @@ void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
{
if (configuration.contains(ProtocolProps::key_proto_config_data(Proto::OpenVpn))) {
QJsonObject jConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::OpenVpn)).toObject();
QString plainConfig = jConfig.value(config_key::config).toString().toUtf8();
if (configuration.contains(ProtocolProps::key_proto_config_data(Proto::Cloak))) {
QJsonObject cloakConfig = configuration.value(ProtocolProps::key_proto_config_data(Proto::Cloak)).toObject();
cloakConfig["NumConn"] = 1;
cloakConfig["ProxyMethod"] = "openvpn";
if (cloakConfig.contains("port")) {
int portValue = cloakConfig.value("port").toInt();
cloakConfig.remove("port");
cloakConfig["RemotePort"] = portValue;
}
if (cloakConfig.contains("remote")) {
QString hostValue = cloakConfig.value("remote").toString();
cloakConfig.remove("remote");
cloakConfig["RemoteHost"] = hostValue;
}
plainConfig += "\n<cloak>\n";
QJsonDocument Doc(cloakConfig);
QByteArray ba = Doc.toJson();
QString plainCloak = ba;
plainConfig += QString::fromLatin1(plainCloak.toUtf8().toBase64().data());
plainConfig += "\n</cloak>\n";
}
m_configFile.open();
m_configFile.write(plainConfig.toUtf8());
m_configFile.write(jConfig.value(config_key::config).toString().toUtf8());
m_configFile.close();
m_configFileName = m_configFile.fileName();
@@ -112,69 +98,60 @@ void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
bool OpenVpnProtocol::openVpnProcessIsRunning() const
{
return Utils::processIsRunning("ovpncli");
return Utils::processIsRunning("openvpn");
}
void OpenVpnProtocol::disconnectFromManagementServer()
{
m_managementServer.stop();
}
QString OpenVpnProtocol::configPath() const
{
return m_configFileName;
}
void OpenVpnProtocol::sendManagementCommand(const QString &command)
{
QIODevice *device = dynamic_cast<QIODevice *>(m_managementServer.socket().data());
if (device) {
QTextStream stream(device);
stream << command << Qt::endl;
}
}
uint OpenVpnProtocol::selectMgmtPort()
{
for (int i = 0; i < 100; ++i) {
quint32 port = QRandomGenerator::global()->generate();
port = (double)(65000 - 15001) * port / UINT32_MAX + 15001;
QTcpServer s;
bool ok = s.listen(QHostAddress::LocalHost, port);
if (ok)
return port;
}
return m_managementPort;
}
void OpenVpnProtocol::updateRouteGateway(QString line)
{
const QString substr = "sitnl_route_best_gw result: via ";
int start = line.indexOf(substr) + substr.size();
int end = line.indexOf(" dev ", start);
m_routeGateway = line.mid(start, (end-start));
}
void OpenVpnProtocol::handle_cli_message(QString message)
{
QString line = message;
if (line.isEmpty()) {
// TODO: fix for macos
line = line.split("ROUTE_GATEWAY", Qt::SkipEmptyParts).at(1);
if (!line.contains("/"))
return;
}
if (line.contains("EVENT: CONNECTED")) {
setConnectionState(Vpn::ConnectionState::Connected);
} else if (line.contains("EXITING")) {
// openVpnStateSigTermHandler();
setConnectionState(Vpn::ConnectionState::Disconnecting);
} else if (line.contains("RECONNECTING")) {
setConnectionState(Vpn::ConnectionState::Reconnecting);
}
if (line.contains("sitnl_route_best_gw")) {
updateRouteGateway(line);
}
if (line.contains("[ifconfig]")) {
updateVpnGateway(line);
}
// TODO: SET CORRECT STRING
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);
}
return;
}
m_routeGateway = line.split("/", Qt::SkipEmptyParts).first();
m_routeGateway.replace(" ", "");
qDebug() << "Set VPN route gateway" << m_routeGateway;
}
ErrorCode OpenVpnProtocol::start()
{
// qDebug() << "Start OpenVPN connection";
OpenVpnProtocol::stop();
qDebug() << " Utils::openVpnExecPath();" << Utils::openVpnExecPath();
if (!QFileInfo::exists(Utils::openVpnExecPath())) {
setLastError(ErrorCode::OpenVpnExecutableMissing);
return lastError();
@@ -207,11 +184,23 @@ ErrorCode OpenVpnProtocol::start()
}
#endif
// QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log";
// Utils::createEmptyFile(vpnLogFileNamePath);
uint mgmtPort = selectMgmtPort();
qDebug() << "OpenVpnProtocol::start mgmt port selected:" << mgmtPort;
if (!m_managementServer.start(m_managementHost, mgmtPort)) {
setLastError(ErrorCode::OpenVpnManagementServerError);
return lastError();
}
setConnectionState(Vpn::ConnectionState::Connecting);
m_openVpnProcess = IpcClient::CreatePrivilegedProcess();
if (!m_openVpnProcess) {
qWarning() << "IpcProcess replica is not created!";
// qWarning() << "IpcProcess replica is not created!";
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
return ErrorCode::AmneziaServiceConnectionFailed;
}
@@ -223,100 +212,122 @@ ErrorCode OpenVpnProtocol::start()
return ErrorCode::AmneziaServiceConnectionFailed;
}
m_openVpnProcess->setProgram(PermittedProcess::OpenVPN);
QStringList arguments({ configPath()/*, "--management", m_managementHost, QString::number(mgmtPort),
"--management-client" *//*, "--log", vpnLogFileNamePath */
QStringList arguments({
"--config", configPath(), "--management", m_managementHost, QString::number(mgmtPort),
"--management-client" /*, "--log", vpnLogFileNamePath */
});
m_openVpnProcess->setArguments(arguments);
qDebug() << arguments.join(" ");
connect(m_openVpnProcess.data(), &PrivilegedProcess::errorOccurred,
[&](QProcess::ProcessError error) {
qDebug() << "PrivilegedProcess errorOccurred" << error;
setConnectionState(Vpn::ConnectionState::Disconnected);
});
[&](QProcess::ProcessError error) { qDebug() << "PrivilegedProcess errorOccurred" << error; });
connect(m_openVpnProcess.data(), &PrivilegedProcess::stateChanged, [&](QProcess::ProcessState newState) {
switch ( newState )
{
case QProcess::Starting:
setConnectionState(Vpn::ConnectionState::Connecting);
break;
case QProcess::Running:
setConnectionState(Vpn::ConnectionState::Connecting);
break;
default:
setConnectionState(Vpn::ConnectionState::Disconnected);
}
qDebug() << "PrivilegedProcess stateChanged" << newState;
});
connect(m_openVpnProcess.data(), &PrivilegedProcess::stateChanged,
[&](QProcess::ProcessState newState) { qDebug() << "PrivilegedProcess stateChanged" << newState; });
connect(m_openVpnProcess.data(), &PrivilegedProcess::finished, this,
[&]() { setConnectionState(Vpn::ConnectionState::Disconnected); });
connect(m_openVpnProcess.data(), &PrivilegedProcess::readyRead, this, [&] {
QRemoteObjectPendingReply<QByteArray> call = m_openVpnProcess->readAll();
auto *watcher = new QRemoteObjectPendingCallWatcher(call, this);
auto *timeoutTimer = new QTimer(this);
timeoutTimer->setSingleShot(true);
m_watchers.insert(watcher, timeoutTimer);
connect(timeoutTimer, &QTimer::timeout, this, [this, watcher, timeoutTimer]() {
qDebug() << "Foo request timed out.";
m_watchers.remove(watcher);
watcher->deleteLater();
timeoutTimer->deleteLater();
});
connect(watcher, &QRemoteObjectPendingCallWatcher::finished, [this](QRemoteObjectPendingCallWatcher *self) {
QTimer *timer = m_watchers.take(self);
if (timer) {
timer->stop();
timer->deleteLater();
}
QByteArray result = self->returnValue().toByteArray();
handle_cli_message(QString(result));
self->deleteLater();
});
timeoutTimer->start(30000);
});
connect(m_openVpnProcess.data(), QOverload<int, QProcess::ExitStatus>::of(&PrivilegedProcess::finished), this, [this](int exitCode, QProcess::ExitStatus exitStatus) {
qDebug().noquote() << "OpenVPN finished, exitCode, exiStatus" << exitCode << exitStatus;
setConnectionState(Vpn::ConnectionState::Disconnected);
if (exitStatus != QProcess::NormalExit) {
emit protocolError(amnezia::ErrorCode::ShadowSocksExecutableCrashed);
stop();
}
if (exitCode !=0 ) {
emit protocolError(amnezia::ErrorCode::InternalError);
stop();
}
});
m_openVpnProcess->start();
// startTimeoutTimer();
return ErrorCode::NoError;
}
bool OpenVpnProtocol::sendTermSignal()
{
return m_managementServer.writeCommand("signal SIGTERM");
}
void OpenVpnProtocol::sendByteCount()
{
m_managementServer.writeCommand("bytecount 1");
}
void OpenVpnProtocol::sendInitialData()
{
m_managementServer.writeCommand("state on");
m_managementServer.writeCommand("log on");
}
void OpenVpnProtocol::onReadyReadDataFromManagementServer()
{
for (;;) {
QString line = m_managementServer.readLine().simplified();
if (line.isEmpty()) {
return;
}
if (!line.contains(">BYTECOUNT")) {
qDebug().noquote() << line;
}
if (line.contains(">INFO:OpenVPN Management Interface")) {
sendInitialData();
} else if (line.startsWith(">STATE")) {
if (line.contains("CONNECTED,SUCCESS")) {
sendByteCount();
stopTimeoutTimer();
setConnectionState(Vpn::ConnectionState::Connected);
continue;
} else if (line.contains("EXITING,SIGTER")) {
// openVpnStateSigTermHandler();
setConnectionState(Vpn::ConnectionState::Disconnecting);
continue;
} else if (line.contains("RECONNECTING")) {
setConnectionState(Vpn::ConnectionState::Reconnecting);
continue;
}
}
if (line.contains("ROUTE_GATEWAY")) {
updateRouteGateway(line);
}
if (line.contains("PUSH: Received control message")) {
updateVpnGateway(line);
}
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);
}
return;
}
QByteArray data(line.toStdString().c_str());
if (data.contains(">BYTECOUNT:")) {
int beg = data.lastIndexOf(">BYTECOUNT:");
int end = data.indexOf("\n", beg);
beg += sizeof(">BYTECOUNT:") - 1;
QList<QByteArray> count = data.mid(beg, end - beg + 1).split(',');
quint64 r = static_cast<quint64>(count.at(0).trimmed().toULongLong());
quint64 s = static_cast<quint64>(count.at(1).trimmed().toULongLong());
setBytesChanged(r, s);
}
}
}
void OpenVpnProtocol::updateVpnGateway(const QString &line)
{
// "[ifconfig] [10.8.0.14] [10.8.0.13]"
QStringList params = line.split("\n");
for (const QString &param : params) {
if (param.contains("ifconfig")) {
QString l = param.right(param.size() - param.indexOf("ifconfig"));
// line looks like
// PUSH: Received control message: 'PUSH_REPLY,route 10.8.0.1,topology net30,ping 10,ping-restart
// 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
QStringList params = line.split(",");
for (const QString &l : params) {
if (l.contains("ifconfig")) {
if (l.split(" ").size() == 3) {
m_vpnLocalAddress = l.split(" ").at(1);
m_vpnLocalAddress.remove("[");m_vpnLocalAddress.remove("]");
m_vpnGateway = l.split(" ").at(2);
m_vpnGateway.remove("[");m_vpnGateway.remove("]");
qDebug() << QString("Set vpn local address %1, gw %2").arg(m_vpnLocalAddress).arg(vpnGateway());
}
}
+10 -2
View File
@@ -5,6 +5,7 @@
#include <QString>
#include <QTimer>
#include "managementserver.h"
#include "vpnprotocol.h"
#include "core/ipcclient.h"
@@ -24,21 +25,28 @@ public:
static QString defaultConfigFileName();
static QString defaultConfigPath();
protected slots:
void onReadyReadDataFromManagementServer();
private:
QString configPath() const;
bool openVpnProcessIsRunning() const;
bool sendTermSignal();
void readOpenVpnConfiguration(const QJsonObject &configuration);
void handle_cli_message(QString message);
void disconnectFromManagementServer();
void killOpenVpnProcess();
void sendByteCount();
void sendInitialData();
void sendManagementCommand(const QString& command);
QHash<QRemoteObjectPendingCallWatcher*, QTimer*> m_watchers;
const QString m_managementHost = "127.0.0.1";
const unsigned int m_managementPort = 57775;
ManagementServer m_managementServer;
QString m_configFileName;
QTemporaryFile m_configFile;
uint selectMgmtPort();
private:
void updateRouteGateway(QString line);
+15 -15
View File
@@ -25,7 +25,8 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app
if (encryptionRequired() && !encrypted) {
for (const QString &key : m_settings.allKeys()) {
if (encryptedKeys.contains(key)) {
const QVariant &val = value(key);
QVariant val;
value(key, val);
setValue(key, val);
}
}
@@ -34,16 +35,18 @@ SecureQSettings::SecureQSettings(const QString &organization, const QString &app
}
}
QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue) const
void SecureQSettings::value(const QString &key, QVariant &returnValue, const QVariant &defaultValue) const
{
QMutexLocker locker(&mutex);
if (m_cache.contains(key)) {
return m_cache.value(key);
returnValue = m_cache.value(key);
return;
}
if (!m_settings.contains(key)) {
returnValue = defaultValue;
return;
}
if (!m_settings.contains(key))
return defaultValue;
QVariant retVal;
@@ -54,7 +57,7 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue
if (getEncKey().isEmpty() || getEncIv().isEmpty()) {
qCritical() << "SecureQSettings::setValue Decryption requested, but key is empty";
return {};
return;
}
QByteArray encryptedValue = retVal.toByteArray().mid(magicString.size());
@@ -75,13 +78,11 @@ QVariant SecureQSettings::value(const QString &key, const QVariant &defaultValue
}
m_cache.insert(key, retVal);
return retVal;
returnValue = retVal;
}
void SecureQSettings::setValue(const QString &key, const QVariant &value)
{
QMutexLocker locker(&mutex);
if (encryptionRequired() && encryptedKeys.contains(key)) {
if (!getEncKey().isEmpty() && !getEncIv().isEmpty()) {
QByteArray decryptedValue;
@@ -107,8 +108,6 @@ void SecureQSettings::setValue(const QString &key, const QVariant &value)
void SecureQSettings::remove(const QString &key)
{
QMutexLocker locker(&mutex);
m_settings.remove(key);
m_cache.remove(key);
@@ -125,7 +124,9 @@ QByteArray SecureQSettings::backupAppConfig() const
QJsonObject cfg;
for (const QString &key : m_settings.allKeys()) {
cfg.insert(key, QJsonValue::fromVariant(value(key)));
QVariant v;
value(key, v);
cfg.insert(key, QJsonValue::fromVariant(v));
}
return QJsonDocument(cfg).toJson();
@@ -253,7 +254,6 @@ void SecureQSettings::setSecTag(const QString &tag, const QByteArray &data)
void SecureQSettings::clearSettings()
{
QMutexLocker locker(&mutex);
m_settings.clear();
m_cache.clear();
sync();
+2 -1
View File
@@ -20,8 +20,9 @@ public:
explicit SecureQSettings(const QString &organization, const QString &application = QString(),
QObject *parent = nullptr);
Q_INVOKABLE QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
Q_INVOKABLE void value(const QString &key, QVariant &eturnValue, const QVariant &defaultValue = QVariant()) const;
Q_INVOKABLE void setValue(const QString &key, const QVariant &value);
void remove(const QString &key);
void sync();
@@ -1,6 +1,5 @@
if which apt-get > /dev/null 2>&1; then LOCK_FILE="/var/lib/dpkg/lock-frontend";\
elif which dnf > /dev/null 2>&1; then LOCK_FILE="/var/run/dnf.pid";\
elif which yum > /dev/null 2>&1; then LOCK_FILE="/var/run/yum.pid";\
elif which pacman > /dev/null 2>&1; then LOCK_FILE="/var/lib/pacman/db.lck";\
else echo "Packet manager not found"; echo "Internal error"; exit 1; fi;\
if command -v fuser > /dev/null 2>&1; then sudo fuser $LOCK_FILE 2>/dev/null; else echo "fuser not installed"; fi
if command -v fuser > /dev/null 2>&1; then sudo fuser $LOCK_FILE 2>/dev/null; else echo "fuser not installed"; fi
-1
View File
@@ -1,7 +1,6 @@
if which apt-get > /dev/null 2>&1; then pm=$(which apt-get); silent_inst="-yq install"; check_pkgs="-yq update"; docker_pkg="docker.io"; dist="debian";\
elif which dnf > /dev/null 2>&1; then pm=$(which dnf); silent_inst="-yq install"; check_pkgs="-yq check-update"; docker_pkg="docker"; dist="fedora";\
elif which yum > /dev/null 2>&1; then pm=$(which yum); silent_inst="-y -q install"; check_pkgs="-y -q check-update"; docker_pkg="docker"; dist="centos";\
elif which pacman > /dev/null 2>&1; then pm=$(which pacman); silent_inst="-S --noconfirm --noprogressbar --quiet"; check_pkgs="> /dev/null 2>&1"; docker_pkg="docker"; dist="archlinux";\
else echo "Packet manager not found"; exit 1; fi;\
echo "Dist: $dist, Packet manager: $pm, Install command: $silent_inst, Check pkgs command: $check_pkgs, Docker pkg: $docker_pkg";\
if [ "$dist" = "debian" ]; then export DEBIAN_FRONTEND=noninteractive; fi;\
+25 -17
View File
@@ -39,12 +39,12 @@ Settings::Settings(QObject *parent) : QObject(parent), m_settings(ORGANIZATION_N
}
}
int Settings::serversCount() const
int Settings::serversCount()
{
return serversArray().size();
}
QJsonObject Settings::server(int index) const
QJsonObject Settings::server(int index)
{
const QJsonArray &servers = serversArray();
if (index >= servers.size())
@@ -88,12 +88,12 @@ void Settings::setDefaultContainer(int serverIndex, DockerContainer container)
editServer(serverIndex, s);
}
DockerContainer Settings::defaultContainer(int serverIndex) const
DockerContainer Settings::defaultContainer(int serverIndex)
{
return ContainerProps::containerFromString(defaultContainerName(serverIndex));
}
QString Settings::defaultContainerName(int serverIndex) const
QString Settings::defaultContainerName(int serverIndex)
{
QString name = server(serverIndex).value(config_key::defaultContainer).toString();
if (name.isEmpty()) {
@@ -102,7 +102,7 @@ QString Settings::defaultContainerName(int serverIndex) const
return name;
}
QMap<DockerContainer, QJsonObject> Settings::containers(int serverIndex) const
QMap<DockerContainer, QJsonObject> Settings::containers(int serverIndex)
{
const QJsonArray &containers = server(serverIndex).value(config_key::containers).toArray();
@@ -186,7 +186,7 @@ void Settings::clearLastConnectionConfig(int serverIndex, DockerContainer contai
setProtocolConfig(serverIndex, container, proto, c);
}
bool Settings::haveAuthData(int serverIndex) const
bool Settings::haveAuthData(int serverIndex)
{
if (serverIndex < 0)
return false;
@@ -194,7 +194,7 @@ bool Settings::haveAuthData(int serverIndex) const
return (!cred.hostName.isEmpty() && !cred.userName.isEmpty() && !cred.secretData.isEmpty());
}
QString Settings::nextAvailableServerName() const
QString Settings::nextAvailableServerName()
{
int i = 0;
bool nameExist = false;
@@ -226,7 +226,7 @@ void Settings::setSaveLogs(bool enabled)
emit saveLogsChanged();
}
QString Settings::routeModeString(RouteMode mode) const
QString Settings::routeModeString(RouteMode mode)
{
switch (mode) {
case VpnAllSites: return "AllSites";
@@ -235,7 +235,7 @@ QString Settings::routeModeString(RouteMode mode) const
}
}
Settings::RouteMode Settings::routeMode() const
Settings::RouteMode Settings::routeMode()
{
return static_cast<RouteMode>(value("Conf/routeMode", 0).toInt());
}
@@ -267,7 +267,7 @@ void Settings::addVpnSites(RouteMode mode, const QMap<QString, QString> &sites)
setVpnSites(mode, allSites);
}
QStringList Settings::getVpnIps(RouteMode mode) const
QStringList Settings::getVpnIps(RouteMode mode)
{
QStringList ips;
const QVariantMap &m = vpnSites(mode);
@@ -323,12 +323,12 @@ void Settings::removeAllVpnSites(RouteMode mode)
setVpnSites(mode, QVariantMap());
}
QString Settings::primaryDns() const
QString Settings::primaryDns()
{
return value("Conf/primaryDns", cloudFlareNs1).toString();
}
QString Settings::secondaryDns() const
QString Settings::secondaryDns()
{
return value("Conf/secondaryDns", cloudFlareNs2).toString();
}
@@ -338,12 +338,12 @@ void Settings::clearSettings()
m_settings.clearSettings();
}
ServerCredentials Settings::defaultServerCredentials() const
ServerCredentials Settings::defaultServerCredentials()
{
return serverCredentials(defaultServerIndex());
}
ServerCredentials Settings::serverCredentials(int index) const
ServerCredentials Settings::serverCredentials(int index)
{
const QJsonObject &s = server(index);
@@ -356,18 +356,26 @@ ServerCredentials Settings::serverCredentials(int index) const
return credentials;
}
QVariant Settings::value(const QString &key, const QVariant &defaultValue) const
QVariant Settings::value(const QString &key, const QVariant &defaultValue)
{
QVariant returnValue;
// if (defaultValue.isNull() || !defaultValue.isValid()) {
// QMetaObject::invokeMethod(&m_settings, "value",
// Qt::QueuedConnection,
// Q_ARG(const QString&, key),
// Q_ARG(QVariant, returnValue));
// } else {
if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
returnValue = m_settings.value(key, defaultValue);
m_settings.value(key, returnValue, defaultValue);
} else {
QMetaObject::invokeMethod(&m_settings, "value",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QVariant, returnValue),
Q_ARG(const QString&, key),
Q_ARG(QVariant&, returnValue),
Q_ARG(const QVariant&, defaultValue));
}
// }
return returnValue;
}
+29 -29
View File
@@ -24,10 +24,10 @@ class Settings : public QObject
public:
explicit Settings(QObject *parent = nullptr);
ServerCredentials defaultServerCredentials() const;
ServerCredentials serverCredentials(int index) const;
ServerCredentials defaultServerCredentials();
ServerCredentials serverCredentials(int index);
QJsonArray serversArray() const
QJsonArray serversArray()
{
return QJsonDocument::fromJson(value("Servers/serversList").toByteArray()).array();
}
@@ -37,13 +37,13 @@ public:
}
// Servers section
int serversCount() const;
QJsonObject server(int index) const;
int serversCount();
QJsonObject server(int index);
void addServer(const QJsonObject &server);
void removeServer(int index);
bool editServer(int index, const QJsonObject &server);
int defaultServerIndex() const
int defaultServerIndex()
{
return value("Servers/defaultServerIndex", 0).toInt();
}
@@ -51,16 +51,16 @@ public:
{
setValue("Servers/defaultServerIndex", index);
}
QJsonObject defaultServer() const
QJsonObject defaultServer()
{
return server(defaultServerIndex());
}
void setDefaultContainer(int serverIndex, DockerContainer container);
DockerContainer defaultContainer(int serverIndex) const;
QString defaultContainerName(int serverIndex) const;
DockerContainer defaultContainer(int serverIndex);
QString defaultContainerName(int serverIndex);
QMap<DockerContainer, QJsonObject> containers(int serverIndex) const;
QMap<DockerContainer, QJsonObject> containers(int serverIndex);
void setContainers(int serverIndex, const QMap<DockerContainer, QJsonObject> &containers);
QJsonObject containerConfig(int serverIndex, DockerContainer container);
@@ -72,11 +72,11 @@ public:
void clearLastConnectionConfig(int serverIndex, DockerContainer container, Proto proto = Proto::Any);
bool haveAuthData(int serverIndex) const;
QString nextAvailableServerName() const;
bool haveAuthData(int serverIndex);
QString nextAvailableServerName();
// App settings section
bool isAutoConnect() const
bool isAutoConnect()
{
return value("Conf/autoConnect", false).toBool();
}
@@ -85,7 +85,7 @@ public:
setValue("Conf/autoConnect", enabled);
}
bool isStartMinimized() const
bool isStartMinimized()
{
return value("Conf/startMinimized", false).toBool();
}
@@ -94,7 +94,7 @@ public:
setValue("Conf/startMinimized", enabled);
}
bool isSaveLogs() const
bool isSaveLogs()
{
return value("Conf/saveLogs", false).toBool();
}
@@ -107,12 +107,12 @@ public:
};
Q_ENUM(RouteMode)
QString routeModeString(RouteMode mode) const;
QString routeModeString(RouteMode mode);
RouteMode routeMode() const;
RouteMode routeMode();
void setRouteMode(RouteMode mode) { setValue("Conf/routeMode", mode); }
QVariantMap vpnSites(RouteMode mode) const
QVariantMap vpnSites(RouteMode mode)
{
return value("Conf/" + routeModeString(mode)).toMap();
}
@@ -123,14 +123,14 @@ public:
}
bool addVpnSite(RouteMode mode, const QString &site, const QString &ip = "");
void addVpnSites(RouteMode mode, const QMap<QString, QString> &sites); // map <site, ip>
QStringList getVpnIps(RouteMode mode) const;
QStringList getVpnIps(RouteMode mode);
void removeVpnSite(RouteMode mode, const QString &site);
void addVpnIps(RouteMode mode, const QStringList &ip);
void removeVpnSites(RouteMode mode, const QStringList &sites);
void removeAllVpnSites(RouteMode mode);
bool useAmneziaDns() const
bool useAmneziaDns()
{
return value("Conf/useAmneziaDns", true).toBool();
}
@@ -139,16 +139,16 @@ public:
setValue("Conf/useAmneziaDns", enabled);
}
QString primaryDns() const;
QString secondaryDns() const;
QString primaryDns();
QString secondaryDns();
// QString primaryDns() const { return m_primaryDns; }
// QString primaryDns() { return m_primaryDns; }
void setPrimaryDns(const QString &primaryDns)
{
setValue("Conf/primaryDns", primaryDns);
}
// QString secondaryDns() const { return m_secondaryDns; }
// QString secondaryDns() { return m_secondaryDns; }
void setSecondaryDns(const QString &secondaryDns)
{
setValue("Conf/secondaryDns", secondaryDns);
@@ -160,7 +160,7 @@ public:
// static constexpr char openNicNs5[] = "94.103.153.176";
// static constexpr char openNicNs13[] = "144.76.103.143";
QByteArray backupAppConfig() const
QByteArray backupAppConfig()
{
return m_settings.backupAppConfig();
}
@@ -178,7 +178,7 @@ public:
setValue("Conf/appLanguage", locale);
};
bool isScreenshotsEnabled() const
bool isScreenshotsEnabled()
{
return value("Conf/screenshotsEnabled", false).toBool();
}
@@ -193,10 +193,10 @@ signals:
void saveLogsChanged();
private:
QVariant value(const QString &key, const QVariant &defaultValue = QVariant()) const;
void setValue(const QString &key, const QVariant &value);
SecureQSettings m_settings;
mutable SecureQSettings m_settings;
QVariant value(const QString &key, const QVariant &defaultValue = QVariant());
void setValue(const QString &key, const QVariant &value);
};
#endif // SETTINGS_H
@@ -15,13 +15,11 @@
SettingsController::SettingsController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const QSharedPointer<LanguageModel> &languageModel,
const QSharedPointer<SitesModel> &sitesModel,
const std::shared_ptr<Settings> &settings, QObject *parent)
: QObject(parent),
m_serversModel(serversModel),
m_containersModel(containersModel),
m_languageModel(languageModel),
m_sitesModel(sitesModel),
m_settings(settings)
{
m_appVersion = QString("%1: %2 (%3)").arg(tr("Software version"), QString(APP_VERSION), __DATE__);
@@ -136,7 +134,6 @@ void SettingsController::clearSettings()
m_serversModel->resetModel();
m_languageModel->changeLanguage(
static_cast<LanguageSettings::AvailableLanguageEnum>(m_languageModel->getCurrentLanguageIndex()));
m_sitesModel->setRouteMode(Settings::RouteMode::VpnAllSites);
emit changeSettingsFinished(tr("All settings have been reset to default values"));
}
@@ -6,7 +6,6 @@
#include "ui/models/containers_model.h"
#include "ui/models/languageModel.h"
#include "ui/models/servers_model.h"
#include "ui/models/sites_model.h"
class SettingsController : public QObject
{
@@ -15,7 +14,6 @@ public:
explicit SettingsController(const QSharedPointer<ServersModel> &serversModel,
const QSharedPointer<ContainersModel> &containersModel,
const QSharedPointer<LanguageModel> &languageModel,
const QSharedPointer<SitesModel> &sitesModel,
const std::shared_ptr<Settings> &settings, QObject *parent = nullptr);
Q_PROPERTY(QString primaryDns READ getPrimaryDns WRITE setPrimaryDns NOTIFY primaryDnsChanged)
@@ -78,7 +76,6 @@ private:
QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<LanguageModel> m_languageModel;
QSharedPointer<SitesModel> m_sitesModel;
std::shared_ptr<Settings> m_settings;
QString m_appVersion;
+1 -1
View File
@@ -231,7 +231,7 @@ ErrorCode ClientManagementModel::appendClient(const QString &clientId, const QSt
}
}
beginInsertRows(QModelIndex(), rowCount(), rowCount() + 1);
beginInsertRows(QModelIndex(), rowCount(), 1);
QJsonObject client;
client[configKey::clientId] = clientId;
+1 -1
View File
@@ -101,7 +101,7 @@ PageType {
text: qsTr("Show other methods on Github")
onClicked: Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client#donate"))
onClicked: Qt.openUrlExternally("https://github.com/amnezia-vpn/amnezia-client#donate")
}
ParagraphTextType {
@@ -135,7 +135,7 @@ PageType {
text: qsTr("I have nothing")
onClicked: Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
onClicked: Qt.openUrlExternally("https://amnezia.org/instructions/0_starter-guide")
}
}
+3 -3
View File
@@ -226,13 +226,13 @@ QStringList Utils::summarizeRoutes(const QStringList &ips, const QString cidr)
QString Utils::openVpnExecPath()
{
#ifdef Q_OS_WIN
return Utils::executable("openvpn/ovpncli", true);
return Utils::executable("openvpn/openvpn", true);
#elif defined Q_OS_LINUX
// We have service that runs OpenVPN on Linux. We need to make same
// path for client and service.
return Utils::executable("../../client/bin/ovpncli", true);
return Utils::executable("../../client/bin/openvpn", true);
#else
return Utils::executable("/ovpncli", true);
return Utils::executable("/openvpn", true);
#endif
}
+1 -1
View File
@@ -261,7 +261,7 @@ QString TapController::getTapInstallPath()
QString TapController::getOpenVpnPath()
{
return qApp->applicationDirPath() + "\\openvpn\\ovpncli.exe";
return qApp->applicationDirPath() + "\\openvpn\\openvpn.exe";
}
QString TapController::getTapDriverDir()