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