requester: Modified MctpDiscovery class

Modified MctpDiscovery class to take list of managers instead of single
fwManager. The change is for adding platform-mc manager.
Added loadStaticEndpoints API for MCTP layer which doesn't implement
/xyz/openbmc_project/MCTP/Endpoint.Interface

The patch is part of implementation of design document below.
https://gerrit.openbmc-project.xyz/c/openbmc/docs/+/47252

Signed-off-by: Gilbert Chen <gilbert.chen@arm.com>
Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: I1e1673504583a87f2a9bc3adf76fb49c2dc30254
diff --git a/requester/mctp_endpoint_discovery.cpp b/requester/mctp_endpoint_discovery.cpp
index a962228..9440ed0 100644
--- a/requester/mctp_endpoint_discovery.cpp
+++ b/requester/mctp_endpoint_discovery.cpp
@@ -1,100 +1,214 @@
+#include "config.h"
+
 #include "mctp_endpoint_discovery.hpp"
 
 #include "common/types.hpp"
 #include "common/utils.hpp"
 
+#include <phosphor-logging/lg2.hpp>
+
 #include <algorithm>
+#include <fstream>
+#include <iostream>
 #include <map>
 #include <string>
 #include <string_view>
 #include <vector>
 
+using namespace sdbusplus::bus::match::rules;
+
+PHOSPHOR_LOG2_USING;
+
 namespace pldm
 {
-MctpDiscovery::MctpDiscovery(sdbusplus::bus_t& bus,
-                             fw_update::Manager* fwManager) :
+MctpDiscovery::MctpDiscovery(
+    sdbusplus::bus::bus& bus,
+    std::initializer_list<MctpDiscoveryHandlerIntf*> list) :
     bus(bus),
-    fwManager(fwManager),
-    mctpEndpointSignal(bus,
-                       sdbusplus::bus::match::rules::interfacesAdded(
-                           "/xyz/openbmc_project/mctp"),
-                       std::bind_front(&MctpDiscovery::dicoverEndpoints, this))
+    mctpEndpointAddedSignal(
+        bus, interfacesAdded(MCTPPath),
+        std::bind_front(&MctpDiscovery::discoverEndpoints, this)),
+    mctpEndpointRemovedSignal(
+        bus, interfacesRemoved(MCTPPath),
+        std::bind_front(&MctpDiscovery::removeEndpoints, this)),
+    handlers(list)
 {
-    pldm::utils::ObjectValueTree objects;
+    getMctpInfos(existingMctpInfos);
+    handleMctpEndpoints(existingMctpInfos);
+}
 
+void MctpDiscovery::getMctpInfos(MctpInfos& mctpInfos)
+{
+    // Find all implementations of the MCTP Endpoint interface
+    pldm::utils::GetSubTreeResponse mapperResponse;
     try
     {
-        objects = pldm::utils::DBusHandler::getManagedObj(MCTPService,
-                                                          MCTPPath);
+        mapperResponse = pldm::utils::DBusHandler().getSubtree(
+            MCTPPath, 0, std::vector<std::string>({MCTPInterface}));
     }
-    catch (const std::exception& e)
+    catch (const sdbusplus::exception_t& e)
     {
-        error("Failed to call the D-Bus Method: {ERROR}", "ERROR", e);
+        error("getSubtree call failed with, {ERROR} {PATH} {INTERFACE}",
+              "ERROR", e, "PATH", MCTPPath, "INTERFACE", MCTPInterface);
         return;
     }
 
-    std::vector<mctp_eid_t> eids;
-
-    for (const auto& [objectPath, interfaces] : objects)
+    for (const auto& [path, services] : mapperResponse)
     {
-        for (const auto& [intfName, properties] : interfaces)
+        for (const auto& serviceIter : services)
         {
-            if (intfName == mctpEndpointIntfName)
+            const std::string& service = serviceIter.first;
+            try
             {
-                if (properties.contains("EID") &&
+                auto properties =
+                    pldm::utils::DBusHandler().getDbusPropertiesVariant(
+                        service.c_str(), path.c_str(), MCTPInterface);
+
+                if (properties.contains("NetworkId") &&
+                    properties.contains("EID") &&
                     properties.contains("SupportedMessageTypes"))
                 {
+                    auto networkId =
+                        std::get<NetworkId>(properties.at("NetworkId"));
                     auto eid = std::get<mctp_eid_t>(properties.at("EID"));
                     auto types = std::get<std::vector<uint8_t>>(
                         properties.at("SupportedMessageTypes"));
                     if (std::find(types.begin(), types.end(), mctpTypePLDM) !=
                         types.end())
                     {
-                        eids.emplace_back(eid);
+                        info("Adding Endpoint networkId={NETWORK} EID={EID}",
+                             "NETWORK", networkId, "EID", unsigned(eid));
+                        mctpInfos.emplace_back(
+                            MctpInfo(eid, emptyUUID, "", networkId));
                     }
                 }
             }
+            catch (const sdbusplus::exception_t& e)
+            {
+                error(
+                    "Error reading MCTP Endpoint property, {ERROR} {SERVICE} {PATH}",
+                    "ERROR", e, "SERVICE", service, "PATH", path);
+                return;
+            }
         }
     }
-
-    if (eids.size() && fwManager)
-    {
-        fwManager->handleMCTPEndpoints(eids);
-    }
 }
 
-void MctpDiscovery::dicoverEndpoints(sdbusplus::message_t& msg)
+void MctpDiscovery::getAddedMctpInfos(sdbusplus::message_t& msg,
+                                      MctpInfos& mctpInfos)
 {
-    constexpr std::string_view mctpEndpointIntfName{
-        "xyz.openbmc_project.MCTP.Endpoint"};
-    std::vector<mctp_eid_t> eids;
+    using ObjectPath = sdbusplus::message::object_path;
+    ObjectPath objPath;
+    using Property = std::string;
+    using PropertyMap = std::map<Property, dbus::Value>;
+    std::map<std::string, PropertyMap> interfaces;
 
-    sdbusplus::message::object_path objPath;
-    std::map<std::string, std::map<std::string, dbus::Value>> interfaces;
-    msg.read(objPath, interfaces);
+    try
+    {
+        msg.read(objPath, interfaces);
+    }
+    catch (const sdbusplus::exception_t& e)
+    {
+        error("Error reading MCTP Endpoint addedInterace message, {ERROR}",
+              "ERROR", e);
+        return;
+    }
 
     for (const auto& [intfName, properties] : interfaces)
     {
-        if (intfName == mctpEndpointIntfName)
+        if (intfName == MCTPInterface)
         {
-            if (properties.contains("EID") &&
+            if (properties.contains("NetworkId") &&
+                properties.contains("EID") &&
                 properties.contains("SupportedMessageTypes"))
             {
+                auto networkId =
+                    std::get<NetworkId>(properties.at("NetworkId"));
                 auto eid = std::get<mctp_eid_t>(properties.at("EID"));
                 auto types = std::get<std::vector<uint8_t>>(
                     properties.at("SupportedMessageTypes"));
                 if (std::find(types.begin(), types.end(), mctpTypePLDM) !=
                     types.end())
                 {
-                    eids.emplace_back(eid);
+                    info("Adding Endpoint networkId={NETWORK} EID={EID}",
+                         "NETWORK", networkId, "EID", unsigned(eid));
+                    mctpInfos.emplace_back(
+                        MctpInfo(eid, emptyUUID, "", networkId));
                 }
             }
         }
     }
+}
 
-    if (eids.size() && fwManager)
+void MctpDiscovery::addToExistingMctpInfos(const MctpInfos& addedInfos)
+{
+    for (const auto& mctpInfo : addedInfos)
     {
-        fwManager->handleMCTPEndpoints(eids);
+        if (std::find(existingMctpInfos.begin(), existingMctpInfos.end(),
+                      mctpInfo) == existingMctpInfos.end())
+        {
+            existingMctpInfos.emplace_back(mctpInfo);
+        }
+    }
+}
+
+void MctpDiscovery::removeFromExistingMctpInfos(MctpInfos& mctpInfos,
+                                                MctpInfos& removedInfos)
+{
+    for (const auto& mctpInfo : existingMctpInfos)
+    {
+        if (std::find(mctpInfos.begin(), mctpInfos.end(), mctpInfo) ==
+            mctpInfos.end())
+        {
+            removedInfos.emplace_back(mctpInfo);
+        }
+    }
+    for (const auto& mctpInfo : removedInfos)
+    {
+        info("Removing Endpoint networkId={NETWORK} EID={EID}", "NETWORK",
+             std::get<3>(mctpInfo), "EID", unsigned(std::get<0>(mctpInfo)));
+        existingMctpInfos.erase(std::remove(existingMctpInfos.begin(),
+                                            existingMctpInfos.end(), mctpInfo),
+                                existingMctpInfos.end());
+    }
+}
+
+void MctpDiscovery::discoverEndpoints(sdbusplus::message_t& msg)
+{
+    MctpInfos addedInfos;
+    getAddedMctpInfos(msg, addedInfos);
+    addToExistingMctpInfos(addedInfos);
+    handleMctpEndpoints(addedInfos);
+}
+
+void MctpDiscovery::removeEndpoints(sdbusplus::message_t&)
+{
+    MctpInfos mctpInfos;
+    MctpInfos removedInfos;
+    getMctpInfos(mctpInfos);
+    removeFromExistingMctpInfos(mctpInfos, removedInfos);
+    handleRemovedMctpEndpoints(removedInfos);
+}
+
+void MctpDiscovery::handleMctpEndpoints(const MctpInfos& mctpInfos)
+{
+    for (const auto& handler : handlers)
+    {
+        if (handler)
+        {
+            handler->handleMctpEndpoints(mctpInfos);
+        }
+    }
+}
+
+void MctpDiscovery::handleRemovedMctpEndpoints(const MctpInfos& mctpInfos)
+{
+    for (const auto& handler : handlers)
+    {
+        if (handler)
+        {
+            handler->handleRemovedMctpEndpoints(mctpInfos);
+        }
     }
 }