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