netipmid: use shared_ptr on messages instead of unique_ptr+references

Messages were being created and held by unique_ptr objects and then
shared via reference. This is dangerous and sidesteps the whole point of
a unique_ptr, which is to enforce single ownership. This replaces the
usage with a shared_ptr, which denotes shared ownership.

Change-Id: I19ed2693f5a0f5ce47d720ed255fa05bdf3844f8
Signed-off-by: Vernon Mauery <vernon.mauery@linux.intel.com>
diff --git a/message_handler.cpp b/message_handler.cpp
index c5d5d4e..b9cc6ab 100644
--- a/message_handler.cpp
+++ b/message_handler.cpp
@@ -16,7 +16,7 @@
 namespace message
 {
 
-std::unique_ptr<Message> Handler::receive()
+std::shared_ptr<Message> Handler::receive()
 {
     std::vector<uint8_t> packet;
     auto readStatus = 0;
@@ -32,7 +32,7 @@
     }
 
     // Unflatten the packet
-    std::unique_ptr<Message> message;
+    std::shared_ptr<Message> message;
     std::tie(message, sessionHeader) = parser::unflatten(packet);
 
     auto session = std::get<session::Manager&>(singletonPool)
@@ -46,18 +46,17 @@
 }
 
 template <>
-std::unique_ptr<Message>
-    Handler::createResponse<PayloadType::IPMI>(std::vector<uint8_t>& output,
-                                               Message& inMessage)
+std::shared_ptr<Message> Handler::createResponse<PayloadType::IPMI>(
+    std::vector<uint8_t>& output, std::shared_ptr<Message> inMessage)
 {
-    auto outMessage = std::make_unique<Message>();
+    auto outMessage = std::make_shared<Message>();
     outMessage->payloadType = PayloadType::IPMI;
 
     outMessage->payload.resize(sizeof(LAN::header::Response) + output.size() +
                                sizeof(LAN::trailer::Response));
 
     auto reqHeader =
-        reinterpret_cast<LAN::header::Request*>(inMessage.payload.data());
+        reinterpret_cast<LAN::header::Request*>(inMessage->payload.data());
     auto respHeader =
         reinterpret_cast<LAN::header::Response*>(outMessage->payload.data());
 
@@ -84,22 +83,23 @@
     return outMessage;
 }
 
-std::unique_ptr<Message> Handler::executeCommand(Message& inMessage)
+std::shared_ptr<Message>
+    Handler::executeCommand(std::shared_ptr<Message> inMessage)
 {
     // Get the CommandID to map into the command table
     auto command = getCommand(inMessage);
     std::vector<uint8_t> output{};
 
-    if (inMessage.payloadType == PayloadType::IPMI)
+    if (inMessage->payloadType == PayloadType::IPMI)
     {
-        if (inMessage.payload.size() <
+        if (inMessage->payload.size() <
             (sizeof(LAN::header::Request) + sizeof(LAN::trailer::Request)))
         {
             return nullptr;
         }
 
-        auto start = inMessage.payload.begin() + sizeof(LAN::header::Request);
-        auto end = inMessage.payload.end() - sizeof(LAN::trailer::Request);
+        auto start = inMessage->payload.begin() + sizeof(LAN::header::Request);
+        auto end = inMessage->payload.end() - sizeof(LAN::trailer::Request);
         std::vector<uint8_t> inPayload(start, end);
 
         output = std::get<command::Table&>(singletonPool)
@@ -108,12 +108,12 @@
     else
     {
         output = std::get<command::Table&>(singletonPool)
-                     .executeCommand(command, inMessage.payload, *this);
+                     .executeCommand(command, inMessage->payload, *this);
     }
 
-    std::unique_ptr<Message> outMessage = nullptr;
+    std::shared_ptr<Message> outMessage = nullptr;
 
-    switch (inMessage.payloadType)
+    switch (inMessage->payloadType)
     {
         case PayloadType::IPMI:
             outMessage = createResponse<PayloadType::IPMI>(output, inMessage);
@@ -135,34 +135,34 @@
             break;
     }
 
-    outMessage->isPacketEncrypted = inMessage.isPacketEncrypted;
-    outMessage->isPacketAuthenticated = inMessage.isPacketAuthenticated;
-    outMessage->rcSessionID = inMessage.rcSessionID;
-    outMessage->bmcSessionID = inMessage.bmcSessionID;
+    outMessage->isPacketEncrypted = inMessage->isPacketEncrypted;
+    outMessage->isPacketAuthenticated = inMessage->isPacketAuthenticated;
+    outMessage->rcSessionID = inMessage->rcSessionID;
+    outMessage->bmcSessionID = inMessage->bmcSessionID;
 
     return outMessage;
 }
 
-uint32_t Handler::getCommand(Message& message)
+uint32_t Handler::getCommand(std::shared_ptr<Message> message)
 {
     uint32_t command = 0;
 
-    command |= (static_cast<uint8_t>(message.payloadType) << 16);
-    if (message.payloadType == PayloadType::IPMI)
+    command |= (static_cast<uint8_t>(message->payloadType) << 16);
+    if (message->payloadType == PayloadType::IPMI)
     {
         command |=
-            ((reinterpret_cast<LAN::header::Request*>(message.payload.data()))
+            ((reinterpret_cast<LAN::header::Request*>(message->payload.data()))
                  ->netfn)
             << 8;
         command |=
-            (reinterpret_cast<LAN::header::Request*>(message.payload.data()))
+            (reinterpret_cast<LAN::header::Request*>(message->payload.data()))
                 ->cmd;
     }
 
     return command;
 }
 
-void Handler::send(Message& outMessage)
+void Handler::send(std::shared_ptr<Message> outMessage)
 {
     auto session =
         std::get<session::Manager&>(singletonPool).getSession(sessionID);
@@ -188,17 +188,16 @@
 
 void Handler::sendSOLPayload(const std::vector<uint8_t>& input)
 {
-    Message outMessage;
-
     auto session =
         std::get<session::Manager&>(singletonPool).getSession(sessionID);
 
-    outMessage.payloadType = PayloadType::SOL;
-    outMessage.payload = input;
-    outMessage.isPacketEncrypted = session->isCryptAlgoEnabled();
-    outMessage.isPacketAuthenticated = session->isIntegrityAlgoEnabled();
-    outMessage.rcSessionID = session->getRCSessionID();
-    outMessage.bmcSessionID = sessionID;
+    auto outMessage = std::make_shared<Message>();
+    outMessage->payloadType = PayloadType::SOL;
+    outMessage->payload = input;
+    outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
+    outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
+    outMessage->rcSessionID = session->getRCSessionID();
+    outMessage->bmcSessionID = sessionID;
 
     send(outMessage);
 }
@@ -206,22 +205,21 @@
 void Handler::sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd,
                                          const std::vector<uint8_t>& output)
 {
-    Message outMessage;
-
     auto session =
         std::get<session::Manager&>(singletonPool).getSession(sessionID);
 
-    outMessage.payloadType = PayloadType::IPMI;
-    outMessage.isPacketEncrypted = session->isCryptAlgoEnabled();
-    outMessage.isPacketAuthenticated = session->isIntegrityAlgoEnabled();
-    outMessage.rcSessionID = session->getRCSessionID();
-    outMessage.bmcSessionID = sessionID;
+    auto outMessage = std::make_shared<Message>();
+    outMessage->payloadType = PayloadType::IPMI;
+    outMessage->isPacketEncrypted = session->isCryptAlgoEnabled();
+    outMessage->isPacketAuthenticated = session->isIntegrityAlgoEnabled();
+    outMessage->rcSessionID = session->getRCSessionID();
+    outMessage->bmcSessionID = sessionID;
 
-    outMessage.payload.resize(sizeof(LAN::header::Request) + output.size() +
-                              sizeof(LAN::trailer::Request));
+    outMessage->payload.resize(sizeof(LAN::header::Request) + output.size() +
+                               sizeof(LAN::trailer::Request));
 
     auto respHeader =
-        reinterpret_cast<LAN::header::Request*>(outMessage.payload.data());
+        reinterpret_cast<LAN::header::Request*>(outMessage->payload.data());
 
     // Add IPMI LAN Message Request Header
     respHeader->rsaddr = LAN::requesterBMCAddress;
@@ -235,12 +233,12 @@
 
     // Copy the output by the execution of the command
     std::copy(output.begin(), output.end(),
-              outMessage.payload.begin() + assembledSize);
+              outMessage->payload.begin() + assembledSize);
     assembledSize += output.size();
 
     // Add the IPMI LAN Message Trailer
     auto trailer = reinterpret_cast<LAN::trailer::Request*>(
-        outMessage.payload.data() + assembledSize);
+        outMessage->payload.data() + assembledSize);
 
     // Calculate the checksum for the field rqaddr in the header to the
     // command data, 3 corresponds to size of the fields before rqaddr( rsaddr,
diff --git a/message_handler.hpp b/message_handler.hpp
index 063f8d2..3c99660 100644
--- a/message_handler.hpp
+++ b/message_handler.hpp
@@ -6,6 +6,7 @@
 #include "sol/console_buffer.hpp"
 
 #include <iostream>
+#include <memory>
 #include <numeric>
 
 namespace message
@@ -38,7 +39,7 @@
      * @return IPMI Message on success and nullptr on failure
      *
      */
-    std::unique_ptr<Message> receive();
+    std::shared_ptr<Message> receive();
 
     /**
      * @brief Process the incoming IPMI message
@@ -51,7 +52,7 @@
      *
      * @return Outgoing message on success and nullptr on failure
      */
-    std::unique_ptr<Message> executeCommand(Message& inMessage);
+    std::shared_ptr<Message> executeCommand(std::shared_ptr<Message> inMessage);
 
     /** @brief Send the outgoing message
      *
@@ -60,7 +61,7 @@
      *
      *  @param[in] outMessage - Outgoing Message
      */
-    void send(Message& outMessage);
+    void send(std::shared_ptr<Message> outMessage);
 
     /** @brief Set socket channel in session object */
     void setChannelInSession() const;
@@ -109,10 +110,10 @@
      * @return Outgoing message on success and nullptr on failure
      */
     template <PayloadType T>
-    std::unique_ptr<Message> createResponse(std::vector<uint8_t>& output,
-                                            Message& inMessage)
+    std::shared_ptr<Message> createResponse(std::vector<uint8_t>& output,
+                                            std::shared_ptr<Message> inMessage)
     {
-        auto outMessage = std::make_unique<Message>();
+        auto outMessage = std::make_shared<Message>();
         outMessage->payloadType = T;
         outMessage->payload = output;
         return outMessage;
@@ -125,7 +126,7 @@
      *
      * @return Command ID in the incoming message
      */
-    uint32_t getCommand(Message& message);
+    uint32_t getCommand(std::shared_ptr<Message> message);
 
     /**
      * @brief Calculate 8 bit 2's complement checksum
diff --git a/message_parsers.cpp b/message_parsers.cpp
index 7497747..ddb9d01 100644
--- a/message_parsers.cpp
+++ b/message_parsers.cpp
@@ -14,7 +14,7 @@
 namespace parser
 {
 
-std::tuple<std::unique_ptr<Message>, SessionHeader>
+std::tuple<std::shared_ptr<Message>, SessionHeader>
     unflatten(std::vector<uint8_t>& inPacket)
 {
     // Check if the packet has atleast the size of the RMCP Header
@@ -54,8 +54,8 @@
     }
 }
 
-std::vector<uint8_t> flatten(Message& outMessage, SessionHeader authType,
-                             session::Session& session)
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             SessionHeader authType, session::Session& session)
 {
     // Call the flatten routine based on the header type
     switch (authType)
@@ -80,7 +80,7 @@
 namespace ipmi15parser
 {
 
-std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
+std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
 {
     // Check if the packet has atleast the Session Header
     if (inPacket.size() < sizeof(SessionHeader_t))
@@ -88,7 +88,7 @@
         throw std::runtime_error("IPMI1.5 Session Header Missing");
     }
 
-    auto message = std::make_unique<Message>();
+    auto message = std::make_shared<Message>();
 
     auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
 
@@ -107,7 +107,8 @@
     return message;
 }
 
-std::vector<uint8_t> flatten(Message& outMessage, session::Session& session)
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             session::Session& session)
 {
     std::vector<uint8_t> packet(sizeof(SessionHeader_t));
 
@@ -120,13 +121,13 @@
     header->base.format.formatType =
         static_cast<uint8_t>(parser::SessionHeader::IPMI15);
     header->sessSeqNum = 0;
-    header->sessId = endian::to_ipmi(outMessage.rcSessionID);
+    header->sessId = endian::to_ipmi(outMessage->rcSessionID);
 
-    header->payloadLength = static_cast<uint8_t>(outMessage.payload.size());
+    header->payloadLength = static_cast<uint8_t>(outMessage->payload.size());
 
     // Insert the Payload into the Packet
-    packet.insert(packet.end(), outMessage.payload.begin(),
-                  outMessage.payload.end());
+    packet.insert(packet.end(), outMessage->payload.begin(),
+                  outMessage->payload.end());
 
     // Insert the Session Trailer
     packet.resize(packet.size() + sizeof(SessionTrailer_t));
@@ -142,7 +143,7 @@
 namespace ipmi20parser
 {
 
-std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
+std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket)
 {
     // Check if the packet has atleast the Session Header
     if (inPacket.size() < sizeof(SessionHeader_t))
@@ -150,7 +151,7 @@
         throw std::runtime_error("IPMI2.0 Session Header Missing");
     }
 
-    auto message = std::make_unique<Message>();
+    auto message = std::make_shared<Message>();
 
     auto header = reinterpret_cast<SessionHeader_t*>(inPacket.data());
 
@@ -166,8 +167,7 @@
 
     if (message->isPacketAuthenticated)
     {
-        if (!(internal::verifyPacketIntegrity(inPacket, *(message.get()),
-                                              payloadLen)))
+        if (!(internal::verifyPacketIntegrity(inPacket, message, payloadLen)))
         {
             throw std::runtime_error("Packet Integrity check failed");
         }
@@ -178,7 +178,7 @@
     {
         // Assign the decrypted payload to the IPMI Message
         message->payload =
-            internal::decryptPayload(inPacket, *(message.get()), payloadLen);
+            internal::decryptPayload(inPacket, message, payloadLen);
     }
     else
     {
@@ -190,7 +190,8 @@
     return message;
 }
 
-std::vector<uint8_t> flatten(Message& outMessage, session::Session& session)
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             session::Session& session)
 {
     std::vector<uint8_t> packet(sizeof(SessionHeader_t));
 
@@ -201,8 +202,8 @@
     header->base.classOfMsg = parser::RMCP_MESSAGE_CLASS_IPMI;
     header->base.format.formatType =
         static_cast<uint8_t>(parser::SessionHeader::IPMI20);
-    header->payloadType = static_cast<uint8_t>(outMessage.payloadType);
-    header->sessId = endian::to_ipmi(outMessage.rcSessionID);
+    header->payloadType = static_cast<uint8_t>(outMessage->payloadType);
+    header->sessId = endian::to_ipmi(outMessage->rcSessionID);
 
     // Add session sequence number
     internal::addSequenceNumber(packet, session);
@@ -210,7 +211,7 @@
     size_t payloadLen = 0;
 
     // Encrypt the payload if needed
-    if (outMessage.isPacketEncrypted)
+    if (outMessage->isPacketEncrypted)
     {
         header->payloadType |= PAYLOAD_ENCRYPT_MASK;
         auto cipherPayload = internal::encryptPayload(outMessage);
@@ -223,15 +224,15 @@
     else
     {
         header->payloadLength =
-            endian::to_ipmi<uint16_t>(outMessage.payload.size());
-        payloadLen = outMessage.payload.size();
+            endian::to_ipmi<uint16_t>(outMessage->payload.size());
+        payloadLen = outMessage->payload.size();
 
         // Insert the Payload into the Packet
-        packet.insert(packet.end(), outMessage.payload.begin(),
-                      outMessage.payload.end());
+        packet.insert(packet.end(), outMessage->payload.begin(),
+                      outMessage->payload.end());
     }
 
-    if (outMessage.isPacketAuthenticated)
+    if (outMessage->isPacketAuthenticated)
     {
         internal::addIntegrityData(packet, outMessage, payloadLen);
     }
@@ -258,7 +259,8 @@
 }
 
 bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
-                           const Message& message, size_t payloadLen)
+                           const std::shared_ptr<Message> message,
+                           size_t payloadLen)
 {
     /*
      * Padding bytes are added to cause the number of bytes in the data range
@@ -281,7 +283,7 @@
     }
 
     auto session = std::get<session::Manager&>(singletonPool)
-                       .getSession(message.bmcSessionID);
+                       .getSession(message->bmcSessionID);
 
     auto integrityAlgo = session->getIntegrityAlgo();
 
@@ -305,8 +307,8 @@
     return integrityAlgo->verifyIntegrityData(packet, length, integrityIter);
 }
 
-void addIntegrityData(std::vector<uint8_t>& packet, const Message& message,
-                      size_t payloadLen)
+void addIntegrityData(std::vector<uint8_t>& packet,
+                      const std::shared_ptr<Message> message, size_t payloadLen)
 {
     // The following logic calculates the number of padding bytes to be added to
     // IPMI packet. If needed each integrity Pad byte is set to FFh.
@@ -322,7 +324,7 @@
     trailer->nextHeader = parser::RMCP_MESSAGE_CLASS_IPMI;
 
     auto session = std::get<session::Manager&>(singletonPool)
-                       .getSession(message.bmcSessionID);
+                       .getSession(message->bmcSessionID);
 
     auto integrityData =
         session->getIntegrityAlgo()->generateIntegrityData(packet);
@@ -331,21 +333,22 @@
 }
 
 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
-                                    const Message& message, size_t payloadLen)
+                                    const std::shared_ptr<Message> message,
+                                    size_t payloadLen)
 {
     auto session = std::get<session::Manager&>(singletonPool)
-                       .getSession(message.bmcSessionID);
+                       .getSession(message->bmcSessionID);
 
     return session->getCryptAlgo()->decryptPayload(
         packet, sizeof(SessionHeader_t), payloadLen);
 }
 
-std::vector<uint8_t> encryptPayload(Message& message)
+std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message)
 {
     auto session = std::get<session::Manager&>(singletonPool)
-                       .getSession(message.bmcSessionID);
+                       .getSession(message->bmcSessionID);
 
-    return session->getCryptAlgo()->encryptPayload(message.payload);
+    return session->getCryptAlgo()->encryptPayload(message->payload);
 }
 
 } // namespace internal
diff --git a/message_parsers.hpp b/message_parsers.hpp
index 0dae43b..b38da40 100644
--- a/message_parsers.hpp
+++ b/message_parsers.hpp
@@ -59,7 +59,7 @@
  *         header type. In case of failure nullptr and session header type
  *         would be invalid.
  */
-std::tuple<std::unique_ptr<Message>, SessionHeader>
+std::tuple<std::shared_ptr<Message>, SessionHeader>
     unflatten(std::vector<uint8_t>& inPacket);
 
 /**
@@ -72,8 +72,8 @@
  *
  * @return IPMI packet on success
  */
-std::vector<uint8_t> flatten(Message& outMessage, SessionHeader authType,
-                             session::Session& session);
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             SessionHeader authType, session::Session& session);
 
 } // namespace parser
 
@@ -101,7 +101,7 @@
  *
  * @return IPMI message in the packet on success
  */
-std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
+std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
 
 /**
  * @brief Flatten an IPMI message and generate the IPMI packet with the
@@ -111,7 +111,8 @@
  *
  * @return IPMI packet on success
  */
-std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             session::Session& session);
 
 } // namespace ipmi15parser
 
@@ -147,7 +148,7 @@
  *
  * @return IPMI message in the packet on success
  */
-std::unique_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
+std::shared_ptr<Message> unflatten(std::vector<uint8_t>& inPacket);
 
 /**
  * @brief Flatten an IPMI message and generate the IPMI packet with the
@@ -157,7 +158,8 @@
  *
  * @return IPMI packet on success
  */
-std::vector<uint8_t> flatten(Message& outMessage, session::Session& session);
+std::vector<uint8_t> flatten(std::shared_ptr<Message> outMessage,
+                             session::Session& session);
 
 namespace internal
 {
@@ -180,7 +182,8 @@
  *
  */
 bool verifyPacketIntegrity(const std::vector<uint8_t>& packet,
-                           const Message& message, size_t payloadLen);
+                           const std::shared_ptr<Message> message,
+                           size_t payloadLen);
 
 /**
  * @brief Add Integrity data to the outgoing IPMI packet
@@ -189,7 +192,8 @@
  * @param[in] message - IPMI Message populated for the outgoing packet
  * @param[in] payloadLen - Length of the IPMI payload
  */
-void addIntegrityData(std::vector<uint8_t>& packet, const Message& message,
+void addIntegrityData(std::vector<uint8_t>& packet,
+                      const std::shared_ptr<Message> message,
                       size_t payloadLen);
 
 /**
@@ -202,7 +206,8 @@
  * @return on successful completion, return the plain text payload
  */
 std::vector<uint8_t> decryptPayload(const std::vector<uint8_t>& packet,
-                                    const Message& message, size_t payloadLen);
+                                    const std::shared_ptr<Message> message,
+                                    size_t payloadLen);
 
 /**
  * @brief Encrypt the plain text payload for the outgoing IPMI packet
@@ -211,7 +216,7 @@
  *
  * @return on successful completion, return the encrypted payload
  */
-std::vector<uint8_t> encryptPayload(Message& message);
+std::vector<uint8_t> encryptPayload(std::shared_ptr<Message> message);
 
 } // namespace internal
 
diff --git a/sd_event_loop.cpp b/sd_event_loop.cpp
index a5fd41d..aa5224a 100644
--- a/sd_event_loop.cpp
+++ b/sd_event_loop.cpp
@@ -29,24 +29,22 @@
         // Initialize the Message Handler with the socket channel
         message::Handler msgHandler(channelPtr);
 
-        std::unique_ptr<message::Message> inMessage;
-
         // Read the incoming IPMI packet
-        inMessage = msgHandler.receive();
+        std::shared_ptr<message::Message> inMessage(msgHandler.receive());
         if (inMessage == nullptr)
         {
             return 0;
         }
 
         // Execute the Command
-        auto outMessage = msgHandler.executeCommand(*(inMessage.get()));
+        auto outMessage = msgHandler.executeCommand(inMessage);
         if (outMessage == nullptr)
         {
             return 0;
         }
 
         // Send the response IPMI Message
-        msgHandler.send(*(outMessage.get()));
+        msgHandler.send(outMessage);
     }
     catch (std::exception& e)
     {