diff options
author | Ed Tanous <edtanous@google.com> | 2022-05-04 21:33:42 +0300 |
---|---|---|
committer | Ed Tanous <edtanous@google.com> | 2022-05-13 00:46:22 +0300 |
commit | 1656b296313d75b172dcdbe5f37ff1d1b54800dc (patch) | |
tree | 826f8bff20cd2d9947a9f1edba0609199715d244 /include/openbmc_dbus_rest.hpp | |
parent | 4c25d66ea7b0d56ee9bbc6fa392582fb76b44911 (diff) | |
download | bmcweb-1656b296313d75b172dcdbe5f37ff1d1b54800dc.tar.xz |
Move /bus/system/<str>/<path> POST to method
Per the reorganization we've done elsewhere, move this large lambda
function to simplify it.
Tested: Code move only. Code compiles.
Signed-off-by: Ed Tanous <edtanous@google.com>
Change-Id: Ib0586b34809167120bdc127868706ac517db4474
Diffstat (limited to 'include/openbmc_dbus_rest.hpp')
-rw-r--r-- | include/openbmc_dbus_rest.hpp | 662 |
1 files changed, 317 insertions, 345 deletions
diff --git a/include/openbmc_dbus_rest.hpp b/include/openbmc_dbus_rest.hpp index 042f193952..4f4bd71ff6 100644 --- a/include/openbmc_dbus_rest.hpp +++ b/include/openbmc_dbus_rest.hpp @@ -2102,6 +2102,321 @@ inline void handleDBusUrl(const crow::Request& req, methodNotAllowedDesc, methodNotAllowedMsg); } +inline void + handleBusSystemPost(const crow::Request& req, + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const std::string& processName, + const std::string& requestedPath) +{ + std::vector<std::string> 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 necessary as the trailing slash gets + // parsed as part of our <path> specifier above, which + // causes the normal trailing backslash redirector to + // fail. + } + 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 + asyncResp->res.result(boost::beast::http::status::not_found); + return; + } + if (interfaceName.empty()) + { + crow::connections::systemBus->async_method_call( + [asyncResp, processName, + objectPath](const boost::system::error_code ec, + const std::string& introspectXml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " << ec.message() + << " on process: " << processName + << " path: " << objectPath << "\n"; + 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 " + << processName << " " << objectPath + << "\n"; + asyncResp->res.jsonValue = {{"status", "XML parse error"}}; + asyncResp->res.result( + boost::beast::http::status::internal_server_error); + return; + } + + BMCWEB_LOG_DEBUG << introspectXml; + asyncResp->res.jsonValue = {{"status", "ok"}, + {"bus_name", processName}, + {"object_path", objectPath}}; + nlohmann::json& interfacesArray = + asyncResp->res.jsonValue["interfaces"]; + interfacesArray = nlohmann::json::array(); + tinyxml2::XMLElement* interface = + pRoot->FirstChildElement("interface"); + + while (interface != nullptr) + { + const char* ifaceName = interface->Attribute("name"); + if (ifaceName != nullptr) + { + interfacesArray.push_back({{"name", ifaceName}}); + } + + interface = interface->NextSiblingElement("interface"); + } + }, + processName, objectPath, "org.freedesktop.DBus.Introspectable", + "Introspect"); + } + else if (methodName.empty()) + { + crow::connections::systemBus->async_method_call( + [asyncResp, processName, objectPath, + interfaceName](const boost::system::error_code ec, + const std::string& introspectXml) { + if (ec) + { + BMCWEB_LOG_ERROR + << "Introspect call failed with error: " << ec.message() + << " on process: " << processName + << " path: " << objectPath << "\n"; + return; + } + tinyxml2::XMLDocument doc; + + doc.Parse(introspectXml.data(), introspectXml.size()); + tinyxml2::XMLNode* pRoot = doc.FirstChildElement("node"); + if (pRoot == nullptr) + { + BMCWEB_LOG_ERROR << "XML document failed to parse " + << processName << " " << objectPath + << "\n"; + asyncResp->res.result( + boost::beast::http::status::internal_server_error); + return; + } + asyncResp->res.jsonValue = {{"status", "ok"}, + {"bus_name", processName}, + {"interface", interfaceName}, + {"object_path", objectPath}}; + + nlohmann::json& methodsArray = + asyncResp->res.jsonValue["methods"]; + methodsArray = nlohmann::json::array(); + + nlohmann::json& signalsArray = + asyncResp->res.jsonValue["signals"]; + signalsArray = nlohmann::json::array(); + + nlohmann::json& propertiesObj = + asyncResp->res.jsonValue["properties"]; + propertiesObj = nlohmann::json::object(); + + // if we know we're the only call, build the + // json directly + tinyxml2::XMLElement* interface = + pRoot->FirstChildElement("interface"); + while (interface != nullptr) + { + const char* ifaceName = interface->Attribute("name"); + + if (ifaceName != nullptr && ifaceName == interfaceName) + { + break; + } + + interface = interface->NextSiblingElement("interface"); + } + if (interface == nullptr) + { + // if we got to the end of the list and + // never found a match, throw 404 + asyncResp->res.result( + boost::beast::http::status::not_found); + return; + } + + tinyxml2::XMLElement* methods = + interface->FirstChildElement("method"); + while (methods != nullptr) + { + nlohmann::json argsArray = nlohmann::json::array(); + tinyxml2::XMLElement* arg = + methods->FirstChildElement("arg"); + while (arg != nullptr) + { + nlohmann::json thisArg; + for (const char* fieldName : std::array<const char*, 3>{ + "name", "direction", "type"}) + { + const char* fieldValue = arg->Attribute(fieldName); + if (fieldValue != nullptr) + { + thisArg[fieldName] = fieldValue; + } + } + argsArray.push_back(std::move(thisArg)); + arg = arg->NextSiblingElement("arg"); + } + + const char* name = methods->Attribute("name"); + if (name != nullptr) + { + std::string uri; + uri.reserve(14 + processName.size() + + objectPath.size() + interfaceName.size() + + strlen(name)); + uri += "/bus/system/"; + uri += processName; + uri += objectPath; + uri += "/"; + uri += interfaceName; + uri += "/"; + uri += name; + methodsArray.push_back({{"name", name}, + {"uri", std::move(uri)}, + {"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) + { + const char* name = arg->Attribute("name"); + const char* type = arg->Attribute("type"); + if (name != nullptr && type != nullptr) + { + argsArray.push_back({ + {"name", name}, + {"type", type}, + }); + } + arg = arg->NextSiblingElement("arg"); + } + const char* name = signals->Attribute("name"); + if (name != nullptr) + { + signalsArray.push_back( + {{"name", name}, {"args", argsArray}}); + } + + signals = signals->NextSiblingElement("signal"); + } + + tinyxml2::XMLElement* property = + interface->FirstChildElement("property"); + while (property != nullptr) + { + const char* name = property->Attribute("name"); + const char* type = property->Attribute("type"); + if (type != nullptr && name != nullptr) + { + sdbusplus::message::message m = + crow::connections::systemBus->new_method_call( + processName.c_str(), objectPath.c_str(), + "org.freedesktop." + "DBus." + "Properties", + "Get"); + m.append(interfaceName, name); + nlohmann::json& propertyItem = propertiesObj[name]; + crow::connections::systemBus->async_send( + m, [&propertyItem, + asyncResp](boost::system::error_code& e, + sdbusplus::message::message& msg) { + if (e) + { + return; + } + + convertDBusToJSON("v", msg, propertyItem); + }); + } + property = property->NextSiblingElement("property"); + } + }, + processName, objectPath, "org.freedesktop.DBus.Introspectable", + "Introspect"); + } + else + { + if (req.method() != boost::beast::http::verb::post) + { + asyncResp->res.result(boost::beast::http::status::not_found); + return; + } + + nlohmann::json requestDbusData = + nlohmann::json::parse(req.body, nullptr, false); + + if (requestDbusData.is_discarded()) + { + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } + if (!requestDbusData.is_array()) + { + asyncResp->res.result(boost::beast::http::status::bad_request); + return; + } + auto transaction = + std::make_shared<InProgressActionData>(asyncResp->res); + + transaction->path = objectPath; + transaction->methodName = methodName; + transaction->arguments = std::move(requestDbusData); + + findActionOnInterface(transaction, processName); + } +} + inline void requestRoutes(App& app) { BMCWEB_ROUTE(app, "/bus/") @@ -2275,351 +2590,8 @@ inline void requestRoutes(App& app) BMCWEB_ROUTE(app, "/bus/system/<str>/<path>") .privileges({{"ConfigureComponents", "ConfigureManager"}}) - .methods(boost::beast::http::verb::get, boost::beast::http::verb::post)( - [](const crow::Request& req, - const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const std::string& processName, - const std::string& requestedPath) { - std::vector<std::string> 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 necessary as the trailing slash gets - // parsed as part of our <path> specifier above, which - // causes the normal trailing backslash redirector to - // fail. - } - 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 - asyncResp->res.result( - boost::beast::http::status::not_found); - return; - } - if (interfaceName.empty()) - { - crow::connections::systemBus->async_method_call( - [asyncResp, processName, - objectPath](const boost::system::error_code ec, - const std::string& introspectXml) { - if (ec) - { - BMCWEB_LOG_ERROR - << "Introspect call failed with error: " - << ec.message() - << " on process: " << processName - << " path: " << objectPath << "\n"; - 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 " - << processName << " " << objectPath << "\n"; - asyncResp->res.jsonValue = { - {"status", "XML parse error"}}; - asyncResp->res.result( - boost::beast::http::status:: - internal_server_error); - return; - } - - BMCWEB_LOG_DEBUG << introspectXml; - asyncResp->res.jsonValue = { - {"status", "ok"}, - {"bus_name", processName}, - {"object_path", objectPath}}; - nlohmann::json& interfacesArray = - asyncResp->res.jsonValue["interfaces"]; - interfacesArray = nlohmann::json::array(); - tinyxml2::XMLElement* interface = - pRoot->FirstChildElement("interface"); - - while (interface != nullptr) - { - const char* ifaceName = - interface->Attribute("name"); - if (ifaceName != nullptr) - { - interfacesArray.push_back( - {{"name", ifaceName}}); - } - - interface = - interface->NextSiblingElement("interface"); - } - }, - processName, objectPath, - "org.freedesktop.DBus.Introspectable", "Introspect"); - } - else if (methodName.empty()) - { - crow::connections::systemBus->async_method_call( - [asyncResp, processName, objectPath, - interfaceName](const boost::system::error_code ec, - const std::string& introspectXml) { - if (ec) - { - BMCWEB_LOG_ERROR - << "Introspect call failed with error: " - << ec.message() - << " on process: " << processName - << " path: " << objectPath << "\n"; - return; - } - tinyxml2::XMLDocument doc; - - doc.Parse(introspectXml.data(), - introspectXml.size()); - tinyxml2::XMLNode* pRoot = - doc.FirstChildElement("node"); - if (pRoot == nullptr) - { - BMCWEB_LOG_ERROR - << "XML document failed to parse " - << processName << " " << objectPath << "\n"; - asyncResp->res.result( - boost::beast::http::status:: - internal_server_error); - return; - } - asyncResp->res.jsonValue = { - {"status", "ok"}, - {"bus_name", processName}, - {"interface", interfaceName}, - {"object_path", objectPath}}; - - nlohmann::json& methodsArray = - asyncResp->res.jsonValue["methods"]; - methodsArray = nlohmann::json::array(); - - nlohmann::json& signalsArray = - asyncResp->res.jsonValue["signals"]; - signalsArray = nlohmann::json::array(); - - nlohmann::json& propertiesObj = - asyncResp->res.jsonValue["properties"]; - propertiesObj = nlohmann::json::object(); - - // if we know we're the only call, build the - // json directly - tinyxml2::XMLElement* interface = - pRoot->FirstChildElement("interface"); - while (interface != nullptr) - { - const char* ifaceName = - interface->Attribute("name"); - - if (ifaceName != nullptr && - ifaceName == interfaceName) - { - break; - } - - interface = - interface->NextSiblingElement("interface"); - } - if (interface == nullptr) - { - // if we got to the end of the list and - // never found a match, throw 404 - asyncResp->res.result( - boost::beast::http::status::not_found); - return; - } - - tinyxml2::XMLElement* methods = - interface->FirstChildElement("method"); - while (methods != nullptr) - { - nlohmann::json argsArray = - nlohmann::json::array(); - tinyxml2::XMLElement* arg = - methods->FirstChildElement("arg"); - while (arg != nullptr) - { - nlohmann::json thisArg; - for (const char* fieldName : - std::array<const char*, 3>{ - "name", "direction", "type"}) - { - const char* fieldValue = - arg->Attribute(fieldName); - if (fieldValue != nullptr) - { - thisArg[fieldName] = fieldValue; - } - } - argsArray.push_back(std::move(thisArg)); - arg = arg->NextSiblingElement("arg"); - } - - const char* name = methods->Attribute("name"); - if (name != nullptr) - { - std::string uri; - uri.reserve(14 + processName.size() + - objectPath.size() + - interfaceName.size() + - strlen(name)); - uri += "/bus/system/"; - uri += processName; - uri += objectPath; - uri += "/"; - uri += interfaceName; - uri += "/"; - uri += name; - methodsArray.push_back( - {{"name", name}, - {"uri", std::move(uri)}, - {"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) - { - const char* name = arg->Attribute("name"); - const char* type = arg->Attribute("type"); - if (name != nullptr && type != nullptr) - { - argsArray.push_back({ - {"name", name}, - {"type", type}, - }); - } - arg = arg->NextSiblingElement("arg"); - } - const char* name = signals->Attribute("name"); - if (name != nullptr) - { - signalsArray.push_back( - {{"name", name}, {"args", argsArray}}); - } - - signals = signals->NextSiblingElement("signal"); - } - - tinyxml2::XMLElement* property = - interface->FirstChildElement("property"); - while (property != nullptr) - { - const char* name = property->Attribute("name"); - const char* type = property->Attribute("type"); - if (type != nullptr && name != nullptr) - { - sdbusplus::message::message m = - crow::connections::systemBus - ->new_method_call( - processName.c_str(), - objectPath.c_str(), - "org.freedesktop." - "DBus." - "Properties", - "Get"); - m.append(interfaceName, name); - nlohmann::json& propertyItem = - propertiesObj[name]; - crow::connections::systemBus->async_send( - m, - [&propertyItem, asyncResp]( - boost::system::error_code& e, - sdbusplus::message::message& msg) { - if (e) - { - return; - } - - convertDBusToJSON("v", msg, - propertyItem); - }); - } - property = - property->NextSiblingElement("property"); - } - }, - processName, objectPath, - "org.freedesktop.DBus.Introspectable", "Introspect"); - } - else - { - if (req.method() != boost::beast::http::verb::post) - { - asyncResp->res.result( - boost::beast::http::status::not_found); - return; - } - - nlohmann::json requestDbusData = - nlohmann::json::parse(req.body, nullptr, false); - - if (requestDbusData.is_discarded()) - { - asyncResp->res.result( - boost::beast::http::status::bad_request); - return; - } - if (!requestDbusData.is_array()) - { - asyncResp->res.result( - boost::beast::http::status::bad_request); - return; - } - auto transaction = - std::make_shared<InProgressActionData>(asyncResp->res); - - transaction->path = objectPath; - transaction->methodName = methodName; - transaction->arguments = std::move(requestDbusData); - - findActionOnInterface(transaction, processName); - } - }); + .methods(boost::beast::http::verb::get, + boost::beast::http::verb::post)(handleBusSystemPost); } } // namespace openbmc_mapper } // namespace crow |