From 1abe55ef9844afcddcab9d862ae06118f3a2390c Mon Sep 17 00:00:00 2001 From: Ed Tanous Date: Wed, 5 Sep 2018 08:30:59 -0700 Subject: Move to clang-format-6.0 This commit moves the codebase to the lastest clang-format file from upstream, as well as clang-format-6.0. Change-Id: Ice8313468097c0c42317fbb9e10ddf036e8cff4c Signed-off-by: Ed Tanous --- include/openbmc_dbus_rest.hpp | 2407 +++++++++++++++++++++++------------------ 1 file changed, 1365 insertions(+), 1042 deletions(-) (limited to 'include/openbmc_dbus_rest.hpp') diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp index 3e6443d29e..4f6c233ff7 100644 --- a/include/openbmc_dbus_rest.hpp +++ b/include/openbmc_dbus_rest.hpp @@ -1,64 +1,78 @@ #include - #include + +#include +#include #include #include #include -#include -#include -namespace crow { -namespace openbmc_mapper { +namespace crow +{ +namespace openbmc_mapper +{ void introspectObjects(crow::Response &res, std::string process_name, std::string path, - std::shared_ptr transaction) { - crow::connections::systemBus->async_method_call( - [ - &res, transaction, processName{std::move(process_name)}, - objectPath{std::move(path)} - ](const boost::system::error_code ec, const std::string &introspect_xml) { - if (ec) { - BMCWEB_LOG_ERROR << "Introspect call failed with error: " - << ec.message() << " on process: " << processName - << " path: " << objectPath << "\n"; - - } else { - transaction->push_back({{"path", objectPath}}); - - tinyxml2::XMLDocument doc; - - doc.Parse(introspect_xml.c_str()); - tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); - if (pRoot == nullptr) { - BMCWEB_LOG_ERROR << "XML document failed to parse " << processName - << " " << objectPath << "\n"; - - } else { - tinyxml2::XMLElement *node = pRoot->FirstChildElement("node"); - while (node != nullptr) { - std::string childPath = node->Attribute("name"); - std::string newpath; - if (objectPath != "/") { - newpath += objectPath; - } - newpath += "/" + childPath; - // introspect the subobjects as well - introspectObjects(res, processName, newpath, transaction); - - node = node->NextSiblingElement("node"); + std::shared_ptr transaction) +{ + crow::connections::systemBus->async_method_call( + [&res, transaction, processName{std::move(process_name)}, + objectPath{std::move(path)}](const boost::system::error_code ec, + const std::string &introspect_xml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " << ec.message() + << " on process: " << processName << " path: " << objectPath + << "\n"; } - } - } - // if we're the last outstanding caller, finish the request - if (transaction.use_count() == 1) { - res.jsonValue = {{"status", "ok"}, - {"bus_name", processName}, - {"objects", std::move(*transaction)}}; - res.end(); - } - }, - process_name, path, "org.freedesktop.DBus.Introspectable", "Introspect"); + else + { + transaction->push_back({{"path", objectPath}}); + + tinyxml2::XMLDocument doc; + + doc.Parse(introspect_xml.c_str()); + tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR << "XML document failed to parse " + << processName << " " << objectPath + << "\n"; + } + else + { + tinyxml2::XMLElement *node = + pRoot->FirstChildElement("node"); + while (node != nullptr) + { + std::string childPath = node->Attribute("name"); + std::string newpath; + if (objectPath != "/") + { + newpath += objectPath; + } + newpath += "/" + childPath; + // introspect the subobjects as well + introspectObjects(res, processName, newpath, + transaction); + + node = node->NextSiblingElement("node"); + } + } + } + // if we're the last outstanding caller, finish the request + if (transaction.use_count() == 1) + { + res.jsonValue = {{"status", "ok"}, + {"bus_name", processName}, + {"objects", std::move(*transaction)}}; + res.end(); + } + }, + process_name, path, "org.freedesktop.DBus.Introspectable", + "Introspect"); } // A smattering of common types to unpack. TODO(ed) this should really iterate @@ -74,46 +88,60 @@ using ManagedObjectType = std::vector>>>; -void getManagedObjectsForEnumerate( - const std::string &object_name, const std::string &connection_name, - crow::Response &res, std::shared_ptr transaction) { - crow::connections::systemBus->async_method_call( - [&res, transaction](const boost::system::error_code ec, - const ManagedObjectType &objects) { - if (ec) { - BMCWEB_LOG_ERROR << ec; - } else { - nlohmann::json &dataJson = *transaction; - - for (auto &objectPath : objects) { - BMCWEB_LOG_DEBUG - << "Reading object " - << static_cast(objectPath.first); - nlohmann::json &objectJson = - dataJson[static_cast(objectPath.first)]; - if (objectJson.is_null()) { - objectJson = nlohmann::json::object(); +void getManagedObjectsForEnumerate(const std::string &object_name, + const std::string &connection_name, + crow::Response &res, + std::shared_ptr transaction) +{ + crow::connections::systemBus->async_method_call( + [&res, transaction](const boost::system::error_code ec, + const ManagedObjectType &objects) { + if (ec) + { + BMCWEB_LOG_ERROR << ec; } - for (const auto &interface : objectPath.second) { - for (const auto &property : interface.second) { - nlohmann::json &propertyJson = objectJson[property.first]; - mapbox::util::apply_visitor( - [&propertyJson](auto &&val) { propertyJson = val; }, - property.second); - } + else + { + nlohmann::json &dataJson = *transaction; + + for (auto &objectPath : objects) + { + BMCWEB_LOG_DEBUG + << "Reading object " + << static_cast(objectPath.first); + nlohmann::json &objectJson = + dataJson[static_cast( + objectPath.first)]; + if (objectJson.is_null()) + { + objectJson = nlohmann::json::object(); + } + for (const auto &interface : objectPath.second) + { + for (const auto &property : interface.second) + { + nlohmann::json &propertyJson = + objectJson[property.first]; + mapbox::util::apply_visitor( + [&propertyJson](auto &&val) { + propertyJson = val; + }, + property.second); + } + } + } } - } - } - if (transaction.use_count() == 1) { - res.jsonValue = {{"message", "200 OK"}, - {"status", "ok"}, - {"data", std::move(*transaction)}}; - res.end(); - } - }, - connection_name, object_name, "org.freedesktop.DBus.ObjectManager", - "GetManagedObjects"); + if (transaction.use_count() == 1) + { + res.jsonValue = {{"message", "200 OK"}, + {"status", "ok"}, + {"data", std::move(*transaction)}}; + res.end(); + } + }, + connection_name, object_name, "org.freedesktop.DBus.ObjectManager", + "GetManagedObjects"); } using GetSubTreeType = std::vector< @@ -121,1025 +149,1320 @@ using GetSubTreeType = std::vector< std::vector>>>>; // Structure for storing data on an in progress action -struct InProgressActionData { - InProgressActionData(crow::Response &res) : res(res){}; - ~InProgressActionData() { - if (res.result() == boost::beast::http::status::internal_server_error) { - // Reset the json object to clear out any data that made it in before the - // error happened - // todo(ed) handle error condition with proper code - res.jsonValue = nlohmann::json::object(); +struct InProgressActionData +{ + InProgressActionData(crow::Response &res) : res(res){}; + ~InProgressActionData() + { + if (res.result() == boost::beast::http::status::internal_server_error) + { + // Reset the json object to clear out any data that made it in + // before the error happened todo(ed) handle error condition with + // proper code + res.jsonValue = nlohmann::json::object(); + } + res.end(); + } + + void setErrorStatus() + { + res.result(boost::beast::http::status::internal_server_error); } - res.end(); - } - - void setErrorStatus() { - res.result(boost::beast::http::status::internal_server_error); - } - crow::Response &res; - std::string path; - std::string methodName; - nlohmann::json arguments; + crow::Response &res; + std::string path; + std::string methodName; + nlohmann::json arguments; }; -std::vector dbusArgSplit(const std::string &string) { - std::vector ret; - if (string.empty()) { - return ret; - } - ret.push_back(""); - int containerDepth = 0; - - for (std::string::const_iterator character = string.begin(); - character != string.end(); character++) { - ret.back() += *character; - switch (*character) { - case ('a'): - break; - case ('('): - case ('{'): - containerDepth++; - break; - case ('}'): - case (')'): - containerDepth--; - if (containerDepth == 0) { - if (character + 1 != string.end()) { - ret.push_back(""); - } - } - break; - default: - if (containerDepth == 0) { - if (character + 1 != string.end()) { - ret.push_back(""); - } +std::vector dbusArgSplit(const std::string &string) +{ + std::vector ret; + if (string.empty()) + { + return ret; + } + ret.push_back(""); + int containerDepth = 0; + + for (std::string::const_iterator character = string.begin(); + character != string.end(); character++) + { + ret.back() += *character; + switch (*character) + { + case ('a'): + break; + case ('('): + case ('{'): + containerDepth++; + break; + case ('}'): + case (')'): + containerDepth--; + if (containerDepth == 0) + { + if (character + 1 != string.end()) + { + ret.push_back(""); + } + } + break; + default: + if (containerDepth == 0) + { + if (character + 1 != string.end()) + { + ret.push_back(""); + } + } + break; } - break; } - } } int convertJsonToDbus(sd_bus_message *m, const std::string &arg_type, - const nlohmann::json &input_json) { - int r = 0; - BMCWEB_LOG_DEBUG << "Converting " << input_json.dump() - << " to type: " << arg_type; - const std::vector argTypes = dbusArgSplit(arg_type); - - // Assume a single object for now. - const nlohmann::json *j = &input_json; - nlohmann::json::const_iterator jIt = input_json.begin(); - - for (const std::string &arg_code : argTypes) { - // If we are decoding multiple objects, grab the pointer to the iterator, - // and increment it for the next loop - if (argTypes.size() > 1) { - if (jIt == input_json.end()) { - return -2; - } - j = &*jIt; - jIt++; - } - const int64_t *int_value = j->get_ptr(); - const uint64_t *uint_value = j->get_ptr(); - const std::string *string_value = j->get_ptr(); - const double *double_value = j->get_ptr(); - const bool *b = j->get_ptr(); - int64_t v = 0; - double d = 0.0; - - // Do some basic type conversions that make sense. uint can be converted to - // int. int and uint can be converted to double - if (uint_value != nullptr && int_value == nullptr) { - v = static_cast(*uint_value); - int_value = &v; - } - if (uint_value != nullptr && double_value == nullptr) { - d = static_cast(*uint_value); - double_value = &d; - } - if (int_value != nullptr && double_value == nullptr) { - d = static_cast(*int_value); - double_value = &d; - } + const nlohmann::json &input_json) +{ + int r = 0; + BMCWEB_LOG_DEBUG << "Converting " << input_json.dump() + << " to type: " << arg_type; + const std::vector argTypes = dbusArgSplit(arg_type); + + // Assume a single object for now. + const nlohmann::json *j = &input_json; + nlohmann::json::const_iterator jIt = input_json.begin(); + + for (const std::string &arg_code : argTypes) + { + // If we are decoding multiple objects, grab the pointer to the + // iterator, and increment it for the next loop + if (argTypes.size() > 1) + { + if (jIt == input_json.end()) + { + return -2; + } + j = &*jIt; + jIt++; + } + const int64_t *int_value = j->get_ptr(); + const uint64_t *uint_value = j->get_ptr(); + const std::string *string_value = j->get_ptr(); + const double *double_value = j->get_ptr(); + const bool *b = j->get_ptr(); + int64_t v = 0; + double d = 0.0; + + // Do some basic type conversions that make sense. uint can be + // converted to int. int and uint can be converted to double + if (uint_value != nullptr && int_value == nullptr) + { + v = static_cast(*uint_value); + int_value = &v; + } + if (uint_value != nullptr && double_value == nullptr) + { + d = static_cast(*uint_value); + double_value = &d; + } + if (int_value != nullptr && double_value == nullptr) + { + d = static_cast(*int_value); + double_value = &d; + } - if (arg_code == "s") { - if (string_value == nullptr) { - return -1; - } - r = sd_bus_message_append_basic(m, arg_code[0], - (void *)string_value->c_str()); - if (r < 0) { - return r; - } - } else if (arg_code == "i") { - if (int_value == nullptr) { - return -1; - } - int32_t i = static_cast(*int_value); - r = sd_bus_message_append_basic(m, arg_code[0], &i); - if (r < 0) { - return r; - } - } else if (arg_code == "b") { - // lots of ways bool could be represented here. Try them all - int bool_int = false; - if (int_value != nullptr) { - bool_int = *int_value > 0 ? 1 : 0; - } else if (b != nullptr) { - bool_int = b ? 1 : 0; - } else if (string_value != nullptr) { - bool_int = boost::istarts_with(*string_value, "t") ? 1 : 0; - } else { - return -1; - } - r = sd_bus_message_append_basic(m, arg_code[0], &bool_int); - if (r < 0) { - return r; - } - } else if (arg_code == "n") { - if (int_value == nullptr) { - return -1; - } - int16_t n = static_cast(*int_value); - r = sd_bus_message_append_basic(m, arg_code[0], &n); - if (r < 0) { - return r; - } - } else if (arg_code == "x") { - if (int_value == nullptr) { - return -1; - } - r = sd_bus_message_append_basic(m, arg_code[0], int_value); - if (r < 0) { - return r; - } - } else if (arg_code == "y") { - if (uint_value == nullptr) { - return -1; - } - uint8_t y = static_cast(*uint_value); - r = sd_bus_message_append_basic(m, arg_code[0], &y); - } else if (arg_code == "q") { - if (uint_value == nullptr) { - return -1; - } - uint16_t q = static_cast(*uint_value); - r = sd_bus_message_append_basic(m, arg_code[0], &q); - } else if (arg_code == "u") { - if (uint_value == nullptr) { - return -1; - } - uint32_t u = static_cast(*uint_value); - r = sd_bus_message_append_basic(m, arg_code[0], &u); - } else if (arg_code == "t") { - if (uint_value == nullptr) { - return -1; - } - r = sd_bus_message_append_basic(m, arg_code[0], uint_value); - } else if (arg_code == "d") { - sd_bus_message_append_basic(m, arg_code[0], double_value); - } else if (boost::starts_with(arg_code, "a")) { - std::string contained_type = arg_code.substr(1); - r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, - contained_type.c_str()); - if (r < 0) { - return r; - } - - for (nlohmann::json::const_iterator it = j->begin(); it != j->end(); - ++it) { - r = convertJsonToDbus(m, contained_type, *it); - if (r < 0) { - return r; + if (arg_code == "s") + { + if (string_value == nullptr) + { + return -1; + } + r = sd_bus_message_append_basic(m, arg_code[0], + (void *)string_value->c_str()); + if (r < 0) + { + return r; + } } + else if (arg_code == "i") + { + if (int_value == nullptr) + { + return -1; + } + int32_t i = static_cast(*int_value); + r = sd_bus_message_append_basic(m, arg_code[0], &i); + if (r < 0) + { + return r; + } + } + else if (arg_code == "b") + { + // lots of ways bool could be represented here. Try them all + int bool_int = false; + if (int_value != nullptr) + { + bool_int = *int_value > 0 ? 1 : 0; + } + else if (b != nullptr) + { + bool_int = b ? 1 : 0; + } + else if (string_value != nullptr) + { + bool_int = boost::istarts_with(*string_value, "t") ? 1 : 0; + } + else + { + return -1; + } + r = sd_bus_message_append_basic(m, arg_code[0], &bool_int); + if (r < 0) + { + return r; + } + } + else if (arg_code == "n") + { + if (int_value == nullptr) + { + return -1; + } + int16_t n = static_cast(*int_value); + r = sd_bus_message_append_basic(m, arg_code[0], &n); + if (r < 0) + { + return r; + } + } + else if (arg_code == "x") + { + if (int_value == nullptr) + { + return -1; + } + r = sd_bus_message_append_basic(m, arg_code[0], int_value); + if (r < 0) + { + return r; + } + } + else if (arg_code == "y") + { + if (uint_value == nullptr) + { + return -1; + } + uint8_t y = static_cast(*uint_value); + r = sd_bus_message_append_basic(m, arg_code[0], &y); + } + else if (arg_code == "q") + { + if (uint_value == nullptr) + { + return -1; + } + uint16_t q = static_cast(*uint_value); + r = sd_bus_message_append_basic(m, arg_code[0], &q); + } + else if (arg_code == "u") + { + if (uint_value == nullptr) + { + return -1; + } + uint32_t u = static_cast(*uint_value); + r = sd_bus_message_append_basic(m, arg_code[0], &u); + } + else if (arg_code == "t") + { + if (uint_value == nullptr) + { + return -1; + } + r = sd_bus_message_append_basic(m, arg_code[0], uint_value); + } + else if (arg_code == "d") + { + sd_bus_message_append_basic(m, arg_code[0], double_value); + } + else if (boost::starts_with(arg_code, "a")) + { + std::string contained_type = arg_code.substr(1); + r = sd_bus_message_open_container(m, SD_BUS_TYPE_ARRAY, + contained_type.c_str()); + if (r < 0) + { + return r; + } + + for (nlohmann::json::const_iterator it = j->begin(); it != j->end(); + ++it) + { + r = convertJsonToDbus(m, contained_type, *it); + if (r < 0) + { + return r; + } - it++; - } - sd_bus_message_close_container(m); - } else if (boost::starts_with(arg_code, "v")) { - std::string contained_type = arg_code.substr(1); - BMCWEB_LOG_DEBUG << "variant type: " << arg_code - << " appending variant of type: " << contained_type; - r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, - contained_type.c_str()); - if (r < 0) { - return r; - } - - r = convertJsonToDbus(m, contained_type, input_json); - if (r < 0) { - return r; - } - - r = sd_bus_message_close_container(m); - if (r < 0) { - return r; - } - } else if (boost::starts_with(arg_code, "(") && - boost::ends_with(arg_code, ")")) { - std::string contained_type = arg_code.substr(1, arg_code.size() - 1); - r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, - contained_type.c_str()); - nlohmann::json::const_iterator it = j->begin(); - for (const std::string &arg_code : dbusArgSplit(arg_type)) { - if (it == j->end()) { - return -1; + it++; + } + sd_bus_message_close_container(m); } - r = convertJsonToDbus(m, arg_code, *it); - if (r < 0) { - return r; + else if (boost::starts_with(arg_code, "v")) + { + std::string contained_type = arg_code.substr(1); + BMCWEB_LOG_DEBUG + << "variant type: " << arg_code + << " appending variant of type: " << contained_type; + r = sd_bus_message_open_container(m, SD_BUS_TYPE_VARIANT, + contained_type.c_str()); + if (r < 0) + { + return r; + } + + r = convertJsonToDbus(m, contained_type, input_json); + if (r < 0) + { + return r; + } + + r = sd_bus_message_close_container(m); + if (r < 0) + { + return r; + } } - it++; - } - r = sd_bus_message_close_container(m); - } else if (boost::starts_with(arg_code, "{") && - boost::ends_with(arg_code, "}")) { - std::string contained_type = arg_code.substr(1, arg_code.size() - 1); - r = sd_bus_message_open_container(m, SD_BUS_TYPE_DICT_ENTRY, - contained_type.c_str()); - std::vector codes = dbusArgSplit(contained_type); - if (codes.size() != 2) { - return -1; - } - const std::string &key_type = codes[0]; - const std::string &value_type = codes[1]; - for (auto it : j->items()) { - r = convertJsonToDbus(m, key_type, it.key()); - if (r < 0) { - return r; + else if (boost::starts_with(arg_code, "(") && + boost::ends_with(arg_code, ")")) + { + std::string contained_type = + arg_code.substr(1, arg_code.size() - 1); + r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, + contained_type.c_str()); + nlohmann::json::const_iterator it = j->begin(); + for (const std::string &arg_code : dbusArgSplit(arg_type)) + { + if (it == j->end()) + { + return -1; + } + r = convertJsonToDbus(m, arg_code, *it); + if (r < 0) + { + return r; + } + it++; + } + r = sd_bus_message_close_container(m); } + else if (boost::starts_with(arg_code, "{") && + boost::ends_with(arg_code, "}")) + { + std::string contained_type = + arg_code.substr(1, arg_code.size() - 1); + r = sd_bus_message_open_container(m, SD_BUS_TYPE_DICT_ENTRY, + contained_type.c_str()); + std::vector codes = dbusArgSplit(contained_type); + if (codes.size() != 2) + { + return -1; + } + const std::string &key_type = codes[0]; + const std::string &value_type = codes[1]; + for (auto it : j->items()) + { + r = convertJsonToDbus(m, key_type, it.key()); + if (r < 0) + { + return r; + } - r = convertJsonToDbus(m, value_type, it.value()); - if (r < 0) { - return r; + r = convertJsonToDbus(m, value_type, it.value()); + if (r < 0) + { + return r; + } + } + r = sd_bus_message_close_container(m); + } + else + { + return -2; + } + if (r < 0) + { + return r; } - } - r = sd_bus_message_close_container(m); - } else { - return -2; - } - if (r < 0) { - return r; - } - if (argTypes.size() > 1) { - jIt++; + if (argTypes.size() > 1) + { + jIt++; + } } - } } void findActionOnInterface(std::shared_ptr transaction, - const std::string &connectionName) { - BMCWEB_LOG_DEBUG << "findActionOnInterface for connection " << connectionName; - crow::connections::systemBus->async_method_call( - [ - transaction, connectionName{std::string(connectionName)} - ](const boost::system::error_code ec, const std::string &introspect_xml) { - BMCWEB_LOG_DEBUG << "got xml:\n " << introspect_xml; - if (ec) { - BMCWEB_LOG_ERROR << "Introspect call failed with error: " - << ec.message() << " on process: " << connectionName - << "\n"; - } else { - tinyxml2::XMLDocument doc; - - doc.Parse(introspect_xml.c_str()); - tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); - if (pRoot == nullptr) { - BMCWEB_LOG_ERROR << "XML document failed to parse " - << connectionName << "\n"; - - } else { - tinyxml2::XMLElement *interface_node = - pRoot->FirstChildElement("interface"); - while (interface_node != nullptr) { - std::string this_interface_name = - interface_node->Attribute("name"); - tinyxml2::XMLElement *method_node = - interface_node->FirstChildElement("method"); - while (method_node != nullptr) { - std::string this_methodName = method_node->Attribute("name"); - BMCWEB_LOG_DEBUG << "Found method: " << this_methodName; - if (this_methodName == transaction->methodName) { - sdbusplus::message::message m = - crow::connections::systemBus->new_method_call( - connectionName.c_str(), transaction->path.c_str(), - this_interface_name.c_str(), - transaction->methodName.c_str()); - - tinyxml2::XMLElement *argument_node = - method_node->FirstChildElement("arg"); - - nlohmann::json::const_iterator arg_it = - transaction->arguments.begin(); - - while (argument_node != nullptr) { - std::string arg_direction = - argument_node->Attribute("direction"); - if (arg_direction == "in") { - std::string arg_type = argument_node->Attribute("type"); - if (arg_it == transaction->arguments.end()) { - transaction->setErrorStatus(); - return; - } - if (convertJsonToDbus(m.get(), arg_type, *arg_it) < 0) { - transaction->setErrorStatus(); - return; - } - - arg_it++; - } - argument_node = method_node->NextSiblingElement("arg"); - } - crow::connections::systemBus->async_send( - m, [transaction](boost::system::error_code ec, - sdbusplus::message::message &m) { - if (ec) { - transaction->setErrorStatus(); - return; + const std::string &connectionName) +{ + BMCWEB_LOG_DEBUG << "findActionOnInterface for connection " + << connectionName; + crow::connections::systemBus->async_method_call( + [transaction, connectionName{std::string(connectionName)}]( + const boost::system::error_code ec, + const std::string &introspect_xml) { + BMCWEB_LOG_DEBUG << "got xml:\n " << introspect_xml; + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " << ec.message() + << " on process: " << connectionName << "\n"; + } + else + { + tinyxml2::XMLDocument doc; + + doc.Parse(introspect_xml.c_str()); + tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR << "XML document failed to parse " + << connectionName << "\n"; + } + else + { + tinyxml2::XMLElement *interface_node = + pRoot->FirstChildElement("interface"); + while (interface_node != nullptr) + { + std::string this_interface_name = + interface_node->Attribute("name"); + tinyxml2::XMLElement *method_node = + interface_node->FirstChildElement("method"); + while (method_node != nullptr) + { + std::string this_methodName = + method_node->Attribute("name"); + BMCWEB_LOG_DEBUG << "Found method: " + << this_methodName; + if (this_methodName == transaction->methodName) + { + sdbusplus::message::message m = + crow::connections::systemBus + ->new_method_call( + connectionName.c_str(), + transaction->path.c_str(), + this_interface_name.c_str(), + transaction->methodName.c_str()); + + tinyxml2::XMLElement *argument_node = + method_node->FirstChildElement("arg"); + + nlohmann::json::const_iterator arg_it = + transaction->arguments.begin(); + + while (argument_node != nullptr) + { + std::string arg_direction = + argument_node->Attribute("direction"); + if (arg_direction == "in") + { + std::string arg_type = + argument_node->Attribute("type"); + if (arg_it == + transaction->arguments.end()) + { + transaction->setErrorStatus(); + return; + } + if (convertJsonToDbus(m.get(), arg_type, + *arg_it) < 0) + { + transaction->setErrorStatus(); + return; + } + + arg_it++; + } + argument_node = + method_node->NextSiblingElement("arg"); + } + crow::connections::systemBus->async_send( + m, [transaction]( + boost::system::error_code ec, + sdbusplus::message::message &m) { + if (ec) + { + transaction->setErrorStatus(); + return; + } + transaction->res.jsonValue = { + {"status", "ok"}, + {"message", "200 OK"}, + {"data", nullptr}}; + }); + break; + } + method_node = + method_node->NextSiblingElement("method"); } - transaction->res.jsonValue = {{"status", "ok"}, - {"message", "200 OK"}, - {"data", nullptr}}; - }); - break; + interface_node = + interface_node->NextSiblingElement("interface"); + } } - method_node = method_node->NextSiblingElement("method"); - } - interface_node = interface_node->NextSiblingElement("interface"); } - } - } - }, - connectionName, transaction->path, "org.freedesktop.DBus.Introspectable", - "Introspect"); + }, + connectionName, transaction->path, + "org.freedesktop.DBus.Introspectable", "Introspect"); } void handle_action(const crow::Request &req, crow::Response &res, - const std::string &objectPath, - const std::string &methodName) { - nlohmann::json requestDbusData = - nlohmann::json::parse(req.body, nullptr, false); - - if (requestDbusData.is_discarded()) { - res.result(boost::beast::http::status::bad_request); - res.end(); - return; - } - if (!requestDbusData.is_array()) { - res.result(boost::beast::http::status::bad_request); - res.end(); - return; - } - auto transaction = std::make_shared(res); - - transaction->path = objectPath; - transaction->methodName = methodName; - transaction->arguments = std::move(requestDbusData); - crow::connections::systemBus->async_method_call( - [transaction]( - const boost::system::error_code ec, - const std::vector>> - &interface_names) { - if (ec || interface_names.size() <= 0) { - transaction->setErrorStatus(); - return; - } + const std::string &objectPath, const std::string &methodName) +{ + nlohmann::json requestDbusData = + nlohmann::json::parse(req.body, nullptr, false); + + if (requestDbusData.is_discarded()) + { + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } + if (!requestDbusData.is_array()) + { + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } + auto transaction = std::make_shared(res); + + transaction->path = objectPath; + transaction->methodName = methodName; + transaction->arguments = std::move(requestDbusData); + crow::connections::systemBus->async_method_call( + [transaction]( + const boost::system::error_code ec, + const std::vector>> + &interface_names) { + if (ec || interface_names.size() <= 0) + { + transaction->setErrorStatus(); + return; + } - BMCWEB_LOG_DEBUG << "GetObject returned objects " - << interface_names.size(); + BMCWEB_LOG_DEBUG << "GetObject returned objects " + << interface_names.size(); - for (const std::pair> &object : - interface_names) { - findActionOnInterface(transaction, object.first); - } - }, - "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", objectPath, - std::array()); + for (const std::pair> + &object : interface_names) + { + findActionOnInterface(transaction, object.first); + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", objectPath, + std::array()); } -void handle_list(crow::Response &res, const std::string &objectPath) { - crow::connections::systemBus->async_method_call( - [&res](const boost::system::error_code ec, - std::vector &objectPaths) { - if (ec) { - res.result(boost::beast::http::status::internal_server_error); - } else { - res.jsonValue = {{"status", "ok"}, - {"message", "200 OK"}, - {"data", std::move(objectPaths)}}; - } - res.end(); - }, - "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", objectPath, - static_cast(99), std::array()); +void handle_list(crow::Response &res, const std::string &objectPath) +{ + crow::connections::systemBus->async_method_call( + [&res](const boost::system::error_code ec, + std::vector &objectPaths) { + if (ec) + { + res.result(boost::beast::http::status::internal_server_error); + } + else + { + res.jsonValue = {{"status", "ok"}, + {"message", "200 OK"}, + {"data", std::move(objectPaths)}}; + } + res.end(); + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", objectPath, + static_cast(99), std::array()); } -void handle_enumerate(crow::Response &res, const std::string &objectPath) { - crow::connections::systemBus->async_method_call( - [&res, objectPath{std::string(objectPath)} ]( - const boost::system::error_code ec, - const GetSubTreeType &object_names) { - if (ec) { - res.jsonValue = {{"message", "200 OK"}, - {"status", "ok"}, - {"data", nlohmann::json::object()}}; - - res.end(); - return; - } +void handle_enumerate(crow::Response &res, const std::string &objectPath) +{ + crow::connections::systemBus->async_method_call( + [&res, objectPath{std::string(objectPath)}]( + const boost::system::error_code ec, + const GetSubTreeType &object_names) { + if (ec) + { + res.jsonValue = {{"message", "200 OK"}, + {"status", "ok"}, + {"data", nlohmann::json::object()}}; - boost::container::flat_set connections; + res.end(); + return; + } - for (const auto &object : object_names) { - for (const auto &Connection : object.second) { - connections.insert(Connection.first); - } - } + boost::container::flat_set connections; - if (connections.size() <= 0) { - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - auto transaction = - std::make_shared(nlohmann::json::object()); - for (const std::string &Connection : connections) { - getManagedObjectsForEnumerate(objectPath, Connection, res, - transaction); - } - }, - "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetSubTree", objectPath, (int32_t)0, - std::array()); + for (const auto &object : object_names) + { + for (const auto &Connection : object.second) + { + connections.insert(Connection.first); + } + } + + if (connections.size() <= 0) + { + res.result(boost::beast::http::status::not_found); + res.end(); + return; + } + auto transaction = + std::make_shared(nlohmann::json::object()); + for (const std::string &Connection : connections) + { + getManagedObjectsForEnumerate(objectPath, Connection, res, + transaction); + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetSubTree", objectPath, + (int32_t)0, std::array()); } void handle_get(crow::Response &res, std::string &objectPath, - std::string &destProperty) { - BMCWEB_LOG_DEBUG << "handle_get: " << objectPath << " prop:" << destProperty; - std::shared_ptr property_name = - std::make_shared(std::move(destProperty)); - - std::shared_ptr path = - std::make_shared(std::move(objectPath)); - - using GetObjectType = - std::vector>>; - crow::connections::systemBus->async_method_call( - [&res, path, property_name](const boost::system::error_code ec, - const GetObjectType &object_names) { - if (ec || object_names.size() <= 0) { - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - std::shared_ptr response = - std::make_shared(nlohmann::json::object()); - // The mapper should never give us an empty interface names list, but - // check anyway - for (const std::pair> connection : - object_names) { - const std::vector &interfaceNames = connection.second; - - if (interfaceNames.size() <= 0) { - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - - for (const std::string &interface : interfaceNames) { - crow::connections::systemBus->async_method_call( - [&res, response, property_name]( - const boost::system::error_code ec, - const std::vector> &properties) { - if (ec) { - BMCWEB_LOG_ERROR << "Bad dbus request error: " << ec; - } else { - for (const std::pair - &property : properties) { - // if property name is empty, or matches our search query, - // add it to the response json - - if (property_name->empty()) { - mapbox::util::apply_visitor( - [&response, &property](auto &&val) { - (*response)[property.first] = val; - }, - property.second); - } else if (property.first == *property_name) { - mapbox::util::apply_visitor( - [&response](auto &&val) { (*response) = val; }, - property.second); - } - } - } - if (response.use_count() == 1) { - res.jsonValue = {{"status", "ok"}, - {"message", "200 OK"}, - {"data", *response}}; - + std::string &destProperty) +{ + BMCWEB_LOG_DEBUG << "handle_get: " << objectPath + << " prop:" << destProperty; + std::shared_ptr property_name = + std::make_shared(std::move(destProperty)); + + std::shared_ptr path = + std::make_shared(std::move(objectPath)); + + using GetObjectType = + std::vector>>; + crow::connections::systemBus->async_method_call( + [&res, path, property_name](const boost::system::error_code ec, + const GetObjectType &object_names) { + if (ec || object_names.size() <= 0) + { + res.result(boost::beast::http::status::not_found); + res.end(); + return; + } + std::shared_ptr response = + std::make_shared(nlohmann::json::object()); + // The mapper should never give us an empty interface names list, + // but check anyway + for (const std::pair> + connection : object_names) + { + const std::vector &interfaceNames = + connection.second; + + if (interfaceNames.size() <= 0) + { + res.result(boost::beast::http::status::not_found); res.end(); - } - }, - connection.first, *path, "org.freedesktop.DBus.Properties", - "GetAll", interface); - } - } - }, - "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", *path, - std::array()); + return; + } + + for (const std::string &interface : interfaceNames) + { + crow::connections::systemBus->async_method_call( + [&res, response, property_name]( + const boost::system::error_code ec, + const std::vector< + std::pair> + &properties) { + if (ec) + { + BMCWEB_LOG_ERROR << "Bad dbus request error: " + << ec; + } + else + { + for (const std::pair + &property : properties) + { + // if property name is empty, or matches our + // search query, add it to the response json + + if (property_name->empty()) + { + mapbox::util::apply_visitor( + [&response, &property](auto &&val) { + (*response)[property.first] = + val; + }, + property.second); + } + else if (property.first == *property_name) + { + mapbox::util::apply_visitor( + [&response](auto &&val) { + (*response) = val; + }, + property.second); + } + } + } + if (response.use_count() == 1) + { + res.jsonValue = {{"status", "ok"}, + {"message", "200 OK"}, + {"data", *response}}; + + res.end(); + } + }, + connection.first, *path, + "org.freedesktop.DBus.Properties", "GetAll", interface); + } + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", *path, + std::array()); } -struct AsyncPutRequest { - AsyncPutRequest(crow::Response &res) : res(res) { - res.jsonValue = { - {"status", "ok"}, {"message", "200 OK"}, {"data", nullptr}}; - } - ~AsyncPutRequest() { - if (res.result() == boost::beast::http::status::internal_server_error) { - // Reset the json object to clear out any data that made it in before the - // error happened - // todo(ed) handle error condition with proper code - res.jsonValue = nlohmann::json::object(); +struct AsyncPutRequest +{ + AsyncPutRequest(crow::Response &res) : res(res) + { + res.jsonValue = { + {"status", "ok"}, {"message", "200 OK"}, {"data", nullptr}}; } + ~AsyncPutRequest() + { + if (res.result() == boost::beast::http::status::internal_server_error) + { + // Reset the json object to clear out any data that made it in + // before the error happened todo(ed) handle error condition with + // proper code + res.jsonValue = nlohmann::json::object(); + } - if (res.jsonValue.empty()) { - res.result(boost::beast::http::status::forbidden); - res.jsonValue = { - {"status", "error"}, - {"message", "403 Forbidden"}, - {"data", - {{"message", - "The specified property cannot be created: " + propertyName}}}}; - } + if (res.jsonValue.empty()) + { + res.result(boost::beast::http::status::forbidden); + res.jsonValue = { + {"status", "error"}, + {"message", "403 Forbidden"}, + {"data", + {{"message", "The specified property cannot be created: " + + propertyName}}}}; + } - res.end(); - } + res.end(); + } - void setErrorStatus() { - res.result(boost::beast::http::status::internal_server_error); - } + void setErrorStatus() + { + res.result(boost::beast::http::status::internal_server_error); + } - crow::Response &res; - std::string objectPath; - std::string propertyName; - nlohmann::json propertyValue; + crow::Response &res; + std::string objectPath; + std::string propertyName; + nlohmann::json propertyValue; }; void handlePut(const crow::Request &req, crow::Response &res, - const std::string &objectPath, const std::string &destProperty) { - nlohmann::json requestDbusData = - nlohmann::json::parse(req.body, nullptr, false); - - if (requestDbusData.is_discarded()) { - res.result(boost::beast::http::status::bad_request); - res.end(); - return; - } - - nlohmann::json::const_iterator propertyIt = requestDbusData.find("data"); - if (propertyIt == requestDbusData.end()) { - res.result(boost::beast::http::status::bad_request); - res.end(); - return; - } - const nlohmann::json &propertySetValue = *propertyIt; - auto transaction = std::make_shared(res); - transaction->objectPath = objectPath; - transaction->propertyName = destProperty; - transaction->propertyValue = propertySetValue; - - using GetObjectType = - std::vector>>; - - crow::connections::systemBus->async_method_call( - [transaction](const boost::system::error_code ec, - const GetObjectType &object_names) { - if (!ec && object_names.size() <= 0) { - transaction->res.result(boost::beast::http::status::not_found); - return; - } + const std::string &objectPath, const std::string &destProperty) +{ + nlohmann::json requestDbusData = + nlohmann::json::parse(req.body, nullptr, false); + + if (requestDbusData.is_discarded()) + { + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } - for (const std::pair> connection : - object_names) { - const std::string &connectionName = connection.first; - - crow::connections::systemBus->async_method_call( - [ connectionName{std::string(connectionName)}, transaction ]( - const boost::system::error_code ec, - const std::string &introspectXml) { - if (ec) { - BMCWEB_LOG_ERROR - << "Introspect call failed with error: " << ec.message() - << " on process: " << connectionName; - transaction->setErrorStatus(); - return; - } - tinyxml2::XMLDocument doc; + nlohmann::json::const_iterator propertyIt = requestDbusData.find("data"); + if (propertyIt == requestDbusData.end()) + { + res.result(boost::beast::http::status::bad_request); + res.end(); + return; + } + const nlohmann::json &propertySetValue = *propertyIt; + auto transaction = std::make_shared(res); + transaction->objectPath = objectPath; + transaction->propertyName = destProperty; + transaction->propertyValue = propertySetValue; + + using GetObjectType = + std::vector>>; + + crow::connections::systemBus->async_method_call( + [transaction](const boost::system::error_code ec, + const GetObjectType &object_names) { + if (!ec && object_names.size() <= 0) + { + transaction->res.result(boost::beast::http::status::not_found); + return; + } - doc.Parse(introspectXml.c_str()); - tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); - if (pRoot == nullptr) { - BMCWEB_LOG_ERROR << "XML document failed to parse: " - << introspectXml; - transaction->setErrorStatus(); - return; - } - tinyxml2::XMLElement *ifaceNode = - pRoot->FirstChildElement("interface"); - while (ifaceNode != nullptr) { - const char *interfaceName = ifaceNode->Attribute("name"); - BMCWEB_LOG_DEBUG << "found interface " << interfaceName; - tinyxml2::XMLElement *propNode = - ifaceNode->FirstChildElement("property"); - while (propNode != nullptr) { - const char *propertyName = propNode->Attribute("name"); - BMCWEB_LOG_DEBUG << "Found property " << propertyName; - if (propertyName == transaction->propertyName) { - const char *argType = propNode->Attribute("type"); - if (argType != nullptr) { - sdbusplus::message::message m = - crow::connections::systemBus->new_method_call( - connectionName.c_str(), - transaction->objectPath.c_str(), - "org.freedesktop.DBus.Properties", "Set"); - m.append(interfaceName, transaction->propertyName); - int r = sd_bus_message_open_container( - m.get(), SD_BUS_TYPE_VARIANT, argType); - if (r < 0) { - transaction->setErrorStatus(); - return; + for (const std::pair> + connection : object_names) + { + const std::string &connectionName = connection.first; + + crow::connections::systemBus->async_method_call( + [connectionName{std::string(connectionName)}, + transaction](const boost::system::error_code ec, + const std::string &introspectXml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " + << ec.message() + << " on process: " << connectionName; + transaction->setErrorStatus(); + return; } - r = convertJsonToDbus(m.get(), argType, - transaction->propertyValue); - if (r < 0) { - transaction->setErrorStatus(); - return; + tinyxml2::XMLDocument doc; + + doc.Parse(introspectXml.c_str()); + tinyxml2::XMLNode *pRoot = + doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR << "XML document failed to parse: " + << introspectXml; + transaction->setErrorStatus(); + return; } - r = sd_bus_message_close_container(m.get()); - if (r < 0) { - transaction->setErrorStatus(); - return; + tinyxml2::XMLElement *ifaceNode = + pRoot->FirstChildElement("interface"); + while (ifaceNode != nullptr) + { + const char *interfaceName = + ifaceNode->Attribute("name"); + BMCWEB_LOG_DEBUG << "found interface " + << interfaceName; + tinyxml2::XMLElement *propNode = + ifaceNode->FirstChildElement("property"); + while (propNode != nullptr) + { + const char *propertyName = + propNode->Attribute("name"); + BMCWEB_LOG_DEBUG << "Found property " + << propertyName; + if (propertyName == transaction->propertyName) + { + const char *argType = + propNode->Attribute("type"); + if (argType != nullptr) + { + sdbusplus::message::message m = + crow::connections::systemBus + ->new_method_call( + connectionName.c_str(), + transaction->objectPath + .c_str(), + "org.freedesktop.DBus." + "Properties", + "Set"); + m.append(interfaceName, + transaction->propertyName); + int r = sd_bus_message_open_container( + m.get(), SD_BUS_TYPE_VARIANT, + argType); + if (r < 0) + { + transaction->setErrorStatus(); + return; + } + r = convertJsonToDbus( + m.get(), argType, + transaction->propertyValue); + if (r < 0) + { + transaction->setErrorStatus(); + return; + } + r = sd_bus_message_close_container( + m.get()); + if (r < 0) + { + transaction->setErrorStatus(); + return; + } + + crow::connections::systemBus + ->async_send( + m, + [transaction]( + boost::system::error_code + ec, + sdbusplus::message::message + &m) { + BMCWEB_LOG_DEBUG << "sent"; + if (ec) + { + transaction->res + .jsonValue + ["status"] = + "error"; + transaction->res + .jsonValue + ["message"] = + ec.message(); + } + }); + } + } + propNode = + propNode->NextSiblingElement("property"); + } + ifaceNode = + ifaceNode->NextSiblingElement("interface"); } - - crow::connections::systemBus->async_send( - m, [transaction](boost::system::error_code ec, - sdbusplus::message::message &m) { - BMCWEB_LOG_DEBUG << "sent"; - if (ec) { - transaction->res.jsonValue["status"] = "error"; - transaction->res.jsonValue["message"] = - ec.message(); - } - }); - } - } - propNode = propNode->NextSiblingElement("property"); - } - ifaceNode = ifaceNode->NextSiblingElement("interface"); - } - }, - connectionName, transaction->objectPath, - "org.freedesktop.DBus.Introspectable", "Introspect"); - } - }, - "xyz.openbmc_project.ObjectMapper", "/xyz/openbmc_project/object_mapper", - "xyz.openbmc_project.ObjectMapper", "GetObject", transaction->objectPath, - std::array()); + }, + connectionName, transaction->objectPath, + "org.freedesktop.DBus.Introspectable", "Introspect"); + } + }, + "xyz.openbmc_project.ObjectMapper", + "/xyz/openbmc_project/object_mapper", + "xyz.openbmc_project.ObjectMapper", "GetObject", + transaction->objectPath, std::array()); } -template -void requestRoutes(Crow &app) { - BMCWEB_ROUTE(app, "/bus/") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res) { - res.jsonValue = {{"busses", {{{"name", "system"}}}}, {"status", "ok"}}; - }); - - BMCWEB_ROUTE(app, "/bus/system/") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res) { - - auto myCallback = [&res](const boost::system::error_code ec, - std::vector &names) { - if (ec) { - BMCWEB_LOG_ERROR << "Dbus call failed with code " << ec; - res.result(boost::beast::http::status::internal_server_error); - } else { - std::sort(names.begin(), names.end()); - nlohmann::json j{{"status", "ok"}}; - auto &objectsSub = j["objects"]; - for (auto &name : names) { - objectsSub.push_back({{"name", name}}); +template void requestRoutes(Crow &app) +{ + BMCWEB_ROUTE(app, "/bus/") + .methods("GET"_method)( + [](const crow::Request &req, crow::Response &res) { + res.jsonValue = {{"busses", {{{"name", "system"}}}}, + {"status", "ok"}}; + }); + + BMCWEB_ROUTE(app, "/bus/system/") + .methods("GET"_method)( + [](const crow::Request &req, crow::Response &res) { + auto myCallback = [&res](const boost::system::error_code ec, + std::vector &names) { + if (ec) + { + BMCWEB_LOG_ERROR << "Dbus call failed with code " << ec; + res.result( + boost::beast::http::status::internal_server_error); + } + else + { + std::sort(names.begin(), names.end()); + nlohmann::json j{{"status", "ok"}}; + auto &objectsSub = j["objects"]; + for (auto &name : names) + { + objectsSub.push_back({{"name", name}}); + } + res.jsonValue = std::move(j); + } + res.end(); + }; + crow::connections::systemBus->async_method_call( + std::move(myCallback), "org.freedesktop.DBus", "/", + "org.freedesktop.DBus", "ListNames"); + }); + + BMCWEB_ROUTE(app, "/list/") + .methods("GET"_method)( + [](const crow::Request &req, crow::Response &res) { + handle_list(res, "/"); + }); + + BMCWEB_ROUTE(app, "/xyz/") + .methods("GET"_method, "PUT"_method, + "POST"_method)([](const crow::Request &req, + crow::Response &res, + const std::string &path) { + std::string objectPath = "/xyz/" + path; + + // Trim any trailing "/" at the end + if (boost::ends_with(objectPath, "/")) + { + objectPath.pop_back(); } - res.jsonValue = std::move(j); - } - res.end(); - }; - crow::connections::systemBus->async_method_call( - std::move(myCallback), "org.freedesktop.DBus", "/", - "org.freedesktop.DBus", "ListNames"); - }); - - BMCWEB_ROUTE(app, "/list/") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res) { - handle_list(res, "/"); - }); - - BMCWEB_ROUTE(app, "/xyz/") - .methods("GET"_method, "PUT"_method, - "POST"_method)([](const crow::Request &req, crow::Response &res, - const std::string &path) { - std::string objectPath = "/xyz/" + path; - - // Trim any trailing "/" at the end - if (boost::ends_with(objectPath, "/")) { - objectPath.pop_back(); - } - - // If accessing a single attribute, fill in and update objectPath, - // otherwise leave destProperty blank - std::string destProperty = ""; - const char *attrSeperator = "/attr/"; - size_t attrPosition = path.find(attrSeperator); - if (attrPosition != path.npos) { - objectPath = "/xyz/" + path.substr(0, attrPosition); - destProperty = - path.substr(attrPosition + strlen(attrSeperator), path.length()); - } - - if (req.method() == "POST"_method) { - constexpr const char *action_seperator = "/action/"; - size_t action_position = path.find(action_seperator); - if (action_position != path.npos) { - objectPath = "/xyz/" + path.substr(0, action_position); - std::string post_property = path.substr( - (action_position + strlen(action_seperator)), path.length()); - handle_action(req, res, objectPath, post_property); - return; - } - } else if (req.method() == "GET"_method) { - if (boost::ends_with(objectPath, "/enumerate")) { - objectPath.erase(objectPath.end() - 10, objectPath.end()); - handle_enumerate(res, objectPath); - } else if (boost::ends_with(objectPath, "/list")) { - objectPath.erase(objectPath.end() - 5, objectPath.end()); - handle_list(res, objectPath); - } else { - handle_get(res, objectPath, destProperty); - } - return; - } else if (req.method() == "PUT"_method) { - handlePut(req, res, objectPath, destProperty); - return; - } - res.result(boost::beast::http::status::method_not_allowed); - res.end(); - }); - - BMCWEB_ROUTE(app, "/bus/system//") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res, - const std::string &Connection) { - std::shared_ptr transaction; - introspectObjects(res, Connection, "/", transaction); - }); - - BMCWEB_ROUTE(app, "/download/dump//") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res, - const std::string &dumpId) { - std::regex validFilename("^[\\w\\- ]+(\\.?[\\w\\- ]+)$"); - if (!std::regex_match(dumpId, validFilename)) { - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - std::experimental::filesystem::path loc( - "/var/lib/phosphor-debug-collector/dumps"); + // If accessing a single attribute, fill in and update objectPath, + // otherwise leave destProperty blank + std::string destProperty = ""; + const char *attrSeperator = "/attr/"; + size_t attrPosition = path.find(attrSeperator); + if (attrPosition != path.npos) + { + objectPath = "/xyz/" + path.substr(0, attrPosition); + destProperty = path.substr(attrPosition + strlen(attrSeperator), + path.length()); + } - loc += dumpId; + if (req.method() == "POST"_method) + { + constexpr const char *action_seperator = "/action/"; + size_t action_position = path.find(action_seperator); + if (action_position != path.npos) + { + objectPath = "/xyz/" + path.substr(0, action_position); + std::string post_property = path.substr( + (action_position + strlen(action_seperator)), + path.length()); + handle_action(req, res, objectPath, post_property); + return; + } + } + else if (req.method() == "GET"_method) + { + if (boost::ends_with(objectPath, "/enumerate")) + { + objectPath.erase(objectPath.end() - 10, objectPath.end()); + handle_enumerate(res, objectPath); + } + else if (boost::ends_with(objectPath, "/list")) + { + objectPath.erase(objectPath.end() - 5, objectPath.end()); + handle_list(res, objectPath); + } + else + { + handle_get(res, objectPath, destProperty); + } + return; + } + else if (req.method() == "PUT"_method) + { + handlePut(req, res, objectPath, destProperty); + return; + } - if (!std::experimental::filesystem::exists(loc) || - !std::experimental::filesystem::is_directory(loc)) { - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - std::experimental::filesystem::directory_iterator files(loc); - for (auto &file : files) { - std::ifstream readFile(file.path()); - if (readFile.good()) { - continue; - } - res.addHeader("Content-Type", "application/octet-stream"); - res.body() = {std::istreambuf_iterator(readFile), - std::istreambuf_iterator()}; - res.end(); - } - res.result(boost::beast::http::status::not_found); - res.end(); - return; - }); - - BMCWEB_ROUTE(app, "/bus/system//") - .methods("GET"_method)([](const crow::Request &req, crow::Response &res, - const std::string &processName, - const std::string &requestedPath) { - std::vector strs; - boost::split(strs, requestedPath, boost::is_any_of("/")); - std::string objectPath; - std::string interfaceName; - std::string methodName; - auto it = strs.begin(); - if (it == strs.end()) { - objectPath = "/"; - } - while (it != strs.end()) { - // Check if segment contains ".". If it does, it must be an - // interface - if (it->find(".") != std::string::npos) { - break; - // THis check is neccesary as the trailing slash gets parsed as - // part of our specifier above, which causes the normal - // trailing backslash redirector to fail. - } else if (!it->empty()) { - objectPath += "/" + *it; - } - it++; - } - if (it != strs.end()) { - interfaceName = *it; - it++; - - // after interface, we might have a method name - if (it != strs.end()) { - methodName = *it; - it++; - } - } - if (it != strs.end()) { - // if there is more levels past the method name, something went - // wrong, return not found - res.result(boost::beast::http::status::not_found); - res.end(); - return; - } - if (interfaceName.empty()) { - crow::connections::systemBus->async_method_call( - [&, processName, objectPath](const boost::system::error_code ec, - const std::string &introspect_xml) { - if (ec) { - BMCWEB_LOG_ERROR - << "Introspect call failed with error: " << ec.message() - << " on process: " << processName - << " path: " << objectPath << "\n"; - - } else { - tinyxml2::XMLDocument doc; - - doc.Parse(introspect_xml.c_str()); - tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); - if (pRoot == nullptr) { - BMCWEB_LOG_ERROR << "XML document failed to parse " - << processName << " " << objectPath - << "\n"; - res.jsonValue = {{"status", "XML parse error"}}; - res.result( - boost::beast::http::status::internal_server_error); - } else { - nlohmann::json interfacesArray = nlohmann::json::array(); - tinyxml2::XMLElement *interface = - pRoot->FirstChildElement("interface"); + res.result(boost::beast::http::status::method_not_allowed); + res.end(); + }); + + BMCWEB_ROUTE(app, "/bus/system//") + .methods("GET"_method)([](const crow::Request &req, crow::Response &res, + const std::string &Connection) { + std::shared_ptr transaction; + introspectObjects(res, Connection, "/", transaction); + }); + + BMCWEB_ROUTE(app, "/download/dump//") + .methods("GET"_method)([](const crow::Request &req, crow::Response &res, + const std::string &dumpId) { + std::regex validFilename("^[\\w\\- ]+(\\.?[\\w\\- ]+)$"); + if (!std::regex_match(dumpId, validFilename)) + { + res.result(boost::beast::http::status::not_found); + res.end(); + return; + } + std::experimental::filesystem::path loc( + "/var/lib/phosphor-debug-collector/dumps"); - while (interface != nullptr) { - std::string ifaceName = interface->Attribute("name"); - interfacesArray.push_back({{"name", ifaceName}}); + loc += dumpId; - interface = interface->NextSiblingElement("interface"); - } - res.jsonValue = {{"status", "ok"}, - {"bus_name", processName}, - {"interfaces", interfacesArray}, - {"objectPath", objectPath}}; - } + if (!std::experimental::filesystem::exists(loc) || + !std::experimental::filesystem::is_directory(loc)) + { + res.result(boost::beast::http::status::not_found); + res.end(); + return; + } + std::experimental::filesystem::directory_iterator files(loc); + for (auto &file : files) + { + std::ifstream readFile(file.path()); + if (readFile.good()) + { + continue; } + res.addHeader("Content-Type", "application/octet-stream"); + res.body() = {std::istreambuf_iterator(readFile), + std::istreambuf_iterator()}; res.end(); - }, - processName, objectPath, "org.freedesktop.DBus.Introspectable", - "Introspect"); - } else { - crow::connections::systemBus->async_method_call( - [ - &, processName, objectPath, - interface_name{std::move(interfaceName)} - ](const boost::system::error_code ec, - const std::string &introspect_xml) { - if (ec) { - BMCWEB_LOG_ERROR - << "Introspect call failed with error: " << ec.message() - << " on process: " << processName - << " path: " << objectPath << "\n"; - - } else { - tinyxml2::XMLDocument doc; - - doc.Parse(introspect_xml.c_str()); - tinyxml2::XMLNode *pRoot = doc.FirstChildElement("node"); - if (pRoot == nullptr) { - BMCWEB_LOG_ERROR << "XML document failed to parse " - << processName << " " << objectPath - << "\n"; - res.result( - boost::beast::http::status::internal_server_error); - - } else { - tinyxml2::XMLElement *node = - pRoot->FirstChildElement("node"); - - // if we know we're the only call, build the json directly - nlohmann::json methodsArray = nlohmann::json::array(); - nlohmann::json signalsArray = nlohmann::json::array(); - tinyxml2::XMLElement *interface = - pRoot->FirstChildElement("interface"); - - while (interface != nullptr) { - std::string ifaceName = interface->Attribute("name"); - - if (ifaceName == interfaceName) { - tinyxml2::XMLElement *methods = - interface->FirstChildElement("method"); - while (methods != nullptr) { - nlohmann::json argsArray = nlohmann::json::array(); - tinyxml2::XMLElement *arg = - methods->FirstChildElement("arg"); - while (arg != nullptr) { - argsArray.push_back( - {{"name", arg->Attribute("name")}, - {"type", arg->Attribute("type")}, - {"direction", arg->Attribute("direction")}}); - arg = arg->NextSiblingElement("arg"); - } - methodsArray.push_back( - {{"name", methods->Attribute("name")}, - {"uri", "/bus/system/" + processName + - objectPath + "/" + interfaceName + - "/" + methods->Attribute("name")}, - {"args", argsArray}}); - methods = methods->NextSiblingElement("method"); - } - tinyxml2::XMLElement *signals = - interface->FirstChildElement("signal"); - while (signals != nullptr) { - nlohmann::json argsArray = nlohmann::json::array(); - - tinyxml2::XMLElement *arg = - signals->FirstChildElement("arg"); - while (arg != nullptr) { - std::string name = arg->Attribute("name"); - std::string type = arg->Attribute("type"); - argsArray.push_back({ - {"name", name}, - {"type", type}, - }); - arg = arg->NextSiblingElement("arg"); - } - signalsArray.push_back( - {{"name", signals->Attribute("name")}, - {"args", argsArray}}); - signals = signals->NextSiblingElement("signal"); - } - - res.jsonValue = { - {"status", "ok"}, - {"bus_name", processName}, - {"interface", interfaceName}, - {"methods", methodsArray}, - {"objectPath", objectPath}, - {"properties", nlohmann::json::object()}, - {"signals", signalsArray}}; - - break; - } - - interface = interface->NextSiblingElement("interface"); - } - if (interface == nullptr) { - // if we got to the end of the list and never found a - // match, throw 404 - res.result(boost::beast::http::status::not_found); - } - } + } + res.result(boost::beast::http::status::not_found); + res.end(); + return; + }); + + BMCWEB_ROUTE(app, "/bus/system//") + .methods("GET"_method)([](const crow::Request &req, crow::Response &res, + const std::string &processName, + const std::string &requestedPath) { + std::vector strs; + boost::split(strs, requestedPath, boost::is_any_of("/")); + std::string objectPath; + std::string interfaceName; + std::string methodName; + auto it = strs.begin(); + if (it == strs.end()) + { + objectPath = "/"; + } + while (it != strs.end()) + { + // Check if segment contains ".". If it does, it must be an + // interface + if (it->find(".") != std::string::npos) + { + break; + // THis check is neccesary as the trailing slash gets parsed + // as part of our specifier above, which causes the + // normal trailing backslash redirector to fail. + } + else if (!it->empty()) + { + objectPath += "/" + *it; } + it++; + } + if (it != strs.end()) + { + interfaceName = *it; + it++; + + // after interface, we might have a method name + if (it != strs.end()) + { + methodName = *it; + it++; + } + } + if (it != strs.end()) + { + // if there is more levels past the method name, something went + // wrong, return not found + res.result(boost::beast::http::status::not_found); res.end(); - }, - processName, objectPath, "org.freedesktop.DBus.Introspectable", - "Introspect"); - } - }); + return; + } + if (interfaceName.empty()) + { + crow::connections::systemBus->async_method_call( + [&, processName, + objectPath](const boost::system::error_code ec, + const std::string &introspect_xml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " + << ec.message() + << " on process: " << processName + << " path: " << objectPath << "\n"; + } + else + { + tinyxml2::XMLDocument doc; + + doc.Parse(introspect_xml.c_str()); + tinyxml2::XMLNode *pRoot = + doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR + << "XML document failed to parse " + << processName << " " << objectPath << "\n"; + res.jsonValue = {{"status", "XML parse error"}}; + res.result(boost::beast::http::status:: + internal_server_error); + } + else + { + nlohmann::json interfacesArray = + nlohmann::json::array(); + tinyxml2::XMLElement *interface = + pRoot->FirstChildElement("interface"); + + while (interface != nullptr) + { + std::string ifaceName = + interface->Attribute("name"); + interfacesArray.push_back( + {{"name", ifaceName}}); + + interface = interface->NextSiblingElement( + "interface"); + } + res.jsonValue = { + {"status", "ok"}, + {"bus_name", processName}, + {"interfaces", interfacesArray}, + {"objectPath", objectPath}}; + } + } + res.end(); + }, + processName, objectPath, + "org.freedesktop.DBus.Introspectable", "Introspect"); + } + else + { + crow::connections::systemBus->async_method_call( + [&, processName, objectPath, + interface_name{std::move(interfaceName)}]( + const boost::system::error_code ec, + const std::string &introspect_xml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " + << ec.message() + << " on process: " << processName + << " path: " << objectPath << "\n"; + } + else + { + tinyxml2::XMLDocument doc; + + doc.Parse(introspect_xml.c_str()); + tinyxml2::XMLNode *pRoot = + doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR + << "XML document failed to parse " + << processName << " " << objectPath << "\n"; + res.result(boost::beast::http::status:: + internal_server_error); + } + else + { + tinyxml2::XMLElement *node = + pRoot->FirstChildElement("node"); + + // if we know we're the only call, build the + // json directly + nlohmann::json methodsArray = + nlohmann::json::array(); + nlohmann::json signalsArray = + nlohmann::json::array(); + tinyxml2::XMLElement *interface = + pRoot->FirstChildElement("interface"); + + while (interface != nullptr) + { + std::string ifaceName = + interface->Attribute("name"); + + if (ifaceName == interfaceName) + { + tinyxml2::XMLElement *methods = + interface->FirstChildElement( + "method"); + while (methods != nullptr) + { + nlohmann::json argsArray = + nlohmann::json::array(); + tinyxml2::XMLElement *arg = + methods->FirstChildElement( + "arg"); + while (arg != nullptr) + { + argsArray.push_back( + {{"name", + arg->Attribute("name")}, + {"type", + arg->Attribute("type")}, + {"direction", + arg->Attribute( + "direction")}}); + arg = arg->NextSiblingElement( + "arg"); + } + methodsArray.push_back( + {{"name", + methods->Attribute("name")}, + {"uri", + "/bus/system/" + processName + + objectPath + "/" + + interfaceName + "/" + + methods->Attribute( + "name")}, + {"args", argsArray}}); + methods = + methods->NextSiblingElement( + "method"); + } + tinyxml2::XMLElement *signals = + interface->FirstChildElement( + "signal"); + while (signals != nullptr) + { + nlohmann::json argsArray = + nlohmann::json::array(); + + tinyxml2::XMLElement *arg = + signals->FirstChildElement( + "arg"); + while (arg != nullptr) + { + std::string name = + arg->Attribute("name"); + std::string type = + arg->Attribute("type"); + argsArray.push_back({ + {"name", name}, + {"type", type}, + }); + arg = arg->NextSiblingElement( + "arg"); + } + signalsArray.push_back( + {{"name", + signals->Attribute("name")}, + {"args", argsArray}}); + signals = + signals->NextSiblingElement( + "signal"); + } + + res.jsonValue = { + {"status", "ok"}, + {"bus_name", processName}, + {"interface", interfaceName}, + {"methods", methodsArray}, + {"objectPath", objectPath}, + {"properties", + nlohmann::json::object()}, + {"signals", signalsArray}}; + + break; + } + + interface = interface->NextSiblingElement( + "interface"); + } + if (interface == nullptr) + { + // if we got to the end of the list and + // never found a match, throw 404 + res.result( + boost::beast::http::status::not_found); + } + } + } + res.end(); + }, + processName, objectPath, + "org.freedesktop.DBus.Introspectable", "Introspect"); + } + }); } -} // namespace openbmc_mapper -} // namespace crow +} // namespace openbmc_mapper +} // namespace crow -- cgit v1.2.3