diff options
author | Jagpal Singh Gill <paligill@gmail.com> | 2024-04-18 02:06:14 +0300 |
---|---|---|
committer | Ed Tanous <ed@tanous.net> | 2024-05-11 07:25:55 +0300 |
commit | ef93eab32e4e4157082ff16767408a610db2c190 (patch) | |
tree | 0544c5ca637863deda5953f60061dcf9e4ab919a | |
parent | a1015048b6a60c06f9634c5756feaff8f12d5266 (diff) | |
download | bmcweb-ef93eab32e4e4157082ff16767408a610db2c190.tar.xz |
updateservice: refactor parse multi-part forms
Refactor parsing multi-part forms into a different function for using it
in legacy vs start update flows. More more details refer to -
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/65738
https://gerrit.openbmc.org/c/openbmc/docs/+/65739
Tested: Used curl to test firmware update.
Change-Id: I2ec1ec9f4ac04349a1fbd588664f2d51bae827ea
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
-rw-r--r-- | redfish-core/lib/update_service.hpp | 105 |
1 files changed, 72 insertions, 33 deletions
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp index 0d424dbb60..f66fe46a11 100644 --- a/redfish-core/lib/update_service.hpp +++ b/redfish-core/lib/update_service.hpp @@ -40,9 +40,11 @@ #include <array> #include <filesystem> +#include <memory> #include <optional> #include <string> #include <string_view> +#include <vector> namespace redfish { @@ -690,22 +692,27 @@ inline void setApplyTime(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, "RequestedApplyTime", "ApplyTime", applyTimeNewVal); } -inline void - updateMultipartContext(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, - const crow::Request& req, - const MultipartParser& parser) +struct MultiPartUpdateParameters +{ + std::optional<std::string> applyTime; + std::string uploadData; + std::vector<boost::urls::url> targets; +}; + +inline std::optional<MultiPartUpdateParameters> + extractMultipartUpdateParameters( + const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + MultipartParser parser) { - const std::string* uploadData = nullptr; - std::optional<std::string> applyTime = "OnReset"; - bool targetFound = false; - for (const FormPart& formpart : parser.mime_fields) + MultiPartUpdateParameters multiRet; + for (FormPart& formpart : parser.mime_fields) { boost::beast::http::fields::const_iterator it = formpart.fields.find("Content-Disposition"); if (it == formpart.fields.end()) { BMCWEB_LOG_ERROR("Couldn't find Content-Disposition"); - return; + return std::nullopt; } BMCWEB_LOG_INFO("Parsing value {}", it->value()); @@ -726,63 +733,95 @@ inline void if (param.second == "UpdateParameters") { - std::vector<std::string> targets; + std::vector<std::string> tempTargets; nlohmann::json content = nlohmann::json::parse(formpart.content); nlohmann::json::object_t* obj = content.get_ptr<nlohmann::json::object_t*>(); if (obj == nullptr) { - messages::propertyValueFormatError(asyncResp->res, targets, - "UpdateParameters"); - return; + messages::propertyValueTypeError( + asyncResp->res, formpart.content, "UpdateParameters"); + return std::nullopt; } if (!json_util::readJsonObject( - *obj, asyncResp->res, "Targets", targets, - "@Redfish.OperationApplyTime", applyTime)) + *obj, asyncResp->res, "Targets", tempTargets, + "@Redfish.OperationApplyTime", multiRet.applyTime)) { - return; + return std::nullopt; } - if (targets.size() != 1) + + for (size_t urlIndex = 0; urlIndex < tempTargets.size(); + urlIndex++) { - messages::propertyValueFormatError(asyncResp->res, targets, - "Targets"); - return; + const std::string& target = tempTargets[urlIndex]; + boost::system::result<boost::urls::url_view> url = + boost::urls::parse_origin_form(target); + if (!url) + { + messages::propertyValueFormatError( + asyncResp->res, target, + std::format("Targets/{}", urlIndex)); + return std::nullopt; + } + multiRet.targets.emplace_back(*url); } - if (targets[0] != "/redfish/v1/Managers/bmc") + if (multiRet.targets.size() != 1) { - messages::propertyValueNotInList(asyncResp->res, targets[0], - "Targets/0"); - return; + messages::propertyValueFormatError( + asyncResp->res, multiRet.targets, "Targets"); + return std::nullopt; + } + if (multiRet.targets[0].path() != "/redfish/v1/Managers/bmc") + { + messages::propertyValueNotInList( + asyncResp->res, multiRet.targets[0], "Targets/0"); + return std::nullopt; } - targetFound = true; } else if (param.second == "UpdateFile") { - uploadData = &(formpart.content); + multiRet.uploadData = std::move(formpart.content); } } } - if (uploadData == nullptr) + if (multiRet.uploadData.empty()) { BMCWEB_LOG_ERROR("Upload data is NULL"); messages::propertyMissing(asyncResp->res, "UpdateFile"); - return; + return std::nullopt; } - if (!targetFound) + if (multiRet.targets.empty()) + { + messages::propertyMissing(asyncResp->res, "Targets"); + return std::nullopt; + } + return multiRet; +} + +inline void + updateMultipartContext(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, + const crow::Request& req, MultipartParser&& parser) +{ + std::optional<MultiPartUpdateParameters> multipart = + extractMultipartUpdateParameters(asyncResp, std::move(parser)); + if (!multipart) { - messages::propertyMissing(asyncResp->res, "targets"); return; } + if (!multipart->applyTime) + { + multipart->applyTime = "OnReset"; + } - setApplyTime(asyncResp, *applyTime); + setApplyTime(asyncResp, *multipart->applyTime); // Setup callback for when new software detected monitorForSoftwareAvailable(asyncResp, req, "/redfish/v1/UpdateService"); - uploadImageFile(asyncResp->res, *uploadData); + uploadImageFile(asyncResp->res, multipart->uploadData); } inline void @@ -821,7 +860,7 @@ inline void return; } - updateMultipartContext(asyncResp, req, parser); + updateMultipartContext(asyncResp, req, std::move(parser)); } else { |