refs #520 CDBusServer style/cleanup.

This commit is contained in:
Mathew Sutcliffe
2015-11-29 20:14:31 +00:00
parent 2a980af25b
commit 01d20c53e7
15 changed files with 186 additions and 234 deletions

View File

@@ -17,44 +17,35 @@ using namespace BlackMisc::Network;
namespace BlackMisc
{
/*
* Constructor
* Remark, without the default "unix:tmpdir=/tmp" any refereal to address crashes
* see http://download.froglogic.com/public/qt5-squishcoco-report/QtBase/source_241_preprocessed.html
* DBus config: http://dbus.freedesktop.org/doc/dbus-daemon.1.html
*/
CDBusServer::CDBusServer(const QString &service, const QString &address, QObject *parent) : QObject(parent)
{
ServerMode m = CDBusServer::addressToDBusMode(address);
switch (m)
m_serverMode = modeOfAddress(address);
switch (m_serverMode)
{
case SERVERMODE_SESSIONBUS:
{
// we use a session bus connection instead of a real P2P connection
this->m_serverMode = CDBusServer::SERVERMODE_SESSIONBUS;
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, ServiceName());
if (!connection.isConnected())
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, coreServiceName());
if (! connection.isConnected())
{
launchDbusDaemon();
connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, ServiceName());
launchDBusDaemon();
connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, coreServiceName());
}
if (!connection.registerService(service))
if (! connection.registerService(service))
{
// registration fails can either mean something wrong with DBus or service already exists
CLogMessage(this).warning("DBus registration: %1") << connection.lastError().message();
CLogMessage(this).warning("Cannot register DBus service, server started? dbus-daemon.exe --session --address=tcp:host=192.168.0.133,port=45000");
CLogMessage(this).warning("Cannot register DBus service, check server running: dbus-daemon.exe --session --address=tcp:host=192.168.0.133,port=45000");
}
}
break;
case SERVERMODE_SYSTEMBUS:
{
// we use a system bus connection instead of a real P2P connection
this->m_serverMode = CDBusServer::SERVERMODE_SYSTEMBUS;
QDBusConnection connection = QDBusConnection::systemBus();
if (!connection.isConnected())
{
launchDbusDaemon();
launchDBusDaemon();
connection = QDBusConnection::systemBus();
}
@@ -62,46 +53,42 @@ namespace BlackMisc
{
// registration fails can either mean something wrong with DBus or service already exists
CLogMessage(this).warning("DBus registration: %1") << connection.lastError().message();
CLogMessage(this).warning("Cannot register DBus service, server started? dbus-daemon.exe --session --address=tcp:host=192.168.0.133,port=45000");
CLogMessage(this).warning("Cannot register DBus service, check server running: dbus-daemon.exe --system --address=tcp:host=192.168.0.133,port=45000");
}
}
break;
case SERVERMODE_P2P:
default:
{
QString dbusAddress(CDBusServer::isQtDBusAddress(address) ? address : "tcp:host=127.0.0.1,port=45000");
QString dbusAddress = isQtDBusAddress(address) ? address : "tcp:host=127.0.0.1,port=45000";
dbusAddress = dbusAddress.toLower().trimmed().replace(' ', "");
if (!dbusAddress.contains("bind=")) { dbusAddress = dbusAddress.append(",bind=*"); }
this->m_serverMode = CDBusServer::SERVERMODE_P2P;
this->m_busServer.reset(
new QDBusServer(
dbusAddress, // "unix:tmpdir=/tmp"
parent)
);
if (! dbusAddress.contains("bind=")) { dbusAddress = dbusAddress.append(",bind=*"); } // bind to all network interfaces
m_busServer.reset(new QDBusServer(dbusAddress, parent));
m_busServer->setAnonymousAuthenticationAllowed(true);
// Note: P2P has no service name
if (!m_busServer->isConnected())
if (m_busServer->isConnected())
{
CLogMessage(this).warning("DBus P2P connection failed: %1") << this->lastQDBusServerError().message();
CLogMessage(this).debug() << "Server listening on address:" << m_busServer->address();
}
else
{
CLogMessage(this).debug() << "Server listening on address: " << m_busServer->address();
CLogMessage(this).warning("DBus P2P connection failed: %1") << lastQDBusServerError().message();
}
connect(m_busServer.data(), &QDBusServer::newConnection, this, &CDBusServer::ps_registerObjectsWithP2PConnection);
}
break;
} // switch
}
}
const QString &CDBusServer::ServiceName()
const QString &CDBusServer::coreServiceName()
{
static const QString sn(SWIFT_SERVICENAME);
static const QString sn = SWIFT_SERVICENAME;
return sn;
}
void CDBusServer::launchDbusDaemon()
void CDBusServer::launchDBusDaemon()
{
const QString program = QStringLiteral("dbus-daemon");
const QStringList arguments = { QStringLiteral("--config-file=../share/dbus-1/session.conf") };
@@ -111,173 +98,157 @@ namespace BlackMisc
bool CDBusServer::isP2PAddress(const QString &address)
{
return CDBusServer::addressToDBusMode(address) == SERVERMODE_P2P;
return modeOfAddress(address) == SERVERMODE_P2P;
}
bool CDBusServer::splitDBusAddressIntoHostAndPort(const QString &dbusAddress, QString &host, int &port)
bool CDBusServer::dBusAddressToHostAndPort(QString address, QString &host, int &port)
{
bool ok = false;
QString dbus(dbusAddress.trimmed().toLower().replace(' ', ""));
if (dbus.contains("host=") || dbus.contains("port="))
address = address.trimmed().toLower().replace(' ', "");
if (address.contains("host=") || address.contains("port="))
{
// "tcp:host=foo.com,port=123"
QStringList parts(dbus.split(','));
for (const QString &p : parts)
QStringList parts(address.split(','));
for (const QString &part : parts)
{
if (p.contains("host="))
if (part.startsWith("host="))
{
host = p.mid(p.lastIndexOf("=") + 1).trimmed();
host = part.mid(part.lastIndexOf("=") + 1).trimmed();
}
else if (p.contains("port="))
else if (part.startsWith("port="))
{
bool ok;
port = p.mid(p.lastIndexOf("=") + 1).trimmed().toInt(&ok);
if (!ok) { port = -1; }
port = part.mid(part.lastIndexOf("=") + 1).trimmed().toInt(&ok);
if (! ok) { port = -1; }
}
}
if (port < 0) { port = 45000; }
if (host.isEmpty()) { host = "127.0.0.1"; }
ok = true;
return true;
}
if (!ok)
else
{
host = "";
port = -1;
return false;
}
return ok;
}
bool CDBusServer::isQtDBusAddress(const QString &address)
{
return
(address.contains("tcp:") ||
address.contains("unix:")
);
return address.startsWith("tcp:") || address.startsWith("unix:");
}
bool CDBusServer::isSessionOrSystemAddress(const QString &address)
{
return address == sessionDBusServer() || address == systemDBusServer();
return address == sessionBusAddress() || address == systemBusAddress();
}
const QString CDBusServer::getClassInfo(QObject *object)
QString CDBusServer::getDBusInterfaceFromClassInfo(QObject *object)
{
if (!object) return "";
if (! object) { return ""; }
const QMetaObject *mo = object->metaObject();
if (mo->classInfoCount() < 1) return "";
for (int i = 0; i < mo->classInfoCount(); i++)
{
QMetaClassInfo ci = mo->classInfo(i);
QString name(ci.name());
if (name == "D-Bus Interface") { return QString(ci.value()); }
if (ci.name() == "D-Bus Interface") { return QString(ci.value()); }
}
return "";
}
bool CDBusServer::ps_registerObjectsWithP2PConnection(const QDBusConnection &connection)
bool CDBusServer::ps_registerObjectsWithP2PConnection(QDBusConnection connection)
{
Q_ASSERT(!this->m_objects.isEmpty());
QDBusConnection newConnection(connection); // copy, because object will be registered on this connection
// insert or replace connection
m_DBusConnections.insert(newConnection.name(), newConnection);
Q_ASSERT(! m_objects.isEmpty());
m_connections.insert(connection.name(), connection);
CLogMessage(this).debug() << "New Connection from:" << connection.name();
bool success = true;
CLogMessage(this).debug() << "New Connection from: " << newConnection.name();
QMap<QString, QObject *>::ConstIterator i = m_objects.begin();
while (i != m_objects.end())
for (auto i = m_objects.begin(); i != m_objects.end(); ++i)
{
CLogMessage(this).debug() << "Adding " << i.key() << CDBusServer::getClassInfo(i.value()) << "to the new connection.";
bool ok = newConnection.registerObject(i.key(), i.value(), CDBusServer::RegisterOptions());
CLogMessage(this).debug() << "Adding" << i.key() << getDBusInterfaceFromClassInfo(i.value()) << "to the new connection.";
bool ok = connection.registerObject(i.key(), i.value(), registerOptions());
Q_ASSERT_X(ok, "CDBusServer::newConnection", "Registration failed");
if (!ok) { success = false; }
++i;
if (! ok) { success = false; }
}
return success;
}
void CDBusServer::addObject(const QString &path, QObject *object)
{
if (!object) { return; }
m_objects.insert(path, object); // For P2P: registered when P2P connection is established
if (! object) { return; }
m_objects.insert(path, object); // will be registered when P2P connection is established
// P2P
if (this->m_serverMode == CDBusServer::SERVERMODE_P2P)
switch (m_serverMode)
{
return;
}
bool success = false;
if (this->m_serverMode == CDBusServer::SERVERMODE_SESSIONBUS)
{
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, ServiceName());
success = connection.registerObject(path, object, CDBusServer::RegisterOptions());
if (success)
case SERVERMODE_SESSIONBUS:
{
CLogMessage(this).debug() << "Adding " << path << CDBusServer::getClassInfo(object) << " to session bus.";
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, coreServiceName());
if (connection.registerObject(path, object, registerOptions()))
{
CLogMessage(this).debug() << "Adding" << path << getDBusInterfaceFromClassInfo(object) << "to session bus.";
}
else
{
CLogMessage(this).error("Error, no success with session bus registration");
}
}
else
break;
case SERVERMODE_SYSTEMBUS:
{
CLogMessage(this).error("Error, no success with session bus registration");
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SystemBus, coreServiceName());
if (connection.registerObject(path, object, registerOptions()))
{
CLogMessage(this).debug() << "Adding" << path << getDBusInterfaceFromClassInfo(object) << "to system bus.";
}
else
{
CLogMessage(this).error("Error, no success with system bus registration");
}
}
}
else if (this->m_serverMode == CDBusServer::SERVERMODE_SYSTEMBUS)
{
QDBusConnection connection = QDBusConnection::connectToBus(QDBusConnection::SystemBus, ServiceName());
success = connection.registerObject(path, object, CDBusServer::RegisterOptions());
if (success)
{
CLogMessage(this).debug() << "Adding " << path << CDBusServer::getClassInfo(object) << " to system bus.";
}
else
{
CLogMessage(this).error("Error, no success with system bus registration");
}
}
else
{
break;
case SERVERMODE_P2P:
break;
default:
Q_ASSERT_X(false, "CDBusServer::addObject", "Wrong server mode");
}
}
QDBusError CDBusServer::lastQDBusServerError() const
{
if (!hasQDBusServer()) { return QDBusError(); }
return this->m_busServer->lastError();
if (! hasQDBusServer()) { return {}; }
return m_busServer->lastError();
}
const QDBusServer *CDBusServer::qDBusServer() const
{
return this->m_busServer.data();
return m_busServer.data();
}
bool CDBusServer::hasQDBusServer() const
{
return !this->m_busServer.isNull();
return ! m_busServer.isNull();
}
void CDBusServer::unregisterAllObjects()
void CDBusServer::removeAllObjects()
{
if (this->m_objects.isEmpty()) return;
foreach(QString path, this->m_objects.keys())
for (const QString &path : m_objects.keys())
{
switch (this->m_serverMode)
switch (m_serverMode)
{
case CDBusServer::SERVERMODE_SESSIONBUS:
case SERVERMODE_SESSIONBUS:
QDBusConnection::sessionBus().unregisterObject(path);
break;
case CDBusServer::SERVERMODE_SYSTEMBUS:
case SERVERMODE_SYSTEMBUS:
QDBusConnection::systemBus().unregisterObject(path);
break;
case CDBusServer::SERVERMODE_P2P:
case SERVERMODE_P2P:
{
foreach(QDBusConnection connection, this->m_DBusConnections)
for(QDBusConnection connection : m_connections)
{
connection.unregisterObject(path);
}
break;
}
}
} // all paths
}
}
const QDBusConnection &CDBusServer::defaultConnection()
@@ -286,15 +257,15 @@ namespace BlackMisc
return defaultConnection;
}
const QString &CDBusServer::sessionDBusServer()
const QString &CDBusServer::sessionBusAddress()
{
static QString session("session");
static QString session = "session";
return session;
}
const QString &CDBusServer::systemDBusServer()
const QString &CDBusServer::systemBusAddress()
{
static QString system("system");
static QString system = "system";
return system;
}
@@ -303,8 +274,7 @@ namespace BlackMisc
QString h = host.isEmpty() ? "127.0.0.1" : host.trimmed();
QString p = port;
// can handle host and port separately or combined
// such as "myHost::1234"
// can handle host and port separately or combined, e.g. "myhost:1234"
if (port.isEmpty())
{
if (h.contains(":"))
@@ -322,47 +292,46 @@ namespace BlackMisc
}
// todo: Replace assert with input validation
Q_ASSERT_X(CNetworkUtils::isValidIPv4Address(p), "p2pAdress", "Wrong IP in String");
QString p2p = QString("tcp:host=%1,port=%2").arg(h).arg(p);
return p2p;
Q_ASSERT_X(CNetworkUtils::isValidIPv4Address(p), "CDBusServer::p2pAddress", "Wrong IP in String");
return QString("tcp:host=%1,port=%2").arg(h).arg(p);
}
QString CDBusServer::fixAddressToDBusAddress(const QString &address)
QString CDBusServer::normalizeAddress(const QString &address)
{
if (address.isEmpty() || address == sessionDBusServer() || address == systemDBusServer()) { return address; }
if (address.startsWith("tcp:") || address.startsWith("unix:")) return address;
if (address.isEmpty() || address == sessionBusAddress() || address == systemBusAddress()) { return address; }
if (isQtDBusAddress(address)) { return address; }
return p2pAddress(address);
}
CDBusServer::ServerMode CDBusServer::addressToDBusMode(const QString &address)
CDBusServer::ServerMode CDBusServer::modeOfAddress(QString address)
{
QString a = address.toLower();
if (a == CDBusServer::systemDBusServer()) { return SERVERMODE_SYSTEMBUS; }
else if (a == CDBusServer::sessionDBusServer()) { return SERVERMODE_SESSIONBUS; }
else { return SERVERMODE_P2P; }
address = address.toLower();
if (address == systemBusAddress()) { return SERVERMODE_SYSTEMBUS; }
else if (address == sessionBusAddress()) { return SERVERMODE_SESSIONBUS; }
else { return SERVERMODE_P2P; }
}
bool CDBusServer::isDBusAvailable(const QString &address, int port, int timeoutMs)
{
QString m;
return CNetworkUtils::canConnect(address, port, m, timeoutMs);
QString unused;
return CNetworkUtils::canConnect(address, port, unused, timeoutMs);
}
bool CDBusServer::isDBusAvailable(const QString &address, int port, QString &message, int timeoutMs)
bool CDBusServer::isDBusAvailable(const QString &address, int port, QString &o_message, int timeoutMs)
{
return CNetworkUtils::canConnect(address, port, message, timeoutMs);
return CNetworkUtils::canConnect(address, port, o_message, timeoutMs);
}
bool CDBusServer::isDBusAvailable(const QString &dbusAddress, QString &message, int timeoutMs)
bool CDBusServer::isDBusAvailable(const QString &dbusAddress, QString &o_message, int timeoutMs)
{
if (dbusAddress.isEmpty()) { message = "no address"; return false; }
if (dbusAddress.isEmpty()) { o_message = "no address"; return false; }
if (isP2PAddress(dbusAddress))
{
QString host;
int port = -1;
if (splitDBusAddressIntoHostAndPort(dbusAddress, host, port))
if (dBusAddressToHostAndPort(dbusAddress, host, port))
{
return isDBusAvailable(host, port, message, timeoutMs);
return isDBusAvailable(host, port, o_message, timeoutMs);
}
else
{
@@ -371,26 +340,20 @@ namespace BlackMisc
}
else
{
QDBusConnection connection(
(dbusAddress == systemDBusServer()) ?
QDBusConnection::systemBus() :
QDBusConnection::connectToBus(QDBusConnection::SessionBus, ServiceName())
);
bool success = connection.isConnected();
QDBusConnection connection(dbusAddress == systemBusAddress() ? QDBusConnection::systemBus() : QDBusConnection::connectToBus(QDBusConnection::SessionBus, coreServiceName()));
// further checks would need to go here
// todo: further checks would need to go here
// failing session bus not detected yet
message = connection.lastError().message();
connection.disconnectFromBus(ServiceName());
return success;
o_message = connection.lastError().message();
return connection.isConnected();
}
}
bool CDBusServer::isDBusAvailable(const QString &dbusAddress, int timeoutMs)
{
QString m;
return isDBusAvailable(dbusAddress, m, timeoutMs);
QString unused;
return isDBusAvailable(dbusAddress, unused, timeoutMs);
}
} // namespace