Session Commands Implementation

Implements Set Session Privilege Command and Close Session
command.

Change-Id: I18aeee7bcae48db3eb8a61292c9333ca2304dcf1
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/command/session_cmds.cpp b/command/session_cmds.cpp
new file mode 100644
index 0000000..f30ef78
--- /dev/null
+++ b/command/session_cmds.cpp
@@ -0,0 +1,79 @@
+#include "session_cmds.hpp"
+
+#include <iostream>
+
+#include "endian.hpp"
+#include "main.hpp"
+#include <host-ipmid/ipmid-api.h>
+
+namespace command
+{
+
+std::vector<uint8_t> setSessionPrivilegeLevel(std::vector<uint8_t>& inPayload,
+                                              const message::Handler& handler)
+{
+    std::cout << ">> setSessionPrivilegeLevel\n";
+
+    std::vector<uint8_t> outPayload(sizeof(SetSessionPrivLevelResp));
+    auto request = reinterpret_cast<SetSessionPrivLevelReq*>(inPayload.data());
+    auto response = reinterpret_cast<SetSessionPrivLevelResp*>
+                    (outPayload.data());
+    response->completionCode = IPMI_CC_OK;
+    uint8_t reqPrivilegeLevel = request->reqPrivLevel;
+
+    auto session = (std::get<session::Manager&>(singletonPool).getSession(
+                       handler.sessionID)).lock();
+
+    if (reqPrivilegeLevel == 0) // Just return present privilege level
+    {
+        response->newPrivLevel = static_cast<uint8_t>(session->curPrivLevel);
+    }
+    else if (reqPrivilegeLevel <= static_cast<uint8_t>(session->maxPrivLevel))
+    {
+        session->curPrivLevel = static_cast<session::Privilege>
+                                (reqPrivilegeLevel);
+        response->newPrivLevel = reqPrivilegeLevel;
+    }
+    else
+    {
+        // Requested level exceeds Channel and/or User Privilege Limit
+        response->completionCode = IPMI_CC_EXCEEDS_USER_PRIV;
+    }
+
+    std::cout << "<< setSessionPrivilegeLevel\n";
+    return outPayload;
+}
+
+std::vector<uint8_t> closeSession(std::vector<uint8_t>& inPayload,
+                                  const message::Handler& handler)
+{
+    std::cout << ">> closeSession\n";
+
+    std::vector<uint8_t> outPayload(sizeof(CloseSessionResponse));
+    auto request = reinterpret_cast<CloseSessionRequest*>(inPayload.data());
+    auto response = reinterpret_cast<CloseSessionResponse*>(outPayload.data());
+    response->completionCode = IPMI_CC_OK ;
+
+    auto bmcSessionID = endian::from_ipmi(request->sessionID);
+
+    // Session 0 is needed to handle session setup, so session zero is never
+    // closed
+    if (bmcSessionID == session::SESSION_ZERO)
+    {
+        response->completionCode = IPMI_CC_INVALID_SESSIONID;
+    }
+    else
+    {
+        auto status = std::get<session::Manager&>(singletonPool).stopSession
+                        (bmcSessionID);
+        if(!status)
+        {
+            response->completionCode = IPMI_CC_INVALID_SESSIONID;
+        }
+    }
+
+    std::cout << "<< closeSession\n";
+    return outPayload;
+}
+
+} // namespace command