Compare commits

...

82 Commits

Author SHA1 Message Date
pokamest a1cb4ac544 Custom routing done
ShadowSocks enabled by default
2021-02-18 15:00:41 +03:00
pokamest f91854594c Merge branch 'dev' into service_refact 2021-02-11 19:17:16 +03:00
pokamest f661ea1d46 Merge branch 'macos_build_fix' into dev 2021-02-10 10:44:37 -08:00
pokamest f50eea3eaf macos signing fixes 2021-02-10 06:57:26 -08:00
pokamest c15b57e690 windows travis fix 2021-02-10 00:07:12 +03:00
pokamest 5f7ef31345 win cert updated 2021-02-09 00:33:26 +03:00
pokamest 447410a27a Macos build fix (#6)
macos deploy fixes
2021-02-08 23:57:35 +03:00
pokamest 2aa9f9cca9 macos build fix 2021-02-08 12:42:48 -08:00
pokamest cba27d354d macos deploy fixes 2021-02-08 21:10:34 +03:00
pokamest b398f42ada ipc process fix 2021-02-03 20:05:50 +03:00
pokamest b6571d99de Qt ro refact 2021-02-03 15:42:36 +03:00
pokamest b2392c1943 Qt Remote objects done 2021-02-02 22:51:31 +03:00
pokamest 048a673d31 Qt remote objects IPC 2021-02-02 01:47:40 +03:00
pokamest c4df9c004b Merge branch 'dev' into service_refact 2021-01-30 15:03:01 +03:00
pokamest b9d4c53eb6 travis macos fix 2021-01-28 14:18:28 +03:00
pokamest 5fdeea0581 travis fix 2021-01-28 13:26:43 +03:00
pokamest e1cd764050 travis fix 2021-01-28 13:11:10 +03:00
pokamest 1e54379cc0 macos travis fix 2021-01-28 12:54:09 +03:00
pokamest ba3f69d206 travis fix 2021-01-27 01:44:32 +03:00
pokamest fcfd4181c7 merge fix 2021-01-27 01:32:36 +03:00
pokamest 9f6ec6d3e2 Merge branch 'master' into gitfix 2021-01-27 00:50:55 +03:00
pokamest 2e50aae603 macos deploy 2021-01-26 22:15:49 +03:00
pokamest 5a16a07b57 travis release 2021-01-26 22:00:58 +03:00
pokamest 953eca6695 Bug fixes:
- auto install tap
- share connectionState
- service crash fix
2021-01-26 15:01:15 +03:00
pokamest a50cdd5bc2 travis fix 2021-01-23 16:45:11 +03:00
pokamest 10eb65e545 travis fix 2021-01-23 16:28:06 +03:00
pokamest 5354344ba7 travis fix 2021-01-23 16:02:21 +03:00
pokamest c000a93eef travis fix 2021-01-23 15:13:46 +03:00
pokamest ef6bc5ae4a travis fix 2021-01-23 15:08:01 +03:00
pokamest 97c4564649 travis fix 2021-01-23 15:03:56 +03:00
pokamest 5bf31a8b50 travis fix 2021-01-23 01:09:27 +03:00
pokamest 18e0d7fb2c travis fix 2021-01-23 00:57:12 +03:00
pokamest ac454d9d78 Server scripts fix 2021-01-22 16:06:43 +03:00
pokamest 806677510f icon changed 2021-01-21 19:16:10 +03:00
pokamest 68e0ba9923 server scripts fix 2021-01-21 19:14:07 +03:00
pokamest 22b33a4f25 remote_obj 2021-01-20 23:07:23 +03:00
pokamest 77f830acd5 travis fix 2021-01-19 09:48:50 +03:00
pokamest eb3b090257 travis fix 2021-01-19 01:58:55 +03:00
pokamest 2e1c219093 travis fix 2021-01-19 01:54:42 +03:00
pokamest e38f69caf0 travis fix 2021-01-19 01:54:27 +03:00
pokamest 795f286923 travis fix 2021-01-19 01:45:47 +03:00
pokamest d62e5b51da travis fix 2021-01-19 01:44:17 +03:00
pokamest 96b267b1f7 travis fix 2021-01-19 01:31:59 +03:00
pokamest 568388367e travis fix 2021-01-19 01:18:23 +03:00
pokamest 5ca46edf33 travis fix 2021-01-19 01:15:05 +03:00
pokamest af41abd346 travis fix 2021-01-19 01:09:41 +03:00
pokamest 5edb61641c travis fix 2021-01-19 00:27:35 +03:00
pokamest af3b1caa87 travis fix 2021-01-18 22:30:32 +03:00
pokamest cc4a7b32b0 travis fix 2021-01-18 22:07:31 +03:00
pokamest dfd61f58d4 travis fix 2021-01-18 21:58:23 +03:00
pokamest 84a3c1f725 travis fix 2021-01-18 19:00:18 +03:00
pokamest 2419fa1a6e travis fix 2021-01-18 18:45:38 +03:00
pokamest 3b8ecd9e9d travis windows fix 2021-01-18 01:41:20 +03:00
pokamest 94ee4b76db travis fix 2021-01-18 01:18:22 +03:00
pokamest d43a1cd753 travis fix 2021-01-18 01:14:04 +03:00
pokamest 8bc6852b39 travis fix 2021-01-17 16:27:33 +03:00
pokamest 3850be08f1 travis fix 2021-01-17 16:22:05 +03:00
pokamest d72d1d56b1 travis fix 2021-01-17 16:15:52 +03:00
pokamest 2a4926843c travis fix 2021-01-17 14:14:26 +03:00
pokamest 1b357055a2 travis fix 2021-01-17 13:53:05 +03:00
pokamest 2d3d64e462 travis fix 2021-01-17 13:17:37 +03:00
pokamest aa648d4e12 travis scripts 2021-01-17 13:11:39 +03:00
pokamest bfa0ac4c34 Macos doc icon 2021-01-16 21:04:16 +03:00
pokamest c37ddd83d5 ui fix 2021-01-16 15:08:27 +03:00
pokamest 96bbc1cdbc ss fix 2021-01-15 23:37:34 +03:00
pokamest ec9ae0ef4f shadowsocks impl 2021-01-15 23:36:35 +03:00
pokamest 95cbb07cbb Merge branch 'dev' into ss/impl 2021-01-12 12:57:58 +03:00
pokamest 7b95d6a5fc ss files 2021-01-11 23:19:30 +03:00
driftingsun bea19a9461 Fix issue with easyrsa 2021-01-11 16:41:17 +03:00
pokamest ba686556d2 Merge branch 'dev' into ss/impl 2021-01-10 20:52:04 +03:00
pokamest 15dc6eaaf8 ss files 2021-01-10 20:37:57 +03:00
driftingsun 3369a387ce Fix crash on fatal error, remove moc files from Windows installation 2021-01-10 18:47:29 +03:00
michael dd46d8cf99 Fix some warnings, fix installation scripts (macOS) 2021-01-10 16:50:38 +03:00
pokamest 0b8c8835c4 new server page fix 2021-01-09 20:05:16 +03:00
pokamest 441811e277 Refactoring
Ui improvements
Bug fixes
2021-01-09 19:55:16 +03:00
pokamest 3645735053 easyrsa scripts for MacOS 2021-01-08 18:10:52 +03:00
pokamest 416d597847 MacOS deploy script fix 2021-01-08 18:08:20 +03:00
pokamest 861c71e3a8 OpenVpn runtime error codes handling 2021-01-08 16:51:58 +03:00
pokamest f45fb442de Scripts fix for macos 2021-01-08 15:43:45 +03:00
pokamest 82241701a9 deploy fix 2021-01-08 00:34:15 +03:00
pokamest bfdbe27a8d Openvpn scripts fixes
some refactoring
2021-01-07 20:53:42 +03:00
pokamest c7dafe9c00 Crash fix in management server 2021-01-07 19:10:24 +03:00
54 changed files with 1010 additions and 990 deletions
+1
View File
@@ -35,6 +35,7 @@ CMakeLists.txt.user*
.DS_Store
._.DS_Store
._*
*.dmg
# tmp files
*.*~
+32 -18
View File
@@ -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
View File
@@ -1,2 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = client service platform
+7 -7
View File
@@ -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
-79
View File
@@ -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));
}
-41
View File
@@ -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
View File
@@ -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
+3
View File
@@ -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");
+79
View File
@@ -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());
}
+42
View File
@@ -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
+14
View File
@@ -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;
}
+3
View File
@@ -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
+32 -14
View File
@@ -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);
}
+3 -1
View File
@@ -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);
-62
View File
@@ -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());
}
-34
View File
@@ -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
+1 -2
View File
@@ -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());
}
-106
View File
@@ -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;
}
-34
View File
@@ -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
+87 -90
View File
@@ -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;
+11 -12
View File
@@ -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
+28 -18
View File
@@ -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();
}
+5 -4
View File
@@ -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
+11 -22
View File
@@ -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;
}
+8 -10
View File
@@ -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
-41
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
+1 -1
View File
@@ -74,7 +74,7 @@ private:
void setTrayIcon(const QString &iconPath);
void setupUiConnections();
void initCustomSites();
void updateSettings();
void updateShareCode();
+12 -49
View File
@@ -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 &quot;Lato&quot;; </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
View File
@@ -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
View File
@@ -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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Regular → Executable
+58 -26
View File
@@ -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
+10 -4
View File
@@ -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
+30
View File
@@ -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
+43
View File
@@ -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) );
};
+97
View File
@@ -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
}
+43
View File
@@ -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
+97
View File
@@ -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();
}
+34
View File
@@ -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
View File
@@ -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));
}
+4 -23
View File
@@ -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
+3 -3
View File
@@ -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)
+8 -3
View File
@@ -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
+3 -3
View File
@@ -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()
+4
View File
@@ -95,6 +95,10 @@ QStringList TapController::getTapList()
else tapList.append(s);
}
if (! tapList.isEmpty()) {
enableTapAdapter(tapList.first());
}
return tapList;
}
+1 -2
View File
@@ -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