bool DBusObjectManager::handleMessage(const DBusMessage& dbusMessage) { const char* objectPath = dbusMessage.getObjectPath(); const char* interfaceName = dbusMessage.getInterface(); assert(objectPath); assert(interfaceName); DBusInterfaceHandlerPath handlerPath(objectPath, interfaceName); objectPathLock_.lock(); auto handlerIterator = dbusRegisteredObjectsTable_.find(handlerPath); const bool foundDBusInterfaceHandler = handlerIterator != dbusRegisteredObjectsTable_.end(); bool dbusMessageHandled = false; if (foundDBusInterfaceHandler) { std::shared_ptr<DBusInterfaceHandler> dbusStubAdapterBase = handlerIterator->second; dbusMessageHandled = dbusStubAdapterBase->onInterfaceDBusMessage(dbusMessage); } else if (dbusMessage.hasInterfaceName("org.freedesktop.DBus.Introspectable")) { dbusMessageHandled = onIntrospectableInterfaceDBusMessage(dbusMessage); } objectPathLock_.unlock(); return dbusMessageHandled; }
bool DBusObjectManager::onIntrospectableInterfaceDBusMessage(const DBusMessage& dbusMessage) { std::shared_ptr<DBusProxyConnection> dbusConnection = dbusConnection_.lock(); if (!dbusConnection || !dbusMessage.isMethodCallType() || !dbusMessage.hasMemberName("Introspect")) { return false; } bool foundRegisteredObjects = false; std::stringstream xmlData(std::ios_base::out); xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\"" DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n" "<node name=\"" << dbusMessage.getObjectPath() << "\">\n" "<interface name=\"org.freedesktop.DBus.Introspectable\">\n" "<method name=\"Introspect\">\n" "<arg type=\"s\" name=\"xml_data\" direction=\"out\"/>\n" "</method>\n" "</interface>\n"; std::unordered_set<std::string> nodeSet; for (auto& registeredObjectsIterator : dbusRegisteredObjectsTable_) { const DBusInterfaceHandlerPath& handlerPath = registeredObjectsIterator.first; const std::string& dbusObjectPath = handlerPath.first; const std::string& dbusInterfaceName = handlerPath.second; std::shared_ptr<DBusInterfaceHandler> dbusStubAdapterBase = registeredObjectsIterator.second; std::vector<std::string> elems = CommonAPI::split(dbusObjectPath, '/'); if (dbusMessage.hasObjectPath(dbusObjectPath)) { foundRegisteredObjects = true; xmlData << "<interface name=\"" << dbusInterfaceName << "\">\n" << dbusStubAdapterBase->getMethodsDBusIntrospectionXmlData() << "\n" "</interface>\n"; nodeSet.insert(elems.back()); } else { if (dbusMessage.hasObjectPath("/") && elems.size() > 1) { if (nodeSet.find(elems[1]) == nodeSet.end()) { if (nodeSet.size() == 0) { xmlData.str(""); xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\"" DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n" "<node>\n"; } xmlData << " <node name=\"" << elems[1] << "\"/>\n"; nodeSet.insert(elems[1]); foundRegisteredObjects = true; } } else { for (unsigned int i = 1; i < elems.size() - 1; i++) { std::string build; for (unsigned int j = 1; j <= i; j++) { build = build + "/" + elems[j]; if (dbusMessage.hasObjectPath(build)) { if (nodeSet.find(elems[j + 1]) == nodeSet.end()) { if (nodeSet.size() == 0) { xmlData.str(""); xmlData << "<!DOCTYPE node PUBLIC \"" DBUS_INTROSPECT_1_0_XML_PUBLIC_IDENTIFIER "\"\n\"" DBUS_INTROSPECT_1_0_XML_SYSTEM_IDENTIFIER"\">\n" "<node>\n"; } xmlData << " <node name=\"" << elems[j + 1] << "\"/>\n"; nodeSet.insert(elems[j + 1]); foundRegisteredObjects = true; } break; } } } } } } if (foundRegisteredObjects) { DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("s"); DBusOutputStream dbusOutputStream(dbusMessageReply); xmlData << "</node>" ""; dbusOutputStream << xmlData.str(); dbusOutputStream.flush(); return dbusConnection->sendDBusMessage(dbusMessageReply); } return false; }