From 8fd43d1b1a08cbb64f265705f2b673e202d50fad Mon Sep 17 00:00:00 2001 From: Nodir Temirkhodjaev Date: Thu, 19 May 2022 12:36:30 +0300 Subject: [PATCH] RpcManager: Try to reconnect to service on error --- src/ui/control/controlmanager.cpp | 18 +++++++-------- src/ui/control/controlworker.cpp | 38 +++++++++++++++++++++++++++---- src/ui/control/controlworker.h | 8 ++++++- src/ui/rpc/drivermanagerrpc.cpp | 2 -- src/ui/rpc/rpcmanager.cpp | 26 +++++++++++++++++---- src/ui/rpc/rpcmanager.h | 2 ++ 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/ui/control/controlmanager.cpp b/src/ui/control/controlmanager.cpp index 61a72ac5..80aedbcd 100644 --- a/src/ui/control/controlmanager.cpp +++ b/src/ui/control/controlmanager.cpp @@ -21,6 +21,8 @@ namespace { +constexpr int maxClientsCount = 9; + const QLoggingCategory LC("control"); } @@ -52,9 +54,9 @@ ControlWorker *ControlManager::newServiceClient(QObject *parent) const connect(w, &ControlWorker::requestReady, this, &ControlManager::processRequest); - if (!w->connectToServer(getServerName(true))) { - qCWarning(LC) << "Server connect error:" << socket->state() << socket->errorString(); - } + w->setServerName(getServerName(/*isService=*/true)); + w->connectToServer(); + return w; } @@ -64,7 +66,7 @@ bool ControlManager::listen() Q_ASSERT(!m_server); m_server = new QLocalServer(this); - m_server->setMaxPendingConnections(3); + m_server->setMaxPendingConnections(maxClientsCount); m_server->setSocketOptions( settings->isService() ? QLocalServer::WorldAccessOption : QLocalServer::NoOptions); @@ -94,10 +96,9 @@ bool ControlManager::postCommand() ControlWorker w(&socket); // Connect to server - if (!w.connectToServer(getServerName())) { - qCWarning(LC) << "Connect to server error:" << socket.errorString(); + w.setServerName(getServerName(/*isService=*/false)); + if (!w.connectToServer()) return false; - } // Send data const QVariantList args = ControlWorker::buildArgs(settings->args()); @@ -110,9 +111,8 @@ bool ControlManager::postCommand() void ControlManager::onNewConnection() { while (QLocalSocket *socket = m_server->nextPendingConnection()) { - constexpr int maxClientsCount = 9; if (m_clients.size() > maxClientsCount) { - qCDebug(LC) << "Client dropped"; + qCDebug(LC) << "Client dropped: Count limit"; delete socket; continue; } diff --git a/src/ui/control/controlworker.cpp b/src/ui/control/controlworker.cpp index 3fe33bb4..ec014fc4 100644 --- a/src/ui/control/controlworker.cpp +++ b/src/ui/control/controlworker.cpp @@ -76,7 +76,11 @@ bool parseArgsData(const QByteArray &buffer, QVariantList &args, bool compressed } ControlWorker::ControlWorker(QLocalSocket *socket, QObject *parent) : - QObject(parent), m_isServiceClient(false), m_isClientValidated(false), m_socket(socket) + QObject(parent), + m_isServiceClient(false), + m_isClientValidated(false), + m_isTryReconnect(false), + m_socket(socket) { } @@ -99,19 +103,35 @@ void ControlWorker::setupForAsync() { socket()->setParent(this); - connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::disconnected); connect(socket(), &QLocalSocket::errorOccurred, this, [&](QLocalSocket::LocalSocketError socketError) { qCWarning(LC) << "Client error:" << id() << socketError << errorString(); close(); }); + connect(socket(), &QLocalSocket::disconnected, this, &ControlWorker::onDisconnected); connect(socket(), &QLocalSocket::readyRead, this, &ControlWorker::processRequest); } -bool ControlWorker::connectToServer(const QString &name) +void ControlWorker::setServerName(const QString &name) { - socket()->connectToServer(name); - return socket()->waitForConnected(100) && socket()->state() == QLocalSocket::ConnectedState; + socket()->setServerName(name); +} + +bool ControlWorker::connectToServer() +{ + socket()->connectToServer(); + + if (!socket()->waitForConnected(150)) { + qCWarning(LC) << "Connection error:" << socket()->state() << socket()->errorString(); + return false; + } + + if (socket()->state() != QLocalSocket::ConnectedState) { + qCWarning(LC) << "Connection state error:" << socket()->state(); + return false; + } + + return true; } void ControlWorker::close() @@ -120,6 +140,14 @@ void ControlWorker::close() socket()->close(); } +void ControlWorker::onDisconnected() +{ + if (isTryReconnect() && connectToServer()) + return; + + emit disconnected(); +} + QByteArray ControlWorker::buildCommandData(Control::Command command, const QVariantList &args) { QByteArray data; diff --git a/src/ui/control/controlworker.h b/src/ui/control/controlworker.h index d0f23847..778c4051 100644 --- a/src/ui/control/controlworker.h +++ b/src/ui/control/controlworker.h @@ -21,6 +21,9 @@ public: bool isClientValidated() const { return m_isClientValidated; } void setIsClientValidated(bool v) { m_isClientValidated = v; } + bool isTryReconnect() const { return m_isTryReconnect; } + void setIsTryReconnect(bool v) { m_isTryReconnect = v; } + QLocalSocket *socket() const { return m_socket; } int id() const; @@ -29,7 +32,8 @@ public: void setupForAsync(); - bool connectToServer(const QString &name); + void setServerName(const QString &name); + bool connectToServer(); static QByteArray buildCommandData(Control::Command command, const QVariantList &args = {}); bool sendCommandData(const QByteArray &commandData); @@ -49,6 +53,7 @@ public slots: void close(); private slots: + void onDisconnected(); void processRequest(); private: @@ -86,6 +91,7 @@ protected: private: bool m_isServiceClient : 1; bool m_isClientValidated : 1; + bool m_isTryReconnect : 1; RequestHeader m_requestHeader; QByteArray m_requestBuffer; diff --git a/src/ui/rpc/drivermanagerrpc.cpp b/src/ui/rpc/drivermanagerrpc.cpp index 59bc4088..fa7514f2 100644 --- a/src/ui/rpc/drivermanagerrpc.cpp +++ b/src/ui/rpc/drivermanagerrpc.cpp @@ -30,8 +30,6 @@ bool DriverManagerRpc::openDevice() bool DriverManagerRpc::closeDevice() { - IoC()->client()->close(); - updateState(0, false); return false; diff --git a/src/ui/rpc/rpcmanager.cpp b/src/ui/rpc/rpcmanager.cpp index ae696239..8aa2ab26 100644 --- a/src/ui/rpc/rpcmanager.cpp +++ b/src/ui/rpc/rpcmanager.cpp @@ -259,6 +259,11 @@ void RpcManager::setUp() } } +void RpcManager::tearDown() +{ + closeClient(); +} + void RpcManager::setupServerSignals() { setupAppInfoManagerSignals(); @@ -363,9 +368,20 @@ void RpcManager::setupClient() auto controlManager = IoC()->setUpDependency(); m_client = controlManager->newServiceClient(this); + client()->setIsTryReconnect(true); + invokeOnServer(Control::Rpc_RpcManager_initClient); } +void RpcManager::closeClient() +{ + if (!client()) + return; + + client()->setIsTryReconnect(false); + client()->close(); +} + bool RpcManager::waitResult() { m_resultCommand = Control::CommandNone; @@ -384,17 +400,17 @@ void RpcManager::sendResult(ControlWorker *w, bool ok, const QVariantList &args) } bool RpcManager::invokeOnServer(Control::Command cmd, const QVariantList &args) -{ - return client()->sendCommand(cmd, args); -} - -bool RpcManager::doOnServer(Control::Command cmd, const QVariantList &args, QVariantList *resArgs) { if (!client()->isConnected()) { IoC()->showErrorBox(tr("Service isn't available.")); return false; } + return client()->sendCommand(cmd, args); +} + +bool RpcManager::doOnServer(Control::Command cmd, const QVariantList &args, QVariantList *resArgs) +{ if (!invokeOnServer(cmd, args)) return false; diff --git a/src/ui/rpc/rpcmanager.h b/src/ui/rpc/rpcmanager.h index a2a44c61..846dd767 100644 --- a/src/ui/rpc/rpcmanager.h +++ b/src/ui/rpc/rpcmanager.h @@ -23,6 +23,7 @@ public: ControlWorker *client() const { return m_client; } void setUp() override; + void tearDown() override; bool waitResult(); void sendResult(ControlWorker *w, bool ok, const QVariantList &args = {}); @@ -43,6 +44,7 @@ private: void setupTaskManagerSignals(); void setupClient(); + void closeClient(); void invokeOnClients(Control::Command cmd, const QVariantList &args = {});