diff --git a/AmneziaVPN.pro b/AmneziaVPN.pro index 20bf4844..c6371ac3 100644 --- a/AmneziaVPN.pro +++ b/AmneziaVPN.pro @@ -1,2 +1,3 @@ TEMPLATE = subdirs SUBDIRS = client service platform + diff --git a/client/client.pro b/client/client.pro index 57e4fe91..fd4a89a0 100644 --- a/client/client.pro +++ b/client/client.pro @@ -10,9 +10,11 @@ include("3rd/QtSsh/src/ssh/ssh.pri") include("3rd/QtSsh/src/botan/botan.pri") HEADERS += \ + ../ipc/ipc.h \ communicator.h \ core/defs.h \ core/errorstrings.h \ + core/ipcclient.h \ core/openvpnconfigurator.h \ core/servercontroller.h \ debug.h \ @@ -32,6 +34,7 @@ HEADERS += \ SOURCES += \ communicator.cpp \ + core/ipcclient.cpp \ core/openvpnconfigurator.cpp \ core/servercontroller.cpp \ debug.cpp \ @@ -101,5 +104,5 @@ macx { LIBS += -framework Cocoa -framework ApplicationServices -framework CoreServices -framework Foundation -framework AppKit } -REPC_REPLICA += ../communicator/communicator.rep +REPC_REPLICA += ../ipc/ipcinterface.rep diff --git a/client/core/ipcclient.cpp b/client/core/ipcclient.cpp new file mode 100644 index 00000000..1450539d --- /dev/null +++ b/client/core/ipcclient.cpp @@ -0,0 +1,51 @@ +#include "ipcclient.h" +#include + +IpcClient &IpcClient::Instance() +{ + static IpcClient s; + return s; +} + +QSharedPointer IpcClient::createPrivilegedProcess() +{ + if (! Instance().m_ipcClient->isReplicaValid()) return nullptr; + + QRemoteObjectPendingReply futureResult = Instance().m_ipcClient->createPrivilegedProcess(); + futureResult.waitForFinished(1000); + + int pid = futureResult.returnValue(); + QSharedPointer replica(new QRemoteObjectNode); + //Instance().m_processNodes.insert(pid, replica); + + replica->connectToNode(QUrl(amnezia::getIpcProcessUrl(pid))); + auto ptr = QSharedPointer(replica->acquire()); + connect(ptr.data(), &IpcProcessInterfaceReplica::destroyed, replica.data(), [replica](){ + replica->deleteLater(); + }); + + return ptr; +} + +IpcClient::IpcClient(QObject *parent) : QObject(parent) +{ + m_ClientNode.connectToNode(QUrl(QStringLiteral(IPC_SERVICE_URL))); + m_ipcClient.reset(m_ClientNode.acquire()); + m_ipcClient->waitForSource(1000); + + + +// connect(m_ipcClient.data(), &IpcInterfaceReplica::stateChanged, [&](QRemoteObjectReplica::State state, QRemoteObjectReplica::State oldState){ + +//// qDebug() << "state" << state; +//// for (int i = 0; i < 10; ++i) { +//// QRemoteObjectPendingReply future = m_ipcClient->createPrivilegedProcess("", QStringList()); + +//// future.waitForFinished(); +//// qDebug() << "QRemoteObjectPendingReply" << QDateTime::currentMSecsSinceEpoch() - future.returnValue(); + +//// } +// }); + + +} diff --git a/client/core/ipcclient.h b/client/core/ipcclient.h new file mode 100644 index 00000000..67ad45ec --- /dev/null +++ b/client/core/ipcclient.h @@ -0,0 +1,30 @@ +#ifndef IPCCLIENT_H +#define IPCCLIENT_H + +#include + +#include "ipc.h" +#include "rep_ipcinterface_replica.h" + +class IpcClient : public QObject +{ + Q_OBJECT +public: + static IpcClient &Instance(); + + static QSharedPointer createPrivilegedProcess(); + + static QSharedPointer ipcClient() { return Instance().m_ipcClient; } + +signals: + +private: + explicit IpcClient(QObject *parent = nullptr); + + QRemoteObjectNode m_ClientNode; // create remote object node + QSharedPointer m_ipcClient; + + //QMap> m_processNodes; +}; + +#endif // IPCCLIENT_H diff --git a/client/protocols/openvpnprotocol.cpp b/client/protocols/openvpnprotocol.cpp index 37d1b77e..d2c912cd 100644 --- a/client/protocols/openvpnprotocol.cpp +++ b/client/protocols/openvpnprotocol.cpp @@ -11,8 +11,8 @@ OpenVpnProtocol::OpenVpnProtocol(const QString& args, QObject* parent) : - VpnProtocol(args, parent), - m_requestFromUserToStop(false) + VpnProtocol(args, parent) + //m_requestFromUserToStop(false) { setConfigFile(args); connect(m_communicator, &Communicator::messageReceived, this, &OpenVpnProtocol::onMessageReceived); @@ -130,14 +130,14 @@ ErrorCode OpenVpnProtocol::start() { qDebug() << "Start OpenVPN connection"; - m_requestFromUserToStop = false; + //m_requestFromUserToStop = false; m_openVpnStateSigTermHandlerTimer.stop(); OpenVpnProtocol::stop(); - if (communicator() && !communicator()->isConnected()) { - setLastError(ErrorCode::AmneziaServiceConnectionFailed); - return lastError(); - } +// if (communicator() && !communicator()->isConnected()) { +// setLastError(ErrorCode::AmneziaServiceConnectionFailed); +// return lastError(); +// } if (!QFileInfo::exists(openVpnExecPath())) { setLastError(ErrorCode::OpenVpnExecutableMissing); @@ -165,7 +165,20 @@ ErrorCode OpenVpnProtocol::start() } setConnectionState(ConnectionState::Connecting); - m_communicator->sendMessage(Message(Message::State::StartRequest, args)); + + QSharedPointer process = IpcClient::createPrivilegedProcess(); + process->waitForSource(1000); + if (!process->isInitialized()) { + return ErrorCode::AmneziaServiceConnectionFailed; + } + process->setProgram(openVpnExecPath()); + process->setArguments(QStringList() << "--config" << configPath()<< + "--management"<< m_managementHost<< QString::number(m_managementPort)<< + "--management-client"<< + "--log-append"<< vpnLogFileNamePath); + process->start(); + + //m_communicator->sendMessage(Message(Message::State::StartRequest, args)); startTimeoutTimer(); return ErrorCode::NoError; diff --git a/client/protocols/openvpnprotocol.h b/client/protocols/openvpnprotocol.h index 3fe8b21e..19b9735a 100644 --- a/client/protocols/openvpnprotocol.h +++ b/client/protocols/openvpnprotocol.h @@ -9,6 +9,8 @@ #include "message.h" #include "vpnprotocol.h" +#include "core/ipcclient.h" + class OpenVpnProtocol : public VpnProtocol { Q_OBJECT @@ -45,7 +47,7 @@ protected: ManagementServer m_managementServer; QString m_configFileName; QTimer m_openVpnStateSigTermHandlerTimer; - bool m_requestFromUserToStop; + //bool m_requestFromUserToStop; private: diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index 6e9c0571..b9f8419d 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -5,6 +5,7 @@ #include #include +#include "ipc.h" #include "protocols/openvpnprotocol.h" #include "protocols/shadowsocksvpnprotocol.h" #include "utils.h" diff --git a/client/vpnconnection.h b/client/vpnconnection.h index 70f4b185..a257103f 100644 --- a/client/vpnconnection.h +++ b/client/vpnconnection.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "protocols/vpnprotocol.h" #include "core/defs.h" @@ -45,6 +46,7 @@ protected: private: Settings m_settings; + }; #endif // VPNCONNECTION_H diff --git a/communicator/communicator.rep b/communicator/communicator.rep deleted file mode 100644 index b28ad56e..00000000 --- a/communicator/communicator.rep +++ /dev/null @@ -1,6 +0,0 @@ -#include -class RpcServer -{ - SLOT(executeProcess(const QString &program, const QStringList &args)); - SIGNAL(sendMessage(const QByteArray &message)); -}; diff --git a/ipc/ipc.h b/ipc/ipc.h new file mode 100644 index 00000000..d17bee13 --- /dev/null +++ b/ipc/ipc.h @@ -0,0 +1,12 @@ +#ifndef IPC_H +#define IPC_H + +#include + +#define IPC_SERVICE_URL "local:AmneziaVpnIpcInterface" + +namespace amnezia { +inline QString getIpcProcessUrl(int pid) { return QString("%1_%2").arg(IPC_SERVICE_URL).arg(pid); } +} + +#endif // IPC_H diff --git a/ipc/ipcinterface.rep b/ipc/ipcinterface.rep new file mode 100644 index 00000000..e9bb9e32 --- /dev/null +++ b/ipc/ipcinterface.rep @@ -0,0 +1,32 @@ +#include + +class IpcInterface +{ + SLOT( int createPrivilegedProcess() ); // return local pid + //SIGNAL(sendMessage(const QByteArray &message)); +}; + +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) ); +}; diff --git a/ipc/ipcserver.cpp b/ipc/ipcserver.cpp new file mode 100644 index 00000000..5095171b --- /dev/null +++ b/ipc/ipcserver.cpp @@ -0,0 +1,20 @@ +#include "ipcserver.h" + +#include + +IpcServer::IpcServer(QObject *parent): + IpcInterfaceSource(parent) +{} + +int IpcServer::createPrivilegedProcess() +{ + m_localpid++; + + ProcessDescriptor pd; + pd.serverNode->setHostUrl(QUrl(amnezia::getIpcProcessUrl(m_localpid))); + pd.serverNode->enableRemoting(pd.ipcProcess.data()); + + m_processes.insert(m_localpid, pd); + + return m_localpid; +} diff --git a/ipc/ipcserver.h b/ipc/ipcserver.h new file mode 100644 index 00000000..d77ac8d0 --- /dev/null +++ b/ipc/ipcserver.h @@ -0,0 +1,32 @@ +#ifndef IPCSERVER_H +#define IPCSERVER_H + +#include + +#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; + +private: + int m_localpid = 0; + + struct ProcessDescriptor { + ProcessDescriptor (QObject *parent = nullptr) { + serverNode = QSharedPointer(new QRemoteObjectHost(parent)); + ipcProcess = QSharedPointer(new IpcServerProcess(parent)); + } + QSharedPointer ipcProcess; + QSharedPointer serverNode; + }; + + QMap m_processes; +}; + +#endif // IPCSERVER_H diff --git a/ipc/ipcserverprocess.cpp b/ipc/ipcserverprocess.cpp new file mode 100644 index 00000000..452faca7 --- /dev/null +++ b/ipc/ipcserverprocess.cpp @@ -0,0 +1,71 @@ +#include "ipcserverprocess.h" +#include + +IpcServerProcess::IpcServerProcess(QObject *parent) : + IpcProcessInterfaceSource(parent), + m_process(QSharedPointer(new QProcess(this))) +{ + connect(m_process.data(), &QProcess::errorOccurred, this, &IpcServerProcess::errorOccurred); + connect(m_process.data(), QOverload::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); +} + +void IpcServerProcess::start(const QString &program, const QStringList &args) +{ + m_process->start(program, args); +} + +void IpcServerProcess::start() +{ + m_process->start(); + qDebug() << "IpcServerProcess started, " << m_process->arguments(); +} + +void IpcServerProcess::close() +{ + m_process->close(); +} + +void IpcServerProcess::setArguments(const QStringList &arguments) +{ + m_process->setArguments(arguments); + qDebug() << "IpcServerProcess started, " << arguments; +} + +void IpcServerProcess::setInputChannelMode(QProcess::InputChannelMode mode) +{ + m_process->setInputChannelMode(mode); +} + +void IpcServerProcess::setNativeArguments(const QString &arguments) +{ + m_process->setNativeArguments(arguments); +} + +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(); +} diff --git a/ipc/ipcserverprocess.h b/ipc/ipcserverprocess.h new file mode 100644 index 00000000..e5222f8d --- /dev/null +++ b/ipc/ipcserverprocess.h @@ -0,0 +1,34 @@ +#ifndef IPCSERVERPROCESS_H +#define IPCSERVERPROCESS_H + +#include +#include "rep_ipcinterface_source.h" + + +class IpcServerProcess : public IpcProcessInterfaceSource +{ + Q_OBJECT +public: + explicit IpcServerProcess(QObject *parent = nullptr); + + void start(const QString &program, const QStringList &args) 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 m_process; +}; + +#endif // IPCSERVERPROCESS_H diff --git a/service/server/localserver.cpp b/service/server/localserver.cpp index 8e797065..f2703b02 100644 --- a/service/server/localserver.cpp +++ b/service/server/localserver.cpp @@ -3,6 +3,7 @@ #include #include +#include "ipc.h" #include "localserver.h" #include "utils.h" @@ -14,19 +15,23 @@ LocalServer::LocalServer(QObject *parent) : QObject(parent), m_clientConnection(nullptr), - m_clientConnected(false) + m_clientConnected(false), + m_ipcServer(this) { m_server = QSharedPointer(new QLocalServer(this)); m_server->setSocketOptions(QLocalServer::WorldAccessOption); - if (!m_server->listen(Utils::serverName())) { - qDebug() << QString("Unable to start the server: %1.").arg(m_server->errorString()); - return; - } +// if (!m_server->listen(Utils::serverName())) { +// qDebug() << QString("Unable to start the server: %1.").arg(m_server->errorString()); +// return; +// } - connect(m_server.data(), &QLocalServer::newConnection, this, &LocalServer::onNewConnection); +// connect(m_server.data(), &QLocalServer::newConnection, this, &LocalServer::onNewConnection); - qDebug().noquote() << QString("Local server started on '%1'").arg(m_server->serverName()); +// 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 + m_serverNode.enableRemoting(&m_ipcServer); // enable remoting/sharing } LocalServer::~LocalServer() @@ -41,7 +46,8 @@ LocalServer::~LocalServer() bool LocalServer::isRunning() const { - return m_server->isListening(); + return true; + //return m_server->isListening(); } void LocalServer::onNewConnection() diff --git a/service/server/localserver.h b/service/server/localserver.h index 68448004..99c263b3 100644 --- a/service/server/localserver.h +++ b/service/server/localserver.h @@ -9,6 +9,7 @@ #include #include "message.h" +#include "ipcserver.h" class QLocalServer; class QLocalSocket; @@ -46,6 +47,9 @@ private: QVector m_processList; bool m_clientConnected; + + IpcServer m_ipcServer; + QRemoteObjectHost m_serverNode; }; #endif // LOCALSERVER_H diff --git a/service/server/server.pro b/service/server/server.pro index 289b0ec4..c5b0ce25 100644 --- a/service/server/server.pro +++ b/service/server/server.pro @@ -1,11 +1,14 @@ 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 \ @@ -14,6 +17,8 @@ HEADERS = \ SOURCES = \ ../../client/message.cpp \ ../../client/utils.cpp \ + ../../ipc/ipcserver.cpp \ + ../../ipc/ipcserverprocess.cpp \ localserver.cpp \ log.cpp \ main.cpp \ @@ -47,3 +52,5 @@ include(../src/qtservice.pri) #} INCLUDEPATH += "$$PWD/../../client" + +REPC_SOURCE += ../../ipc/ipcinterface.rep