diff options
author | Tom Joseph <tomjoseph@in.ibm.com> | 2016-08-08 08:42:39 -0500 |
---|---|---|
committer | Tom Joseph <tomjoseph@in.ibm.com> | 2016-12-12 23:38:39 +0530 |
commit | 3e61aa0db2b1a6edd4e6dacd889a272d42895a6c (patch) | |
tree | 62f72ecea98fa0e7f6fb9c5efc06f26a9be4b822 /sessions_manager.cpp | |
parent | f0ca513a4c354c772e8c5e228d7b5484ed666381 (diff) | |
download | phosphor-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.cpp | 166 |
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 |