Add yielding utility calls

utils.hpp provides a bunch of blocking D-Bus calls that are used
liberally in the ipmi handlers. By adding a yielding option that takes
the ipmi::Context::ptr, this can easily turn all the blocking calls into
yielding calls as the handlers get rewritten.

Tested: Used the upcoming modification of XYZ call:
    Before:
       ipmitool get session info
    After:
       ipmitool get session info

Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
Change-Id: Ia537eeda060ea8e56b94b99ccb46b05f18372589
diff --git a/include/ipmid/utils.hpp b/include/ipmid/utils.hpp
index 3515eb6..cb71835 100644
--- a/include/ipmid/utils.hpp
+++ b/include/ipmid/utils.hpp
@@ -1,7 +1,9 @@
 #pragma once
 
+#include <boost/system/error_code.hpp>
 #include <chrono>
 #include <ipmid/api-types.hpp>
+#include <ipmid/message.hpp>
 #include <ipmid/types.hpp>
 #include <optional>
 #include <sdbusplus/server.hpp>
@@ -200,6 +202,180 @@
 ObjectTree getAllAncestors(sdbusplus::bus::bus& bus, const std::string& path,
                            InterfaceList&& interfaces);
 
+/********* Begin co-routine yielding alternatives ***************/
+
+/** @brief Get the D-Bus Service name for the input D-Bus path
+ *
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] intf - D-Bus Interface
+ *  @param[in] path - D-Bus Object Path
+ *  @param[out] service - requested service name
+ *  @return boost error code
+ *
+ */
+boost::system::error_code getService(Context::ptr ctx, const std::string& intf,
+                                     const std::string& path,
+                                     std::string& service);
+
+/** @brief Gets the D-Bus object info implementing the given interface
+ *         from the given subtree.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] interface - D-Bus interface.
+ *  @param[in][optional] subtreePath - subtree from where the search starts.
+ *  @param[in][optional] match - identifier for object.
+ *  @param[out] D-Bus object with path and service name
+ *  @return - boost error code object
+ */
+boost::system::error_code getDbusObject(Context::ptr ctx,
+                                        const std::string& interface,
+                                        const std::string& subtreePath,
+                                        const std::string& match,
+                                        DbusObjectInfo& dbusObject);
+
+// default for ROOT for subtreePath and std::string{} for match
+static inline boost::system::error_code
+    getDbusObject(Context::ptr ctx, const std::string& interface,
+                  DbusObjectInfo& dbusObject)
+{
+    return getDbusObject(ctx, interface, ROOT, {}, dbusObject);
+}
+
+// default std::string{} for match
+static inline boost::system::error_code
+    getDbusObject(Context::ptr ctx, const std::string& interface,
+                  const std::string& subtreePath, DbusObjectInfo& dbusObject)
+{
+    return getDbusObject(ctx, interface, subtreePath, {}, dbusObject);
+}
+
+/** @brief Gets the value associated with the given object
+ *         and the interface.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] service - D-Bus service name.
+ *  @param[in] objPath - D-Bus object path.
+ *  @param[in] interface - D-Bus interface.
+ *  @param[in] property - name of the property.
+ *  @param[out] propertyValue - value of the D-Bus property.
+ *  @return - boost error code object
+ */
+template <typename Type>
+boost::system::error_code
+    getDbusProperty(Context::ptr ctx, const std::string& service,
+                    const std::string& objPath, const std::string& interface,
+                    const std::string& property, Type& propertyValue)
+{
+    boost::system::error_code ec;
+    auto variant = ctx->bus->yield_method_call<std::variant<Type>>(
+        ctx->yield, ec, service.c_str(), objPath.c_str(), PROP_INTF, METHOD_GET,
+        interface, property);
+    if (!ec)
+    {
+        Type* tmp = std::get_if<Type>(&variant);
+        if (tmp)
+        {
+            propertyValue = *tmp;
+            return ec;
+        }
+        // user requested incorrect type; make an error code for them
+        ec = boost::system::errc::make_error_code(
+            boost::system::errc::invalid_argument);
+    }
+    return ec;
+}
+
+/** @brief Gets all the properties associated with the given object
+ *         and the interface.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] service - D-Bus service name.
+ *  @param[in] objPath - D-Bus object path.
+ *  @param[in] interface - D-Bus interface.
+ *  @param[out] properties - map of name value pair.
+ *  @return - boost error code object
+ */
+boost::system::error_code getAllDbusProperties(Context::ptr ctx,
+                                               const std::string& service,
+                                               const std::string& objPath,
+                                               const std::string& interface,
+                                               PropertyMap& properties);
+
+/** @brief Sets the property value of the given object.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] service - D-Bus service name.
+ *  @param[in] objPath - D-Bus object path.
+ *  @param[in] interface - D-Bus interface.
+ *  @param[in] property - name of the property.
+ *  @param[in] value - value which needs to be set.
+ *  @return - boost error code object
+ */
+boost::system::error_code
+    setDbusProperty(Context::ptr ctx, const std::string& service,
+                    const std::string& objPath, const std::string& interface,
+                    const std::string& property, const Value& value);
+
+/** @brief  Gets all the D-Bus objects from the given service root
+ *          which matches the object identifier.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] serviceRoot - Service root path.
+ *  @param[in] interface - D-Bus interface.
+ *  @param[in][optional] match - Identifier for a path.
+ *  @param[out] objectree - map of object path and service info.
+ *  @return - boost error code object
+ */
+boost::system::error_code getAllDbusObjects(Context::ptr ctx,
+                                            const std::string& serviceRoot,
+                                            const std::string& interface,
+                                            const std::string& match,
+                                            ObjectTree& objectTree);
+
+// default std::string{} for match
+static inline boost::system::error_code
+    getAllDbusObjects(Context::ptr ctx, const std::string& serviceRoot,
+                      const std::string& interface, ObjectTree& objectTree)
+{
+    return getAllDbusObjects(ctx, serviceRoot, interface, {}, objectTree);
+}
+
+/** @brief Deletes all the D-Bus objects from the given service root
+           which matches the object identifier.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[out] ec - boost error code object
+ *  @param[in] serviceRoot - Service root path.
+ *  @param[in] interface - D-Bus interface.
+ *  @param[in] match - Identifier for object.
+ */
+boost::system::error_code deleteAllDbusObjects(Context::ptr ctx,
+                                               const std::string& serviceRoot,
+                                               const std::string& interface,
+                                               const std::string& match = {});
+
+/** @brief Gets all managed objects associated with the given object
+ *         path and service.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[out] objects - map of name value pair.
+ *  @param[in] service - D-Bus service name.
+ *  @param[in] objPath - D-Bus object path.
+ *  @return - boost error code object
+ */
+boost::system::error_code getManagedObjects(Context::ptr ctx,
+                                            ObjectValueTree& objects,
+                                            const std::string& service,
+                                            const std::string& objPath);
+
+/** @brief Gets the ancestor objects of the given object
+           which implements the given interface.
+ *  @param[in] ctx - ipmi::Context::ptr
+ *  @param[in] path - Child D-Bus object path.
+ *  @param[in] interfaces - D-Bus interface list.
+ *  @param[out] ObjectTree - map of object path and service info.
+ *  @return - boost error code object
+ */
+boost::system::error_code getAllAncestors(Context::ptr ctx,
+                                          const std::string& path,
+                                          const InterfaceList& interfaces,
+                                          ObjectTree& objectTree);
+
+/********* End co-routine yielding alternatives ***************/
+
 /** @struct VariantToDoubleVisitor
  *  @brief Visitor to convert variants to doubles
  *  @details Performs a static cast on the underlying type