1 #pragma once
2 
3 #include <iostream>
4 #include <numeric>
5 
6 #include "message.hpp"
7 #include "message_parsers.hpp"
8 #include "session.hpp"
9 
10 namespace message
11 {
12 
13 class Handler
14 {
15     public:
16 
17         explicit Handler(std::shared_ptr<udpsocket::Channel> inChannel):
18             channel(inChannel) {}
19 
20         Handler() = delete;
21         ~Handler() = default;
22         Handler(const Handler&) = default;
23         Handler& operator=(const Handler&) = default;
24         Handler(Handler&&) = default;
25         Handler& operator=(Handler&&) = default;
26 
27         /*
28          * @brief Receive the IPMI packet
29          *
30          * Read the data on the socket, get the parser based on the Session
31          * header type and flatten the payload and generate the IPMI message
32          *
33          * @return IPMI Message on success and nullptr on failure
34          *
35          */
36         std::unique_ptr<Message> receive();
37 
38         /*
39          * @brief Process the incoming IPMI message
40          *
41          * The incoming message payload is handled and the command handler for
42          * the Network function and Command is executed and the response message
43          * is returned
44          *
45          * @param[in] inMessage - Incoming Message
46          *
47          * @return Outgoing message on success and nullptr on failure
48          */
49         std::unique_ptr<Message> executeCommand(Message& inMessage);
50 
51         /*
52          * @brief Send the outgoing message
53          *
54          * The payload in the outgoing message is flattened and sent out on the
55          * socket
56          *
57          * @param[in] outMessage - Outgoing Message
58          *
59          * @return Zero on success and <0 on failure
60          */
61         int send(Message& outMessage);
62 
63         // BMC Session ID for the Channel
64         session::SessionID sessionID;
65     private:
66         // Socket channel for communicating with the remote client
67         std::shared_ptr<udpsocket::Channel> channel;
68 
69         // IPMI 1.5 or IPMI 2.0 Session Header
70         parser::SessionHeader sessionHeader;
71 
72         /*
73          * @brief Create the response IPMI message
74          *
75          * The IPMI outgoing message is constructed out of payload and the
76          * corresponding fields are populated.For the payload type IPMI, the
77          * LAN message header and trailer are added.
78          *
79          * @tparam[in] T - Outgoing message payload type
80          * @param[in] output - Payload for outgoing message
81          * @param[in] inMessage - Incoming IPMI message
82          *
83          * @return Outgoing message on success and nullptr on failure
84          */
85         template<PayloadType T>
86         std::unique_ptr<Message> createResponse(std::vector<uint8_t>& output,
87                                                 Message& inMessage)
88         {
89             auto outMessage = std::make_unique<Message>();
90             outMessage->payloadType = T;
91             outMessage->payload = output;
92             return outMessage;
93         }
94 
95         /*
96          * @brief Extract the command from the IPMI payload
97          *
98          * @param[in] message - Incoming message
99          *
100          * @return Command ID in the incoming message
101          */
102         uint32_t getCommand(Message& message);
103 
104         /*
105          * @brief Calculate 8 bit 2's complement checksum
106          *
107          * Initialize checksum to 0. For each byte, checksum = (checksum + byte)
108          * modulo 256. Then checksum = - checksum. When the checksum and the
109          * bytes are added together, modulo 256, the result should be 0.
110          */
111         uint8_t crc8bit(const uint8_t* ptr, const size_t len)
112         {
113             return (0x100 - std::accumulate(ptr,ptr+len,0));
114         }
115 
116 };
117 
118 } //namespace message
119