pldmd: D-Bus to host effecter translation

This commit implements a mechanism to move the Host's boot state
from 'not started' to 'boot complete' by setting the relevant
Host effecter when the associated D-Bus property is set in the BMC.

Also added an example JSON to match D-Bus to host effecters

Change-Id: I41025d99d2b4b3452d4c51b03efe3750e159328b
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/dbus_to_host_effecters.hpp b/dbus_to_host_effecters.hpp
new file mode 100644
index 0000000..7c37c88
--- /dev/null
+++ b/dbus_to_host_effecters.hpp
@@ -0,0 +1,182 @@
+#pragma once
+
+#include "dbus_impl_requester.hpp"
+#include "types.hpp"
+#include "utils.hpp"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace pldm
+{
+
+using namespace utils;
+using namespace dbus_api;
+
+namespace host_effecters
+{
+
+using DbusChgHostEffecterProps = std::map<dbus::Property, PropertyValue>;
+
+/** @struct State
+ *  Contains the state set id and the possible states for
+ *  an effecter
+ */
+struct PossibleState
+{
+    uint16_t stateSetId;         //!< State set id
+    std::vector<uint8_t> states; //!< Possible states
+};
+
+/** @struct DBusEffecterMapping
+ *  Contains the D-Bus information for an effecter
+ */
+struct DBusEffecterMapping
+{
+    DBusMapping dbusMap;
+    std::vector<PropertyValue> propertyValues; //!< D-Bus property values
+    PossibleState state; //!< Corresponding effecter states
+};
+
+/** @struct EffecterInfo
+ *  Contains the effecter information as a whole
+ */
+struct EffecterInfo
+{
+    uint8_t mctpEid;         //!< Host mctp eid
+    uint16_t containerId;    //!< Container Id for host effecter
+    uint16_t entityType;     //!< Entity type for the host effecter
+    uint16_t entityInstance; //!< Entity instance for the host effecter
+    uint8_t compEffecterCnt; //!< Composite effecter count
+    std::vector<DBusEffecterMapping>
+        dbusInfo; //!< D-Bus information for the effecter id
+};
+
+/** @class HostEffecterParser
+ *
+ *  @brief This class parses the Host Effecter json file and monitors for the
+ *         D-Bus changes for the effecters. Upon change, calls the corresponding
+ *         setStateEffecterStates on the host
+ */
+class HostEffecterParser
+{
+  public:
+    HostEffecterParser() = delete;
+    HostEffecterParser(const HostEffecterParser&) = delete;
+    HostEffecterParser& operator=(const HostEffecterParser&) = delete;
+    HostEffecterParser(HostEffecterParser&&) = delete;
+    HostEffecterParser& operator=(HostEffecterParser&&) = delete;
+    virtual ~HostEffecterParser() = default;
+
+    /** @brief Constructor to create a HostEffecterParser object.
+     *  @param[in] requester - PLDM Requester object pointer
+     *  @param[in] fd - socket fd to communicate to host
+     *  @param[in] repo -  PLDM PDR repository
+     *  @param[in] dbusHandler - D-bus Handler
+     *  @param[in] jsonPath - path for the json file
+     *  @param[in] verbose - verbosity
+     */
+    explicit HostEffecterParser(Requester* requester, int fd,
+                                const pldm_pdr* repo,
+                                DBusHandler* const dbusHandler,
+                                const std::string& jsonPath,
+                                bool verbose = false) :
+        requester(requester),
+        sockFd(fd), pdrRepo(repo), dbusHandler(dbusHandler), verbose(verbose)
+    {
+        try
+        {
+            parseEffecterJson(jsonPath);
+        }
+        catch (const std::exception& e)
+        {
+            std::cerr << "The json file does not exist or malformed, ERROR="
+                      << e.what() << "\n";
+        }
+    }
+
+    /* @brief Parses the host effecter json
+     *
+     * @param[in] jsonPath - path for the json file
+     */
+    void parseEffecterJson(const std::string& jsonPath);
+
+    /* @brief Method to take action when the subscribed D-Bus property is
+     *        changed
+     * @param[in] chProperties - list of properties which have changed
+     * @param[in] effecterInfoIndex - index of effecterInfo pointer in
+     *                                hostEffecterInfo
+     * @param[in] dbusInfoIndex - index on dbusInfo pointer in each effecterInfo
+     * @param[in] effecterId - host effecter id
+     * @return - none
+     */
+    void processHostEffecterChangeNotification(
+        const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
+        size_t dbusInfoIndex, uint16_t effecterId);
+
+    /* @brief Populate the property values in each dbusInfo from the json
+     *
+     * @param[in] dBusValues - json values
+     * @param[out] propertyValues - dbusInfo property values
+     * @param[in] propertyType - type of the D-Bus property
+     * @return - none
+     */
+    void populatePropVals(const Json& dBusValues,
+                          std::vector<PropertyValue>& propertyValues,
+                          const std::string& propertyType);
+
+    /* @brief Set a host state effecter
+     *
+     * @param[in] effecterInfoIndex - index of effecterInfo pointer in
+     *                                hostEffecterInfo
+     * @param[in] stateField - vector of state fields equal to composite
+     *                         effecter count in number
+     * @param[in] effecterId - host effecter id
+     * @return - PLDM status code
+     */
+    virtual int
+        setHostStateEffecter(size_t effecterInfoIndex,
+                             std::vector<set_effecter_state_field>& stateField,
+                             uint16_t effecterId);
+
+    /* @brief Fetches the new state value and the index in stateField set which
+     *        needs to be set with the new value in the setStateEffecter call
+     * @param[in] effecterInfoIndex - index of effecterInfo in hostEffecterInfo
+     * @param[in] dbusInfoIndex - index of dbusInfo within effecterInfo
+     * @param[in] propertyValue - the changed D-Bus property value
+     * @return - the new state value
+     */
+    uint8_t findNewStateValue(size_t effecterInfoIndex, size_t dbusInfoIndex,
+                              const PropertyValue& propertyValue);
+
+    /* @brief Subscribes for D-Bus property change signal on the specified
+     * object
+     *
+     * @param[in] objectPath - D-Bus object path to look for
+     * @param[in] interface - D-Bus interface
+     * @param[in] effecterInfoIndex - index of effecterInfo pointer in
+     *                                hostEffecterInfo
+     * @param[in] dbusInfoIndex - index of dbusInfo within effecterInfo
+     * @param[in] effecterId - host effecter id
+     */
+    virtual void createHostEffecterMatch(const std::string& objectPath,
+                                         const std::string& interface,
+                                         size_t effecterInfoIndex,
+                                         size_t dbusInfoIndex,
+                                         uint16_t effecterId);
+
+  protected:
+    Requester* requester;    //!< Reference to Requester to obtain instance id
+    int sockFd;              //!< Socket fd to send message to host
+    const pldm_pdr* pdrRepo; //!< Reference to PDR repo
+    std::vector<EffecterInfo> hostEffecterInfo; //!< Parsed effecter information
+    std::vector<std::unique_ptr<sdbusplus::bus::match::match>>
+        effecterInfoMatch; //!< vector to catch the D-Bus property change
+                           //!< signals for the effecters
+    const DBusHandler* dbusHandler; //!< D-bus Handler
+    bool verbose;                   //!< verbose flag
+};
+
+} // namespace host_effecters
+} // namespace pldm