#pragma once #include "message.hpp" #include "message_parsers.hpp" #include "session.hpp" #include "sol/console_buffer.hpp" #include #include #include namespace message { class Handler { public: explicit Handler( std::shared_ptr channel, uint32_t sessionID = message::Message::MESSAGE_INVALID_SESSION_ID) : sessionID(sessionID), channel(channel) { } Handler() = delete; ~Handler() = default; Handler(const Handler&) = default; Handler& operator=(const Handler&) = default; Handler(Handler&&) = default; Handler& operator=(Handler&&) = default; /** * @brief Receive the IPMI packet * * Read the data on the socket, get the parser based on the Session * header type and flatten the payload and generate the IPMI message * * @return IPMI Message on success and nullptr on failure * */ std::shared_ptr receive(); /** * @brief Process the incoming IPMI message * * The incoming message payload is handled and the command handler for * the Network function and Command is executed and the response message * is returned * * @param[in] inMessage - Incoming Message * * @return Outgoing message on success and nullptr on failure */ std::shared_ptr executeCommand(std::shared_ptr inMessage); /** @brief Send the outgoing message * * The payload in the outgoing message is flattened and sent out on the * socket * * @param[in] outMessage - Outgoing Message */ void send(std::shared_ptr outMessage); /** @brief Set socket channel in session object */ void setChannelInSession() const; /** @brief Send the SOL payload * * The SOL payload is flattened and sent out on the socket * * @param[in] input - SOL Payload */ void sendSOLPayload(const std::vector& input); /** @brief Send the unsolicited IPMI payload to the remote console. * * This is used by commands like SOL activating, in which case the BMC * has to notify the remote console that a SOL payload is activating * on another channel. * * @param[in] netfn - Net function. * @param[in] cmd - Command. * @param[in] input - Command request data. */ void sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd, const std::vector& input); // BMC Session ID for the Channel session::SessionID sessionID; private: /** @brief Socket channel for communicating with the remote client.*/ std::shared_ptr channel; parser::SessionHeader sessionHeader = parser::SessionHeader::IPMI20; /** * @brief Create the response IPMI message * * The IPMI outgoing message is constructed out of payload and the * corresponding fields are populated.For the payload type IPMI, the * LAN message header and trailer are added. * * @tparam[in] T - Outgoing message payload type * @param[in] output - Payload for outgoing message * @param[in] inMessage - Incoming IPMI message * * @return Outgoing message on success and nullptr on failure */ template std::shared_ptr createResponse(std::vector& output, std::shared_ptr inMessage) { auto outMessage = std::make_shared(); outMessage->payloadType = T; outMessage->payload = output; return outMessage; } /** * @brief Extract the command from the IPMI payload * * @param[in] message - Incoming message * * @return Command ID in the incoming message */ uint32_t getCommand(std::shared_ptr message); /** * @brief Calculate 8 bit 2's complement checksum * * Initialize checksum to 0. For each byte, checksum = (checksum + byte) * modulo 256. Then checksum = - checksum. When the checksum and the * bytes are added together, modulo 256, the result should be 0. */ uint8_t crc8bit(const uint8_t* ptr, const size_t len) { return (0x100 - std::accumulate(ptr, ptr + len, 0)); } }; } // namespace message