replace tuple-based singleton with individual singletons
The tuple-based singletons did not actually enforce singleton behavior
and the requirement of the accessor mechanism to include all of the
member types at once was starting to cause a header prerequisite
tangle. This removes the cross-dependencies and enforces actual
singletons by making a single way to access the class.
Tested: Run ipmitool to show that behavior has not changed
Change-Id: Ie966e1142363d279365b1095066380c8383e9f9b
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/comm_module.cpp b/comm_module.cpp
index acc9089..7b6b496 100644
--- a/comm_module.cpp
+++ b/comm_module.cpp
@@ -6,7 +6,6 @@
#include "command/rakp34.hpp"
#include "command/session_cmds.hpp"
#include "command_table.hpp"
-#include "main.hpp"
#include "session.hpp"
#include <algorithm>
@@ -57,11 +56,10 @@
for (auto& iter : commands)
{
- std::get<command::Table&>(singletonPool)
- .registerCommand(iter.command,
- std::make_unique<command::NetIpmidEntry>(
- iter.command, iter.functor, iter.privilege,
- iter.sessionless));
+ command::Table::get().registerCommand(
+ iter.command,
+ std::make_unique<command::NetIpmidEntry>(
+ iter.command, iter.functor, iter.privilege, iter.sessionless));
}
}
diff --git a/command/open_session.cpp b/command/open_session.cpp
index 9ba00ec..2887d37 100644
--- a/command/open_session.cpp
+++ b/command/open_session.cpp
@@ -2,7 +2,7 @@
#include "comm_module.hpp"
#include "endian.hpp"
-#include "main.hpp"
+#include "sessions_manager.hpp"
#include <phosphor-logging/log.hpp>
@@ -77,15 +77,11 @@
try
{
// Start an IPMI session
- session =
- std::get<session::Manager&>(singletonPool)
- .startSession(
- endian::from_ipmi<>(request->remoteConsoleSessionID), priv,
- static_cast<cipher::rakp_auth::Algorithms>(
- request->authAlgo),
- static_cast<cipher::integrity::Algorithms>(
- request->intAlgo),
- static_cast<cipher::crypt::Algorithms>(request->confAlgo));
+ session = session::Manager::get().startSession(
+ endian::from_ipmi<>(request->remoteConsoleSessionID), priv,
+ static_cast<cipher::rakp_auth::Algorithms>(request->authAlgo),
+ static_cast<cipher::integrity::Algorithms>(request->intAlgo),
+ static_cast<cipher::crypt::Algorithms>(request->confAlgo));
}
catch (std::exception& e)
{
diff --git a/command/payload_cmds.cpp b/command/payload_cmds.cpp
index bc987c5..ecb86e7 100644
--- a/command/payload_cmds.cpp
+++ b/command/payload_cmds.cpp
@@ -1,6 +1,6 @@
#include "payload_cmds.hpp"
-#include "main.hpp"
+#include "sessions_manager.hpp"
#include "sol/sol_manager.hpp"
#include "sol_cmds.hpp"
@@ -41,10 +41,9 @@
return outPayload;
}
- std::get<sol::Manager&>(singletonPool)
- .updateSOLParameter(ipmi::convertCurrentChannelNum(
- ipmi::currentChNum, getInterfaceIndex()));
- if (!std::get<sol::Manager&>(singletonPool).enable)
+ sol::Manager::get().updateSOLParameter(ipmi::convertCurrentChannelNum(
+ ipmi::currentChNum, getInterfaceIndex()));
+ if (!sol::Manager::get().enable)
{
response->completionCode = IPMI_CC_PAYLOAD_TYPE_DISABLED;
return outPayload;
@@ -57,8 +56,7 @@
return outPayload;
}
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(handler.sessionID);
+ auto session = session::Manager::get().getSession(handler.sessionID);
if (!request->encryption && session->isCryptAlgoEnabled())
{
@@ -78,8 +76,7 @@
return outPayload;
}
- auto status = std::get<sol::Manager&>(singletonPool)
- .isPayloadActive(request->payloadInstance);
+ auto status = sol::Manager::get().isPayloadActive(request->payloadInstance);
if (status)
{
response->completionCode = IPMI_CC_PAYLOAD_ALREADY_ACTIVE;
@@ -92,8 +89,8 @@
// Start the SOL payload
try
{
- std::get<sol::Manager&>(singletonPool)
- .startPayloadInstance(request->payloadInstance, handler.sessionID);
+ sol::Manager::get().startPayloadInstance(request->payloadInstance,
+ handler.sessionID);
}
catch (std::exception& e)
{
@@ -142,8 +139,7 @@
return outPayload;
}
- auto status = std::get<sol::Manager&>(singletonPool)
- .isPayloadActive(request->payloadInstance);
+ auto status = sol::Manager::get().isPayloadActive(request->payloadInstance);
if (!status)
{
response->completionCode = IPMI_CC_PAYLOAD_DEACTIVATED;
@@ -152,12 +148,11 @@
try
{
- auto& context = std::get<sol::Manager&>(singletonPool)
- .getContext(request->payloadInstance);
+ auto& context =
+ sol::Manager::get().getContext(request->payloadInstance);
auto sessionID = context.sessionID;
- std::get<sol::Manager&>(singletonPool)
- .stopPayloadInstance(request->payloadInstance);
+ sol::Manager::get().stopPayloadInstance(request->payloadInstance);
try
{
@@ -213,8 +208,7 @@
response->capacity = maxSolPayloadInstances;
// Currently we support only one SOL session
- response->instance1 =
- std::get<sol::Manager&>(singletonPool).isPayloadActive(1);
+ response->instance1 = sol::Manager::get().isPayloadActive(1);
return outPayload;
}
@@ -244,13 +238,12 @@
response->completionCode = IPMI_CC_INVALID_FIELD_REQUEST;
return outPayload;
}
- auto status = std::get<sol::Manager&>(singletonPool)
- .isPayloadActive(request->payloadInstance);
+ auto status = sol::Manager::get().isPayloadActive(request->payloadInstance);
if (status)
{
- auto& context = std::get<sol::Manager&>(singletonPool)
- .getContext(request->payloadInstance);
+ auto& context =
+ sol::Manager::get().getContext(request->payloadInstance);
response->sessionID = context.sessionID;
}
else
diff --git a/command/rakp12.cpp b/command/rakp12.cpp
index 099c5dc..7d349c6 100644
--- a/command/rakp12.cpp
+++ b/command/rakp12.cpp
@@ -3,7 +3,7 @@
#include "comm_module.hpp"
#include "endian.hpp"
#include "guid.hpp"
-#include "main.hpp"
+#include "sessions_manager.hpp"
#include <openssl/rand.h>
@@ -50,9 +50,8 @@
std::shared_ptr<session::Session> session;
try
{
- session =
- std::get<session::Manager&>(singletonPool)
- .getSession(endian::from_ipmi(request->managedSystemSessionID));
+ session = session::Manager::get().getSession(
+ endian::from_ipmi(request->managedSystemSessionID));
}
catch (std::exception& e)
{
diff --git a/command/rakp34.cpp b/command/rakp34.cpp
index b106b6f..a8ad86a 100644
--- a/command/rakp34.cpp
+++ b/command/rakp34.cpp
@@ -3,8 +3,8 @@
#include "comm_module.hpp"
#include "endian.hpp"
#include "guid.hpp"
-#include "main.hpp"
#include "rmcp.hpp"
+#include "sessions_manager.hpp"
#include <algorithm>
#include <cstring>
@@ -17,8 +17,7 @@
void applyIntegrityAlgo(const uint32_t bmcSessionID)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(bmcSessionID);
+ auto session = session::Manager::get().getSession(bmcSessionID);
auto authAlgo = session->getAuthAlgo();
@@ -45,8 +44,7 @@
void applyCryptAlgo(const uint32_t bmcSessionID)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(bmcSessionID);
+ auto session = session::Manager::get().getSession(bmcSessionID);
auto authAlgo = session->getAuthAlgo();
@@ -97,8 +95,7 @@
try
{
session =
- std::get<session::Manager&>(singletonPool)
- .getSession(endian::from_ipmi(request->managedSystemSessionID));
+ session::Manager::get().getSession(request->managedSystemSessionID);
}
catch (std::exception& e)
{
@@ -174,8 +171,7 @@
response->remoteConsoleSessionID = rcSessionID;
// close the session
- std::get<session::Manager&>(singletonPool)
- .stopSession(session->getBMCSessionID());
+ session::Manager::get().stopSession(session->getBMCSessionID());
return outPayload;
}
diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
index 98016c9..84c6e85 100644
--- a/command/session_cmds.cpp
+++ b/command/session_cmds.cpp
@@ -1,7 +1,7 @@
#include "session_cmds.hpp"
#include "endian.hpp"
-#include "main.hpp"
+#include "sessions_manager.hpp"
#include <ipmid/api.h>
@@ -34,8 +34,7 @@
response->completionCode = IPMI_CC_OK;
uint8_t reqPrivilegeLevel = request->reqPrivLevel;
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(handler.sessionID);
+ auto session = session::Manager::get().getSession(handler.sessionID);
if (reqPrivilegeLevel == 0) // Just return present privilege level
{
@@ -176,10 +175,8 @@
{
if (reqSessionId == session::sessionZero)
{
- reqSessionId = std::get<session::Manager&>(singletonPool)
- .getSessionIDbyHandle(
- reqSessionHandle &
- session::multiIntfaceSessionHandleMask);
+ reqSessionId = session::Manager::get().getSessionIDbyHandle(
+ reqSessionHandle & session::multiIntfaceSessionHandleMask);
if (!reqSessionId)
{
return session::ccInvalidSessionHandle;
@@ -187,15 +184,14 @@
}
auto closeSessionInstance =
- std::get<session::Manager&>(singletonPool).getSession(reqSessionId);
+ session::Manager::get().getSession(reqSessionId);
uint8_t closeSessionPriv = closeSessionInstance->currentPrivilege();
if (currentSessionPriv < closeSessionPriv)
{
return ipmi::ccInsufficientPrivilege;
}
- status = std::get<session::Manager&>(singletonPool)
- .stopSession(reqSessionId);
+ status = session::Manager::get().stopSession(reqSessionId);
if (!status)
{
@@ -262,10 +258,9 @@
try
{
- ipmiNetworkInstance =
- std::get<session::Manager&>(singletonPool).getNetworkInstance();
- auto currentSession = std::get<session::Manager&>(singletonPool)
- .getSession(handler.sessionID);
+ ipmiNetworkInstance = session::Manager::get().getNetworkInstance();
+ auto currentSession =
+ session::Manager::get().getSession(handler.sessionID);
currentSessionPriv = currentSession->currentPrivilege();
}
catch (sdbusplus::exception::SdBusError& e)
@@ -285,8 +280,7 @@
{
response->completionCode = closeMyNetInstanceSession(
reqSessionId, reqSessionHandle, currentSessionPriv);
- std::get<session::Manager&>(singletonPool)
- .scheduleSessionCleaner(100us);
+ session::Manager::get().scheduleSessionCleaner(100us);
}
else
{
diff --git a/command/sol_cmds.cpp b/command/sol_cmds.cpp
index a1e820f..1253ac5 100644
--- a/command/sol_cmds.cpp
+++ b/command/sol_cmds.cpp
@@ -1,6 +1,6 @@
#include "sol_cmds.hpp"
-#include "main.hpp"
+#include "sessions_manager.hpp"
#include "sol/sol_context.hpp"
#include "sol/sol_manager.hpp"
@@ -35,8 +35,7 @@
try
{
- auto& context = std::get<sol::Manager&>(singletonPool)
- .getContext(handler.sessionID);
+ auto& context = sol::Manager::get().getContext(handler.sessionID);
context.processInboundPayload(
request->packetSeqNum, request->packetAckSeqNum,
@@ -62,8 +61,7 @@
request->majorVersion = MAJOR_VERSION;
request->minorVersion = MINOR_VERSION;
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
message::Handler msgHandler(session->channelPtr, sessionID);
@@ -90,23 +88,22 @@
{
case Parameter::PROGRESS:
{
- outPayload.push_back(
- std::get<sol::Manager&>(singletonPool).progress);
+ outPayload.push_back(sol::Manager::get().progress);
break;
}
case Parameter::ENABLE:
{
- outPayload.push_back(std::get<sol::Manager&>(singletonPool).enable);
+ outPayload.push_back(sol::Manager::get().enable);
break;
}
case Parameter::AUTHENTICATION:
{
Auth value{0};
- value.encrypt = std::get<sol::Manager&>(singletonPool).forceEncrypt;
- value.auth = std::get<sol::Manager&>(singletonPool).forceAuth;
- value.privilege = static_cast<uint8_t>(
- std::get<sol::Manager&>(singletonPool).solMinPrivilege);
+ value.encrypt = sol::Manager::get().forceEncrypt;
+ value.auth = sol::Manager::get().forceAuth;
+ value.privilege =
+ static_cast<uint8_t>(sol::Manager::get().solMinPrivilege);
auto buffer = reinterpret_cast<const uint8_t*>(&value);
std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
@@ -116,11 +113,9 @@
{
Accumulate value{0};
- value.interval = std::get<sol::Manager&>(singletonPool)
- .accumulateInterval.count() /
+ value.interval = sol::Manager::get().accumulateInterval.count() /
sol::accIntervalFactor;
- value.threshold =
- std::get<sol::Manager&>(singletonPool).sendThreshold;
+ value.threshold = sol::Manager::get().sendThreshold;
auto buffer = reinterpret_cast<const uint8_t*>(&value);
std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
@@ -130,10 +125,9 @@
{
Retry value{0};
- value.count = std::get<sol::Manager&>(singletonPool).retryCount;
- value.interval =
- std::get<sol::Manager&>(singletonPool).retryInterval.count() /
- sol::retryIntervalFactor;
+ value.count = sol::Manager::get().retryCount;
+ value.interval = sol::Manager::get().retryInterval.count() /
+ sol::retryIntervalFactor;
auto buffer = reinterpret_cast<const uint8_t*>(&value);
std::copy_n(buffer, sizeof(value), std::back_inserter(outPayload));
@@ -149,8 +143,7 @@
}
case Parameter::CHANNEL:
{
- outPayload.push_back(
- std::get<sol::Manager&>(singletonPool).channel);
+ outPayload.push_back(sol::Manager::get().channel);
break;
}
case Parameter::NVBITRATE:
diff --git a/command_table.cpp b/command_table.cpp
index 1d9e063..a42d981 100644
--- a/command_table.cpp
+++ b/command_table.cpp
@@ -62,8 +62,7 @@
return;
}
std::shared_ptr<session::Session> session =
- std::get<session::Manager&>(singletonPool)
- .getSession(handler->sessionID);
+ session::Manager::get().getSession(handler->sessionID);
// Ignore messages that are not part of an active session
auto state = static_cast<session::State>(session->state());
@@ -122,8 +121,7 @@
if (handler->sessionID != session::sessionZero)
{
std::shared_ptr<session::Session> session =
- std::get<session::Manager&>(singletonPool)
- .getSession(handler->sessionID);
+ session::Manager::get().getSession(handler->sessionID);
auto state = static_cast<session::State>(session->state());
if ((state != session::State::setupInProgress) &&
(state != session::State::active))
diff --git a/command_table.hpp b/command_table.hpp
index e882300..172c015 100644
--- a/command_table.hpp
+++ b/command_table.hpp
@@ -216,8 +216,16 @@
*/
class Table
{
+ private:
+ struct Private
+ {
+ };
+
public:
- Table() = default;
+ explicit Table(const Private&)
+ {
+ }
+ Table() = delete;
~Table() = default;
// Command Table is a singleton so copy, copy-assignment, move and
// move assignment is deleted
@@ -226,6 +234,21 @@
Table(Table&&) = default;
Table& operator=(Table&&) = default;
+ /**
+ * @brief Get a reference to the singleton Table
+ *
+ * @return Table reference
+ */
+ static Table& get()
+ {
+ static std::shared_ptr<Table> ptr = nullptr;
+ if (!ptr)
+ {
+ ptr = std::make_shared<Table>(Private());
+ }
+ return *ptr;
+ }
+
using CommandTable = std::map<uint32_t, std::unique_ptr<Entry>>;
/**
diff --git a/main.cpp b/main.cpp
index 4092211..eab9a2f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -5,6 +5,8 @@
#include "command_table.hpp"
#include "message.hpp"
#include "message_handler.hpp"
+#include "sd_event_loop.hpp"
+#include "sessions_manager.hpp"
#include "socket_channel.hpp"
#include "sol_module.hpp"
@@ -24,16 +26,11 @@
using namespace phosphor::logging;
-// Tuple of Global Singletons
static auto io = std::make_shared<boost::asio::io_context>();
-session::Manager manager(io);
-command::Table table;
-eventloop::EventLoop loop(io);
-sol::Manager solManager(io);
-
-std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
- sol::Manager&>
- singletonPool(manager, table, loop, solManager);
+std::shared_ptr<boost::asio::io_context> getIo()
+{
+ return io;
+}
sd_bus* bus = nullptr;
@@ -102,7 +99,7 @@
setInterfaceIndex(channel);
}
- std::get<session::Manager&>(singletonPool).managerInit(channel);
+ session::Manager::get().managerInit(channel);
// Register callback to update cache for a GUID change and cache the GUID
command::registerGUIDChangeCallback();
cache::guid = command::getSystemGUID();
@@ -113,7 +110,7 @@
// Register the phosphor-net-ipmid SOL commands
sol::command::registerCommands();
- auto& loop = std::get<eventloop::EventLoop&>(singletonPool);
+ auto& loop = eventloop::EventLoop::get();
if (loop.setupSocket(sdbusp, channel))
{
return EXIT_FAILURE;
diff --git a/main.hpp b/main.hpp
index 7c78554..fa7584b 100644
--- a/main.hpp
+++ b/main.hpp
@@ -1,18 +1,9 @@
#pragma once
-#include "command/guid.hpp"
-#include "sd_event_loop.hpp"
-#include "sol/sol_manager.hpp"
-
-#include <command_table.hpp>
+#include <boost/asio/io_context.hpp>
#include <cstddef>
+#include <memory>
#include <sdbusplus/asio/connection.hpp>
-#include <sessions_manager.hpp>
-#include <tuple>
-
-extern std::tuple<session::Manager&, command::Table&, eventloop::EventLoop&,
- sol::Manager&>
- singletonPool;
// Select call timeout is set arbitrarily set to 30 sec
static constexpr size_t SELECT_CALL_TIMEOUT = 30;
@@ -21,3 +12,4 @@
extern sd_bus* bus;
std::shared_ptr<sdbusplus::asio::connection> getSdBus();
+std::shared_ptr<boost::asio::io_context> getIo();
diff --git a/message_handler.cpp b/message_handler.cpp
index 6dadbfc..33bb195 100644
--- a/message_handler.cpp
+++ b/message_handler.cpp
@@ -42,8 +42,7 @@
void Handler::updSessionData(std::shared_ptr<Message>& inMessage)
{
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(inMessage->bmcSessionID);
+ auto session = session::Manager::get().getSession(inMessage->bmcSessionID);
sessionID = inMessage->bmcSessionID;
inMessage->rcSessionID = session->getRCSessionID();
@@ -114,8 +113,7 @@
auto command = inMessage->getCommand();
if (inMessage->payloadType == PayloadType::IPMI)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
// Process PayloadType::IPMI only if ipmi is enabled or for sessionless
// or for session establisbment command
if (this->sessionID == session::sessionZero ||
@@ -131,8 +129,8 @@
inMessage->payload.begin() + sizeof(LAN::header::Request);
auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
std::vector<uint8_t> inPayload(start, end);
- std::get<command::Table&>(singletonPool)
- .executeCommand(command, inPayload, shared_from_this());
+ command::Table::get().executeCommand(command, inPayload,
+ shared_from_this());
}
else
{
@@ -142,8 +140,8 @@
}
else
{
- std::get<command::Table&>(singletonPool)
- .executeCommand(command, inMessage->payload, shared_from_this());
+ command::Table::get().executeCommand(command, inMessage->payload,
+ shared_from_this());
}
}
@@ -169,8 +167,7 @@
void Handler::send(std::shared_ptr<Message> outMessage)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
// Flatten the packet
auto packet = parser::flatten(outMessage, sessionHeader, session);
@@ -181,16 +178,14 @@
void Handler::setChannelInSession() const
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
session->channelPtr = channel;
}
void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
auto outMessage = std::make_shared<Message>();
outMessage->payloadType = PayloadType::SOL;
@@ -206,8 +201,7 @@
void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
const std::vector<uint8_t>& output)
{
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
auto outMessage = std::make_shared<Message>();
outMessage->payloadType = PayloadType::IPMI;
diff --git a/message_parsers.cpp b/message_parsers.cpp
index 7b8d832..4271c13 100644
--- a/message_parsers.cpp
+++ b/message_parsers.cpp
@@ -181,8 +181,7 @@
uint32_t sessionID = endian::from_ipmi(header->sessId);
- auto session =
- std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ auto session = session::Manager::get().getSession(sessionID);
if (!session)
{
throw std::runtime_error("RMCP+ message from unknown session");
@@ -345,8 +344,7 @@
return false;
}
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(message->bmcSessionID);
+ auto session = session::Manager::get().getSession(message->bmcSessionID);
auto integrityAlgo = session->getIntegrityAlgo();
@@ -386,8 +384,7 @@
trailer->padLength = paddingLen;
trailer->nextHeader = parser::RMCP_MESSAGE_CLASS_IPMI;
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(message->bmcSessionID);
+ auto session = session::Manager::get().getSession(message->bmcSessionID);
auto integrityData =
session->getIntegrityAlgo()->generateIntegrityData(packet);
@@ -399,8 +396,7 @@
const std::shared_ptr<Message> message,
size_t payloadLen)
{
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(message->bmcSessionID);
+ auto session = session::Manager::get().getSession(message->bmcSessionID);
return session->getCryptAlgo()->decryptPayload(
packet, sizeof(SessionHeader_t), payloadLen);
@@ -408,8 +404,7 @@
std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message)
{
- auto session = std::get<session::Manager&>(singletonPool)
- .getSession(message->bmcSessionID);
+ auto session = session::Manager::get().getSession(message->bmcSessionID);
return session->getCryptAlgo()->encryptPayload(message->payload);
}
diff --git a/sd_event_loop.hpp b/sd_event_loop.hpp
index 60b4434..1c3d1c2 100644
--- a/sd_event_loop.hpp
+++ b/sd_event_loop.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "main.hpp"
#include "sol/sol_manager.hpp"
#include <systemd/sd-event.h>
@@ -40,8 +41,14 @@
class EventLoop
{
+ private:
+ struct Private
+ {
+ };
+
public:
- explicit EventLoop(std::shared_ptr<boost::asio::io_context> io) : io(io)
+ EventLoop(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
+ io(io)
{
}
EventLoop() = delete;
@@ -51,6 +58,22 @@
EventLoop(EventLoop&&) = delete;
EventLoop& operator=(EventLoop&&) = delete;
+ /**
+ * @brief Get a reference to the singleton EventLoop
+ *
+ * @return EventLoop reference
+ */
+ static EventLoop& get()
+ {
+ static std::shared_ptr<EventLoop> ptr = nullptr;
+ if (!ptr)
+ {
+ std::shared_ptr<boost::asio::io_context> io = getIo();
+ ptr = std::make_shared<EventLoop>(io, Private());
+ }
+ return *ptr;
+ }
+
/** @brief Initialise the event loop and add the handler for incoming
* IPMI packets.
*
diff --git a/sessions_manager.hpp b/sessions_manager.hpp
index f1d060e..14027db 100644
--- a/sessions_manager.hpp
+++ b/sessions_manager.hpp
@@ -1,5 +1,6 @@
#pragma once
+#include "main.hpp"
#include "session.hpp"
#include <boost/asio/steady_timer.hpp>
@@ -32,12 +33,17 @@
class Manager
{
+ private:
+ struct Private
+ {
+ };
+
public:
// BMC Session ID is the key for the map
using SessionMap = std::map<SessionID, std::shared_ptr<Session>>;
Manager() = delete;
- explicit Manager(std::shared_ptr<boost::asio::io_context>& io) :
+ Manager(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
io(io), timer(*io){};
~Manager() = default;
Manager(const Manager&) = delete;
@@ -46,6 +52,26 @@
Manager& operator=(Manager&&) = default;
/**
+ * @brief Get a reference to the singleton Manager
+ *
+ * @return Manager reference
+ */
+ static Manager& get()
+ {
+ static std::shared_ptr<Manager> ptr = nullptr;
+ if (!ptr)
+ {
+ std::shared_ptr<boost::asio::io_context> io = getIo();
+ ptr = std::make_shared<Manager>(io, Private());
+ if (!ptr)
+ {
+ throw std::runtime_error("failed to create session manager");
+ }
+ }
+ return *ptr;
+ }
+
+ /**
* @brief Start an IPMI session
*
* @param[in] remoteConsoleSessID - Remote Console Session ID mentioned
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
index 3b2b892..f0e036c 100644
--- a/sol/sol_context.cpp
+++ b/sol/sol_context.cpp
@@ -1,7 +1,9 @@
#include "sol_context.hpp"
#include "main.hpp"
+#include "message_handler.hpp"
#include "sd_event_loop.hpp"
+#include "sessions_manager.hpp"
#include "sol_manager.hpp"
#include <phosphor-logging/log.hpp>
@@ -18,7 +20,7 @@
sendThreshold(sendThreshold), payloadInstance(instance),
sessionID(sessionID)
{
- session = std::get<session::Manager&>(singletonPool).getSession(sessionID);
+ session = session::Manager::get().getSession(sessionID);
}
std::shared_ptr<Context>
@@ -35,8 +37,7 @@
void Context::enableAccumulateTimer(bool enable)
{
// fetch the timeout from the SOL manager
- std::chrono::microseconds interval =
- std::get<sol::Manager&>(singletonPool).accumulateInterval;
+ std::chrono::microseconds interval = sol::Manager::get().accumulateInterval;
if (enable)
{
accumulateTimer.expires_after(interval);
@@ -61,8 +62,7 @@
if (enable)
{
// fetch the timeout from the SOL manager
- std::chrono::microseconds interval =
- std::get<sol::Manager&>(singletonPool).retryInterval;
+ std::chrono::microseconds interval = sol::Manager::get().retryInterval;
retryTimer.expires_after(interval);
std::weak_ptr<Context> weakRef = weak_from_this();
retryTimer.async_wait([weakRef](const boost::system::error_code& ec) {
@@ -133,7 +133,7 @@
else if ((count == expectedCharCount) && ackSeqNum)
{
// Clear the Host Console Buffer
- std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
+ sol::Manager::get().dataBuffer.erase(count);
// Once it is acknowledged stop the retry interval timer
enableRetryTimer(false);
@@ -146,8 +146,7 @@
// Write character data to the Host Console
if (!input.empty() && seqNum)
{
- auto rc =
- std::get<sol::Manager&>(singletonPool).writeConsoleSocket(input);
+ auto rc = sol::Manager::get().writeConsoleSocket(input);
if (rc)
{
log<level::ERR>("Writing to console socket descriptor failed");
@@ -182,7 +181,7 @@
void Context::prepareResponse(uint8_t ackSeqNum, uint8_t count, bool ack)
{
- auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+ auto bufferSize = sol::Manager::get().dataBuffer.size();
/* Sent a ACK only response */
if (payloadCache.size() != 0 || (bufferSize < sendThreshold))
@@ -207,7 +206,7 @@
response->outOperation.ack = ack;
response->packetSeqNum = seqNums.incOutboundSeqNum();
- auto handle = std::get<sol::Manager&>(singletonPool).dataBuffer.read();
+ auto handle = sol::Manager::get().dataBuffer.read();
std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
expectedCharCount = readSize;
@@ -225,7 +224,7 @@
return -1;
}
- auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+ auto bufferSize = sol::Manager::get().dataBuffer.size();
auto readSize = std::min(bufferSize, MAX_PAYLOAD_SIZE);
payloadCache.resize(sizeof(Payload) + readSize);
@@ -235,7 +234,7 @@
response->outOperation.ack = false;
response->packetSeqNum = seqNums.incOutboundSeqNum();
- auto handle = std::get<sol::Manager&>(singletonPool).dataBuffer.read();
+ auto handle = sol::Manager::get().dataBuffer.read();
std::copy_n(handle, readSize, payloadCache.data() + sizeof(Payload));
expectedCharCount = readSize;
@@ -255,8 +254,7 @@
{
payloadCache.clear();
expectedCharCount = 0;
- std::get<sol::Manager&>(singletonPool)
- .dataBuffer.erase(expectedCharCount);
+ sol::Manager::get().dataBuffer.erase(expectedCharCount);
}
}
@@ -269,7 +267,7 @@
void Context::charAccTimerHandler()
{
- auto bufferSize = std::get<sol::Manager&>(singletonPool).dataBuffer.size();
+ auto bufferSize = sol::Manager::get().dataBuffer.size();
try
{
diff --git a/sol/sol_manager.cpp b/sol/sol_manager.cpp
index 8407292..2102032 100644
--- a/sol/sol_manager.cpp
+++ b/sol/sol_manager.cpp
@@ -255,8 +255,7 @@
if (state != nullptr && *state == false)
{
// Stop all the payload session.
- std::get<sol::Manager&>(singletonPool)
- .stopAllPayloadInstance();
+ sol::Manager::get().stopAllPayloadInstance();
}
}
});
diff --git a/sol/sol_manager.hpp b/sol/sol_manager.hpp
index 4e797d4..b266519 100644
--- a/sol/sol_manager.hpp
+++ b/sol/sol_manager.hpp
@@ -1,6 +1,7 @@
#pragma once
#include "console_buffer.hpp"
+#include "main.hpp"
#include "session.hpp"
#include "sol_context.hpp"
@@ -36,6 +37,11 @@
*/
class Manager
{
+ private:
+ struct Private
+ {
+ };
+
public:
/** @brief SOL Payload Instance is the key for the map, the value is the
* SOL context.
@@ -49,10 +55,27 @@
Manager(Manager&&) = default;
Manager& operator=(Manager&&) = default;
- Manager(std::shared_ptr<boost::asio::io_context> io) : io(io)
+ Manager(std::shared_ptr<boost::asio::io_context>& io, const Private&) :
+ io(io)
{
}
+ /**
+ * @brief Get a reference to the singleton Manager
+ *
+ * @return Manager reference
+ */
+ static Manager& get()
+ {
+ static std::shared_ptr<Manager> ptr = nullptr;
+ if (!ptr)
+ {
+ std::shared_ptr<boost::asio::io_context> io = getIo();
+ ptr = std::make_shared<Manager>(io, Private());
+ }
+ return *ptr;
+ }
+
/** @brief io context to add events to */
std::shared_ptr<boost::asio::io_context> io;
diff --git a/sol_module.cpp b/sol_module.cpp
index 2b1fb46..d9a9a7c 100644
--- a/sol_module.cpp
+++ b/sol_module.cpp
@@ -1,7 +1,6 @@
#include "command/payload_cmds.hpp"
#include "command/sol_cmds.hpp"
#include "command_table.hpp"
-#include "main.hpp"
#include "session.hpp"
namespace sol
@@ -52,11 +51,10 @@
for (const auto& iter : commands)
{
- std::get<::command::Table&>(singletonPool)
- .registerCommand(iter.command,
- std::make_unique<::command::NetIpmidEntry>(
- iter.command, iter.functor, iter.privilege,
- iter.sessionless));
+ ::command::Table::get().registerCommand(
+ iter.command,
+ std::make_unique<::command::NetIpmidEntry>(
+ iter.command, iter.functor, iter.privilege, iter.sessionless));
}
}