inline CallStatus handleDBusMessageReply( const CallStatus _dbusMessageCallStatus, const DBusMessage& _dbusMessage, index_sequence<ArgIndices_...>, std::tuple<ArgTypes_...>& _argTuple) const { (void)_argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650 CallStatus callStatus = _dbusMessageCallStatus; if (_dbusMessageCallStatus == CallStatus::SUCCESS) { DBusInputStream dbusInputStream(_dbusMessage); if(DBusSerializableArguments<ArgTypes_...>::deserialize(dbusInputStream, std::get<ArgIndices_>(_argTuple)...)) { } else { callStatus = CallStatus::REMOTE_ERROR; } } else { if(_dbusMessage.isErrorType()) { //ensure that delegate object (e.g. Proxy and its error events) survives if(auto itsDelegateObject = this->delegate_.object_.lock()) { DBusErrorEventHelper::notifyListeners(_dbusMessage, _dbusMessage.getError(), typename make_sequence_range<sizeof...(ErrorEvents_), 0>::type(), errorEvents_); } } } //ensure that delegate object (i.e Proxy) is not destroyed while callback function is invoked if(auto itsDelegateObject = this->delegate_.object_.lock()) this->delegate_.function_(callStatus, std::move(std::get<ArgIndices_>(_argTuple))...); return callStatus; }
inline CallStatus handleDBusMessageReply( const CallStatus dbusMessageCallStatus, const DBusMessage& dbusMessage, index_sequence<ArgIndices_...>, std::tuple<ArgTypes_...> argTuple) const { (void)argTuple; // this suppresses warning "set but not used" in case of empty _ArgTypes // Looks like: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57560 - Bug 57650 CallStatus callStatus = dbusMessageCallStatus; if (dbusMessageCallStatus == CallStatus::SUCCESS) { if (!dbusMessage.isErrorType()) { DBusInputStream dbusInputStream(dbusMessage); const bool success = DBusSerializableArguments<ArgTypes_...>::deserialize( dbusInputStream, std::get<ArgIndices_>(argTuple)...); if (!success) callStatus = CallStatus::REMOTE_ERROR; } else { callStatus = CallStatus::REMOTE_ERROR; } } callback_(callStatus, std::move(std::get<ArgIndices_>(argTuple))...); return callStatus; }
bool DBusObjectManagerStub::onInterfaceDBusMessage(const DBusMessage& dbusMessage) { auto dbusConnection = dbusConnection_.lock(); if (!dbusConnection || !dbusConnection->isConnected()) { return false; } if (!dbusMessage.isMethodCallType() || !dbusMessage.hasMemberName("GetManagedObjects")) { return false; } std::lock_guard<std::mutex> dbusObjectManagerStubLock(dbusObjectManagerStubLock_); DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict; for (const auto& registeredDBusObjectPathIterator : registeredDBusObjectPathsMap_) { const std::string& registeredDBusObjectPath = registeredDBusObjectPathIterator.first; const auto& registeredDBusInterfacesMap = registeredDBusObjectPathIterator.second; DBusInterfacesAndPropertiesDict dbusInterfacesAndPropertiesDict; assert(registeredDBusObjectPath.length() > 0); assert(registeredDBusInterfacesMap.size() > 0); for (const auto& registeredDBusInterfaceIterator : registeredDBusInterfacesMap) { const std::string& registeredDBusInterfaceName = registeredDBusInterfaceIterator.first; const auto& registeredDBusStubAdapter = registeredDBusInterfaceIterator.second; assert(registeredDBusInterfaceName.length() > 0); dbusInterfacesAndPropertiesDict.insert({ registeredDBusInterfaceName, DBusPropertiesChangedDict() }); if (registeredDBusStubAdapter->isManagingInterface()) { dbusInterfacesAndPropertiesDict.insert({ getInterfaceName(), DBusPropertiesChangedDict() }); } } dbusObjectPathAndInterfacesDict.insert({ registeredDBusObjectPath, std::move(dbusInterfacesAndPropertiesDict) }); } DBusMessage dbusMessageReply = dbusMessage.createMethodReturn("a{oa{sa{sv}}}"); DBusOutputStream dbusOutputStream(dbusMessageReply); dbusOutputStream << dbusObjectPathAndInterfacesDict; dbusOutputStream.flush(); const bool dbusMessageReplySent = dbusConnection->sendDBusMessage(dbusMessageReply); return dbusMessageReplySent; }
SubscriptionStatus DBusServiceRegistry::onSignalDBusMessage(const DBusMessage& dbusMessage) { const std::string& dbusServiceUniqueName = dbusMessage.getSenderName(); assert(dbusMessage.isSignalType()); assert(dbusMessage.hasInterfaceName("org.freedesktop.DBus.ObjectManager")); assert(dbusMessage.hasMemberName("InterfacesAdded") || dbusMessage.hasMemberName("InterfacesRemoved")); DBusInputStream dbusInputStream(dbusMessage); std::string dbusObjectPath; std::unordered_set<std::string> dbusInterfaceNames; DBusRecordState dbusInterfaceNameState; dbusInputStream >> dbusObjectPath; if (dbusMessage.hasMemberName("InterfacesAdded")) { dbusInterfaceNameState = DBusRecordState::AVAILABLE; typedef std::unordered_map<std::string, bool> DBusPropertiesChangedDict; typedef std::unordered_map<std::string, DBusPropertiesChangedDict> DBusInterfacesAndPropertiesDict; typedef std::unordered_map<std::string, DBusInterfacesAndPropertiesDict> DBusObjectPathAndInterfacesDict; DBusObjectPathAndInterfacesDict dbusObjectPathAndInterfacesDict; dbusInputStream >> dbusObjectPathAndInterfacesDict; for (auto& dbusInterfaceIterator : dbusObjectPathAndInterfacesDict) { const auto& dbusInterfaceName = dbusInterfaceIterator.first; dbusInterfaceNames.insert(dbusInterfaceName); } } else {
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; }