Implement API to handle inbound SOL Payload

Change-Id: I4bcb98568d84ba384ac11b7777d936c7d5fc124e
Signed-off-by: Tom Joseph <tomjoseph@in.ibm.com>
diff --git a/sol/sol_context.cpp b/sol/sol_context.cpp
new file mode 100644
index 0000000..b81281b
--- /dev/null
+++ b/sol/sol_context.cpp
@@ -0,0 +1,123 @@
+#include <phosphor-logging/log.hpp>
+#include "main.hpp"
+#include "sd_event_loop.hpp"
+#include "sol_context.hpp"
+#include "sol_manager.hpp"
+
+namespace sol
+{
+
+using namespace phosphor::logging;
+
+void Context::processInboundPayload(uint8_t seqNum,
+                                    uint8_t ackSeqNum,
+                                    uint8_t count,
+                                    bool status,
+                                    const Buffer& input)
+{
+    uint8_t respAckSeqNum = 0;
+    uint8_t acceptedCount = 0;
+    auto ack = false;
+
+    /*
+     * Check if the Inbound sequence number is same as the expected one.
+     * If the Packet Sequence Number is 0, it is an ACK-Only packet. Multiple
+     * outstanding sequence numbers are not supported in this version of the SOL
+     * specification. Retried packets use the same sequence number as the first
+     * packet.
+     */
+    if(seqNum && (seqNum != seqNums.get(true)))
+    {
+        log<level::INFO>("Out of sequence SOL packet - packet is dropped");
+        return;
+    }
+
+    /*
+     * Check if the expected ACK/NACK sequence number is same as the
+     * ACK/NACK sequence number in the packet. If packet ACK/NACK sequence
+     * number is 0, then it is an informational packet. No request packet being
+     * ACK'd or NACK'd.
+     */
+    if (ackSeqNum && (ackSeqNum != seqNums.get(false)))
+    {
+        log<level::INFO>("Out of sequence ack number - SOL packet is dropped");
+        return;
+    }
+
+    /*
+     * Retry the SOL payload packet in the following conditions:
+     *
+     * a) NACK in Operation/Status
+     * b) Accepted Character Count does not match with the sent out SOL payload
+     * c) Non-zero Packet ACK/NACK Sequence Number
+     */
+    if (status || ((count != expectedCharCount) && ackSeqNum))
+    {
+        resendPayload(noClear);
+        std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+                (payloadInstance, eventloop::Timers::RETRY, false);
+        std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+                (payloadInstance, eventloop::Timers::RETRY, true);
+        return;
+    }
+    /*
+     * Clear the sent data once the acknowledgment sequence number matches
+     * and the expected character count matches.
+     */
+    else if ((count == expectedCharCount) && ackSeqNum)
+    {
+        // Clear the Host Console Buffer
+        std::get<sol::Manager&>(singletonPool).dataBuffer.erase(count);
+
+        // Once it is acknowledged stop the retry interval timer
+        std::get<eventloop::EventLoop&>(singletonPool).switchTimer(
+                payloadInstance, eventloop::Timers::RETRY, false);
+
+        retryCounter = maxRetryCount;
+        expectedCharCount = 0;
+        payloadCache.clear();
+    }
+
+    // Write character data to the Host Console
+    if (!input.empty() && seqNum)
+    {
+        auto rc = std::get<sol::Manager&>(singletonPool).writeConsoleSocket(
+                input);
+        if (rc)
+        {
+            log<level::ERR>("Writing to console socket descriptor failed");
+            ack = true;
+        }
+        else
+        {
+            respAckSeqNum = seqNum;
+            ack = false;
+            acceptedCount = input.size();
+        }
+    }
+
+    if (seqNum != 0)
+    {
+        seqNums.incInboundSeqNum();
+        prepareResponse(respAckSeqNum, acceptedCount, ack);
+    }
+    else
+    {
+        std::get<eventloop::EventLoop&>(singletonPool).switchTimer
+                (payloadInstance, eventloop::Timers::ACCUMULATE, true);
+    }
+}
+
+void Context::prepareResponse(uint8_t ackSeqNum,
+                              uint8_t count,
+                              bool ack)
+{
+
+}
+
+void Context::resendPayload(bool clear)
+{
+
+}
+
+} // namespace sol