add D-Bus interface for unstructured HTTP push

Add the D-Bus interface for unstructured HTTP push update. Unstructured
HTTP push updates are discouraged in favor of Multipart-form based
updates, hence D-Bus interface has been added only for BMC updates for
backward compatibility. Fore more details refer to [1].

Tested:
```
> curl -k -H "X-Auth-Token: $token" -H "Content-Type: application/octet-stream" -X POST -T obmc-phosphor-image-romulus-20240529184214.static.mtd.tar https://${bmc}/redfish/v1/UpdateService/update
{
  "@odata.id": "/redfish/v1/TaskService/Tasks/0",
  "@odata.type": "#Task.v1_4_3.Task",
  "Id": "0",
  "TaskState": "Running",
  "TaskStatus": "OK"
}
```

[1]: https://www.dmtf.org/sites/default/files/standards/documents/DSP2062_1.0.1.pdf

Change-Id: I365c0c188190032cb191940072399d9abd8a87b3
Signed-off-by: Jagpal Singh Gill <paligill@gmail.com>
diff --git a/redfish-core/lib/update_service.hpp b/redfish-core/lib/update_service.hpp
index 2888cbf..9a399af 100644
--- a/redfish-core/lib/update_service.hpp
+++ b/redfish-core/lib/update_service.hpp
@@ -995,17 +995,10 @@
 
 inline void
     processUpdateRequest(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
-                         const crow::Request& req, std::string_view body,
+                         task::Payload&& payload, std::string_view body,
                          const std::string& applyTime,
                          std::vector<std::string>& targets)
 {
-    std::string applyTimeNewVal;
-
-    if (!convertApplyTime(asyncResp->res, applyTime, applyTimeNewVal))
-    {
-        return;
-    }
-
     MemoryFileDescriptor memfd("update-image");
     if (memfd.fd == -1)
     {
@@ -1026,10 +1019,9 @@
         return;
     }
 
-    task::Payload payload(req);
     if (!targets.empty() && targets[0] == BMCWEB_REDFISH_MANAGER_URI_NAME)
     {
-        startUpdate(asyncResp, std::move(payload), memfd, applyTimeNewVal,
+        startUpdate(asyncResp, std::move(payload), memfd, applyTime,
                     "/xyz/openbmc_project/software/bmc",
                     "xyz.openbmc_project.Software.Manager");
     }
@@ -1040,12 +1032,12 @@
         dbus::utility::getSubTreePaths(
             "/xyz/openbmc_project/software", 1, interfaces,
             [asyncResp, payload = std::move(payload), memfd = std::move(memfd),
-             applyTimeNewVal,
+             applyTime,
              targets](const boost::system::error_code& ec,
                       const dbus::utility::MapperGetSubTreePathsResponse&
                           subtree) mutable {
             getSwInfo(asyncResp, std::move(payload), std::move(memfd),
-                      applyTimeNewVal, targets[0], ec, subtree);
+                      applyTime, targets[0], ec, subtree);
         });
     }
 }
@@ -1067,8 +1059,17 @@
 
     if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS)
     {
-        processUpdateRequest(asyncResp, req, multipart->uploadData,
-                             *multipart->applyTime, multipart->targets);
+        std::string applyTimeNewVal;
+        if (!convertApplyTime(asyncResp->res, *multipart->applyTime,
+                              applyTimeNewVal))
+        {
+            return;
+        }
+        task::Payload payload(req);
+
+        processUpdateRequest(asyncResp, std::move(payload),
+                             multipart->uploadData, applyTimeNewVal,
+                             multipart->targets);
     }
     else
     {
@@ -1082,6 +1083,33 @@
     }
 }
 
+inline void doHTTPUpdate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                         const crow::Request& req)
+{
+    if constexpr (BMCWEB_REDFISH_UPDATESERVICE_USE_DBUS)
+    {
+        task::Payload payload(req);
+        // HTTP push only supports BMC updates (with ApplyTime as immediate) for
+        // backwards compatibility. Specific component updates will be handled
+        // through Multipart form HTTP push.
+        std::vector<std::string> targets;
+        targets.emplace_back(BMCWEB_REDFISH_MANAGER_URI_NAME);
+
+        processUpdateRequest(
+            asyncResp, std::move(payload), req.body(),
+            "xyz.openbmc_project.Software.ApplyTime.RequestedApplyTimes.Immediate",
+            targets);
+    }
+    else
+    {
+        // Setup callback for when new software detected
+        monitorForSoftwareAvailable(asyncResp, req,
+                                    "/redfish/v1/UpdateService");
+
+        uploadImageFile(asyncResp->res, req.body());
+    }
+}
+
 inline void
     handleUpdateServicePost(App& app, const crow::Request& req,
                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
@@ -1098,11 +1126,7 @@
     // multipart/form-data
     if (bmcweb::asciiIEquals(contentType, "application/octet-stream"))
     {
-        // Setup callback for when new software detected
-        monitorForSoftwareAvailable(asyncResp, req,
-                                    "/redfish/v1/UpdateService");
-
-        uploadImageFile(asyncResp->res, req.body());
+        doHTTPUpdate(asyncResp, req);
     }
     else if (contentType.starts_with("multipart/form-data"))
     {