#include "ipcclient.h" #include "ipc.h" #include #include namespace { thread_local IpcClient ipcClient; } IpcClient::IpcClient(QObject *parent) : QObject(parent) { m_localSocket.setServerName(amnezia::getIpcServiceUrl()); connect(&m_localSocket, &QLocalSocket::connected, this, [this]() { m_ClientNode.addClientSideConnection(&m_localSocket); m_ipcClient.reset(m_ClientNode.acquire()); m_Tun2SocksClient.reset(m_ClientNode.acquire()); m_isSocketConnected = true; }); connect(&m_localSocket, &QLocalSocket::disconnected, this, [this]() { m_ipcClient.clear(); m_Tun2SocksClient.clear(); m_isSocketConnected = false; }); } IpcClient *IpcClient::Instance() { if (!ipcClient.m_isSocketConnected) { ipcClient.establishConnection(); } return &ipcClient; } QSharedPointer IpcClient::Interface() { QSharedPointer rep = Instance()->m_ipcClient; if (rep.isNull()) { qCritical() << "IpcClient::Interface(): Failed to acquire replica"; return nullptr; } 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 IpcClient::InterfaceTun2Socks() { QSharedPointer rep = Instance()->m_Tun2SocksClient; if (rep.isNull()) { qCritical() << "IpcClient::InterfaceTun2Socks: Replica is undefined"; return nullptr; } 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::establishConnection() { m_localSocket.connectToServer(); return m_localSocket.waitForConnected(); } QSharedPointer IpcClient::CreatePrivilegedProcess() { QSharedPointer rep = Interface(); if (!rep) { qCritical() << "IpcClient::createPrivilegedProcess: Replica is invalid"; return nullptr; } QRemoteObjectPendingReply pidReply = rep->createPrivilegedProcess(); if (!pidReply.waitForFinished(5000)){ qCritical() << "IpcClient::createPrivilegedProcess: Failed to execute RO createPrivilegedProcess call"; return nullptr; } int pid = pidReply.returnValue(); QSharedPointer pd(new ProcessDescriptor()); pd->localSocket.reset(new QLocalSocket(pd->replicaNode.data())); connect(pd->localSocket.data(), &QLocalSocket::connected, pd->replicaNode.data(), [pd]() { pd->replicaNode->addClientSideConnection(pd->localSocket.data()); IpcProcessInterfaceReplica *repl = pd->replicaNode->acquire(); // TODO: rework the unsafe cast below PrivilegedProcess *priv = static_cast(repl); pd->ipcProcess.reset(priv); if (!pd->ipcProcess) { qWarning() << "Acquire PrivilegedProcess failed"; } else { pd->ipcProcess->waitForSource(1000); if (!pd->ipcProcess->isReplicaValid()) { qWarning() << "PrivilegedProcess replica is not connected!"; } QObject::connect(pd->ipcProcess.data(), &PrivilegedProcess::destroyed, pd->ipcProcess.data(), [pd]() { pd->replicaNode->deleteLater(); }); } }); pd->localSocket->connectToServer(amnezia::getIpcProcessUrl(pid)); if (!pd->localSocket->waitForConnected()) { qCritical() << "IpcClient::createPrivilegedProcess: Failed to connect to process' socket"; return nullptr; } auto processReplica = QSharedPointer(pd->ipcProcess); return processReplica; }