1 #pragma once 2 3 #include "message.hpp" 4 #include "message_parsers.hpp" 5 #include "session.hpp" 6 #include "sessions_manager.hpp" 7 #include "sol/console_buffer.hpp" 8 9 #include <memory> 10 11 namespace message 12 { 13 14 class Handler : public std::enable_shared_from_this<Handler> 15 { 16 public: 17 /** 18 * @brief Create a Handler intended for a full transaction 19 * that may or may not use asynchronous responses 20 */ 21 Handler(std::shared_ptr<udpsocket::Channel> channel, 22 std::shared_ptr<boost::asio::io_context> io, 23 uint32_t sessionID = message::Message::MESSAGE_INVALID_SESSION_ID) : 24 sessionID(sessionID), channel(channel), io(io) 25 { 26 if (sessionID != message::Message::MESSAGE_INVALID_SESSION_ID) 27 { 28 session = session::Manager::get().getSession(sessionID); 29 } 30 } 31 32 /** 33 * @brief Create a Handler intended for a send only (SOL) 34 */ 35 Handler(std::shared_ptr<udpsocket::Channel> channel, 36 uint32_t sessionID = message::Message::MESSAGE_INVALID_SESSION_ID) : 37 sessionID(sessionID), channel(channel), io(nullptr) 38 { 39 if (sessionID != message::Message::MESSAGE_INVALID_SESSION_ID) 40 { 41 session = session::Manager::get().getSession(sessionID); 42 } 43 } 44 45 ~Handler(); 46 Handler() = delete; 47 Handler(const Handler&) = delete; 48 Handler& operator=(const Handler&) = delete; 49 Handler(Handler&&) = delete; 50 Handler& operator=(Handler&&) = delete; 51 52 /** 53 * @brief Process the incoming IPMI message 54 * 55 * The incoming payload is read from the channel. If a message is read, it 56 * is passed onto executeCommand, which may or may not execute the command 57 * asynchrounously. If the command is executed asynchrounously, a shared_ptr 58 * of self via shared_from_this will keep this object alive until the 59 * response is ready. Then on the destructor, the response will be sent. 60 */ 61 void processIncoming(); 62 63 /** @brief Set socket channel in session object */ 64 void setChannelInSession() const; 65 66 /** @brief Send the SOL payload 67 * 68 * The SOL payload is flattened and sent out on the socket 69 * 70 * @param[in] input - SOL Payload 71 */ 72 void sendSOLPayload(const std::vector<uint8_t>& input); 73 74 /** @brief Send the unsolicited IPMI payload to the remote console. 75 * 76 * This is used by commands like SOL activating, in which case the BMC 77 * has to notify the remote console that a SOL payload is activating 78 * on another channel. 79 * 80 * @param[in] netfn - Net function. 81 * @param[in] cmd - Command. 82 * @param[in] input - Command request data. 83 */ 84 void sendUnsolicitedIPMIPayload(uint8_t netfn, uint8_t cmd, 85 const std::vector<uint8_t>& input); 86 87 // BMC Session ID for the Channel 88 session::SessionID sessionID; 89 90 /** @brief response to send back */ 91 std::optional<std::vector<uint8_t>> outPayload; 92 93 private: 94 /** 95 * @brief Receive the IPMI packet 96 * 97 * Read the data on the socket, get the parser based on the Session 98 * header type and flatten the payload and generate the IPMI message 99 */ 100 bool receive(); 101 102 /** 103 * @brief Get Session data from the IPMI packet 104 * 105 */ 106 void updSessionData(std::shared_ptr<Message>& inMessage); 107 108 /** 109 * @brief Process the incoming IPMI message 110 * 111 * The incoming message payload is handled and the command handler for 112 * the Network function and Command is executed and the response message 113 * is returned 114 */ 115 void executeCommand(); 116 117 /** @brief Send the outgoing message 118 * 119 * The payload in the outgoing message is flattened and sent out on the 120 * socket 121 * 122 * @param[in] outMessage - Outgoing Message 123 */ 124 void send(std::shared_ptr<Message> outMessage); 125 126 #ifdef RMCP_PING 127 /** @brief Send the outgoing ASF message 128 * 129 * The outgoing ASF message contains only ASF message header 130 * which is flattened and sent out on the socket 131 */ 132 void sendASF(); 133 #endif // RMCP_PING 134 135 /** @brief Write the packet to the socket 136 * 137 * @param[in] packet - Outgoing packet 138 */ 139 void writeData(const std::vector<uint8_t>& packet); 140 141 /** @brief Socket channel for communicating with the remote client.*/ 142 std::shared_ptr<udpsocket::Channel> channel; 143 144 /** @brief asio io context to run asynchrounously */ 145 std::shared_ptr<boost::asio::io_context> io; 146 147 parser::SessionHeader sessionHeader = parser::SessionHeader::IPMI20; 148 149 std::shared_ptr<message::Message> inMessage{}; 150 151 /** @brief The IPMI session of the handler */ 152 std::shared_ptr<session::Session> session{}; 153 }; 154 155 } // namespace message 156