mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-24 02:00:24 +07:00
fix: make ipc connection a singleton (#2069)
This commit is contained in:
+54
-89
@@ -1,123 +1,88 @@
|
|||||||
#include "ipcclient.h"
|
#include "ipcclient.h"
|
||||||
|
#include "ipc.h"
|
||||||
#include <QRemoteObjectNode>
|
#include <QRemoteObjectNode>
|
||||||
|
#include <QtNetwork/qlocalsocket.h>
|
||||||
IpcClient *IpcClient::m_instance = nullptr;
|
|
||||||
|
|
||||||
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
IpcClient::IpcClient(QObject *parent) : QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
m_localSocket.setServerName(amnezia::getIpcServiceUrl());
|
||||||
|
|
||||||
IpcClient::~IpcClient()
|
connect(&m_localSocket, &QLocalSocket::connected, this, [this]() {
|
||||||
{
|
m_ClientNode.addClientSideConnection(&m_localSocket);
|
||||||
if (m_localSocket)
|
m_ipcClient.reset(m_ClientNode.acquire<IpcInterfaceReplica>());
|
||||||
m_localSocket->close();
|
m_Tun2SocksClient.reset(m_ClientNode.acquire<IpcProcessTun2SocksReplica>());
|
||||||
}
|
m_isSocketConnected = true;
|
||||||
|
});
|
||||||
|
|
||||||
bool IpcClient::isSocketConnected() const
|
connect(&m_localSocket, &QLocalSocket::disconnected, [this]() {
|
||||||
{
|
m_ipcClient.clear();
|
||||||
return m_isSocketConnected;
|
m_Tun2SocksClient.clear();
|
||||||
}
|
m_isSocketConnected = false;
|
||||||
|
});
|
||||||
void IpcClient::closeAndResetInstance(bool deleteSelf)
|
|
||||||
{
|
|
||||||
if (m_localSocket)
|
|
||||||
{
|
|
||||||
m_localSocket->disconnectFromServer();
|
|
||||||
m_localSocket->deleteLater();
|
|
||||||
m_localSocket.clear();
|
|
||||||
}
|
|
||||||
m_ipcClient.reset();
|
|
||||||
m_Tun2SocksClient.reset();
|
|
||||||
m_isSocketConnected = false;
|
|
||||||
if (deleteSelf) {
|
|
||||||
m_instance = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IpcClient *IpcClient::Instance()
|
IpcClient *IpcClient::Instance()
|
||||||
{
|
{
|
||||||
return m_instance;
|
static IpcClient instance;
|
||||||
|
|
||||||
|
QMutexLocker locker(&instance.m_mutex);
|
||||||
|
|
||||||
|
if (!instance.m_isSocketConnected) {
|
||||||
|
instance.establishConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
|
QSharedPointer<IpcInterfaceReplica> IpcClient::Interface()
|
||||||
{
|
{
|
||||||
if (!Instance())
|
auto rep = Instance()->m_ipcClient;
|
||||||
|
if (!rep) {
|
||||||
|
qCritical() << "IpcClient::Interface(): Replica is undefined";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return Instance()->m_ipcClient;
|
}
|
||||||
|
if (!rep->waitForSource(1000)) {
|
||||||
|
qCritical() << "IpcClient::Interface(): Failed to initialize replica";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!rep->isReplicaValid()) {
|
||||||
|
qWarning() << "IpcClient::Interface(): Replica is invalid";
|
||||||
|
}
|
||||||
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
|
QSharedPointer<IpcProcessTun2SocksReplica> IpcClient::InterfaceTun2Socks()
|
||||||
{
|
{
|
||||||
if (!Instance())
|
auto rep = Instance()->m_Tun2SocksClient;
|
||||||
|
if (!rep) {
|
||||||
|
qCritical() << "IpcClient::InterfaceTun2Socks: Replica is undefined";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return Instance()->m_Tun2SocksClient;
|
}
|
||||||
|
if (!rep->waitForSource(1000)) {
|
||||||
|
qCritical() << "IpcClient::InterfaceTun2Socks: Failed to initialize replica";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!rep->isReplicaValid()) {
|
||||||
|
qWarning() << "IpcClient::InterfaceTun2Socks(): Replica is invalid";
|
||||||
|
}
|
||||||
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IpcClient::init(IpcClient *instance)
|
bool IpcClient::establishConnection()
|
||||||
{
|
{
|
||||||
if (m_instance && m_instance != instance) {
|
m_localSocket.connectToServer();
|
||||||
m_instance->closeAndResetInstance(false);
|
return m_localSocket.waitForConnected();
|
||||||
m_instance->deleteLater();
|
|
||||||
}
|
|
||||||
m_instance = instance;
|
|
||||||
|
|
||||||
Instance()->m_localSocket = new QLocalSocket(Instance());
|
|
||||||
connect(Instance()->m_localSocket.data(), &QLocalSocket::connected, &Instance()->m_ClientNode, []() {
|
|
||||||
Instance()->m_ClientNode.addClientSideConnection(Instance()->m_localSocket.data());
|
|
||||||
auto cliNode = Instance()->m_ClientNode.acquire<IpcInterfaceReplica>();
|
|
||||||
cliNode->waitForSource(5000);
|
|
||||||
Instance()->m_ipcClient.reset(cliNode);
|
|
||||||
|
|
||||||
if (!Instance()->m_ipcClient) {
|
|
||||||
qWarning() << "IpcClient is not ready!";
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance()->m_ipcClient->waitForSource(1000);
|
|
||||||
|
|
||||||
if (!Instance()->m_ipcClient->isReplicaValid()) {
|
|
||||||
qWarning() << "IpcClient replica is not connected!";
|
|
||||||
}
|
|
||||||
|
|
||||||
auto t2sNode = Instance()->m_ClientNode.acquire<IpcProcessTun2SocksReplica>();
|
|
||||||
t2sNode->waitForSource(5000);
|
|
||||||
Instance()->m_Tun2SocksClient.reset(t2sNode);
|
|
||||||
|
|
||||||
if (!Instance()->m_Tun2SocksClient) {
|
|
||||||
qWarning() << "IpcClient::m_Tun2SocksClient is not ready!";
|
|
||||||
}
|
|
||||||
|
|
||||||
Instance()->m_Tun2SocksClient->waitForSource(1000);
|
|
||||||
|
|
||||||
if (!Instance()->m_Tun2SocksClient->isReplicaValid()) {
|
|
||||||
qWarning() << "IpcClient::m_Tun2SocksClient replica is not connected!";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(Instance()->m_localSocket, &QLocalSocket::disconnected,
|
|
||||||
[instance]() { instance->m_isSocketConnected = false; });
|
|
||||||
|
|
||||||
Instance()->m_localSocket->connectToServer(amnezia::getIpcServiceUrl());
|
|
||||||
Instance()->m_localSocket->waitForConnected();
|
|
||||||
|
|
||||||
if (!Instance()->m_ipcClient) {
|
|
||||||
qDebug() << "IpcClient::init failed";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
qDebug() << "IpcClient::init succeed";
|
|
||||||
instance->m_isSocketConnected = (Instance()->m_ipcClient->isReplicaValid() && Instance()->m_Tun2SocksClient->isReplicaValid());
|
|
||||||
|
|
||||||
return Instance()->isSocketConnected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
|
QSharedPointer<PrivilegedProcess> IpcClient::CreatePrivilegedProcess()
|
||||||
{
|
{
|
||||||
if (!Instance()->m_ipcClient || !Instance()->m_ipcClient->isReplicaValid()) {
|
auto rep = Interface();
|
||||||
qWarning() << "IpcClient::createPrivilegedProcess : IpcClient IpcClient replica is not valid";
|
if (!rep) {
|
||||||
|
qCritical() << "IpcClient::createPrivilegedProcess : IpcClient IpcClient replica is not valid";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRemoteObjectPendingReply<int> futureResult = Instance()->m_ipcClient->createPrivilegedProcess();
|
QRemoteObjectPendingReply<int> futureResult = rep->createPrivilegedProcess();
|
||||||
futureResult.waitForFinished(5000);
|
futureResult.waitForFinished(5000);
|
||||||
|
|
||||||
int pid = futureResult.returnValue();
|
int pid = futureResult.returnValue();
|
||||||
|
|||||||
@@ -17,24 +17,20 @@ public:
|
|||||||
explicit IpcClient(QObject *parent = nullptr);
|
explicit IpcClient(QObject *parent = nullptr);
|
||||||
|
|
||||||
static IpcClient *Instance();
|
static IpcClient *Instance();
|
||||||
static bool init(IpcClient *instance);
|
|
||||||
static QSharedPointer<IpcInterfaceReplica> Interface();
|
static QSharedPointer<IpcInterfaceReplica> Interface();
|
||||||
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
|
static QSharedPointer<IpcProcessTun2SocksReplica> InterfaceTun2Socks();
|
||||||
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
|
static QSharedPointer<PrivilegedProcess> CreatePrivilegedProcess();
|
||||||
|
|
||||||
bool isSocketConnected() const;
|
bool isSocketConnected() const;
|
||||||
void closeAndResetInstance(bool deleteSelf = false);
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~IpcClient() override;
|
bool establishConnection();
|
||||||
|
|
||||||
|
QMutex m_mutex;
|
||||||
|
QLocalSocket m_localSocket;
|
||||||
QRemoteObjectNode m_ClientNode;
|
QRemoteObjectNode m_ClientNode;
|
||||||
QRemoteObjectNode m_Tun2SocksNode;
|
|
||||||
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
QSharedPointer<IpcInterfaceReplica> m_ipcClient;
|
||||||
QPointer<QLocalSocket> m_localSocket;
|
|
||||||
QPointer<QLocalSocket> m_tun2socksSocket;
|
|
||||||
QSharedPointer<IpcProcessTun2SocksReplica> m_Tun2SocksClient;
|
QSharedPointer<IpcProcessTun2SocksReplica> m_Tun2SocksClient;
|
||||||
|
|
||||||
struct ProcessDescriptor {
|
struct ProcessDescriptor {
|
||||||
@@ -50,8 +46,6 @@ private:
|
|||||||
|
|
||||||
QMap<int, QSharedPointer<ProcessDescriptor>> m_processNodes;
|
QMap<int, QSharedPointer<ProcessDescriptor>> m_processNodes;
|
||||||
bool m_isSocketConnected {false};
|
bool m_isSocketConnected {false};
|
||||||
|
|
||||||
static IpcClient *m_instance;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // IPCCLIENT_H
|
#endif // IPCCLIENT_H
|
||||||
|
|||||||
@@ -218,27 +218,16 @@ void VpnConnection::deleteRoutes(const QStringList &ips)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: replace with something like
|
||||||
|
// VpnConnection::withInterface([](iface){ })
|
||||||
bool VpnConnection::InterfaceReady()
|
bool VpnConnection::InterfaceReady()
|
||||||
{
|
{
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
if (m_IpcClient) {
|
if (auto iface = IpcClient::Interface(); iface == nullptr) {
|
||||||
m_IpcClient->closeAndResetInstance(true);
|
qWarning() << "Error occurred when init IPC client";
|
||||||
m_IpcClient->deleteLater();
|
emit serviceIsNotReady();
|
||||||
m_IpcClient = nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
if (!m_IpcClient) {
|
|
||||||
m_IpcClient = new IpcClient(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_IpcClient->isSocketConnected()) {
|
|
||||||
if (!IpcClient::init(m_IpcClient)) {
|
|
||||||
qWarning() << "Error occurred when init IPC client";
|
|
||||||
emit serviceIsNotReady();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IpcClient::Interface() != nullptr;
|
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,10 +93,6 @@ private:
|
|||||||
// Only for iOS for now, check counters
|
// Only for iOS for now, check counters
|
||||||
QTimer m_checkTimer;
|
QTimer m_checkTimer;
|
||||||
|
|
||||||
#ifdef AMNEZIA_DESKTOP
|
|
||||||
IpcClient *m_IpcClient {nullptr};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
AndroidVpnProtocol* androidVpnProtocol = nullptr;
|
AndroidVpnProtocol* androidVpnProtocol = nullptr;
|
||||||
|
|
||||||
|
|||||||
@@ -91,17 +91,8 @@ void Logger::deInit()
|
|||||||
bool Logger::setServiceLogsEnabled(bool enabled)
|
bool Logger::setServiceLogsEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
IpcClient *m_IpcClient = new IpcClient;
|
if (auto iface = IpcClient::Interface(); iface) {
|
||||||
|
iface->setLogsEnabled(enabled);
|
||||||
if (!m_IpcClient->isSocketConnected()) {
|
|
||||||
if (!IpcClient::init(m_IpcClient)) {
|
|
||||||
qWarning() << "Error occurred when init IPC client";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_IpcClient->Interface()) {
|
|
||||||
m_IpcClient->Interface()->setLogsEnabled(enabled);
|
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Error occurred setting up service logs";
|
qWarning() << "Error occurred setting up service logs";
|
||||||
return false;
|
return false;
|
||||||
@@ -208,19 +199,8 @@ void Logger::clearLogs(bool isServiceLogger)
|
|||||||
void Logger::clearServiceLogs()
|
void Logger::clearServiceLogs()
|
||||||
{
|
{
|
||||||
#ifdef AMNEZIA_DESKTOP
|
#ifdef AMNEZIA_DESKTOP
|
||||||
IpcClient *m_IpcClient = new IpcClient;
|
if (auto iface = IpcClient::Interface(); iface) {
|
||||||
|
iface->clearLogs();
|
||||||
if (!m_IpcClient->isSocketConnected()) {
|
|
||||||
if (!IpcClient::init(m_IpcClient)) {
|
|
||||||
qWarning() << "Error occurred when init IPC client";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_IpcClient->Interface()) {
|
|
||||||
m_IpcClient->Interface()->clearLogs();
|
|
||||||
} else {
|
|
||||||
qWarning() << "Error occurred cleaning up service logs";
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user