summaryrefslogtreecommitdiffstats
path: root/sessions_manager.cpp
diff options
context:
space:
mode:
authorTom Joseph <tomjoseph@in.ibm.com>2016-08-08 08:42:39 -0500
committerTom Joseph <tomjoseph@in.ibm.com>2016-12-12 23:38:39 +0530
commit3e61aa0db2b1a6edd4e6dacd889a272d42895a6c (patch)
tree62f72ecea98fa0e7f6fb9c5efc06f26a9be4b822 /sessions_manager.cpp
parentf0ca513a4c354c772e8c5e228d7b5484ed666381 (diff)
downloadphosphor-net-ipmid-3e61aa0db2b1a6edd4e6dacd889a272d42895a6c.tar.gz
phosphor-net-ipmid-3e61aa0db2b1a6edd4e6dacd889a272d42895a6c.zip
Sessions Manager to manage IPMI sessions
IPMI Sessions manager is responsible for managing IPMI sessions and routines for starting and stopping sessions. Change-Id: Ic5c559fdc0dab0145e463689026c2f1c66f24a59 Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
Diffstat (limited to 'sessions_manager.cpp')
-rw-r--r--sessions_manager.cpp166
1 files changed, 166 insertions, 0 deletions
diff --git a/sessions_manager.cpp b/sessions_manager.cpp
new file mode 100644
index 0000000..ff17727
--- /dev/null
+++ b/sessions_manager.cpp
@@ -0,0 +1,166 @@
+#include "sessions_manager.hpp"
+
+#include <algorithm>
+#include <cstdlib>
+#include <iomanip>
+#include <iostream>
+#include <memory>
+
+#include "session.hpp"
+
+namespace session
+{
+
+Manager::Manager()
+{
+ /*
+ * Session ID is 0000_0000h for messages that are sent outside the session.
+ * The session setup commands are sent on this session, so when the session
+ * manager comes up, is creates the Session ID 0000_0000h. It is active
+ * through the lifetime of the Session Manager.
+ */
+ sessionsMap.emplace(0, std::make_shared<Session>());
+ // Seeding the pseudo-random generator
+ std::srand(std::time(0));
+}
+
+std::weak_ptr<Session> Manager::startSession(SessionID remoteConsoleSessID,
+ Privilege priv, cipher::rakp_auth::Algorithms authAlgo)
+{
+ std::shared_ptr<Session> session = nullptr;
+ SessionID sessionID = 0;
+ cleanStaleEntries();
+ auto activeSessions = sessionsMap.size() - MAX_SESSIONLESS_COUNT;
+
+ if (activeSessions < MAX_SESSION_COUNT)
+ {
+ do
+ {
+ session = std::make_shared<Session>(remoteConsoleSessID, priv);
+
+ /*
+ * Every IPMI Session has two ID's attached to it Remote Console
+ * Session ID and BMC Session ID. The remote console ID is passed
+ * along with the Open Session request command. The BMC session ID
+ * is the key for the session map and is generated using std::rand.
+ * There is a rare chance for collision of BMC session ID, so the
+ * following check validates that. In the case of collision the
+ * created session is reseted and a new session is created for
+ * validating collision.
+ */
+ auto iterator = sessionsMap.find(session->getBMCSessionID());
+ if (iterator != sessionsMap.end())
+ {
+ //Detected BMC Session ID collisions
+ session.reset();
+ continue;
+ }
+ else
+ {
+ break;
+ }
+ }
+ while (1);
+
+ // Set the Authentication Algorithm to RAKP_HMAC_SHA1
+ switch (authAlgo)
+ {
+ case cipher::rakp_auth::Algorithms::RAKP_HMAC_SHA1:
+ {
+ session->setAuthAlgo(
+ std::make_unique<cipher::rakp_auth::AlgoSHA1>());
+ break;
+ }
+ default:
+ {
+ throw std::runtime_error("Invalid Authentication Algorithm");
+ }
+ }
+ sessionID = session->getBMCSessionID();
+ sessionsMap.emplace(sessionID, std::move(session));
+ }
+ else
+ {
+ std::cerr << "E> No free sessions left: Active: " << activeSessions <<
+ " Allowed: " <<
+ MAX_SESSION_COUNT << "\n";
+
+ for (const auto& iterator : sessionsMap)
+ {
+ std::cerr << "E> Active Session: 0x" << std::hex
+ << std::setfill('0') << std::setw(8)
+ << (iterator.second)->getBMCSessionID() << "\n";
+ }
+ throw std::runtime_error("No free sessions left");
+ }
+
+ return getSession(sessionID);
+}
+
+void Manager::stopSession(SessionID bmcSessionID)
+{
+ // If the session is valid and not session zero
+ if(bmcSessionID != SESSION_ZERO)
+ {
+ auto iter = sessionsMap.find(bmcSessionID);
+ if (iter != sessionsMap.end())
+ {
+ iter->second->state = State::TEAR_DOWN_IN_PROGRESS;
+ }
+ }
+}
+
+std::weak_ptr<Session> Manager::getSession(SessionID sessionID,
+ RetrieveOption option)
+{
+ switch (option)
+ {
+ case RetrieveOption::BMC_SESSION_ID:
+ {
+ auto iter = sessionsMap.find(sessionID);
+ if (iter != sessionsMap.end())
+ {
+ return iter->second;
+ }
+ }
+ case RetrieveOption::RC_SESSION_ID:
+ {
+ auto iter = std::find_if(sessionsMap.begin(),
+ sessionsMap.end(),
+ [sessionID](const std::pair<const uint32_t,
+ std::shared_ptr<Session>>& in)
+ -> bool
+ {
+ return sessionID == in.second->getRCSessionID();
+ });
+
+ if (iter != sessionsMap.end())
+ {
+ return iter->second;
+ }
+ }
+ default:
+ throw std::runtime_error("Invalid retrieval option");
+ }
+
+ throw std::runtime_error("Session ID not found");
+}
+
+void Manager::cleanStaleEntries()
+{
+ for(auto iter = sessionsMap.begin(); iter != sessionsMap.end();)
+ {
+ auto session = iter->second;
+ if ((session->getBMCSessionID() != SESSION_ZERO) &&
+ !(session->isSessionActive()))
+ {
+ iter = sessionsMap.erase(iter);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+}
+
+} // namespace session
OpenPOWER on IntegriCloud