diff --git a/src/blackcore/context/contextapplicationproxy.cpp b/src/blackcore/context/contextapplicationproxy.cpp index 4b4670531..42f944a8c 100644 --- a/src/blackcore/context/contextapplicationproxy.cpp +++ b/src/blackcore/context/contextapplicationproxy.cpp @@ -9,10 +9,10 @@ #include "blackcore/context/contextapplicationproxy.h" #include "blackmisc/dbus.h" +#include "blackmisc/dbusserver.h" #include "blackmisc/genericdbusinterface.h" #include "blackmisc/identifierlist.h" #include "blackmisc/loghandler.h" -#include "blackmisc/settingscache.h" #include #include @@ -20,6 +20,7 @@ #include using namespace BlackMisc; + namespace BlackCore { namespace Context @@ -179,5 +180,28 @@ namespace BlackCore if (fileName.isEmpty()) { return false; } return this->m_dBusInterface->callDBusRet(QLatin1Literal("existsFile"), fileName); } + + bool CContextApplicationProxy::isContextResponsive(const QString &dBusAddress, QString &msg, int timeoutMs) + { + const bool connected = CDBusServer::isDBusAvailable(dBusAddress, msg, timeoutMs); + if (!connected) { return false; } + + static const QString dBusName("contexttest"); + QDBusConnection connection = CDBusServer::connectToDBus(dBusAddress, dBusName); + CContextApplicationProxy proxy(BlackMisc::CDBusServer::coreServiceName(), connection, CCoreFacadeConfig::Remote, nullptr); + const CIdentifier id("swift proxy test"); + const CIdentifier pingId = proxy.registerApplication(id); + const bool ok = (id == pingId); + if (ok) + { + proxy.unregisterApplication(id); + } + else + { + msg = "Mismatch in proxy ping, context not ready."; + } + CDBusServer::disconnectFromDBus(connection, dBusAddress); + return ok; + } } // namespace } // namespace diff --git a/src/blackcore/context/contextapplicationproxy.h b/src/blackcore/context/contextapplicationproxy.h index 5d563a971..2d5cde774 100644 --- a/src/blackcore/context/contextapplicationproxy.h +++ b/src/blackcore/context/contextapplicationproxy.h @@ -74,6 +74,11 @@ namespace BlackCore virtual bool existsFile(const QString &fileName) const override; //! @} + //! Used to test if there is a core running? + //! \note creates and connects via proxy object, so not meant for very frequent tests + //! \sa CDBusServer::isDBusAvailable as lightweight, but less accurate alternative + static bool isContextResponsive(const QString &dbusAddress, QString &msg, int timeoutMs = 1500); + protected: //! Constructor CContextApplicationProxy(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime) : IContextApplication(mode, runtime), m_dBusInterface(nullptr) {} diff --git a/src/blackmisc/dbusserver.cpp b/src/blackmisc/dbusserver.cpp index 85276c0fd..b2f2f09b9 100644 --- a/src/blackmisc/dbusserver.cpp +++ b/src/blackmisc/dbusserver.cpp @@ -36,7 +36,7 @@ namespace BlackMisc testConnection.disconnectFromBus(coreServiceName()); // Sleep for 200 ms in order for dbus-daemon to finish loading. - // FIXME: Dirty workaround. Instead poll the the server up to x times every 50 ms until it connection is accepted. + // FIXME: Dirty workaround. Instead polling the server up to x times every 50 ms until its connection is accepted. QThread::msleep(200); QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, coreServiceName()); @@ -122,7 +122,7 @@ namespace BlackMisc if (address.contains("host=") || address.contains("port=")) { // "tcp:host=foo.com,port=123" - QStringList parts(address.split(',')); + const QStringList parts(address.split(',')); for (const QString &part : parts) { if (part.startsWith("host=")) @@ -148,6 +148,12 @@ namespace BlackMisc } } + bool CDBusServer::isQtDefaultConnection(const QDBusConnection &connection) + { + return connection.name() == QDBusConnection::sessionBus().name() || + connection.name() == QDBusConnection::systemBus().name(); + } + bool CDBusServer::isQtDBusAddress(const QString &address) { return address.startsWith("tcp:") || address.startsWith("unix:"); @@ -300,6 +306,39 @@ namespace BlackMisc return system; } + QDBusConnection CDBusServer::connectToDBus(const QString &dBusAddress, const QString &name) + { + if (dBusAddress == sessionBusAddress()) + { + if (name.isEmpty()) return QDBusConnection::sessionBus(); + return QDBusConnection::connectToBus(QDBusConnection::SessionBus, name); + } + else if (dBusAddress == systemBusAddress()) + { + if (name.isEmpty()) return QDBusConnection::systemBus(); + return QDBusConnection::connectToBus(QDBusConnection::SystemBus, name); + } + else if (isP2PAddress(dBusAddress)) + { + return QDBusConnection::connectToPeer(dBusAddress, + name.isEmpty() ? CDBusServer::p2pConnectionName() : name); + } + return QDBusConnection("invalid"); + } + + void CDBusServer::disconnectFromDBus(const QDBusConnection &connection, const QString &dBusAddress) + { + if (CDBusServer::isQtDefaultConnection(connection)) return; // do not touch the default connections + if (CDBusServer::isP2PAddress(dBusAddress)) + { + QDBusConnection::disconnectFromPeer(connection.name()); + } + else + { + QDBusConnection::disconnectFromBus(connection.name()); + } + } + QString CDBusServer::p2pAddress(const QString &host, const QString &port) { QString h = host.trimmed().toLower().remove(' '); @@ -329,7 +368,7 @@ namespace BlackMisc // 192.168.5.3:9300 style if (h.contains(":")) { - QStringList parts = h.split(":"); + const QStringList parts = h.split(":"); h = parts.at(0).trimmed(); p = parts.at(1).trimmed(); } @@ -344,6 +383,12 @@ namespace BlackMisc return QString("tcp:host=%1,port=%2").arg(h).arg(p); } + const QString &CDBusServer::p2pConnectionName() + { + static const QString n("p2pConnection"); + return n; + } + QString CDBusServer::normalizeAddress(const QString &address) { const QString lc(address.toLower().trimmed()); @@ -355,7 +400,7 @@ namespace BlackMisc if (lc.startsWith("sys")) { return systemBusAddress(); } if (lc.startsWith("ses")) { return sessionBusAddress(); } - // Qt / p2p + // Qt / P2P if (isQtDBusAddress(address)) { return address; } return p2pAddress(address); } @@ -374,41 +419,28 @@ namespace BlackMisc return CNetworkUtils::canConnect(address, port, unused, timeoutMs); } - bool CDBusServer::isDBusAvailable(const QString &address, int port, QString &o_message, int timeoutMs) + bool CDBusServer::isDBusAvailable(const QString &address, int port, QString &message, int timeoutMs) { - return CNetworkUtils::canConnect(address, port, o_message, timeoutMs); + return CNetworkUtils::canConnect(address, port, message, timeoutMs); } - bool CDBusServer::isDBusAvailable(const QString &dbusAddress, QString &o_message, int timeoutMs) + bool CDBusServer::isDBusAvailable(const QString &dBusAddress, QString &message, int timeoutMs) { - if (dbusAddress.isEmpty()) { o_message = "no address"; return false; } - if (isP2PAddress(dbusAddress)) + if (dBusAddress.isEmpty()) { message = "No address."; return false; } + if (isP2PAddress(dBusAddress)) { QString host; int port = -1; - if (dBusAddressToHostAndPort(dbusAddress, host, port)) - { - return isDBusAvailable(host, port, o_message, timeoutMs); - } - else - { - return false; - } + return CDBusServer::dBusAddressToHostAndPort(dBusAddress, host, port) ? + CDBusServer::isDBusAvailable(host, port, message, timeoutMs) : + false; } else { - QString name = coreServiceName(); - QDBusConnection connection = dbusAddress == systemBusAddress() ? - QDBusConnection::connectToBus(QDBusConnection::SystemBus, name) : - QDBusConnection::connectToBus(QDBusConnection::SessionBus, name); - - // todo: further checks would need to go here - // failing session bus not detected yet - - o_message = connection.lastError().message(); - bool isConnected = connection.isConnected(); - - QDBusConnection::disconnectFromBus(name); + QDBusConnection connection = CDBusServer::connectToDBus(dBusAddress); + const bool isConnected = connection.isConnected(); + message = connection.lastError().message(); + CDBusServer::disconnectFromDBus(connection, dBusAddress); return isConnected; } } @@ -416,6 +448,6 @@ namespace BlackMisc bool CDBusServer::isDBusAvailable(const QString &dbusAddress, int timeoutMs) { QString unused; - return isDBusAvailable(dbusAddress, unused, timeoutMs); + return CDBusServer::isDBusAvailable(dbusAddress, unused, timeoutMs); } } // namespace diff --git a/src/blackmisc/dbusserver.h b/src/blackmisc/dbusserver.h index 4627ef008..a990f4a36 100644 --- a/src/blackmisc/dbusserver.h +++ b/src/blackmisc/dbusserver.h @@ -85,11 +85,20 @@ namespace BlackMisc //! Address denoting a system bus server static const QString &systemBusAddress(); + //! Connect to DBus + static QDBusConnection connectToDBus(const QString &dbusAddress, const QString &name = {}); + + //! Disconnect from Bus/Peer to peer + static void disconnectFromDBus(const QDBusConnection &connection, const QString &dBusAddress); + //! Address denoting a P2P server at the given host and port. //! \remarks Port number may be embedding in the host string after a colon. //! \return p2p address like "tcp:host=foo.bar.com,port=1234" static QString p2pAddress(const QString &host, const QString &port = ""); + //! P2P connection name + static const QString &p2pConnectionName(); + //! Turn something like 127.0.0.1:45000 into "tcp:host=127.0.0.1,port=45000" //! \note Handles also "session" and "system" as valid address while CDBusServer::p2pAddress is for //! P2P addresses only. @@ -110,11 +119,15 @@ namespace BlackMisc //! Extract host and port from a DBus address static bool dBusAddressToHostAndPort(QString dbusAddress, QString &o_host, int &o_port); + //! Is the given connection one of the default connections? + static bool isQtDefaultConnection(const QDBusConnection &connection); + //! Is there a DBus server running at the given address? + //! \note This is an incomplete test showing too optimistic results for session DBus //! @{ static bool isDBusAvailable(const QString &host, int port, int timeoutMs = 1500); - static bool isDBusAvailable(const QString &host, int port, QString &o_message, int timeoutMs = 1500); - static bool isDBusAvailable(const QString &dbusAddress, QString &o_message, int timeoutMs = 1500); + static bool isDBusAvailable(const QString &host, int port, QString &message, int timeoutMs = 1500); + static bool isDBusAvailable(const QString &dbusAddress, QString &message, int timeoutMs = 1500); static bool isDBusAvailable(const QString &dbusAddress, int timeoutMs = 1500); //! @}