1 #pragma once 2 3 #include "message.hpp" 4 #include "message_parsers.hpp" 5 #include "session.hpp" 6 #include "sol/console_buffer.hpp" 7 8 #include <iostream> 9 #include <memory> 10 #include <numeric> 11 12 namespace message 13 { 14 15 class Handler 16 { 17 public: 18 explicit Handler( 19 std::shared_ptr<udpsocket::Channel> channel, 20 uint32_t sessionID = message::Message::MESSAGE_INVALID_SESSION_ID) : 21 sessionID(sessionID), 22 channel(channel) 23 { 24 } 25 26 Handler() = delete; 27 ~Handler() = default; 28 Handler(const Handler&) = default; 29 Handler& operator=(const Handler&) = default; 30 Handler(Handler&&) = default; 31 Handler& operator=(Handler&&) = default; 32 33 /** 34 * @brief Receive the IPMI packet 35 * 36 * Read the data on the socket, get the parser based on the Session 37 * header type and flatten the payload and generate the IPMI message 38 * 39 * @return IPMI Message on success and nullptr on failure 40 * 41 */ 42 std::shared_ptr<Message> receive(); 43 44 /** 45 * @brief Process the incoming IPMI message 46 * 47 * The incoming message payload is handled and the command handler for 48 * the Network function and Command is executed and the response message 49 * is returned 50 * 51 * @param[in] inMessage - Incoming Message 52 * 53 * @return Outgoing message on success and nullptr on failure 54 */ 55 std::shared_ptr<Message> executeCommand(std::shared_ptr<Message> inMessage); 56 57 /** @brief Send the outgoing message 58 * 59 * The payload in the outgoing message is flattened and sent out on the 60 * socket 61 * 62 * @param[in] outMessage - Outgoing Message 63 */ 64 void send(std::shared_ptr<Message> outMessage); 65 66 /** @brief Set socket channel in session object */ 67 void setChannelInSession() const; 68 69 /** @brief Send the SOL payload 70 * 71 * The SOL payload is flattened and sent out on the socket 72 * 73 * @param[in] input - SOL Payload 74 */ 75 void sendSOLPayload(const std::vector<uint8_t>& input); 76 77 /** @brief Send the unsolicited IPMI payload to the remote console. 78 * 79 * This is used by commands like SOL activating, in which case the BMC 80 * has to notify the remote console that a SOL payload is activating 81 * on another channel. 82 * 83 * @param[in] netfn - Net function. 84 * @param[in] cmd - Command. 85 * @param[in] input - Command request data. 86 */ 87 void sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd, 88 const std::vector<uint8_t>& input); 89 90 // BMC Session ID for the Channel 91 session::SessionID sessionID; 92 93 private: 94 /** @brief Socket channel for communicating with the remote client.*/ 95 std::shared_ptr<udpsocket::Channel> channel; 96 97 parser::SessionHeader sessionHeader = parser::SessionHeader::IPMI20; 98 99 /** 100 * @brief Create the response IPMI message 101 * 102 * The IPMI outgoing message is constructed out of payload and the 103 * corresponding fields are populated.For the payload type IPMI, the 104 * LAN message header and trailer are added. 105 * 106 * @tparam[in] T - Outgoing message payload type 107 * @param[in] output - Payload for outgoing message 108 * @param[in] inMessage - Incoming IPMI message 109 * 110 * @return Outgoing message on success and nullptr on failure 111 */ 112 template <PayloadType T> 113 std::shared_ptr<Message> createResponse(std::vector<uint8_t>& output, 114 std::shared_ptr<Message> inMessage) 115 { 116 auto outMessage = std::make_shared<Message>(); 117 outMessage->payloadType = T; 118 outMessage->payload = output; 119 return outMessage; 120 } 121 122 /** 123 * @brief Extract the command from the IPMI payload 124 * 125 * @param[in] message - Incoming message 126 * 127 * @return Command ID in the incoming message 128 */ 129 uint32_t getCommand(std::shared_ptr<Message> message); 130 131 /** 132 * @brief Calculate 8 bit 2's complement checksum 133 * 134 * Initialize checksum to 0. For each byte, checksum = (checksum + byte) 135 * modulo 256. Then checksum = - checksum. When the checksum and the 136 * bytes are added together, modulo 256, the result should be 0. 137 */ 138 uint8_t crc8bit(const uint8_t* ptr, const size_t len) 139 { 140 return (0x100 - std::accumulate(ptr, ptr + len, 0)); 141 } 142 }; 143 144 } // namespace message 145