Support any message type in /subscribe callbacks Instead of hardcoding the possible variant types in the PropertiesChanged and InterfacesAdded callbacks used by the /subscribe REST operation, use convertDBusToJSON which can convert every D-Bus type to JSON. Tested: With the web UI running: * Restart the State.Host service, which triggers an InterfacesAdded callback since the web UI subscribes to that. It no longer crashes bmcweb with an sdbusplus error. * Change power states, and verify the web UI sees them through its subscription on the CurrentHostState property. Resolves openbmc/bmcweb#35 Change-Id: Ifa16c159d199005b42e3dfd4419bd3f9792c2d22 Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/include/dbus_monitor.hpp b/include/dbus_monitor.hpp index 44a7a94..d4f2647 100644 --- a/include/dbus_monitor.hpp +++ b/include/dbus_monitor.hpp
@@ -5,6 +5,7 @@ #include <boost/container/flat_map.hpp> #include <boost/container/flat_set.hpp> #include <dbus_singleton.hpp> +#include <openbmc_dbus_rest.hpp> #include <sdbusplus/bus/match.hpp> #include <sdbusplus/message/types.hpp> @@ -52,34 +53,50 @@ return 0; } sdbusplus::message::message message(m); - using VariantType = sdbusplus::message::variant<std::string, bool, int64_t, - uint64_t, double>; nlohmann::json j{{"event", message.get_member()}, {"path", message.get_path()}}; if (strcmp(message.get_member(), "PropertiesChanged") == 0) { - std::string interface_name; - boost::container::flat_map<std::string, VariantType> values; - message.read(interface_name, values); - j["properties"] = values; - j["interface"] = std::move(interface_name); + nlohmann::json data; + int r = openbmc_mapper::convertDBusToJSON("sa{sv}as", message, data); + if (r < 0) + { + BMCWEB_LOG_ERROR << "convertDBusToJSON failed with " << r; + return 0; + } + if (!data.is_array()) + { + BMCWEB_LOG_ERROR << "No data in PropertiesChanged signal"; + return 0; + } + + // data is type sa{sv}as and is an array[3] of string, object, array + j["interface"] = data[0]; + j["properties"] = data[1]; } else if (strcmp(message.get_member(), "InterfacesAdded") == 0) { - std::string object_name; - boost::container::flat_map< - std::string, boost::container::flat_map<std::string, VariantType>> - values; - message.read(object_name, values); - for (const std::pair< - std::string, - boost::container::flat_map<std::string, VariantType>>& paths : - values) + nlohmann::json data; + int r = openbmc_mapper::convertDBusToJSON("oa{sa{sv}}", message, data); + if (r < 0) { - auto it = thisSession->second.interfaces.find(paths.first); + BMCWEB_LOG_ERROR << "convertDBusToJSON failed with " << r; + return 0; + } + + if (!data.is_array()) + { + BMCWEB_LOG_ERROR << "No data in InterfacesAdded signal"; + return 0; + } + + // data is type oa{sa{sv}} which is an array[2] of string, object + for (auto& entry : data[1].items()) + { + auto it = thisSession->second.interfaces.find(entry.key()); if (it != thisSession->second.interfaces.end()) { - j["interfaces"][paths.first] = paths.second; + j["interfaces"][entry.key()] = entry.value(); } } }