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