Close active SOL session after disable SSH SOL

Issue: When SOL-SSH is being disable by Control BMC service command,
       the active SOL session are not being closed.

Fix: Stop the Payload Instance and Host console for active SOL
     session when SSH SOL is being disable.

Tested:
Verified using ipmitool sol commands.
1. Enable SSH SOL using control BMC service command
Command: ipmitool raw 0x30 0xb1 0x01 0x40 0x00  //SOL activate
Response:                           // Success
Check the status using below busctl command
command: busctl introspect xyz.openbmc_project.Control.Service.Manager
         /xyz/openbmc_project/control/service/obmc_2dconsole_40ttyS2
Response: .Enabled    true
2. Activate SOL session
Command: ipmitool -I lanplus -U root -P 0penBmc -H <BMC_IP> -C 17
         sol activate
Response:                         // Success
3. Disable SSH SOL using control BMC service command
Command: ipmitool raw 0x30 0xb1 0x00 0x40 0x00
Response:                                    // Success
Check the status using below busctl command
command: busctl introspect xyz.openbmc_project.Control.Service.Manager
         /xyz/openbmc_project/control/service/obmc_2dconsole_40ttyS2
Response: .Enabled    false
4.  Enable SSH SOL using control BMC service command.
Command: ipmitool raw 0x30 0xb1 0x01 0x40 0x00
Response:                                // Success
Check the status using below busctl command
command: busctl introspect xyz.openbmc_project.Control.Service.Manager
         /xyz/openbmc_project/control/service/obmc_2dconsole_40ttyS2
Response: .Enabled    true
5. Activate SOL session
Command: ipmitool -I lanplus -U root -P 0penBmc -H <BMC_IP> -C 17
         sol activate
Response:               // Successfully establish the session

Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
Change-Id: I08a459e5a4245d969529c033e4b88625b0796fb2
diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
index 87f9ed7..a118457 100644
--- a/sol/sol_manager.cpp
+++ b/sol/sol_manager.cpp
@@ -12,6 +12,7 @@
 #include <boost/asio/write.hpp>
 #include <chrono>
 #include <cmath>
+#include <ipmid/utils.hpp>
 #include <phosphor-logging/log.hpp>
 
 namespace sol
@@ -19,6 +20,8 @@
 
 using namespace phosphor::logging;
 
+std::unique_ptr<sdbusplus::bus::match_t> matchPtrSOL(nullptr);
+
 void Manager::initConsoleSocket()
 {
     // explicit length constructor for NUL-prefixed abstract path
@@ -74,6 +77,13 @@
     {
         initConsoleSocket();
     }
+
+    // Register callback to close SOL session for disable SSH SOL
+    if (matchPtrSOL == nullptr)
+    {
+        registerSOLServiceChangeCallback();
+    }
+
     consoleSocket->async_wait(boost::asio::socket_base::wait_read,
                               [this](const boost::system::error_code& ec) {
                                   if (!ec)
@@ -137,4 +147,61 @@
     }
 }
 
+void Manager::stopAllPayloadInstance()
+{
+    // Erase all payload instance
+    payloadMap.erase(payloadMap.begin(), payloadMap.end());
+
+    stopHostConsole();
+
+    dataBuffer.erase(dataBuffer.size());
+}
+
+void registerSOLServiceChangeCallback()
+{
+    using namespace sdbusplus::bus::match::rules;
+    sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
+    try
+    {
+        auto servicePath = ipmi::getDbusObject(
+            bus, "xyz.openbmc_project.Control.Service.Attributes",
+            "/xyz/openbmc_project/control/service", "obmc_2dconsole");
+
+        if (!std::empty(servicePath.first))
+        {
+            matchPtrSOL = std::make_unique<sdbusplus::bus::match_t>(
+                bus,
+                path_namespace(servicePath.first) +
+                    "arg0namespace='xyz.openbmc_project.Control.Service."
+                    "Attributes'"
+                    ", " +
+                    type::signal() + member("PropertiesChanged") +
+                    interface("org.freedesktop.DBus.Properties"),
+                [](sdbusplus::message::message& msg) {
+                    std::string intfName;
+                    std::map<std::string, std::variant<bool>> properties;
+                    msg.read(intfName, properties);
+
+                    const auto it = properties.find("Enabled");
+                    if (it != properties.end())
+                    {
+                        const bool* state = std::get_if<bool>(&it->second);
+
+                        if (state != nullptr && *state == false)
+                        {
+                            // Stop all the payload session.
+                            std::get<sol::Manager&>(singletonPool)
+                                .stopAllPayloadInstance();
+                        }
+                    }
+                });
+        }
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        log<level::ERR>(
+            "Failed to get service path in registerSOLServiceChangeCallback");
+    }
+}
+
 } // namespace sol
diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
index 74ce8e9..5b48add 100644
--- a/sol/sol_manager.hpp
+++ b/sol/sol_manager.hpp
@@ -192,6 +192,9 @@
      */
     void stopPayloadInstance(uint8_t payloadInstance);
 
+    /* @brief Stop all the active SOL payload instances */
+    void stopAllPayloadInstance();
+
     /** @brief Get SOL Context by Payload Instance.
      *
      *  @param[in] payloadInstance - SOL payload instance.
@@ -264,4 +267,7 @@
     void consoleInputHandler();
 };
 
+/** @brief Callback method to close SOL sessions for SOL service change  */
+void registerSOLServiceChangeCallback();
+
 } // namespace sol