mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-20 02:00:55 +07:00
Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1cb4ac544 | |||
| f91854594c | |||
| f661ea1d46 | |||
| f50eea3eaf | |||
| c15b57e690 | |||
| 5f7ef31345 | |||
| 447410a27a | |||
| 2aa9f9cca9 | |||
| cba27d354d | |||
| b398f42ada | |||
| b6571d99de | |||
| b2392c1943 | |||
| 048a673d31 | |||
| c4df9c004b | |||
| b9d4c53eb6 | |||
| 5fdeea0581 | |||
| e1cd764050 | |||
| 1e54379cc0 | |||
| ba3f69d206 | |||
| fcfd4181c7 | |||
| 9f6ec6d3e2 | |||
| 2e50aae603 | |||
| 5a16a07b57 | |||
| 953eca6695 | |||
| a50cdd5bc2 | |||
| 10eb65e545 | |||
| 5354344ba7 | |||
| c000a93eef | |||
| ef6bc5ae4a | |||
| 97c4564649 | |||
| 5bf31a8b50 | |||
| 18e0d7fb2c | |||
| ac454d9d78 | |||
| 806677510f | |||
| 68e0ba9923 | |||
| 22b33a4f25 | |||
| 77f830acd5 | |||
| eb3b090257 | |||
| 2e1c219093 | |||
| e38f69caf0 | |||
| 795f286923 | |||
| d62e5b51da | |||
| 96b267b1f7 | |||
| 568388367e | |||
| 5ca46edf33 | |||
| af41abd346 | |||
| 5edb61641c | |||
| af3b1caa87 | |||
| cc4a7b32b0 | |||
| dfd61f58d4 | |||
| 84a3c1f725 | |||
| 2419fa1a6e | |||
| 3b8ecd9e9d | |||
| 94ee4b76db | |||
| d43a1cd753 | |||
| 8bc6852b39 | |||
| 3850be08f1 | |||
| d72d1d56b1 | |||
| 2a4926843c | |||
| 1b357055a2 | |||
| 2d3d64e462 | |||
| aa648d4e12 | |||
| bfa0ac4c34 | |||
| c37ddd83d5 | |||
| 96bbc1cdbc | |||
| ec9ae0ef4f | |||
| 95cbb07cbb | |||
| 7b95d6a5fc | |||
| bea19a9461 | |||
| ba686556d2 | |||
| 15dc6eaaf8 | |||
| 3369a387ce | |||
| dd46d8cf99 | |||
| 0b8c8835c4 | |||
| 441811e277 | |||
| 3645735053 | |||
| 416d597847 | |||
| 861c71e3a8 | |||
| f45fb442de | |||
| 82241701a9 | |||
| bfdbe27a8d | |||
| c7dafe9c00 |
@@ -35,6 +35,7 @@ CMakeLists.txt.user*
|
||||
.DS_Store
|
||||
._.DS_Store
|
||||
._*
|
||||
*.dmg
|
||||
|
||||
# tmp files
|
||||
*.*~
|
||||
|
||||
+32
-18
@@ -11,16 +11,30 @@ jobs:
|
||||
- name: MacOS
|
||||
os: osx
|
||||
osx_image: xcode12.2
|
||||
|
||||
|
||||
env:
|
||||
- QT_VERSION=5.15.1
|
||||
|
||||
script:
|
||||
- |
|
||||
if [ ! -f $HOME/Qt/5.14.2/clang_64/bin/qmake ]; then \
|
||||
if [ ! -f $HOME/Qt/$QT_VERSION/clang_64/bin/qmake ]; then \
|
||||
brew install p7zip && \
|
||||
pip3 install aqtinstall requests py7zr && \
|
||||
python3 -m aqt install --outputdir $HOME/Qt 5.14.2 mac desktop clang_64 -m qtbase && \
|
||||
python3 -m aqt install --outputdir $HOME/Qt $QT_VERSION mac desktop clang_64 -m qtbase && \
|
||||
python3 -m aqt tool --outputdir $HOME/Qt mac tools_ifw 4.0.1 qt.tools.ifw.40;
|
||||
fi
|
||||
- bash deploy/build_macos.sh
|
||||
- bash deploy/build_macos.sh
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
token: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file:
|
||||
- "AmneziaVPN_unsigned.dmg"
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
|
||||
- name: Windows
|
||||
os: windows
|
||||
@@ -44,24 +58,24 @@ jobs:
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo 'call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsamd64_x86.bat"' >> winbuild.bat
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo -e "deploy\\\build_windows.bat" >> winbuild.bat
|
||||
- cat winbuild.bat
|
||||
- echo -e "set WIN_CERT_PW=$WIN_CERT_PW" >> winbuild.bat
|
||||
- echo -e "\r\n" >> winbuild.bat
|
||||
- echo -e "call deploy\\\build_windows.bat" >> winbuild.bat
|
||||
- cmd //c winbuild.bat
|
||||
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
token: $GH_TOKEN
|
||||
skip_cleanup: true
|
||||
file:
|
||||
- "AmneziaVPN.exe"
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
deploy:
|
||||
provider: releases
|
||||
api_key: $GH_TOKEN
|
||||
file:
|
||||
- "AmneziaVPN.exe"
|
||||
- "AmneziaVPN.dmg"
|
||||
|
||||
skip_cleanup: true
|
||||
on:
|
||||
tags: true
|
||||
branch: master
|
||||
|
||||
|
||||
before_cache:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then brew cleanup; fi
|
||||
# Cache only .git files under "/usr/local/Homebrew" so "brew update" does not take 5min every build
|
||||
@@ -71,4 +85,4 @@ cache:
|
||||
directories:
|
||||
- $HOME/Qt
|
||||
- /C/Qt
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
- $HOME/Library/Caches/Homebrew
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = client service platform
|
||||
|
||||
|
||||
+7
-7
@@ -1,4 +1,4 @@
|
||||
QT += widgets core gui network xml
|
||||
QT += widgets core gui network xml remoteobjects
|
||||
|
||||
TARGET = AmneziaVPN
|
||||
TEMPLATE = app
|
||||
@@ -10,16 +10,15 @@ include("3rd/QtSsh/src/ssh/ssh.pri")
|
||||
include("3rd/QtSsh/src/botan/botan.pri")
|
||||
|
||||
HEADERS += \
|
||||
communicator.h \
|
||||
../ipc/ipc.h \
|
||||
core/defs.h \
|
||||
core/errorstrings.h \
|
||||
core/ipcclient.h \
|
||||
core/openvpnconfigurator.h \
|
||||
core/servercontroller.h \
|
||||
debug.h \
|
||||
defines.h \
|
||||
localclient.h \
|
||||
managementserver.h \
|
||||
message.h \
|
||||
protocols/shadowsocksvpnprotocol.h \
|
||||
runguard.h \
|
||||
settings.h \
|
||||
@@ -31,14 +30,12 @@ HEADERS += \
|
||||
protocols/openvpnprotocol.h \
|
||||
|
||||
SOURCES += \
|
||||
communicator.cpp \
|
||||
core/ipcclient.cpp \
|
||||
core/openvpnconfigurator.cpp \
|
||||
core/servercontroller.cpp \
|
||||
debug.cpp \
|
||||
localclient.cpp \
|
||||
main.cpp \
|
||||
managementserver.cpp \
|
||||
message.cpp \
|
||||
protocols/shadowsocksvpnprotocol.cpp \
|
||||
runguard.cpp \
|
||||
settings.cpp \
|
||||
@@ -100,3 +97,6 @@ macx {
|
||||
|
||||
LIBS += -framework Cocoa -framework ApplicationServices -framework CoreServices -framework Foundation -framework AppKit
|
||||
}
|
||||
|
||||
REPC_REPLICA += ../ipc/ipcinterface.rep
|
||||
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
#include "communicator.h"
|
||||
#include "defines.h"
|
||||
#include "localclient.h"
|
||||
#include "utils.h"
|
||||
|
||||
Communicator::Communicator(QObject* parent) : QObject(parent),
|
||||
m_localClient(nullptr)
|
||||
{
|
||||
connectToServer();
|
||||
}
|
||||
|
||||
Communicator::~Communicator()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Communicator::connectToServer()
|
||||
{
|
||||
if (m_localClient) {
|
||||
delete m_localClient;
|
||||
}
|
||||
|
||||
m_localClient = new LocalClient(this);
|
||||
connect(m_localClient, &LocalClient::connected, this, &Communicator::onConnected);
|
||||
connect(m_localClient, &LocalClient::lineAvailable, this, &Communicator::onLineAvailable);
|
||||
|
||||
m_localClient->connectToServer(Utils::serverName());
|
||||
}
|
||||
|
||||
void Communicator::onConnected()
|
||||
{
|
||||
qDebug().noquote() << QString("Connected to local server '%1'").arg(m_localClient->serverName());
|
||||
Message message(Message::State::Initialize, QStringList({"Client"}));
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
void Communicator::onLineAvailable(const QString& line)
|
||||
{
|
||||
Message message(line);
|
||||
if (!message.isValid()) {
|
||||
qDebug() << "Message is not valid";
|
||||
return;
|
||||
}
|
||||
|
||||
emit messageReceived(message);
|
||||
}
|
||||
|
||||
bool Communicator::isConnected() const
|
||||
{
|
||||
if (!m_localClient) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_localClient->connectedState();
|
||||
}
|
||||
|
||||
QString Communicator::readData()
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
bool Communicator::writeData(const QString& data)
|
||||
{
|
||||
return m_localClient->write(data.toUtf8());
|
||||
}
|
||||
|
||||
void Communicator::sendMessage(const Message& message)
|
||||
{
|
||||
if (!isConnected()) {
|
||||
return;
|
||||
}
|
||||
const QString data = message.toString();
|
||||
bool status = writeData(data + "\n");
|
||||
|
||||
qDebug().noquote() << QString("Send message '%1',%2 status '%2'").
|
||||
arg(static_cast<int>(message.state())).
|
||||
arg(data).
|
||||
arg(Utils::toString(status));
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
#ifndef COMMUNICATOR_H
|
||||
#define COMMUNICATOR_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include "message.h"
|
||||
|
||||
class LocalClient;
|
||||
|
||||
class Communicator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Communicator(QObject* parent = nullptr);
|
||||
~Communicator();
|
||||
|
||||
bool isConnected() const;
|
||||
void sendMessage(const Message& message);
|
||||
|
||||
signals:
|
||||
void messageReceived(const Message& message);
|
||||
|
||||
void comminicatorConnected();
|
||||
void comminicatorDisconnected();
|
||||
|
||||
protected slots:
|
||||
void onConnected();
|
||||
void onLineAvailable(const QString& line);
|
||||
|
||||
protected:
|
||||
QString readData();
|
||||
bool writeData(const QString& data);
|
||||
void connectToServer();
|
||||
|
||||
LocalClient* m_localClient;
|
||||
};
|
||||
|
||||
|
||||
#endif // COMMUNICATOR_H
|
||||
+11
-1
@@ -34,8 +34,9 @@ enum ErrorCode
|
||||
InternalError,
|
||||
NotImplementedError,
|
||||
|
||||
// Server errorz
|
||||
// Server errors
|
||||
ServerCheckFailed,
|
||||
ServerPortAlreadyAllocatedError,
|
||||
|
||||
// Ssh connection errors
|
||||
SshSocketError, SshTimeoutError, SshProtocolError,
|
||||
@@ -62,6 +63,15 @@ enum ErrorCode
|
||||
OpenVpnUnknownError
|
||||
};
|
||||
|
||||
namespace config {
|
||||
// config keys
|
||||
static QString key_openvpn_config_data() { return "openvpn_config_data"; }
|
||||
static QString key_openvpn_config_path() { return "openvpn_config_path"; }
|
||||
static QString key_shadowsocks_config_data() { return "shadowsocks_config_data"; }
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace amnezia
|
||||
|
||||
#endif // DEFS_H
|
||||
|
||||
@@ -11,7 +11,10 @@ static QString errorString(ErrorCode code){
|
||||
case(NoError): return QObject::tr("No error");
|
||||
case(UnknownError): return QObject::tr("Unknown Error");
|
||||
case(NotImplementedError): return QObject::tr("Function not implemented");
|
||||
|
||||
// Server errors
|
||||
case(ServerCheckFailed): return QObject::tr("Server check failed");
|
||||
case(ServerPortAlreadyAllocatedError): return QObject::tr("Server port already used. Check for another software");
|
||||
|
||||
// Ssh connection errors
|
||||
case(SshSocketError): return QObject::tr("Ssh connection error");
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
#include "ipcclient.h"
|
||||
#include <QRemoteObjectNode>
|
||||
|
||||
IpcClient &IpcClient::Instance()
|
||||
{
|
||||
static IpcClient s;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool IpcClient::init()
|
||||
{
|
||||
Instance().m_localSocket->waitForConnected();
|
||||
|
||||
if (!Instance().m_ipcClient) {
|
||||
qDebug() << "IpcClient::init failed";
|
||||
return false;
|
||||
}
|
||||
return Instance().m_ipcClient->isReplicaValid();
|
||||
}
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> IpcClient::CreatePrivilegedProcess()
|
||||
{
|
||||
if (! Instance().m_ipcClient || ! Instance().m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient::createPrivilegedProcess : IpcClient IpcClient replica is not valid";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QRemoteObjectPendingReply<int> futureResult = Instance().m_ipcClient->createPrivilegedProcess();
|
||||
futureResult.waitForFinished(1000);
|
||||
|
||||
int pid = futureResult.returnValue();
|
||||
|
||||
auto pd = QSharedPointer<ProcessDescriptor>(new ProcessDescriptor());
|
||||
Instance().m_processNodes.insert(pid, pd);
|
||||
|
||||
pd->localSocket.reset(new QLocalSocket(pd->replicaNode.data()));
|
||||
|
||||
connect(pd->localSocket.data(), &QLocalSocket::connected, pd->replicaNode.data(), [pd]() {
|
||||
pd->replicaNode->addClientSideConnection(pd->localSocket.data());
|
||||
|
||||
pd->ipcProcess.reset(pd->replicaNode->acquire<IpcProcessInterfaceReplica>());
|
||||
if (!pd->ipcProcess) {
|
||||
qWarning() << "Acquire IpcProcessInterfaceReplica failed";
|
||||
}
|
||||
else {
|
||||
pd->ipcProcess->waitForSource(1000);
|
||||
if (!pd->ipcProcess->isReplicaValid()) {
|
||||
qWarning() << "IpcProcessInterfaceReplica replica is not connected!";
|
||||
}
|
||||
|
||||
connect(pd->ipcProcess.data(), &IpcProcessInterfaceReplica::destroyed, pd->ipcProcess.data(), [pd](){
|
||||
pd->replicaNode->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
pd->localSocket->connectToServer(amnezia::getIpcProcessUrl(pid));
|
||||
pd->localSocket->waitForConnected();
|
||||
|
||||
auto proccessReplica = QSharedPointer<IpcProcessInterfaceReplica>(pd->ipcProcess);
|
||||
return proccessReplica;
|
||||
}
|
||||
|
||||
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||
{
|
||||
m_localSocket.reset(new QLocalSocket(this));
|
||||
connect(m_localSocket.data(), &QLocalSocket::connected, &m_ClientNode, [this]() {
|
||||
m_ClientNode.addClientSideConnection(m_localSocket.data());
|
||||
|
||||
m_ipcClient.reset(m_ClientNode.acquire<IpcInterfaceReplica>());
|
||||
m_ipcClient->waitForSource(1000);
|
||||
|
||||
if (!m_ipcClient->isReplicaValid()) {
|
||||
qWarning() << "IpcClient replica is not connected!";
|
||||
}
|
||||
|
||||
});
|
||||
m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#ifndef IPCCLIENT_H
|
||||
#define IPCCLIENT_H
|
||||
|
||||
#include <QLocalSocket>
|
||||
#include <QObject>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "rep_ipcinterface_replica.h"
|
||||
|
||||
class IpcClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static IpcClient &Instance();
|
||||
static bool init();
|
||||
static QSharedPointer<IpcInterfaceReplica> Interface() { return Instance().m_ipcClient; }
|
||||
static QSharedPointer<IpcProcessInterfaceReplica> CreatePrivilegedProcess();
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
explicit IpcClient(QObject *parent = nullptr);
|
||||
|
||||
QRemoteObjectNode m_ClientNode;
|
||||
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
||||
QSharedPointer<QLocalSocket> m_localSocket;
|
||||
|
||||
struct ProcessDescriptor {
|
||||
ProcessDescriptor () {
|
||||
replicaNode = QSharedPointer<QRemoteObjectNode>(new QRemoteObjectNode());
|
||||
ipcProcess = QSharedPointer<IpcProcessInterfaceReplica>();
|
||||
localSocket = QSharedPointer<QLocalSocket>();
|
||||
}
|
||||
QSharedPointer<IpcProcessInterfaceReplica> ipcProcess;
|
||||
QSharedPointer<QRemoteObjectNode> replicaNode;
|
||||
QSharedPointer<QLocalSocket> localSocket;
|
||||
};
|
||||
|
||||
QMap<int, QSharedPointer<ProcessDescriptor>> m_processNodes;
|
||||
};
|
||||
|
||||
#endif // IPCCLIENT_H
|
||||
@@ -195,6 +195,12 @@ OpenVpnConfigurator::ConnectionData OpenVpnConfigurator::prepareOpenVpnConfig(co
|
||||
return connData;
|
||||
}
|
||||
|
||||
Settings &OpenVpnConfigurator::m_settings()
|
||||
{
|
||||
static Settings s;
|
||||
return s;
|
||||
}
|
||||
|
||||
QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentials,
|
||||
Protocol proto, ErrorCode *errorCode)
|
||||
{
|
||||
@@ -217,6 +223,13 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
||||
config.replace("$LOCAL_PROXY_PORT", QString::number(ServerController::ssContainerPort()));
|
||||
}
|
||||
|
||||
config.replace("$PRIMARY_DNS", m_settings().primaryDns());
|
||||
config.replace("$SECONDARY_DNS", m_settings().secondaryDns());
|
||||
|
||||
if (m_settings().customRouting()) {
|
||||
config.replace("redirect-gateway def1 bypass-dhcp", "");
|
||||
}
|
||||
|
||||
config.replace("$REMOTE_HOST", connData.host);
|
||||
config.replace("$REMOTE_PORT", "1194");
|
||||
config.replace("$CA_CERT", connData.caCert);
|
||||
@@ -224,5 +237,6 @@ QString OpenVpnConfigurator::genOpenVpnConfig(const ServerCredentials &credentia
|
||||
config.replace("$PRIV_KEY", connData.privKey);
|
||||
config.replace("$TA_KEY", connData.taKey);
|
||||
|
||||
//qDebug().noquote() << config;
|
||||
return config;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
#include "defs.h"
|
||||
#include "settings.h"
|
||||
#include "servercontroller.h"
|
||||
|
||||
|
||||
@@ -37,6 +38,8 @@ private:
|
||||
|
||||
static ConnectionData prepareOpenVpnConfig(const ServerCredentials &credentials,
|
||||
Protocol proto, ErrorCode *errorCode = nullptr);
|
||||
|
||||
static Settings &m_settings();
|
||||
};
|
||||
|
||||
#endif // OPENVPNCONFIGURATOR_H
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <QTimer>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QApplication>
|
||||
|
||||
#include "sshconnectionmanager.h"
|
||||
|
||||
@@ -23,7 +24,9 @@ QString ServerController::getContainerName(DockerContainer container)
|
||||
}
|
||||
|
||||
ErrorCode ServerController::runScript(DockerContainer container,
|
||||
const SshConnectionParameters &sshParams, QString script)
|
||||
const SshConnectionParameters &sshParams, QString script,
|
||||
const std::function<void(const QString &)> &cbReadStdOut,
|
||||
const std::function<void(const QString &)> &cbReadStdErr)
|
||||
{
|
||||
QLoggingCategory::setFilterRules(QStringLiteral("qtc.ssh=false"));
|
||||
|
||||
@@ -66,18 +69,20 @@ ErrorCode ServerController::runScript(DockerContainer container,
|
||||
wait.quit();
|
||||
});
|
||||
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, [proc](){
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardOutput, &wait, [proc, cbReadStdOut](){
|
||||
QString s = proc->readAllStandardOutput();
|
||||
if (s != "." && !s.isEmpty()) {
|
||||
qDebug().noquote() << s;
|
||||
qDebug().noquote() << "stdout" << s;
|
||||
}
|
||||
if (cbReadStdOut) cbReadStdOut(s);
|
||||
});
|
||||
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, [proc](){
|
||||
QObject::connect(proc.data(), &SshRemoteProcess::readyReadStandardError, &wait, [proc, cbReadStdErr](){
|
||||
QString s = proc->readAllStandardError();
|
||||
if (s != "." && !s.isEmpty()) {
|
||||
qDebug().noquote() << s;
|
||||
qDebug().noquote() << "stderr" << s;
|
||||
}
|
||||
if (cbReadStdErr) cbReadStdErr(s);
|
||||
});
|
||||
|
||||
proc->start();
|
||||
@@ -272,11 +277,12 @@ ErrorCode ServerController::removeServer(const ServerCredentials &credentials, P
|
||||
QString scriptFileName;
|
||||
DockerContainer container;
|
||||
|
||||
ErrorCode errorCode;
|
||||
if (proto == Protocol::Any) {
|
||||
removeServer(credentials, Protocol::OpenVpn);
|
||||
removeServer(credentials, Protocol::ShadowSocks);
|
||||
return ErrorCode::NoError;
|
||||
ErrorCode e = removeServer(credentials, Protocol::OpenVpn);
|
||||
if (e) {
|
||||
return e;
|
||||
}
|
||||
return removeServer(credentials, Protocol::ShadowSocks);
|
||||
}
|
||||
else if (proto == Protocol::OpenVpn) {
|
||||
scriptFileName = ":/server_scripts/remove_container.sh";
|
||||
@@ -309,14 +315,14 @@ ErrorCode ServerController::setupServer(const ServerCredentials &credentials, Pr
|
||||
return setupShadowSocksServer(credentials);
|
||||
}
|
||||
else if (proto == Protocol::Any) {
|
||||
return ErrorCode::NotImplementedError;
|
||||
//return ErrorCode::NotImplementedError;
|
||||
|
||||
// TODO: run concurently
|
||||
// return setupOpenVpnServer(credentials);
|
||||
//setupShadowSocksServer(credentials);
|
||||
setupOpenVpnServer(credentials);
|
||||
setupShadowSocksServer(credentials);
|
||||
}
|
||||
|
||||
return ErrorCode::NotImplementedError;
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credentials)
|
||||
@@ -329,8 +335,20 @@ ErrorCode ServerController::setupOpenVpnServer(const ServerCredentials &credenti
|
||||
scriptData = file.readAll();
|
||||
if (scriptData.isEmpty()) return ErrorCode::InternalError;
|
||||
|
||||
ErrorCode e = runScript(DockerContainer::OpenVpn, sshParams(credentials), scriptData);
|
||||
QString stdOut;
|
||||
auto cbReadStdOut = [&](const QString &data) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
auto cbReadStdErr = [&](const QString &data) {
|
||||
stdOut += data + "\n";
|
||||
};
|
||||
|
||||
ErrorCode e = runScript(DockerContainer::OpenVpn, sshParams(credentials), scriptData, cbReadStdOut, cbReadStdErr);
|
||||
if (e) return e;
|
||||
QApplication::processEvents();
|
||||
|
||||
if (stdOut.contains("port is already allocated")) return ErrorCode::ServerPortAlreadyAllocatedError;
|
||||
if (stdOut.contains("Error response from daemon")) return ErrorCode::ServerCheckFailed;
|
||||
|
||||
return checkOpenVpnServer(DockerContainer::OpenVpn, credentials);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,9 @@ public:
|
||||
private:
|
||||
static QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams);
|
||||
static ErrorCode runScript(DockerContainer container,
|
||||
const QSsh::SshConnectionParameters &sshParams, QString script);
|
||||
const QSsh::SshConnectionParameters &sshParams, QString script,
|
||||
const std::function<void(const QString &)> &cbReadStdOut = nullptr,
|
||||
const std::function<void(const QString &)> &cbReadStdErr = nullptr);
|
||||
|
||||
static ErrorCode setupOpenVpnServer(const ServerCredentials &credentials);
|
||||
static ErrorCode setupShadowSocksServer(const ServerCredentials &credentials);
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
#include <QDebug>
|
||||
#include <QtNetwork>
|
||||
|
||||
#include "localclient.h"
|
||||
|
||||
LocalClient::LocalClient(QObject *parent) : QObject(parent),
|
||||
m_socket(new QLocalSocket(this))
|
||||
{
|
||||
m_in.setDevice(m_socket);
|
||||
m_in.setVersion(QDataStream::Qt_5_10);
|
||||
|
||||
connect(m_socket, &QLocalSocket::readyRead, this, &LocalClient::onReadyRead);
|
||||
connect(m_socket, &QLocalSocket::connected, this, &LocalClient::onConnected);
|
||||
connect(m_socket, QOverload<QLocalSocket::LocalSocketError>::of(&QLocalSocket::error), this, &LocalClient::displayError);
|
||||
}
|
||||
|
||||
void LocalClient::connectToServer(const QString& name)
|
||||
{
|
||||
m_blockSize = 0;
|
||||
m_socket->abort();
|
||||
m_socket->connectToServer(name);
|
||||
}
|
||||
|
||||
QString LocalClient::serverName() const
|
||||
{
|
||||
return m_socket->serverName();
|
||||
}
|
||||
|
||||
void LocalClient::onConnected()
|
||||
{
|
||||
emit connected();
|
||||
}
|
||||
|
||||
bool LocalClient::connectedState() const
|
||||
{
|
||||
return (m_socket->state() == QLocalSocket::ConnectedState);
|
||||
}
|
||||
|
||||
quint64 LocalClient::write(const QByteArray& data)
|
||||
{
|
||||
return m_socket->write(data);
|
||||
}
|
||||
|
||||
void LocalClient::onReadyRead()
|
||||
{
|
||||
if (m_socket->canReadLine()) {
|
||||
char buf[1024];
|
||||
qint64 lineLength = m_socket->readLine(buf, sizeof(buf));
|
||||
if (lineLength != -1) {
|
||||
QString line = buf;
|
||||
line = line.simplified();
|
||||
qDebug().noquote() << QString("Read line: '%1'").arg(line);
|
||||
emit lineAvailable(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LocalClient::displayError(QLocalSocket::LocalSocketError socketError)
|
||||
{
|
||||
Q_UNUSED(socketError)
|
||||
qDebug().noquote() << QString("The following error occurred: %1.").arg(m_socket->errorString());
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef LOCALCLIENT_H
|
||||
#define LOCALCLIENT_H
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QLocalSocket>
|
||||
|
||||
class LocalClient : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LocalClient(QObject *parent = nullptr);
|
||||
|
||||
QString serverName() const;
|
||||
bool connectedState() const;
|
||||
quint64 write(const QByteArray& data);
|
||||
void connectToServer(const QString& name);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void lineAvailable(const QString& line);
|
||||
|
||||
private slots:
|
||||
void displayError(QLocalSocket::LocalSocketError socketError);
|
||||
void onConnected();
|
||||
void onReadyRead();
|
||||
|
||||
private:
|
||||
QLocalSocket* m_socket;
|
||||
QDataStream m_in;
|
||||
quint32 m_blockSize;
|
||||
};
|
||||
|
||||
#endif // LOCALCLIENT_H
|
||||
@@ -54,8 +54,7 @@ void ManagementServer::onNewConnection()
|
||||
|
||||
void ManagementServer::onSocketError(QAbstractSocket::SocketError socketError)
|
||||
{
|
||||
Q_UNUSED(socketError);
|
||||
|
||||
Q_UNUSED(socketError)
|
||||
qDebug().noquote() << QString("Mananement server error: %1").arg(m_socket->errorString());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
#include "message.h"
|
||||
|
||||
Message::Message(State state, const QStringList& args) :
|
||||
m_valid(true),
|
||||
m_state(state),
|
||||
m_args(args)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Message::isValid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
||||
|
||||
QString Message::textState() const
|
||||
{
|
||||
switch (m_state) {
|
||||
case State::Unknown: return "Unknown";
|
||||
case State::Initialize: return "Initialize";
|
||||
case State::StartRequest: return "StartRequest";
|
||||
case State::Started: return "Started";
|
||||
case State::FinishRequest: return "FinishRequest";
|
||||
case State::Finished: return "Finished";
|
||||
case State::RoutesAddRequest: return "RoutesAddRequest";
|
||||
case State::RouteDeleteRequest: return "RouteDeleteRequest";
|
||||
case State::ClearSavedRoutesRequest: return "ClearSavedRoutesRequest";
|
||||
case State::FlushDnsRequest: return "FlushDnsRequest";
|
||||
case State::InstallDriverRequest: return "InstallDriverRequest";
|
||||
default:
|
||||
;
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString Message::rawData() const
|
||||
{
|
||||
return m_rawData;
|
||||
}
|
||||
|
||||
Message::State Message::state() const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
QString Message::toString() const
|
||||
{
|
||||
if (!isValid()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return QString("%1%2%3")
|
||||
.arg(textState())
|
||||
.arg(m_dataSeparator)
|
||||
.arg(argsToString());
|
||||
}
|
||||
|
||||
QString Message::argAtIndex(int index) const
|
||||
{
|
||||
if ((index + 1) > args().size()) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return args().at(index);
|
||||
}
|
||||
|
||||
QStringList Message::args() const
|
||||
{
|
||||
return m_args;
|
||||
}
|
||||
|
||||
QString Message::argsToString() const
|
||||
{
|
||||
return m_args.join(m_argSeparator);
|
||||
}
|
||||
|
||||
Message::Message(const QString& data)
|
||||
{
|
||||
m_rawData = data;
|
||||
m_valid = false;
|
||||
if (data.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList dataList = data.split(m_dataSeparator);
|
||||
if ((dataList.size() != 2)) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool stateFound = false;
|
||||
for (int i = static_cast<int>(State::Unknown); i <= static_cast<int>(State::InstallDriverRequest); i++ ) {
|
||||
m_state = static_cast<State>(i);
|
||||
if (textState() == dataList.at(0)) {
|
||||
stateFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!stateFound) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_args = dataList.at(1).split(m_argSeparator);
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef MESSAGE_H
|
||||
#define MESSAGE_H
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
class Message {
|
||||
|
||||
public:
|
||||
enum class State {Unknown, Initialize, StartRequest, Started, FinishRequest, Finished,
|
||||
RoutesAddRequest, RouteDeleteRequest, ClearSavedRoutesRequest, FlushDnsRequest, InstallDriverRequest};
|
||||
Message(State state, const QStringList& args);
|
||||
Message(const QString& data);
|
||||
|
||||
QString argAtIndex(int index) const;
|
||||
QString argsToString() const;
|
||||
QString toString() const;
|
||||
QStringList args() const;
|
||||
State state() const;
|
||||
bool isValid() const;
|
||||
QString rawData() const;
|
||||
|
||||
protected:
|
||||
QString textState() const;
|
||||
|
||||
const QString m_argSeparator = ",";
|
||||
const QString m_dataSeparator = "|";
|
||||
|
||||
bool m_valid;
|
||||
State m_state;
|
||||
QStringList m_args;
|
||||
QString m_rawData;
|
||||
};
|
||||
|
||||
#endif // MESSAGE_H
|
||||
@@ -4,18 +4,15 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "communicator.h"
|
||||
//#include "communicator.h"
|
||||
#include "debug.h"
|
||||
#include "openvpnprotocol.h"
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QString& args, QObject* parent) :
|
||||
VpnProtocol(args, parent),
|
||||
m_requestFromUserToStop(false)
|
||||
OpenVpnProtocol::OpenVpnProtocol(const QJsonObject &configuration, QObject* parent) :
|
||||
VpnProtocol(configuration, parent)
|
||||
{
|
||||
setConfigFile(args);
|
||||
connect(m_communicator, &Communicator::messageReceived, this, &OpenVpnProtocol::onMessageReceived);
|
||||
readOpenVpnConfiguration(configuration);
|
||||
connect(&m_managementServer, &ManagementServer::readyRead, this, &OpenVpnProtocol::onReadyReadDataFromManagementServer);
|
||||
}
|
||||
|
||||
@@ -25,35 +22,14 @@ OpenVpnProtocol::~OpenVpnProtocol()
|
||||
OpenVpnProtocol::stop();
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::onMessageReceived(const Message& message)
|
||||
{
|
||||
if (!message.isValid()) {
|
||||
qWarning().noquote() << QString("Message received: '%1', but it is not valid").arg(message.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (message.state()) {
|
||||
case Message::State::Started:
|
||||
qDebug() << "OpenVPN process started";
|
||||
break;
|
||||
case Message::State::Finished:
|
||||
qDebug().noquote() << QString("OpenVPN process finished with status %1").arg(message.argAtIndex(1));
|
||||
onOpenVpnProcessFinished(message.argAtIndex(1).toInt());
|
||||
break;
|
||||
default:
|
||||
qDebug().noquote() << QString("Message received: '%1'").arg(message.toString());
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::stop()
|
||||
{
|
||||
// TODO: need refactoring
|
||||
// sendTermSignal() will evet return true while server connected
|
||||
// sendTermSignal() will even return true while server connected ???
|
||||
if ((m_connectionState == VpnProtocol::ConnectionState::Preparing) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Connecting) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Connected) ||
|
||||
(m_connectionState == VpnProtocol::ConnectionState::TunnelReconnecting)) {
|
||||
(m_connectionState == VpnProtocol::ConnectionState::Reconnecting)) {
|
||||
if (!sendTermSignal()) {
|
||||
killOpenVpnProcess();
|
||||
}
|
||||
@@ -61,27 +37,51 @@ void OpenVpnProtocol::stop()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::killOpenVpnProcess()
|
||||
ErrorCode OpenVpnProtocol::checkAndSetupTapDriver()
|
||||
{
|
||||
// send command to kill openvpn process (if any).
|
||||
if (!IpcClient::Interface()) {
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
QRemoteObjectPendingReply<QStringList> resultCheck = IpcClient::Interface()->getTapList();
|
||||
resultCheck.waitForFinished();
|
||||
|
||||
if (resultCheck.returnValue().isEmpty()){
|
||||
QRemoteObjectPendingReply<bool> resultInstall = IpcClient::Interface()->checkAndInstallDriver();
|
||||
resultInstall.waitForFinished();
|
||||
|
||||
if (!resultInstall.returnValue()) return ErrorCode::OpenVpnUnknownError;
|
||||
}
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::setConfigFile(const QString& configFileNamePath)
|
||||
void OpenVpnProtocol::killOpenVpnProcess()
|
||||
{
|
||||
m_configFileName = configFileNamePath;
|
||||
QFileInfo file(m_configFileName);
|
||||
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
if (m_openVpnProcess){
|
||||
m_openVpnProcess->close();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_configFileName.isEmpty()) {
|
||||
return false;
|
||||
void OpenVpnProtocol::readOpenVpnConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
if (configuration.contains(config::key_openvpn_config_data())) {
|
||||
m_configFile.open();
|
||||
m_configFile.write(configuration.value(config::key_openvpn_config_data()).toString().toUtf8());
|
||||
m_configFile.close();
|
||||
m_configFileName = m_configFile.fileName();
|
||||
|
||||
qDebug().noquote() << QString("Set config data") << m_configFileName;
|
||||
}
|
||||
else if (configuration.contains(config::key_openvpn_config_path())) {
|
||||
m_configFileName = configuration.value(config::key_openvpn_config_path()).toString();
|
||||
QFileInfo file(m_configFileName);
|
||||
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
if (file.fileName().isEmpty()) {
|
||||
m_configFileName = Utils::defaultVpnConfigFileName();
|
||||
}
|
||||
|
||||
return false;
|
||||
qDebug().noquote() << QString("Set config file: '%1'").arg(configPath());
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::openVpnProcessIsRunning() const
|
||||
@@ -99,7 +99,7 @@ QString OpenVpnProtocol::configPath() const
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::writeCommand(const QString& command)
|
||||
void OpenVpnProtocol::sendManagementCommand(const QString& command)
|
||||
{
|
||||
QIODevice *device = dynamic_cast<QIODevice*>(m_managementServer.socket().data());
|
||||
if (device) {
|
||||
@@ -128,17 +128,9 @@ QString OpenVpnProtocol::openVpnExecPath() const
|
||||
|
||||
ErrorCode OpenVpnProtocol::start()
|
||||
{
|
||||
qDebug() << "Start OpenVPN connection";
|
||||
|
||||
m_requestFromUserToStop = false;
|
||||
m_openVpnStateSigTermHandlerTimer.stop();
|
||||
//qDebug() << "Start OpenVPN connection";
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
if (communicator() && !communicator()->isConnected()) {
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
if (!QFileInfo::exists(openVpnExecPath())) {
|
||||
setLastError(ErrorCode::OpenVpnExecutableMissing);
|
||||
return lastError();
|
||||
@@ -152,39 +144,56 @@ ErrorCode OpenVpnProtocol::start()
|
||||
QString vpnLogFileNamePath = Utils::systemLogPath() + "/openvpn.log";
|
||||
Utils::createEmptyFile(vpnLogFileNamePath);
|
||||
|
||||
QStringList args({openVpnExecPath(),
|
||||
"--config" , configPath(),
|
||||
"--management", m_managementHost, QString::number(m_managementPort),
|
||||
"--management-client",
|
||||
"--log-append", vpnLogFileNamePath
|
||||
});
|
||||
|
||||
if (!m_managementServer.start(m_managementHost, m_managementPort)) {
|
||||
setLastError(ErrorCode::OpenVpnManagementServerError);
|
||||
return lastError();
|
||||
}
|
||||
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
m_communicator->sendMessage(Message(Message::State::StartRequest, args));
|
||||
startTimeoutTimer();
|
||||
|
||||
m_openVpnProcess = IpcClient::CreatePrivilegedProcess();
|
||||
|
||||
if (!m_openVpnProcess) {
|
||||
//qWarning() << "IpcProcess replica is not created!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
m_openVpnProcess->waitForSource(1000);
|
||||
if (!m_openVpnProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
m_openVpnProcess->setProgram(openVpnExecPath());
|
||||
QStringList arguments({"--config" , configPath(),
|
||||
"--management", m_managementHost, QString::number(m_managementPort),
|
||||
"--management-client",
|
||||
"--log-append", vpnLogFileNamePath
|
||||
});
|
||||
m_openVpnProcess->setArguments(arguments);
|
||||
|
||||
qDebug() << arguments.join(" ");
|
||||
connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::errorOccurred, [&](QProcess::ProcessError error) {
|
||||
qDebug() << "IpcProcessInterfaceReplica errorOccurred" << error;
|
||||
});
|
||||
|
||||
connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::stateChanged, [&](QProcess::ProcessState newState) {
|
||||
qDebug() << "IpcProcessInterfaceReplica stateChanged" << newState;
|
||||
});
|
||||
|
||||
connect(m_openVpnProcess.data(), &IpcProcessInterfaceReplica::finished, this, [&]() {
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
});
|
||||
|
||||
m_openVpnProcess->start();
|
||||
|
||||
//m_communicator->sendMessage(Message(Message::State::StartRequest, args));
|
||||
//startTimeoutTimer();
|
||||
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::openVpnStateSigTermHandlerTimerEvent()
|
||||
{
|
||||
bool processStatus = openVpnProcessIsRunning();
|
||||
if (processStatus) {
|
||||
killOpenVpnProcess();
|
||||
}
|
||||
onOpenVpnProcessFinished(0);
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::openVpnStateSigTermHandler()
|
||||
{
|
||||
m_openVpnStateSigTermHandlerTimer.start(5000);
|
||||
}
|
||||
|
||||
bool OpenVpnProtocol::sendTermSignal()
|
||||
{
|
||||
return m_managementServer.writeCommand("signal SIGTERM");
|
||||
@@ -224,10 +233,11 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
||||
setConnectionState(VpnProtocol::ConnectionState::Connected);
|
||||
continue;
|
||||
} else if (line.contains("EXITING,SIGTER")) {
|
||||
openVpnStateSigTermHandler();
|
||||
//openVpnStateSigTermHandler();
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnecting);
|
||||
continue;
|
||||
} else if (line.contains("RECONNECTING")) {
|
||||
setConnectionState(VpnProtocol::ConnectionState::TunnelReconnecting);
|
||||
setConnectionState(VpnProtocol::ConnectionState::Reconnecting);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -262,19 +272,6 @@ void OpenVpnProtocol::onReadyReadDataFromManagementServer()
|
||||
}
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::onOpenVpnProcessFinished(int exitCode)
|
||||
{
|
||||
m_openVpnStateSigTermHandlerTimer.stop();
|
||||
if (m_connectionState == VpnProtocol::ConnectionState::Disconnected) {
|
||||
qDebug() << "Already in disconnected state";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug().noquote() << QString("Process finished with code: %1").arg(exitCode);
|
||||
|
||||
setConnectionState(VpnProtocol::ConnectionState::Disconnected);
|
||||
}
|
||||
|
||||
void OpenVpnProtocol::updateVpnGateway()
|
||||
{
|
||||
QProcess ipconfig;
|
||||
|
||||
@@ -6,51 +6,50 @@
|
||||
#include <QTimer>
|
||||
|
||||
#include "managementserver.h"
|
||||
#include "message.h"
|
||||
#include "vpnprotocol.h"
|
||||
|
||||
#include "core/ipcclient.h"
|
||||
|
||||
class OpenVpnProtocol : public VpnProtocol
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OpenVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
explicit OpenVpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~OpenVpnProtocol() override;
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
ErrorCode checkAndSetupTapDriver();
|
||||
|
||||
protected slots:
|
||||
void onMessageReceived(const Message& message);
|
||||
void onOpenVpnProcessFinished(int exitCode);
|
||||
void onReadyReadDataFromManagementServer();
|
||||
|
||||
protected:
|
||||
private:
|
||||
QString configPath() const;
|
||||
QString openVpnExecPath() const;
|
||||
bool openVpnProcessIsRunning() const;
|
||||
bool sendTermSignal();
|
||||
bool setConfigFile(const QString& configFileNamePath);
|
||||
void readOpenVpnConfiguration(const QJsonObject &configuration);
|
||||
void disconnectFromManagementServer();
|
||||
void killOpenVpnProcess();
|
||||
void openVpnStateSigTermHandler();
|
||||
void openVpnStateSigTermHandlerTimerEvent();
|
||||
void sendByteCount();
|
||||
void sendInitialData();
|
||||
void writeCommand(const QString& command);
|
||||
void sendManagementCommand(const QString& command);
|
||||
|
||||
const QString m_managementHost = "127.0.0.1";
|
||||
const unsigned int m_managementPort = 57775;
|
||||
|
||||
ManagementServer m_managementServer;
|
||||
QString m_configFileName;
|
||||
QTimer m_openVpnStateSigTermHandlerTimer;
|
||||
bool m_requestFromUserToStop;
|
||||
|
||||
QTemporaryFile m_configFile;
|
||||
|
||||
private:
|
||||
void updateRouteGateway(QString line);
|
||||
void updateVpnGateway();
|
||||
|
||||
QSharedPointer<IpcProcessInterfaceReplica> m_openVpnProcess;
|
||||
};
|
||||
|
||||
#endif // OPENVPNPROTOCOL_H
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
#include "shadowsocksvpnprotocol.h"
|
||||
#include "core/servercontroller.h"
|
||||
|
||||
#include "communicator.h"
|
||||
//#include "communicator.h"
|
||||
#include "debug.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QString &args, QObject *parent):
|
||||
OpenVpnProtocol(args, parent)
|
||||
ShadowSocksVpnProtocol::ShadowSocksVpnProtocol(const QJsonObject &configuration, QObject *parent):
|
||||
OpenVpnProtocol(configuration, parent)
|
||||
{
|
||||
m_shadowSocksConfig = args;
|
||||
readShadowSocksConfiguration(configuration);
|
||||
}
|
||||
|
||||
ErrorCode ShadowSocksVpnProtocol::start()
|
||||
{
|
||||
qDebug() << "ShadowSocksVpnProtocol::start()";
|
||||
QJsonObject config = QJsonDocument::fromJson(m_shadowSocksConfig.toUtf8()).object();
|
||||
|
||||
ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
m_ssProcess.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
ssProcess.setProgram(shadowSocksExecPath());
|
||||
ssProcess.setArguments(QStringList() << "-s" << config.value("server").toString()
|
||||
<< "-p" << QString::number(config.value("server_port").toInt())
|
||||
<< "-l" << QString::number(config.value("local_port").toInt())
|
||||
<< "-m" << config.value("method").toString()
|
||||
<< "-k" << config.value("password").toString()
|
||||
m_ssProcess.setProgram(shadowSocksExecPath());
|
||||
m_ssProcess.setArguments(QStringList() << "-s" << m_shadowSocksConfig.value("server").toString()
|
||||
<< "-p" << QString::number(m_shadowSocksConfig.value("server_port").toInt())
|
||||
<< "-l" << QString::number(m_shadowSocksConfig.value("local_port").toInt())
|
||||
<< "-m" << m_shadowSocksConfig.value("method").toString()
|
||||
<< "-k" << m_shadowSocksConfig.value("password").toString()
|
||||
);
|
||||
|
||||
ssProcess.start();
|
||||
ssProcess.waitForStarted();
|
||||
connect(&m_ssProcess, &QProcess::readyRead, this, [this](){
|
||||
qDebug().noquote() << m_ssProcess.readAll();
|
||||
});
|
||||
|
||||
if (ssProcess.state() == QProcess::ProcessState::Running) {
|
||||
m_ssProcess.start();
|
||||
m_ssProcess.waitForStarted();
|
||||
|
||||
if (m_ssProcess.state() == QProcess::ProcessState::Running) {
|
||||
setConnectionState(ConnectionState::Connecting);
|
||||
|
||||
return OpenVpnProtocol::start();
|
||||
@@ -42,8 +45,10 @@ ErrorCode ShadowSocksVpnProtocol::start()
|
||||
|
||||
void ShadowSocksVpnProtocol::stop()
|
||||
{
|
||||
OpenVpnProtocol::stop();
|
||||
|
||||
qDebug() << "ShadowSocksVpnProtocol::stop()";
|
||||
ssProcess.kill();
|
||||
m_ssProcess.close();
|
||||
}
|
||||
|
||||
QString ShadowSocksVpnProtocol::shadowSocksExecPath() const
|
||||
@@ -55,7 +60,7 @@ QString ShadowSocksVpnProtocol::shadowSocksExecPath() const
|
||||
#endif
|
||||
}
|
||||
|
||||
QString ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto)
|
||||
QJsonObject ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto)
|
||||
{
|
||||
QJsonObject ssConfig;
|
||||
ssConfig.insert("server", credentials.hostName);
|
||||
@@ -64,5 +69,10 @@ QString ShadowSocksVpnProtocol::genShadowSocksConfig(const ServerCredentials &cr
|
||||
ssConfig.insert("password", credentials.password);
|
||||
ssConfig.insert("timeout", 60);
|
||||
ssConfig.insert("method", ServerController::ssEncryption());
|
||||
return QJsonDocument(ssConfig).toJson();
|
||||
return ssConfig;
|
||||
}
|
||||
|
||||
void ShadowSocksVpnProtocol::readShadowSocksConfiguration(const QJsonObject &configuration)
|
||||
{
|
||||
m_shadowSocksConfig = configuration.value(config::key_shadowsocks_config_data()).toObject();
|
||||
}
|
||||
|
||||
@@ -7,21 +7,22 @@
|
||||
class ShadowSocksVpnProtocol : public OpenVpnProtocol
|
||||
{
|
||||
public:
|
||||
ShadowSocksVpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
ShadowSocksVpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
|
||||
ErrorCode start() override;
|
||||
void stop() override;
|
||||
|
||||
static QString genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto = Protocol::ShadowSocks);
|
||||
static QJsonObject genShadowSocksConfig(const ServerCredentials &credentials, Protocol proto = Protocol::ShadowSocks);
|
||||
|
||||
protected:
|
||||
void readShadowSocksConfiguration(const QJsonObject &configuration);
|
||||
QString shadowSocksExecPath() const;
|
||||
|
||||
protected:
|
||||
QString m_shadowSocksConfig;
|
||||
QJsonObject m_shadowSocksConfig;
|
||||
|
||||
private:
|
||||
QProcess ssProcess;
|
||||
QProcess m_ssProcess;
|
||||
};
|
||||
|
||||
#endif // SHADOWSOCKSVPNPROTOCOL_H
|
||||
|
||||
@@ -1,42 +1,26 @@
|
||||
#include <QDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "communicator.h"
|
||||
#include "vpnprotocol.h"
|
||||
#include "core/errorstrings.h"
|
||||
|
||||
Communicator* VpnProtocol::m_communicator = nullptr;
|
||||
|
||||
VpnProtocol::VpnProtocol(const QString& args, QObject* parent)
|
||||
VpnProtocol::VpnProtocol(const QJsonObject &configuration, QObject* parent)
|
||||
: QObject(parent),
|
||||
m_connectionState(ConnectionState::Unknown),
|
||||
m_rawConfig(configuration),
|
||||
m_timeoutTimer(new QTimer(this)),
|
||||
m_receivedBytes(0),
|
||||
m_sentBytes(0)
|
||||
{
|
||||
m_timeoutTimer->setSingleShot(true);
|
||||
connect(m_timeoutTimer, &QTimer::timeout, this, &VpnProtocol::onTimeout);
|
||||
|
||||
Q_UNUSED(args)
|
||||
}
|
||||
|
||||
void VpnProtocol::initializeCommunicator(QObject* parent)
|
||||
{
|
||||
if (!m_communicator) {
|
||||
m_communicator = new Communicator(parent);
|
||||
}
|
||||
}
|
||||
|
||||
Communicator* VpnProtocol::communicator()
|
||||
{
|
||||
return m_communicator;
|
||||
}
|
||||
|
||||
void VpnProtocol::setLastError(ErrorCode lastError)
|
||||
{
|
||||
m_lastError = lastError;
|
||||
if (lastError){
|
||||
setConnectionState(ConnectionState::Disconnected);
|
||||
setConnectionState(ConnectionState::Error);
|
||||
}
|
||||
qCritical().noquote() << "VpnProtocol error, code" << m_lastError << errorString(m_lastError);
|
||||
}
|
||||
@@ -79,9 +63,14 @@ void VpnProtocol::setBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
||||
|
||||
void VpnProtocol::setConnectionState(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
qDebug() << "VpnProtocol::setConnectionState" << textConnectionState(state);
|
||||
|
||||
if (m_connectionState == state) {
|
||||
return;
|
||||
}
|
||||
if (m_connectionState == ConnectionState::Disconnected && state == ConnectionState::Disconnecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_connectionState = state;
|
||||
if (m_connectionState == ConnectionState::Disconnected) {
|
||||
@@ -113,7 +102,7 @@ QString VpnProtocol::textConnectionState(ConnectionState connectionState)
|
||||
case ConnectionState::Connecting: return tr("Connecting...");
|
||||
case ConnectionState::Connected: return tr("Connected");
|
||||
case ConnectionState::Disconnecting: return tr("Disconnecting...");
|
||||
case ConnectionState::TunnelReconnecting: return tr("Reconnecting...");
|
||||
case ConnectionState::Reconnecting: return tr("Reconnecting...");
|
||||
case ConnectionState::Error: return tr("Error");
|
||||
default:
|
||||
;
|
||||
@@ -127,12 +116,12 @@ QString VpnProtocol::textConnectionState() const
|
||||
return textConnectionState(m_connectionState);
|
||||
}
|
||||
|
||||
bool VpnProtocol::onConnected() const
|
||||
bool VpnProtocol::isConnected() const
|
||||
{
|
||||
return m_connectionState == ConnectionState::Connected;
|
||||
}
|
||||
|
||||
bool VpnProtocol::onDisconnected() const
|
||||
bool VpnProtocol::isDisconnected() const
|
||||
{
|
||||
return m_connectionState == ConnectionState::Disconnected;
|
||||
}
|
||||
|
||||
@@ -3,30 +3,29 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "core/defs.h"
|
||||
using namespace amnezia;
|
||||
|
||||
class QTimer;
|
||||
class Communicator;
|
||||
|
||||
class VpnProtocol : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit VpnProtocol(const QString& args = QString(), QObject* parent = nullptr);
|
||||
explicit VpnProtocol(const QJsonObject& configuration, QObject* parent = nullptr);
|
||||
virtual ~VpnProtocol() override = default;
|
||||
|
||||
enum class ConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, TunnelReconnecting, Error};
|
||||
enum ConnectionState {Unknown, Disconnected, Preparing, Connecting, Connected, Disconnecting, Reconnecting, Error};
|
||||
Q_ENUM(ConnectionState)
|
||||
|
||||
static Communicator* communicator();
|
||||
static QString textConnectionState(ConnectionState connectionState);
|
||||
static void initializeCommunicator(QObject* parent = nullptr);
|
||||
|
||||
|
||||
virtual bool onConnected() const;
|
||||
virtual bool onDisconnected() const;
|
||||
virtual bool isConnected() const;
|
||||
virtual bool isDisconnected() const;
|
||||
virtual ErrorCode start() = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
@@ -54,18 +53,17 @@ protected:
|
||||
virtual void setBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
virtual void setConnectionState(VpnProtocol::ConnectionState state);
|
||||
|
||||
static Communicator* m_communicator;
|
||||
|
||||
ConnectionState m_connectionState;
|
||||
QString m_routeGateway;
|
||||
QString m_vpnGateway;
|
||||
|
||||
QJsonObject m_rawConfig;
|
||||
|
||||
private:
|
||||
QTimer* m_timeoutTimer;
|
||||
ErrorCode m_lastError;
|
||||
quint64 m_receivedBytes;
|
||||
quint64 m_sentBytes;
|
||||
|
||||
};
|
||||
|
||||
#endif // VPNPROTOCOL_H
|
||||
|
||||
@@ -12,6 +12,11 @@ tls-client
|
||||
tls-version-min 1.2
|
||||
key-direction 1
|
||||
remote-cert-tls server
|
||||
redirect-gateway def1 bypass-dhcp
|
||||
|
||||
dhcp-option DNS $PRIMARY_DNS
|
||||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
remote $REMOTE_HOST $REMOTE_PORT
|
||||
|
||||
|
||||
@@ -12,6 +12,11 @@ tls-client
|
||||
tls-version-min 1.2
|
||||
key-direction 1
|
||||
remote-cert-tls server
|
||||
redirect-gateway def1 bypass-dhcp
|
||||
|
||||
dhcp-option DNS $PRIMARY_DNS
|
||||
dhcp-option DNS $SECONDARY_DNS
|
||||
block-outside-dns
|
||||
|
||||
socks-proxy 127.0.0.1 $LOCAL_PROXY_PORT
|
||||
route $REMOTE_HOST 255.255.255.255 net_gateway
|
||||
|
||||
@@ -6,27 +6,6 @@ Settings::Settings(QObject* parent) :
|
||||
QObject(parent),
|
||||
m_settings (ORGANIZATION_NAME, APPLICATION_NAME, this)
|
||||
{
|
||||
read();
|
||||
}
|
||||
|
||||
void Settings::read()
|
||||
{
|
||||
m_settings.beginGroup("Server");
|
||||
m_userName = m_settings.value("userName", QString()).toString();
|
||||
m_password = m_settings.value("password", QString()).toString();
|
||||
m_serverName = m_settings.value("serverName", QString()).toString();
|
||||
m_serverPort = m_settings.value("serverPort", 22).toInt();
|
||||
m_settings.endGroup();
|
||||
}
|
||||
|
||||
void Settings::save()
|
||||
{
|
||||
m_settings.beginGroup("Server");
|
||||
m_settings.setValue("userName", m_userName);
|
||||
m_settings.setValue("password", m_password);
|
||||
m_settings.setValue("serverName", m_serverName);
|
||||
m_settings.setValue("serverPort", m_serverPort);
|
||||
m_settings.endGroup();
|
||||
}
|
||||
|
||||
bool Settings::haveAuthData() const
|
||||
@@ -34,26 +13,6 @@ bool Settings::haveAuthData() const
|
||||
return (!serverName().isEmpty() && !userName().isEmpty() && !password().isEmpty());
|
||||
}
|
||||
|
||||
void Settings::setUserName(const QString& login)
|
||||
{
|
||||
m_userName = login;
|
||||
}
|
||||
|
||||
void Settings::setPassword(const QString& password)
|
||||
{
|
||||
m_password = password;
|
||||
}
|
||||
|
||||
void Settings::setServerName(const QString& serverName)
|
||||
{
|
||||
m_serverName = serverName;
|
||||
}
|
||||
|
||||
void Settings::setServerPort(int serverPort)
|
||||
{
|
||||
m_serverPort = serverPort;
|
||||
}
|
||||
|
||||
void Settings::setServerCredentials(const ServerCredentials &credentials)
|
||||
{
|
||||
setServerName(credentials.hostName);
|
||||
|
||||
+32
-22
@@ -18,40 +18,50 @@ class Settings : public QObject
|
||||
public:
|
||||
explicit Settings(QObject* parent = nullptr);
|
||||
|
||||
void read();
|
||||
void save();
|
||||
QString userName() const { return m_settings.value("Server/userName", QString()).toString(); }
|
||||
void setUserName(const QString& login) { m_settings.setValue("Server/userName", login); }
|
||||
|
||||
void setUserName(const QString& login);
|
||||
void setPassword(const QString& password);
|
||||
void setServerName(const QString& serverName);
|
||||
void setServerPort(int serverPort = 22);
|
||||
void setServerCredentials(const ServerCredentials &credentials);
|
||||
QString password() const { return m_settings.value("Server/password", QString()).toString(); }
|
||||
void setPassword(const QString& password) { m_settings.setValue("Server/password", password); }
|
||||
|
||||
QString serverName() const { return m_settings.value("Server/serverName", QString()).toString(); }
|
||||
void setServerName(const QString& serverName) { m_settings.setValue("Server/serverName", serverName); }
|
||||
|
||||
int serverPort() const { return m_settings.value("Server/serverPort", 22).toInt(); }
|
||||
void setServerPort(int serverPort = 22) { m_settings.setValue("Server/serverPort", serverPort); }
|
||||
|
||||
QString userName() const { return m_userName; }
|
||||
QString password() const { return m_password; }
|
||||
QString serverName() const { return m_serverName; }
|
||||
int serverPort() const { return m_serverPort; }
|
||||
ServerCredentials serverCredentials();
|
||||
|
||||
|
||||
void setServerCredentials(const ServerCredentials &credentials);
|
||||
bool haveAuthData() const;
|
||||
|
||||
bool customRouting() const { return m_settings.value("Conf/customRouting", false).toBool(); }
|
||||
void setCustomRouting(bool customRouting) { m_settings.setValue("Conf/customRouting", customRouting); }
|
||||
|
||||
// list of sites to pass blocking added by user
|
||||
QStringList customSites() { return m_settings.value("customSites").toStringList(); }
|
||||
void setCustomSites(const QStringList &customSites) { m_settings.setValue("customSites", customSites); }
|
||||
QStringList customSites() { return m_settings.value("Conf/customSites").toStringList(); }
|
||||
void setCustomSites(const QStringList &customSites) { m_settings.setValue("Conf/customSites", customSites); }
|
||||
|
||||
// list of ips to pass blocking generated from customSites
|
||||
QStringList customIps() { return m_settings.value("customIps").toStringList(); }
|
||||
void setCustomIps(const QStringList &customIps) { m_settings.setValue("customIps", customIps); }
|
||||
QStringList customIps() { return m_settings.value("Conf/customIps").toStringList(); }
|
||||
void setCustomIps(const QStringList &customIps) { m_settings.setValue("Conf/customIps", customIps); }
|
||||
|
||||
QString primaryDns() const { return m_settings.value("Conf/primaryDns", cloudFlareNs1()).toString(); }
|
||||
QString secondaryDns() const { return m_settings.value("Conf/secondaryDns", cloudFlareNs2()).toString(); }
|
||||
|
||||
protected:
|
||||
//QString primaryDns() const { return m_primaryDns; }
|
||||
void setPrimaryDns(const QString &primaryDns) { m_settings.setValue("Conf/primaryDns", primaryDns); }
|
||||
|
||||
//QString secondaryDns() const { return m_secondaryDns; }
|
||||
void setSecondaryDns(const QString &secondaryDns) { m_settings.setValue("Conf/secondaryDns", secondaryDns); }
|
||||
|
||||
QString cloudFlareNs1() const { return "1.1.1.1"; }
|
||||
QString cloudFlareNs2() const { return "1.0.0.1"; }
|
||||
|
||||
QString openNicNs5() const { return "94.103.153.176"; }
|
||||
QString openNicNs13() const { return "144.76.103.143"; }
|
||||
|
||||
private:
|
||||
QSettings m_settings;
|
||||
QString m_userName;
|
||||
QString m_password;
|
||||
QString m_serverName;
|
||||
int m_serverPort;
|
||||
};
|
||||
|
||||
#endif // SETTINGS_H
|
||||
|
||||
+41
-24
@@ -11,7 +11,7 @@
|
||||
#include <QThread>
|
||||
#include <QTimer>
|
||||
|
||||
#include "communicator.h"
|
||||
//#include "communicator.h"
|
||||
|
||||
#include "core/errorstrings.h"
|
||||
#include "core/openvpnconfigurator.h"
|
||||
@@ -71,9 +71,9 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->pushButton_sites_add_custom->click();
|
||||
});
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
ui->pushButton_general_settings_exit->hide();
|
||||
//ui->pushButton_general_settings_exit->hide();
|
||||
//ui->pushButton_share_connection->hide();
|
||||
|
||||
setFixedSize(width(),height());
|
||||
@@ -101,7 +101,7 @@ MainWindow::~MainWindow()
|
||||
for (int i = 0; i < 50; i++) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
QThread::msleep(100);
|
||||
if (m_vpnConnection->onDisconnected()) {
|
||||
if (m_vpnConnection->isDisconnected()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -249,7 +249,6 @@ void MainWindow::onPushButtonNewServerConnectWithNewData(bool)
|
||||
|
||||
if (ok) {
|
||||
m_settings.setServerCredentials(serverCredentials);
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Vpn);
|
||||
qApp->processEvents();
|
||||
@@ -272,7 +271,6 @@ void MainWindow::onPushButtonNewServerConnectWithExistingCode(bool)
|
||||
credentials.password = o.value("w").toString();
|
||||
|
||||
m_settings.setServerCredentials(credentials);
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Vpn);
|
||||
qDebug() << QString("Added server %3@%1:%2").
|
||||
@@ -299,7 +297,7 @@ bool MainWindow::installServer(ServerCredentials credentials,
|
||||
timer.start(1000);
|
||||
|
||||
|
||||
ErrorCode e = ServerController::setupServer(credentials, Protocol::OpenVpn);
|
||||
ErrorCode e = ServerController::setupServer(credentials, Protocol::Any);
|
||||
if (e) {
|
||||
page->setEnabled(true);
|
||||
button->setVisible(true);
|
||||
@@ -377,14 +375,11 @@ void MainWindow::onPushButtonForgetServer(bool)
|
||||
m_settings.setServerName("");
|
||||
m_settings.setServerPort();
|
||||
|
||||
m_settings.save();
|
||||
|
||||
goToPage(Page::Start);
|
||||
}
|
||||
|
||||
void MainWindow::onBytesChanged(quint64 receivedData, quint64 sentData)
|
||||
{
|
||||
qDebug() << "MainWindow::onBytesChanged" << receivedData << sentData;
|
||||
ui->label_speed_received->setText(VpnConnection::bytesPerSecToText(receivedData));
|
||||
ui->label_speed_sent->setText(VpnConnection::bytesPerSecToText(sentData));
|
||||
}
|
||||
@@ -394,6 +389,7 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
qDebug() << "MainWindow::onConnectionStateChanged" << VpnProtocol::textConnectionState(state);
|
||||
|
||||
bool pushButtonConnectEnabled = false;
|
||||
bool radioButtonsModeEnabled = false;
|
||||
ui->label_state->setText(VpnProtocol::textConnectionState(state));
|
||||
|
||||
setTrayState(state);
|
||||
@@ -403,32 +399,41 @@ void MainWindow::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
onBytesChanged(0,0);
|
||||
ui->pushButton_connect->setChecked(false);
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Preparing:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Connecting:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Connected:
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Disconnecting:
|
||||
pushButtonConnectEnabled = false;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::TunnelReconnecting:
|
||||
case VpnProtocol::ConnectionState::Reconnecting:
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = false;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Error:
|
||||
ui->pushButton_connect->setChecked(false);
|
||||
pushButtonConnectEnabled = true;
|
||||
radioButtonsModeEnabled = true;
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Unknown:
|
||||
default:
|
||||
pushButtonConnectEnabled = true;
|
||||
;
|
||||
radioButtonsModeEnabled = true;
|
||||
}
|
||||
|
||||
ui->pushButton_connect->setEnabled(pushButtonConnectEnabled);
|
||||
ui->radioButton_mode_all_sites->setEnabled(radioButtonsModeEnabled);
|
||||
ui->radioButton_mode_selected_sites->setEnabled(radioButtonsModeEnabled);
|
||||
}
|
||||
|
||||
void MainWindow::onVpnProtocolError(ErrorCode errorCode)
|
||||
@@ -519,7 +524,7 @@ void MainWindow::setupUiConnections()
|
||||
connect(ui->pushButton_server_settings_clear, SIGNAL(clicked(bool)), this, SLOT(onPushButtonClearServer(bool)));
|
||||
connect(ui->pushButton_server_settings_forget, SIGNAL(clicked(bool)), this, SLOT(onPushButtonForgetServer(bool)));
|
||||
|
||||
connect(ui->pushButton_blocked_list, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); });
|
||||
connect(ui->pushButton_vpn_add_site, &QPushButton::clicked, this, [this](){ goToPage(Page::Sites); });
|
||||
connect(ui->pushButton_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::GeneralSettings); });
|
||||
connect(ui->pushButton_server_settings, &QPushButton::clicked, this, [this](){ goToPage(Page::ServerSettings); });
|
||||
connect(ui->pushButton_share_connection, &QPushButton::clicked, this, [this](){
|
||||
@@ -545,6 +550,12 @@ void MainWindow::setupUiConnections()
|
||||
|
||||
connect(ui->pushButton_sites_add_custom, &QPushButton::clicked, this, [this](){ onPushButtonAddCustomSitesClicked(); });
|
||||
connect(ui->pushButton_sites_delete_custom, &QPushButton::clicked, this, [this](){ onPushButtonDeleteCustomSiteClicked(); });
|
||||
|
||||
connect(ui->radioButton_mode_selected_sites, &QRadioButton::toggled, ui->pushButton_vpn_add_site, &QPushButton::setEnabled);
|
||||
|
||||
connect(ui->radioButton_mode_selected_sites, &QRadioButton::toggled, this, [this](bool toggled) {
|
||||
m_settings.setCustomRouting(toggled);
|
||||
});
|
||||
}
|
||||
|
||||
void MainWindow::setTrayState(VpnProtocol::ConnectionState state)
|
||||
@@ -570,7 +581,7 @@ void MainWindow::setTrayState(VpnProtocol::ConnectionState state)
|
||||
case VpnProtocol::ConnectionState::Disconnecting:
|
||||
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::TunnelReconnecting:
|
||||
case VpnProtocol::ConnectionState::Reconnecting:
|
||||
setTrayIcon(QString(resourcesPath).arg(DisconnectedTrayIconName));
|
||||
break;
|
||||
case VpnProtocol::ConnectionState::Error:
|
||||
@@ -663,13 +674,13 @@ void MainWindow::onPushButtonAddCustomSitesClicked()
|
||||
customIps.append(newIp);
|
||||
m_settings.setCustomIps(customIps);
|
||||
|
||||
// add to routes immediatelly
|
||||
// if (vpnStatus() == VPNStatusConnected) {
|
||||
// //Router::Instance().routeAdd(newIp, vpnGate());
|
||||
// }
|
||||
if (m_vpnConnection->connectionState() == VpnProtocol::ConnectionState::Connected) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnConnection->vpnProtocol()->vpnGateway(),
|
||||
QStringList() << newIp);
|
||||
}
|
||||
}
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
ui->lineEdit_sites_add_custom->clear();
|
||||
}
|
||||
@@ -700,15 +711,19 @@ void MainWindow::onPushButtonDeleteCustomSiteClicked()
|
||||
m_settings.setCustomIps(customIps);
|
||||
|
||||
|
||||
initCustomSites();
|
||||
updateSettings();
|
||||
|
||||
//Router::Instance().routeDelete(Utils::getIPAddress(ipToDelete));
|
||||
//Router::Instance().flushDns();
|
||||
if (m_vpnConnection->connectionState() == VpnProtocol::ConnectionState::Connected) {
|
||||
IpcClient::Interface()->routeDelete(ipToDelete);
|
||||
IpcClient::Interface()->flushDns();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::initCustomSites()
|
||||
void MainWindow::updateSettings()
|
||||
{
|
||||
customSitesModel->setStringList(m_settings.customSites());
|
||||
ui->radioButton_mode_selected_sites->setChecked(m_settings.customRouting());
|
||||
ui->pushButton_vpn_add_site->setEnabled(m_settings.customRouting());
|
||||
}
|
||||
|
||||
void MainWindow::updateShareCode()
|
||||
@@ -721,4 +736,6 @@ void MainWindow::updateShareCode()
|
||||
|
||||
QByteArray ba = QJsonDocument(o).toJson().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
ui->textEdit_sharing_code->setText(QString("vpn://%1").arg(QString(ba)));
|
||||
|
||||
//qDebug() << "Share code" << QJsonDocument(o).toJson();
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ private:
|
||||
void setTrayIcon(const QString &iconPath);
|
||||
|
||||
void setupUiConnections();
|
||||
void initCustomSites();
|
||||
void updateSettings();
|
||||
|
||||
void updateShareCode();
|
||||
|
||||
|
||||
+12
-49
@@ -259,7 +259,7 @@ QPushButton:hover {
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>2</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page_start">
|
||||
<widget class="QLabel" name="label_23">
|
||||
@@ -315,32 +315,6 @@ color: #333333;</string>
|
||||
<string>Connection code</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QProgressBar" name="progressBar_new_server_connection_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>40</x>
|
||||
<y>220</y>
|
||||
<width>301</width>
|
||||
<height>41</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background: #181922;
|
||||
border-radius: 4px;</string>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="format">
|
||||
<string>Connecting...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -944,7 +918,10 @@ font: 16px "Lato"; </string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="pushButton_blocked_list">
|
||||
<widget class="QPushButton" name="pushButton_vpn_add_site">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>20</x>
|
||||
@@ -972,7 +949,10 @@ font-size: 16px;
|
||||
line-height: 21px;
|
||||
|
||||
}
|
||||
</string>
|
||||
|
||||
QPushButton:!enabled {
|
||||
background: #484952;
|
||||
}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>+ Add site</string>
|
||||
@@ -1099,7 +1079,7 @@ color: #181922;
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="radioButton_mode_all_sites">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -1116,9 +1096,9 @@ color: #181922;
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="radioButton_mode_include_selected_sites">
|
||||
<widget class="QRadioButton" name="radioButton_mode_selected_sites">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
@@ -1157,23 +1137,6 @@ color: #181922;
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_19">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>460</y>
|
||||
<width>361</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">image: url(:/images/AmneziaVPN.png);
|
||||
background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_sites">
|
||||
<property name="styleSheet">
|
||||
|
||||
+73
-44
@@ -1,19 +1,31 @@
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <core/openvpnconfigurator.h>
|
||||
#include <core/servercontroller.h>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "core/ipcclient.h"
|
||||
#include "protocols/openvpnprotocol.h"
|
||||
#include "protocols/shadowsocksvpnprotocol.h"
|
||||
#include "utils.h"
|
||||
#include "vpnconnection.h"
|
||||
#include "communicator.h"
|
||||
|
||||
VpnConnection::VpnConnection(QObject* parent) : QObject(parent)
|
||||
{
|
||||
VpnProtocol::initializeCommunicator(parent);
|
||||
QTimer::singleShot(0, this, [this](){
|
||||
if (!IpcClient::init()) {
|
||||
qWarning() << "Error occured when init IPC client";
|
||||
emit serviceIsNotReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
VpnConnection::~VpnConnection()
|
||||
{
|
||||
m_vpnProtocol.clear();
|
||||
}
|
||||
|
||||
void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
||||
@@ -23,28 +35,37 @@ void VpnConnection::onBytesChanged(quint64 receivedBytes, quint64 sentBytes)
|
||||
|
||||
void VpnConnection::onConnectionStateChanged(VpnProtocol::ConnectionState state)
|
||||
{
|
||||
// if (state == VpnProtocol::ConnectionState::Connected){
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::FlushDnsRequest, QStringList()));
|
||||
if (IpcClient::Interface()) {
|
||||
if (state == VpnProtocol::ConnectionState::Connected && IpcClient::Interface()){
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
// // add routes
|
||||
// const QStringList &black_custom = m_settings.customIps();
|
||||
// qDebug() << "onConnect :: adding custom black routes, count:" << black_custom.size();
|
||||
if (m_settings.customRouting()) {
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(),
|
||||
QStringList() << m_settings.primaryDns() << m_settings.secondaryDns());
|
||||
|
||||
const QStringList &black_custom = m_settings.customIps();
|
||||
qDebug() << "onConnect :: adding custom black routes, count:" << black_custom.size();
|
||||
|
||||
// QStringList args;
|
||||
// args << m_vpnProtocol->vpnGateway();
|
||||
// args << black_custom;
|
||||
IpcClient::Interface()->routeAddList(m_vpnProtocol->vpnGateway(), black_custom);
|
||||
}
|
||||
}
|
||||
else if (state == VpnProtocol::ConnectionState::Error || state == VpnProtocol::ConnectionState::Disconnected) {
|
||||
IpcClient::Interface()->flushDns();
|
||||
|
||||
if (m_settings.customRouting()) {
|
||||
IpcClient::Interface()->clearSavedRoutes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Message m(Message::State::RoutesAddRequest, args);
|
||||
// m_vpnProtocol->communicator()->sendMessage(m);
|
||||
// }
|
||||
// else if (state == VpnProtocol::ConnectionState::Error) {
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::ClearSavedRoutesRequest, QStringList()));
|
||||
// m_vpnProtocol->communicator()->sendMessage(Message(Message::State::FlushDnsRequest, QStringList()));
|
||||
// }
|
||||
emit connectionStateChanged(state);
|
||||
}
|
||||
|
||||
QSharedPointer<VpnProtocol> VpnConnection::vpnProtocol() const
|
||||
{
|
||||
return m_vpnProtocol;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::lastError() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
@@ -54,11 +75,12 @@ ErrorCode VpnConnection::lastError() const
|
||||
return m_vpnProtocol.data()->lastError();
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials, Protocol protocol)
|
||||
ErrorCode VpnConnection::createVpnConfiguration(const ServerCredentials &credentials, Protocol protocol)
|
||||
{
|
||||
ErrorCode errorCode = ErrorCode::NoError;
|
||||
if (protocol == Protocol::OpenVpn || protocol == Protocol::ShadowSocks) {
|
||||
QString configData = OpenVpnConfigurator::genOpenVpnConfig(credentials, protocol, &errorCode);
|
||||
QString openVpnConfigData = OpenVpnConfigurator::genOpenVpnConfig(credentials, protocol, &errorCode);
|
||||
m_vpnConfiguration.insert(config::key_openvpn_config_data(), openVpnConfigData);
|
||||
if (errorCode) {
|
||||
return errorCode;
|
||||
}
|
||||
@@ -66,57 +88,64 @@ ErrorCode VpnConnection::requestVpnConfig(const ServerCredentials &credentials,
|
||||
QFile file(Utils::defaultVpnConfigFileName());
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)){
|
||||
QTextStream stream(&file);
|
||||
stream << configData << endl;
|
||||
return ErrorCode::NoError;
|
||||
stream << openVpnConfigData << endl;
|
||||
}
|
||||
else {
|
||||
return ErrorCode::FailedToSaveConfigData;
|
||||
}
|
||||
|
||||
return ErrorCode::FailedToSaveConfigData;
|
||||
}
|
||||
else {
|
||||
return ErrorCode::NotImplementedError;
|
||||
}
|
||||
return ErrorCode::NotImplementedError;
|
||||
|
||||
if (protocol == Protocol::ShadowSocks) {
|
||||
QJsonObject ssConfigData = ShadowSocksVpnProtocol::genShadowSocksConfig(credentials);
|
||||
m_vpnConfiguration.insert(config::key_shadowsocks_config_data(), ssConfigData);
|
||||
}
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
|
||||
ErrorCode VpnConnection::connectToVpn(const ServerCredentials &credentials, Protocol protocol)
|
||||
{
|
||||
// protocol = Protocol::ShadowSocks;
|
||||
qDebug() << "connectToVpn, CustomRouting is" << m_settings.customRouting();
|
||||
//protocol = Protocol::ShadowSocks;
|
||||
|
||||
// TODO: Try protocols one by one in case of Protocol::Any
|
||||
// TODO: Implement some behavior in case if connection not stable
|
||||
qDebug() << "Connect to VPN";
|
||||
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Connecting);
|
||||
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
m_vpnProtocol->stop();
|
||||
m_vpnProtocol->deleteLater();
|
||||
}
|
||||
|
||||
qApp->processEvents();
|
||||
|
||||
if (protocol == Protocol::Any || protocol == Protocol::OpenVpn) {
|
||||
ErrorCode e = requestVpnConfig(credentials, Protocol::OpenVpn);
|
||||
ErrorCode e = createVpnConfiguration(credentials, Protocol::OpenVpn);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
}
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
|
||||
m_vpnProtocol.reset(new OpenVpnProtocol(m_vpnConfiguration));
|
||||
e = static_cast<OpenVpnProtocol *>(m_vpnProtocol.data())->checkAndSetupTapDriver();
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
}
|
||||
m_vpnProtocol.reset(new OpenVpnProtocol());
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
}
|
||||
else if (protocol == Protocol::ShadowSocks) {
|
||||
ErrorCode e = requestVpnConfig(credentials, Protocol::ShadowSocks);
|
||||
ErrorCode e = createVpnConfiguration(credentials, Protocol::ShadowSocks);
|
||||
if (e) {
|
||||
emit connectionStateChanged(VpnProtocol::ConnectionState::Error);
|
||||
return e;
|
||||
}
|
||||
if (m_vpnProtocol) {
|
||||
disconnect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
}
|
||||
|
||||
m_vpnProtocol.reset(new ShadowSocksVpnProtocol(ShadowSocksVpnProtocol::genShadowSocksConfig(credentials)));
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
|
||||
m_vpnProtocol.reset(new ShadowSocksVpnProtocol(m_vpnConfiguration));
|
||||
}
|
||||
|
||||
connect(m_vpnProtocol.data(), &VpnProtocol::protocolError, this, &VpnConnection::vpnProtocolError);
|
||||
connect(m_vpnProtocol.data(), SIGNAL(connectionStateChanged(VpnProtocol::ConnectionState)), this, SLOT(onConnectionStateChanged(VpnProtocol::ConnectionState)));
|
||||
connect(m_vpnProtocol.data(), SIGNAL(bytesChanged(quint64, quint64)), this, SLOT(onBytesChanged(quint64, quint64)));
|
||||
|
||||
@@ -148,20 +177,20 @@ VpnProtocol::ConnectionState VpnConnection::connectionState()
|
||||
return m_vpnProtocol->connectionState();
|
||||
}
|
||||
|
||||
bool VpnConnection::onConnected() const
|
||||
bool VpnConnection::isConnected() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_vpnProtocol.data()->onConnected();
|
||||
return m_vpnProtocol.data()->isConnected();
|
||||
}
|
||||
|
||||
bool VpnConnection::onDisconnected() const
|
||||
bool VpnConnection::isDisconnected() const
|
||||
{
|
||||
if (!m_vpnProtocol.data()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return m_vpnProtocol.data()->onDisconnected();
|
||||
return m_vpnProtocol.data()->isDisconnected();
|
||||
}
|
||||
|
||||
+15
-6
@@ -4,9 +4,11 @@
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QScopedPointer>
|
||||
#include <QRemoteObjectNode>
|
||||
|
||||
#include "protocols/vpnprotocol.h"
|
||||
#include "core/defs.h"
|
||||
#include "core/ipcclient.h"
|
||||
#include "settings.h"
|
||||
|
||||
using namespace amnezia;
|
||||
@@ -17,34 +19,41 @@ class VpnConnection : public QObject
|
||||
|
||||
public:
|
||||
explicit VpnConnection(QObject* parent = nullptr);
|
||||
~VpnConnection() override = default;
|
||||
~VpnConnection() override;
|
||||
|
||||
static QString bytesPerSecToText(quint64 bytes);
|
||||
|
||||
ErrorCode lastError() const;
|
||||
ErrorCode requestVpnConfig(const ServerCredentials &credentials, Protocol protocol);
|
||||
ErrorCode createVpnConfiguration(const ServerCredentials &credentials, Protocol protocol);
|
||||
|
||||
ErrorCode connectToVpn(const ServerCredentials &credentials, Protocol protocol = Protocol::Any);
|
||||
bool onConnected() const;
|
||||
bool onDisconnected() const;
|
||||
void disconnectFromVpn();
|
||||
|
||||
bool isConnected() const;
|
||||
bool isDisconnected() const;
|
||||
|
||||
VpnProtocol::ConnectionState connectionState();
|
||||
|
||||
QSharedPointer<VpnProtocol> vpnProtocol() const;
|
||||
|
||||
signals:
|
||||
void bytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void connectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
void vpnProtocolError(amnezia::ErrorCode error);
|
||||
|
||||
void serviceIsNotReady();
|
||||
|
||||
protected slots:
|
||||
void onBytesChanged(quint64 receivedBytes, quint64 sentBytes);
|
||||
void onConnectionStateChanged(VpnProtocol::ConnectionState state);
|
||||
|
||||
protected:
|
||||
|
||||
QScopedPointer<VpnProtocol> m_vpnProtocol;
|
||||
QSharedPointer<VpnProtocol> m_vpnProtocol;
|
||||
|
||||
private:
|
||||
Settings m_settings;
|
||||
QJsonObject m_vpnConfiguration;
|
||||
|
||||
};
|
||||
|
||||
#endif // VPNCONNECTION_H
|
||||
|
||||
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Regular → Executable
+58
-26
@@ -5,46 +5,37 @@ set -o errexit -o nounset
|
||||
|
||||
# Hold on to current directory
|
||||
PROJECT_DIR=$(pwd)
|
||||
SCRIPT_DIR=$PROJECT_DIR/deploy
|
||||
DEPLOY_DIR=$PROJECT_DIR/deploy
|
||||
|
||||
mkdir -p $SCRIPT_DIR/build
|
||||
WORK_DIR=$SCRIPT_DIR/build
|
||||
mkdir -p $DEPLOY_DIR/build
|
||||
BUILD_DIR=$DEPLOY_DIR/build
|
||||
|
||||
echo "Project dir: ${PROJECT_DIR}"
|
||||
echo "Build dir: ${WORK_DIR}"
|
||||
echo "Build dir: ${BUILD_DIR}"
|
||||
|
||||
APP_NAME=AmneziaVPN
|
||||
APP_FILENAME=$APP_NAME.app
|
||||
APP_DOMAIN=org.amneziavpn.package
|
||||
PLIST_NAME=$APP_NAME.plist
|
||||
|
||||
RELEASE_DIR=$WORK_DIR
|
||||
OUT_APP_DIR=$RELEASE_DIR/client
|
||||
OUT_APP_DIR=$BUILD_DIR/client
|
||||
BUNDLE_DIR=$OUT_APP_DIR/$APP_FILENAME
|
||||
DEPLOY_DATA_DIR=$PROJECT_DIR/deploy/data/macos
|
||||
INSTALLER_DATA_DIR=$RELEASE_DIR/installer/packages/$APP_DOMAIN/data
|
||||
INSTALLER_DATA_DIR=$BUILD_DIR/installer/packages/$APP_DOMAIN/data
|
||||
|
||||
PRO_FILE_PATH=$PROJECT_DIR/$APP_NAME.pro
|
||||
QMAKE_STASH_FILE=$PROJECT_DIR/.qmake_stash
|
||||
TARGET_FILENAME=$PROJECT_DIR/$APP_NAME.dmg
|
||||
DMG_FILENAME=$PROJECT_DIR/${APP_NAME}_unsigned.dmg
|
||||
|
||||
# Seacrh Qt
|
||||
echo "Brew Qt version $(brew --prefix qt)"
|
||||
if [ -z "${QT_VERSION+x}" ]; then export QT_VERSION=5.15.2; fi
|
||||
|
||||
|
||||
#if [ -f $(brew --prefix qt)/clang_64/bin/qmake ]; then QT_BIN_DIR=$(brew --prefix qt)/clang_64/bin;
|
||||
#else QT_BIN_DIR=$HOME/Qt/5.14.2/clang_64/bin; fi
|
||||
|
||||
QT_BIN_DIR=$HOME/Qt/5.14.2/clang_64/bin
|
||||
|
||||
#QIF_BIN_DIR=$HOME/Qt/Tools/QtInstallerFramework/4.0/bin
|
||||
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/clang_64/bin
|
||||
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/4.0/bin
|
||||
|
||||
echo "Using Qt in $QT_BIN_DIR"
|
||||
echo "Using QIF in $QIF_BIN_DIR"
|
||||
|
||||
ls -al $QT_BIN_DIR/../../..
|
||||
|
||||
|
||||
# Checking env
|
||||
$QT_BIN_DIR/qmake -v
|
||||
@@ -53,7 +44,7 @@ clang -v
|
||||
|
||||
# Build App
|
||||
echo "Building App..."
|
||||
cd $WORK_DIR
|
||||
cd $BUILD_DIR
|
||||
|
||||
$QT_BIN_DIR/qmake $PROJECT_DIR/AmneziaVPN.pro 'CONFIG+=release CONFIG+=x86_64'
|
||||
make -j `sysctl -n hw.ncpu`
|
||||
@@ -67,15 +58,41 @@ echo "____________________________________"
|
||||
# Package
|
||||
echo "Packaging ..."
|
||||
|
||||
#cd $SCRIPT_DIR
|
||||
#cd $DEPLOY_DIR
|
||||
|
||||
$QT_BIN_DIR/macdeployqt $OUT_APP_DIR/$APP_FILENAME -always-overwrite
|
||||
cp -av $RELEASE_DIR/service/server/$APP_NAME-service.app/Contents/macOS/$APP_NAME-service $BUNDLE_DIR/Contents/macOS
|
||||
cp -av $BUILD_DIR/service/server/$APP_NAME-service.app/Contents/macOS/$APP_NAME-service $BUNDLE_DIR/Contents/macOS
|
||||
cp -Rv $PROJECT_DIR/deploy/data/macos/* $BUNDLE_DIR/Contents/macOS
|
||||
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
|
||||
CERTIFICATE_P12=$DEPLOY_DIR/PrivacyTechAppleCertDeveloperId.p12
|
||||
WWDRCA=$DEPLOY_DIR/WWDRCA.cer
|
||||
KEYCHAIN=amnezia.build.keychain
|
||||
TEMP_PASS=tmp_pass
|
||||
|
||||
security create-keychain -p $TEMP_PASS $KEYCHAIN || true
|
||||
security default-keychain -s $KEYCHAIN
|
||||
security unlock-keychain -p $TEMP_PASS $KEYCHAIN
|
||||
|
||||
security default-keychain
|
||||
security list-keychains
|
||||
|
||||
security import $WWDRCA -k $KEYCHAIN -T /usr/bin/codesign || true
|
||||
security import $CERTIFICATE_P12 -k $KEYCHAIN -P $MAC_CERT_PW -T /usr/bin/codesign || true
|
||||
|
||||
security set-key-partition-list -S apple-tool:,apple: -k $TEMP_PASS $KEYCHAIN
|
||||
security find-identity -p codesigning
|
||||
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $BUNDLE_DIR
|
||||
/usr/bin/codesign --verify -vvvv $BUNDLE_DIR || true
|
||||
spctl -a -vvvv $BUNDLE_DIR || true
|
||||
|
||||
fi
|
||||
|
||||
|
||||
mkdir -p $INSTALLER_DATA_DIR
|
||||
cp -av $PROJECT_DIR/deploy/installer $RELEASE_DIR
|
||||
cp -av $PROJECT_DIR/deploy/installer $BUILD_DIR
|
||||
cp -av $DEPLOY_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_install.sh
|
||||
cp -av $DEPLOY_DATA_DIR/post_uninstall.sh $INSTALLER_DATA_DIR/post_uninstall.sh
|
||||
cp -av $DEPLOY_DATA_DIR/$PLIST_NAME $INSTALLER_DATA_DIR/$PLIST_NAME
|
||||
@@ -86,9 +103,24 @@ chmod a+x $INSTALLER_DATA_DIR/post_install.sh $INSTALLER_DATA_DIR/post_uninstall
|
||||
cd $BUNDLE_DIR
|
||||
tar czf $INSTALLER_DATA_DIR/$APP_NAME.tar.gz ./
|
||||
|
||||
cd $RELEASE_DIR/installer
|
||||
$QIF_BIN_DIR/binarycreator --offline-only -v -c config/macos.xml -p packages -f $APP_NAME
|
||||
hdiutil create -volname $APP_NAME -srcfolder $APP_NAME.app -ov -format UDZO $TARGET_FILENAME
|
||||
cd $BUILD_DIR/installer
|
||||
$QIF_BIN_DIR/binarycreator --offline-only -v -c config/macos.xml -p packages -f $APP_FILENAME
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $APP_FILENAME
|
||||
fi
|
||||
|
||||
hdiutil create -volname $APP_NAME -srcfolder $APP_NAME.app -ov -format UDZO $DMG_FILENAME
|
||||
|
||||
echo "Finished, artifact is $PROJECT_DIR/$APP_NAME.dmg"
|
||||
if [ "${MAC_CERT_PW+x}" ]; then
|
||||
/usr/bin/codesign --deep --force --verbose --timestamp -o runtime --sign "Developer ID Application: Privacy Technologies OU (X7UJ388FXK)" $DMG_FILENAME
|
||||
/usr/bin/codesign --verify -vvvv $DMG_FILENAME || true
|
||||
spctl -a -vvvv $DMG_FILENAME || true
|
||||
#xcrun altool --notarize-app -f $DMG_FILENAME -t osx --primary-bundle-id $APP_DOMAIN -u $APPLE_DEV_EMAIL
|
||||
#xcrun stapler staple $DMG_FILENAME
|
||||
#xcrun stapler validate $DMG_FILENAME
|
||||
fi
|
||||
|
||||
echo "Finished, artifact is $DMG_FILENAME"
|
||||
|
||||
# restore keychain
|
||||
security default-keychain -s login.keychain
|
||||
|
||||
@@ -44,6 +44,12 @@ echo "PRO_FILE_PATH: %PRO_FILE_PATH%"
|
||||
echo "QMAKE_STASH_FILE: %QMAKE_STASH_FILE%"
|
||||
echo "TARGET_FILENAME: %TARGET_FILENAME%"
|
||||
|
||||
rem Signing staff
|
||||
powershell Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine
|
||||
powershell Get-ExecutionPolicy -List
|
||||
|
||||
powershell Import-PfxCertificate -FilePath %SCRIPT_DIR:"=%\PrivacyTechWindowsCert.pfx -CertStoreLocation Cert:\LocalMachine\My -Password $(ConvertTo-SecureString -String $Env:WIN_CERT_PW -AsPlainText -Force)
|
||||
|
||||
echo "Cleanup..."
|
||||
Rmdir /Q /S %RELEASE_DIR%
|
||||
Del %QMAKE_STASH_FILE%
|
||||
@@ -59,7 +65,6 @@ cd %PROJECT_DIR%
|
||||
cd %WORK_DIR%
|
||||
set CL=/MP
|
||||
nmake /A /NOLOGO
|
||||
break
|
||||
nmake clean
|
||||
rem if not exist "%OUT_APP_DIR:"=%\%APP_FILENAME:"=%" break
|
||||
|
||||
@@ -70,11 +75,11 @@ copy "%WORK_DIR:"=%\platform\post-uninstall\release\post-uninstall.exe" %OUT_APP
|
||||
|
||||
echo "Signing exe"
|
||||
cd %OUT_APP_DIR%
|
||||
signtool sign /f "%SCRIPT_DIR:"=%\PrivacyTechWindowsCert.pfx" /p %WIN_CERT_PW% /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 *.exe
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 *.exe
|
||||
|
||||
"%QT_BIN_DIR:"=%\windeployqt" --release --force --no-translations "%OUT_APP_DIR:"=%\%APP_FILENAME:"=%"
|
||||
signtool sign /f "%SCRIPT_DIR:"=%\PrivacyTechWindowsCert.pfx" /p %WIN_CERT_PW% /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 *.dll
|
||||
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 *.dll
|
||||
|
||||
echo "Copying deploy data..."
|
||||
xcopy %DEPLOY_DATA_DIR% %OUT_APP_DIR% /s /e /y /i /f
|
||||
@@ -96,6 +101,7 @@ echo "Creating installer..."
|
||||
"%QIF_BIN_DIR:"=%\binarycreator" --offline-only -v -c config\windows.xml -p packages -f %TARGET_FILENAME%
|
||||
|
||||
cd %PROJECT_DIR%
|
||||
signtool sign /f "%SCRIPT_DIR:"=%\PrivacyTechWindowsCert.pfx" /p %WIN_CERT_PW% /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 %TARGET_FILENAME%
|
||||
signtool sign /v /sm /s My /n "Privacy Technologies OU" /fd sha256 /tr http://timestamp.comodoca.com/?td=sha256 /td sha256 %TARGET_FILENAME%
|
||||
|
||||
echo "Finished, see %TARGET_FILENAME%"
|
||||
exit 0
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef IPC_H
|
||||
#define IPC_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
|
||||
#define IPC_SERVICE_URL "local:AmneziaVpnIpcInterface"
|
||||
|
||||
namespace amnezia {
|
||||
|
||||
inline QString getIpcServiceUrl() {
|
||||
#ifdef Q_OS_WIN
|
||||
return IPC_SERVICE_URL;
|
||||
#else
|
||||
return QString("/tmp/%1").arg(IPC_SERVICE_URL);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline QString getIpcProcessUrl(int pid) {
|
||||
#ifdef Q_OS_WIN
|
||||
return QString("%1_%2").arg(IPC_SERVICE_URL).arg(pid);
|
||||
#else
|
||||
return QString("/tmp/%1_%2").arg(IPC_SERVICE_URL).arg(pid);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace amnezia
|
||||
|
||||
#endif // IPC_H
|
||||
@@ -0,0 +1,43 @@
|
||||
#include <QtCore>
|
||||
#include <QString>
|
||||
|
||||
class IpcInterface
|
||||
{
|
||||
SLOT( int createPrivilegedProcess() ); // return local pid
|
||||
//SIGNAL(sendMessage(const QByteArray &message));
|
||||
|
||||
// Route functions
|
||||
SLOT( bool routeAdd(const QString &ip, const QString &gw, const QString &mask) );
|
||||
SLOT( int routeAddList(const QString &gw, const QStringList &ips) );
|
||||
SLOT( bool clearSavedRoutes() );
|
||||
SLOT( bool routeDelete(const QString &ip) );
|
||||
SLOT( void flushDns() );
|
||||
|
||||
SLOT( bool checkAndInstallDriver() );
|
||||
SLOT( QStringList getTapList() );
|
||||
};
|
||||
|
||||
class IpcProcessInterface
|
||||
{
|
||||
SLOT( start(const QString &program, const QStringList &args) );
|
||||
SLOT( start() );
|
||||
SLOT( close() );
|
||||
|
||||
SLOT( setArguments(const QStringList &arguments) );
|
||||
SLOT( setInputChannelMode(QProcess::InputChannelMode mode) );
|
||||
SLOT( setNativeArguments(const QString &arguments) );
|
||||
SLOT( setProcessChannelMode(QProcess::ProcessChannelMode mode) );
|
||||
SLOT( setProgram(const QString &program) );
|
||||
SLOT( setWorkingDirectory(const QString &dir) );
|
||||
|
||||
SLOT( QByteArray readAllStandardError() );
|
||||
SLOT( QByteArray readAllStandardOutput() );
|
||||
|
||||
|
||||
SIGNAL( errorOccurred(QProcess::ProcessError error) );
|
||||
SIGNAL( finished(int exitCode, QProcess::ExitStatus exitStatus) );
|
||||
SIGNAL( readyReadStandardError() );
|
||||
SIGNAL( readyReadStandardOutput() );
|
||||
SIGNAL( started() );
|
||||
SIGNAL( stateChanged(QProcess::ProcessState newState) );
|
||||
};
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "ipcserver.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QDateTime>
|
||||
#include <QLocalSocket>
|
||||
|
||||
#include "router.h"
|
||||
#ifdef Q_OS_WIN
|
||||
#include "tapcontroller_win.h"
|
||||
#endif
|
||||
|
||||
IpcServer::IpcServer(QObject *parent):
|
||||
IpcInterfaceSource(parent)
|
||||
{}
|
||||
|
||||
int IpcServer::createPrivilegedProcess()
|
||||
{
|
||||
m_localpid++;
|
||||
|
||||
ProcessDescriptor pd(this);
|
||||
// pd.serverNode->setHostUrl(QUrl(amnezia::getIpcProcessUrl(m_localpid)));
|
||||
// pd.serverNode->enableRemoting(pd.ipcProcess.data());
|
||||
|
||||
|
||||
|
||||
//pd.localServer = QSharedPointer<QLocalServer>(new QLocalServer(this));
|
||||
pd.localServer->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
if (!pd.localServer->listen(amnezia::getIpcProcessUrl(m_localpid))) {
|
||||
qDebug() << QString("Unable to start the server: %1.").arg(pd.localServer->errorString());
|
||||
return -1;
|
||||
}
|
||||
|
||||
// connect(m_server.data(), &QLocalServer::newConnection, this, &LocalServer::onNewConnection);
|
||||
|
||||
// qDebug().noquote() << QString("Local server started on '%1'").arg(m_server->serverName());
|
||||
|
||||
// m_serverNode.setHostUrl(QUrl(QStringLiteral(IPC_SERVICE_URL))); // create host node without Registry
|
||||
|
||||
|
||||
|
||||
// Make sure any connections are handed to QtRO
|
||||
QObject::connect(pd.localServer.data(), &QLocalServer::newConnection, this, [pd]() {
|
||||
qDebug() << "LocalServer new connection";
|
||||
if (pd.serverNode) {
|
||||
pd.serverNode->addHostSideConnection(pd.localServer->nextPendingConnection());
|
||||
pd.serverNode->enableRemoting(pd.ipcProcess.data());
|
||||
}
|
||||
});
|
||||
|
||||
m_processes.insert(m_localpid, pd);
|
||||
|
||||
return m_localpid;
|
||||
}
|
||||
|
||||
bool IpcServer::routeAdd(const QString &ip, const QString &gw, const QString &mask)
|
||||
{
|
||||
return Router::Instance().routeAdd(ip, gw, mask);
|
||||
}
|
||||
|
||||
int IpcServer::routeAddList(const QString &gw, const QStringList &ips)
|
||||
{
|
||||
return Router::Instance().routeAddList(gw, ips);
|
||||
}
|
||||
|
||||
bool IpcServer::clearSavedRoutes()
|
||||
{
|
||||
return Router::Instance().clearSavedRoutes();
|
||||
}
|
||||
|
||||
bool IpcServer::routeDelete(const QString &ip)
|
||||
{
|
||||
return Router::Instance().routeDelete(ip);
|
||||
}
|
||||
|
||||
void IpcServer::flushDns()
|
||||
{
|
||||
return Router::Instance().flushDns();
|
||||
}
|
||||
|
||||
bool IpcServer::checkAndInstallDriver()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return TapController::checkAndSetup();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
QStringList IpcServer::getTapList()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
return TapController::getTapList();
|
||||
#else
|
||||
return QStringList();
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef IPCSERVER_H
|
||||
#define IPCSERVER_H
|
||||
|
||||
#include <QLocalServer>
|
||||
#include <QObject>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "ipcserverprocess.h"
|
||||
|
||||
#include "rep_ipcinterface_source.h"
|
||||
|
||||
class IpcServer : public IpcInterfaceSource
|
||||
{
|
||||
public:
|
||||
explicit IpcServer(QObject *parent = nullptr);
|
||||
virtual int createPrivilegedProcess() override;
|
||||
|
||||
virtual bool routeAdd(const QString &ip, const QString &gw, const QString &mask = QString()) override;
|
||||
virtual int routeAddList(const QString &gw, const QStringList &ips) override;
|
||||
virtual bool clearSavedRoutes() override;
|
||||
virtual bool routeDelete(const QString &ip) override;
|
||||
virtual void flushDns() override;
|
||||
virtual bool checkAndInstallDriver() override;
|
||||
virtual QStringList getTapList() override;
|
||||
|
||||
private:
|
||||
int m_localpid = 0;
|
||||
|
||||
struct ProcessDescriptor {
|
||||
ProcessDescriptor (QObject *parent = nullptr) {
|
||||
serverNode = QSharedPointer<QRemoteObjectHost>(new QRemoteObjectHost(parent));
|
||||
ipcProcess = QSharedPointer<IpcServerProcess>(new IpcServerProcess(parent));
|
||||
localServer = QSharedPointer<QLocalServer>(new QLocalServer(parent));
|
||||
}
|
||||
QSharedPointer<IpcServerProcess> ipcProcess;
|
||||
QSharedPointer<QRemoteObjectHost> serverNode;
|
||||
QSharedPointer<QLocalServer> localServer;
|
||||
};
|
||||
|
||||
QMap<int, ProcessDescriptor> m_processes;
|
||||
};
|
||||
|
||||
#endif // IPCSERVER_H
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "ipcserverprocess.h"
|
||||
#include <QProcess>
|
||||
|
||||
IpcServerProcess::IpcServerProcess(QObject *parent) :
|
||||
IpcProcessInterfaceSource(parent),
|
||||
m_process(QSharedPointer<QProcess>(new QProcess()))
|
||||
{
|
||||
connect(m_process.data(), &QProcess::errorOccurred, this, &IpcServerProcess::errorOccurred);
|
||||
connect(m_process.data(), QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &IpcServerProcess::finished);
|
||||
connect(m_process.data(), &QProcess::readyReadStandardError, this, &IpcServerProcess::readyReadStandardError);
|
||||
connect(m_process.data(), &QProcess::readyReadStandardOutput, this, &IpcServerProcess::readyReadStandardOutput);
|
||||
connect(m_process.data(), &QProcess::started, this, &IpcServerProcess::started);
|
||||
connect(m_process.data(), &QProcess::stateChanged, this, &IpcServerProcess::stateChanged);
|
||||
|
||||
connect(m_process.data(), &QProcess::errorOccurred, [&](QProcess::ProcessError error){
|
||||
qDebug() << "IpcServerProcess errorOccurred " << error;
|
||||
});
|
||||
|
||||
connect(m_process.data(), &QProcess::readyReadStandardError, [&](){
|
||||
qDebug() << "IpcServerProcess StandardError " << m_process->readAllStandardError();
|
||||
|
||||
});
|
||||
connect(m_process.data(), &QProcess::readyReadStandardOutput, [&](){
|
||||
qDebug() << "IpcServerProcess StandardOutput " << m_process->readAllStandardOutput();
|
||||
});
|
||||
|
||||
connect(m_process.data(), &QProcess::readyRead, [&](){
|
||||
qDebug() << "IpcServerProcess StandardOutput " << m_process->readAll();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void IpcServerProcess::start(const QString &program, const QStringList &arguments)
|
||||
{
|
||||
m_process->start(program, arguments);
|
||||
qDebug() << "IpcServerProcess started, " << arguments;
|
||||
|
||||
m_process->waitForStarted();
|
||||
qDebug() << "waitForStarted started, " << m_process->errorString();
|
||||
}
|
||||
|
||||
void IpcServerProcess::start()
|
||||
{
|
||||
m_process->start();
|
||||
qDebug() << "IpcServerProcess started, " << m_process->program() << m_process->arguments();
|
||||
|
||||
m_process->waitForStarted();
|
||||
qDebug() << "waitForStarted , " << m_process->errorString() << m_process->error();
|
||||
}
|
||||
|
||||
void IpcServerProcess::close()
|
||||
{
|
||||
m_process->close();
|
||||
}
|
||||
|
||||
void IpcServerProcess::setArguments(const QStringList &arguments)
|
||||
{
|
||||
m_process->setArguments(arguments);
|
||||
}
|
||||
|
||||
void IpcServerProcess::setInputChannelMode(QProcess::InputChannelMode mode)
|
||||
{
|
||||
m_process->setInputChannelMode(mode);
|
||||
}
|
||||
|
||||
void IpcServerProcess::setNativeArguments(const QString &arguments)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
m_process->setNativeArguments(arguments);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void IpcServerProcess::setProcessChannelMode(QProcess::ProcessChannelMode mode)
|
||||
{
|
||||
m_process->setProcessChannelMode(mode);
|
||||
}
|
||||
|
||||
void IpcServerProcess::setProgram(const QString &program)
|
||||
{
|
||||
m_process->setProgram(program);
|
||||
}
|
||||
|
||||
void IpcServerProcess::setWorkingDirectory(const QString &dir)
|
||||
{
|
||||
m_process->setWorkingDirectory(dir);
|
||||
}
|
||||
|
||||
QByteArray IpcServerProcess::readAllStandardError()
|
||||
{
|
||||
return m_process->readAllStandardError();
|
||||
}
|
||||
|
||||
QByteArray IpcServerProcess::readAllStandardOutput()
|
||||
{
|
||||
return m_process->readAllStandardOutput();
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef IPCSERVERPROCESS_H
|
||||
#define IPCSERVERPROCESS_H
|
||||
|
||||
#include <QObject>
|
||||
#include "rep_ipcinterface_source.h"
|
||||
|
||||
|
||||
class IpcServerProcess : public IpcProcessInterfaceSource
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit IpcServerProcess(QObject *parent = nullptr);
|
||||
|
||||
void start(const QString &program, const QStringList &arguments) override;
|
||||
void start() override;
|
||||
void close() override;
|
||||
|
||||
void setArguments(const QStringList &arguments) override;
|
||||
void setInputChannelMode(QProcess::InputChannelMode mode) override;
|
||||
void setNativeArguments(const QString &arguments) override;
|
||||
void setProcessChannelMode(QProcess::ProcessChannelMode mode) override;
|
||||
void setProgram(const QString &program) override;
|
||||
void setWorkingDirectory(const QString &dir) override;
|
||||
|
||||
QByteArray readAllStandardError() override;
|
||||
QByteArray readAllStandardOutput() override;
|
||||
|
||||
signals:
|
||||
|
||||
private:
|
||||
QSharedPointer<QProcess> m_process;
|
||||
};
|
||||
|
||||
#endif // IPCSERVERPROCESS_H
|
||||
+12
-184
@@ -3,6 +3,7 @@
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
|
||||
#include "ipc.h"
|
||||
#include "localserver.h"
|
||||
#include "utils.h"
|
||||
|
||||
@@ -13,203 +14,30 @@
|
||||
#endif
|
||||
|
||||
LocalServer::LocalServer(QObject *parent) : QObject(parent),
|
||||
m_clientConnection(nullptr),
|
||||
m_clientConnected(false)
|
||||
m_ipcServer(this)
|
||||
{
|
||||
// Create the server and listen outside of QtRO
|
||||
m_server = QSharedPointer<QLocalServer>(new QLocalServer(this));
|
||||
m_server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
if (!m_server->listen(Utils::serverName())) {
|
||||
if (!m_server->listen(amnezia::getIpcServiceUrl())) {
|
||||
qDebug() << QString("Unable to start the server: %1.").arg(m_server->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
connect(m_server.data(), &QLocalServer::newConnection, this, &LocalServer::onNewConnection);
|
||||
QObject::connect(m_server.data(), &QLocalServer::newConnection, this, [this]() {
|
||||
qDebug() << "LocalServer new connection";
|
||||
m_serverNode.addHostSideConnection(m_server->nextPendingConnection());
|
||||
|
||||
qDebug().noquote() << QString("Local server started on '%1'").arg(m_server->serverName());
|
||||
if (!m_isRemotingEnabled) {
|
||||
m_isRemotingEnabled = true;
|
||||
m_serverNode.enableRemoting(&m_ipcServer);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
LocalServer::~LocalServer()
|
||||
{
|
||||
m_clientConnected = false;
|
||||
m_server->disconnect();
|
||||
|
||||
QFile::remove(Utils::serverName());
|
||||
|
||||
qDebug() << "Local server stopped";
|
||||
}
|
||||
|
||||
bool LocalServer::isRunning() const
|
||||
{
|
||||
return m_server->isListening();
|
||||
}
|
||||
|
||||
void LocalServer::onNewConnection()
|
||||
{
|
||||
if (m_clientConnection) {
|
||||
m_clientConnection->deleteLater();
|
||||
}
|
||||
|
||||
m_clientConnection = m_server->nextPendingConnection();
|
||||
connect(m_clientConnection, &QLocalSocket::disconnected, this, &LocalServer::onDisconnected);
|
||||
m_clientConnected = true;
|
||||
|
||||
qDebug() << "New connection";
|
||||
|
||||
for(;;) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
if (!m_clientConnected || !m_clientConnection) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_clientConnection->waitForReadyRead(1000) && m_clientConnection->canReadLine()) {
|
||||
char buf[1024];
|
||||
qint64 lineLength = m_clientConnection->readLine(buf, sizeof(buf));
|
||||
if (lineLength != -1) {
|
||||
QString line = buf;
|
||||
line = line.simplified();
|
||||
qDebug().noquote() << QString("Read line: '%1'").arg(line);
|
||||
Message incomingMessage(line);
|
||||
if (!incomingMessage.isValid()) {
|
||||
qWarning().noquote() << "Message is not valid!";
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
qDebug().noquote() << QString("Got message id: '%1'").arg(static_cast<int>(incomingMessage.state()));
|
||||
//qDebug().noquote() << incomingMessage.rawData();
|
||||
}
|
||||
|
||||
switch (incomingMessage.state()) {
|
||||
case Message::State::Initialize:
|
||||
#ifdef Q_OS_WIN
|
||||
TapController::Instance().checkAndSetup();
|
||||
#endif
|
||||
sendMessage(Message(Message::State::Initialize, QStringList({"Server"})));
|
||||
break;
|
||||
case Message::State::StartRequest:
|
||||
startProcess(incomingMessage.args());
|
||||
break;
|
||||
case Message::State::FinishRequest:
|
||||
finishProcess(incomingMessage.args());
|
||||
break;
|
||||
|
||||
case Message::State::RoutesAddRequest:
|
||||
routesAddRequest(incomingMessage.args());
|
||||
break;
|
||||
case Message::State::RouteDeleteRequest:
|
||||
routeDeleteRequest(incomingMessage.args());
|
||||
break;
|
||||
case Message::State::ClearSavedRoutesRequest:
|
||||
Router::Instance().clearSavedRoutes();
|
||||
break;
|
||||
case Message::State::FlushDnsRequest:
|
||||
Router::Instance().flushDns();
|
||||
break;
|
||||
case Message::State::InstallDriverRequest:
|
||||
checkAndInstallDriver(incomingMessage.args());
|
||||
break;
|
||||
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Released";
|
||||
}
|
||||
|
||||
void LocalServer::finishProcess(const QStringList& args)
|
||||
{
|
||||
Q_UNUSED(args)
|
||||
}
|
||||
|
||||
void LocalServer::startProcess(const QStringList& messageArgs)
|
||||
{
|
||||
if (messageArgs.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
QProcess* process = new QProcess();
|
||||
connect(process, SIGNAL(started()), this, SLOT(onStarted()));
|
||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onFinished(int, QProcess::ExitStatus)));
|
||||
|
||||
const QString program = messageArgs.at(0);
|
||||
QStringList args;
|
||||
for (int i = 1; i < messageArgs.size(); i++) {
|
||||
args.append(messageArgs.at(i));
|
||||
}
|
||||
|
||||
QFileInfo fi(program);
|
||||
const QString baseName = fi.baseName();
|
||||
if (!fi.exists()) {
|
||||
qWarning() << "This program does not exist";
|
||||
sendMessage(Message(Message::State::Started, QStringList({baseName})));
|
||||
sendMessage(Message(Message::State::Finished, QStringList({baseName, QString::number(-1)})));
|
||||
return;
|
||||
}
|
||||
|
||||
process->setObjectName(baseName);
|
||||
|
||||
qDebug().noquote() << QString("Start process '%1' - '%2' with args '%3'")
|
||||
.arg(baseName).arg(program).arg(args.join(","));
|
||||
|
||||
process->start(program, args);
|
||||
m_processList.append(process);
|
||||
}
|
||||
|
||||
void LocalServer::routesAddRequest(const QStringList &messageArgs)
|
||||
{
|
||||
Router::Instance().routeAddList(messageArgs.first(), messageArgs.mid(1));
|
||||
}
|
||||
|
||||
void LocalServer::routeDeleteRequest(const QStringList &messageArgs)
|
||||
{
|
||||
Router::Instance().routeDelete(messageArgs.first());
|
||||
}
|
||||
|
||||
void LocalServer::checkAndInstallDriver(const QStringList &messageArgs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void LocalServer::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
Q_UNUSED(exitStatus)
|
||||
|
||||
QProcess* process = (QProcess*)sender();
|
||||
sendMessage(Message(Message::State::Finished, QStringList({process->objectName(), QString::number(exitCode)})));
|
||||
}
|
||||
|
||||
void LocalServer::onStarted()
|
||||
{
|
||||
QProcess* process = (QProcess*)sender();
|
||||
sendMessage(Message(Message::State::Started, QStringList({process->objectName()})));
|
||||
}
|
||||
|
||||
void LocalServer::onDisconnected()
|
||||
{
|
||||
if (!m_clientConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_clientConnected = false;
|
||||
QLocalSocket* clientConnection = (QLocalSocket*)sender();
|
||||
clientConnection->deleteLater();
|
||||
|
||||
qDebug() << "Diconnected";
|
||||
}
|
||||
|
||||
void LocalServer::sendMessage(const Message& message)
|
||||
{
|
||||
if (!m_clientConnection || !m_clientConnected) {
|
||||
qDebug()<< "Cannot send data, remote peer is not connected";
|
||||
return;
|
||||
}
|
||||
|
||||
const QString data = message.toString();
|
||||
bool status = m_clientConnection->write(QString(data + "\n").toUtf8());
|
||||
|
||||
qDebug().noquote() << QString("Send message '%1', status '%2'").arg(data).arg(Utils::toString(status));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
#include "message.h"
|
||||
#include "ipcserver.h"
|
||||
|
||||
class QLocalServer;
|
||||
class QLocalSocket;
|
||||
@@ -22,30 +22,11 @@ public:
|
||||
explicit LocalServer(QObject* parent = nullptr);
|
||||
~LocalServer();
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
protected slots:
|
||||
void onDisconnected();
|
||||
void onNewConnection();
|
||||
|
||||
void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onStarted();
|
||||
|
||||
private:
|
||||
void finishProcess(const QStringList& messageArgs);
|
||||
void sendMessage(const Message& message);
|
||||
void startProcess(const QStringList& messageArgs);
|
||||
|
||||
void routesAddRequest(const QStringList& messageArgs);
|
||||
void routeDeleteRequest(const QStringList& messageArgs);
|
||||
|
||||
void checkAndInstallDriver(const QStringList& messageArgs);
|
||||
|
||||
QSharedPointer<QLocalServer> m_server;
|
||||
QPointer <QLocalSocket> m_clientConnection;
|
||||
|
||||
QVector<QProcess*> m_processList;
|
||||
bool m_clientConnected;
|
||||
IpcServer m_ipcServer;
|
||||
QRemoteObjectHost m_serverNode;
|
||||
bool m_isRemotingEnabled = false;
|
||||
};
|
||||
|
||||
#endif // LOCALSERVER_H
|
||||
|
||||
@@ -10,9 +10,9 @@ int runApplication(int argc, char** argv)
|
||||
{
|
||||
QCoreApplication app(argc,argv);
|
||||
LocalServer localServer;
|
||||
if (!localServer.isRunning()) {
|
||||
return -1;
|
||||
}
|
||||
// if (!localServer.isRunning()) {
|
||||
// return -1;
|
||||
// }
|
||||
return app.exec();
|
||||
}
|
||||
int main(int argc, char **argv)
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
TARGET = AmneziaVPN-service
|
||||
TEMPLATE = app
|
||||
CONFIG += console qt no_batch
|
||||
QT += core network
|
||||
QT += core network remoteobjects
|
||||
|
||||
HEADERS = \
|
||||
../../client/message.h \
|
||||
../../client/utils.h \
|
||||
../../ipc/ipc.h \
|
||||
../../ipc/ipcserver.h \
|
||||
../../ipc/ipcserverprocess.h \
|
||||
localserver.h \
|
||||
log.h \
|
||||
router.h \
|
||||
systemservice.h
|
||||
|
||||
SOURCES = \
|
||||
../../client/message.cpp \
|
||||
../../client/utils.cpp \
|
||||
../../ipc/ipcserver.cpp \
|
||||
../../ipc/ipcserverprocess.cpp \
|
||||
localserver.cpp \
|
||||
log.cpp \
|
||||
main.cpp \
|
||||
@@ -47,3 +50,5 @@ include(../src/qtservice.pri)
|
||||
#}
|
||||
|
||||
INCLUDEPATH += "$$PWD/../../client"
|
||||
|
||||
REPC_SOURCE += ../../ipc/ipcinterface.rep
|
||||
|
||||
@@ -13,9 +13,9 @@ void SystemService::start()
|
||||
QCoreApplication* app = application();
|
||||
m_localServer = new LocalServer();
|
||||
|
||||
if (!m_localServer->isRunning()) {
|
||||
app->quit();
|
||||
}
|
||||
// if (!m_localServer->isRunning()) {
|
||||
// app->quit();
|
||||
// }
|
||||
}
|
||||
|
||||
void SystemService::stop()
|
||||
|
||||
@@ -95,6 +95,10 @@ QStringList TapController::getTapList()
|
||||
else tapList.append(s);
|
||||
}
|
||||
|
||||
if (! tapList.isEmpty()) {
|
||||
enableTapAdapter(tapList.first());
|
||||
}
|
||||
|
||||
return tapList;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef TAPCONTROLLER_H
|
||||
#ifndef TAPCONTROLLER_H
|
||||
#define TAPCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
@@ -35,7 +35,6 @@ private:
|
||||
static bool setupDriverCertificate();
|
||||
static bool removeDriver(const QString& tapInstanceId);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // TAPCONTROLLER_H
|
||||
|
||||
Reference in New Issue
Block a user