xref: /openbmc/phosphor-net-ipmid/message_handler.hpp (revision 0a4dde44f1612cac531b2cc01096ef6ee44d0d49)
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),
25         channel(channel), io(io)
26     {
27         if (sessionID != message::Message::MESSAGE_INVALID_SESSION_ID)
28         {
29             session = session::Manager::get().getSession(sessionID);
30         }
31     }
32 
33     /**
34      * @brief Create a Handler intended for a send only (SOL)
35      */
36     Handler(std::shared_ptr<udpsocket::Channel> channel,
37             uint32_t sessionID = message::Message::MESSAGE_INVALID_SESSION_ID) :
38         sessionID(sessionID),
39         channel(channel), io(nullptr)
40     {
41         if (sessionID != message::Message::MESSAGE_INVALID_SESSION_ID)
42         {
43             session = session::Manager::get().getSession(sessionID);
44         }
45     }
46 
47     ~Handler();
48     Handler() = delete;
49     Handler(const Handler&) = delete;
50     Handler& operator=(const Handler&) = delete;
51     Handler(Handler&&) = delete;
52     Handler& operator=(Handler&&) = delete;
53 
54     /**
55      * @brief Process the incoming IPMI message
56      *
57      * The incoming payload is read from the channel. If a message is read, it
58      * is passed onto executeCommand, which may or may not execute the command
59      * asynchrounously. If the command is executed asynchrounously, a shared_ptr
60      * of self via shared_from_this will keep this object alive until the
61      * response is ready. Then on the destructor, the response will be sent.
62      */
63     void processIncoming();
64 
65     /** @brief Set socket channel in session object */
66     void setChannelInSession() const;
67 
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);
75 
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);
88 
89     // BMC Session ID for the Channel
90     session::SessionID sessionID;
91 
92     /** @brief response to send back */
93     std::optional<std::vector<uint8_t>> outPayload;
94 
95   private:
96     /**
97      * @brief Receive the IPMI packet
98      *
99      * Read the data on the socket, get the parser based on the Session
100      * header type and flatten the payload and generate the IPMI message
101      */
102     bool receive();
103 
104     /**
105      * @brief Get Session data from the IPMI packet
106      *
107      */
108     void updSessionData(std::shared_ptr<Message>& inMessage);
109 
110     /**
111      * @brief Process the incoming IPMI message
112      *
113      * The incoming message payload is handled and the command handler for
114      * the Network function and Command is executed and the response message
115      * is returned
116      */
117     void executeCommand();
118 
119     /** @brief Send the outgoing message
120      *
121      *  The payload in the outgoing message is flattened and sent out on the
122      *  socket
123      *
124      *  @param[in] outMessage - Outgoing Message
125      */
126     void send(std::shared_ptr<Message> outMessage);
127 
128 #ifdef RMCP_PING
129     /** @brief Send the outgoing ASF message
130      *
131      *  The outgoing ASF message contains only ASF message header
132      *  which is flattened and sent out on the socket
133      */
134     void sendASF();
135 #endif // RMCP_PING
136 
137     /** @brief Write the packet to the socket
138      *
139      *  @param[in] packet - Outgoing packet
140      */
141     void writeData(const std::vector<uint8_t>& packet);
142 
143     /** @brief Socket channel for communicating with the remote client.*/
144     std::shared_ptr<udpsocket::Channel> channel;
145 
146     /** @brief asio io context to run asynchrounously */
147     std::shared_ptr<boost::asio::io_context> io;
148 
149     parser::SessionHeader sessionHeader = parser::SessionHeader::IPMI20;
150 
151     std::shared_ptr<message::Message> inMessage;
152 
153     /** @brief The IPMI session of the handler */
154     std::shared_ptr<session::Session> session;
155 };
156 
157 } // namespace message
158