blob: b9ddbf57b592c9e6986188f353eb0f258b9177df [file] [log] [blame]
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05001#include "pldm_cmd_helper.hpp"
2
John Wang58a0e062019-11-08 15:38:15 +08003namespace pldmtool
4{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05005
John Wang58a0e062019-11-08 15:38:15 +08006namespace helper
7{
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -05008
9/*
10 * print the input buffer
11 *
12 */
13void printBuffer(const std::vector<uint8_t>& buffer)
14{
15 std::ostringstream tempStream;
16 if (!buffer.empty())
17 {
18 for (int byte : buffer)
19 {
20 tempStream << std::setfill('0') << std::setw(2) << std::hex << byte
21 << " ";
22 }
23 }
John Wang58a0e062019-11-08 15:38:15 +080024 std::cout << tempStream.str() << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050025}
26
27/*
28 * Initialize the socket, send pldm command & recieve response from socket
29 *
30 */
31int mctpSockSendRecv(const std::vector<uint8_t>& requestMsg,
32 std::vector<uint8_t>& responseMsg)
33{
34 const char devPath[] = "\0mctp-mux";
35 int returnCode = 0;
36
37 int sockFd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
38 if (-1 == sockFd)
39 {
40 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080041 std::cerr << "Failed to create the socket : RC = " << sockFd
42 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050043 return returnCode;
44 }
John Wang58a0e062019-11-08 15:38:15 +080045 std::cout << "Success in creating the socket : RC = " << sockFd
46 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050047
48 struct sockaddr_un addr
49 {
50 };
51 addr.sun_family = AF_UNIX;
52
53 memcpy(addr.sun_path, devPath, sizeof(devPath) - 1);
54
55 CustomFD socketFd(sockFd);
56 int result = connect(socketFd(), reinterpret_cast<struct sockaddr*>(&addr),
57 sizeof(devPath) + sizeof(addr.sun_family) - 1);
58 if (-1 == result)
59 {
60 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080061 std::cerr << "Failed to connect to socket : RC = " << returnCode
62 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050063 return returnCode;
64 }
John Wang58a0e062019-11-08 15:38:15 +080065 std::cout << "Success in connecting to socket : RC = " << returnCode
66 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050067
68 auto pldmType = MCTP_MSG_TYPE_PLDM;
69 result = write(socketFd(), &pldmType, sizeof(pldmType));
70 if (-1 == result)
71 {
72 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080073 std::cerr << "Failed to send message type as pldm to mctp : RC = "
74 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050075 return returnCode;
76 }
John Wang58a0e062019-11-08 15:38:15 +080077 std::cout << "Success in sending message type as pldm to mctp : RC = "
78 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050079
80 result = send(socketFd(), requestMsg.data(), requestMsg.size(), 0);
81 if (-1 == result)
82 {
83 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +080084 std::cerr << "Write to socket failure : RC = " << returnCode
85 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050086 return returnCode;
87 }
John Wang58a0e062019-11-08 15:38:15 +080088 std::cout << "Write to socket successful : RC = " << result << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050089
90 // Read the response from socket
91 ssize_t peekedLength = recv(socketFd(), nullptr, 0, MSG_TRUNC | MSG_PEEK);
92 if (0 == peekedLength)
93 {
John Wang58a0e062019-11-08 15:38:15 +080094 std::cerr << "Socket is closed : peekedLength = " << peekedLength
95 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -050096 return returnCode;
97 }
98 else if (peekedLength <= -1)
99 {
100 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800101 std::cerr << "recv() system call failed : RC = " << returnCode
102 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500103 return returnCode;
104 }
105 else
106 {
107 // loopback response message
108 std::vector<uint8_t> loopBackRespMsg(peekedLength);
109 auto recvDataLength =
110 recv(socketFd(), reinterpret_cast<void*>(loopBackRespMsg.data()),
111 peekedLength, 0);
112 if (recvDataLength == peekedLength)
113 {
John Wang58a0e062019-11-08 15:38:15 +0800114 std::cout << "Total length:" << recvDataLength << std::endl;
115 std::cout << "Loopback response message:" << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500116 printBuffer(loopBackRespMsg);
117 }
118 else
119 {
John Wang58a0e062019-11-08 15:38:15 +0800120 std::cerr << "Failure to read peeked length packet : RC = "
121 << returnCode << std::endl;
122 std::cerr << "peekedLength: " << peekedLength << std::endl;
123 std::cerr << "Total length: " << recvDataLength << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500124 return returnCode;
125 }
126
127 // Confirming on the first recv() the Request bit is set in
128 // pldm_msg_hdr struct. If set proceed with recv() or else, quit.
129 auto hdr = reinterpret_cast<const pldm_msg_hdr*>(&loopBackRespMsg[2]);
130 uint8_t request = hdr->request;
131 if (request == PLDM_REQUEST)
132 {
John Wang58a0e062019-11-08 15:38:15 +0800133 std::cout << "On first recv(),response == request : RC = "
134 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500135 ssize_t peekedLength =
136 recv(socketFd(), nullptr, 0, MSG_PEEK | MSG_TRUNC);
137
138 responseMsg.resize(peekedLength);
139 recvDataLength =
140 recv(socketFd(), reinterpret_cast<void*>(responseMsg.data()),
141 peekedLength, 0);
142 if (recvDataLength == peekedLength)
143 {
John Wang58a0e062019-11-08 15:38:15 +0800144 std::cout << "Total length: " << recvDataLength << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500145 }
146 else
147 {
John Wang58a0e062019-11-08 15:38:15 +0800148 std::cerr << "Failure to read response length packet: length = "
149 << recvDataLength << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500150 return returnCode;
151 }
152 }
153 else
154 {
John Wang58a0e062019-11-08 15:38:15 +0800155 std::cerr << "On first recv(),request != response : RC = "
156 << returnCode << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500157 return returnCode;
158 }
159 }
160 returnCode = shutdown(socketFd(), SHUT_RDWR);
161 if (-1 == returnCode)
162 {
163 returnCode = -errno;
John Wang58a0e062019-11-08 15:38:15 +0800164 std::cerr << "Failed to shutdown the socket : RC = " << returnCode
165 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500166 return returnCode;
167 }
168
John Wang58a0e062019-11-08 15:38:15 +0800169 std::cout << "Shutdown Socket successful : RC = " << returnCode
170 << std::endl;
Lakshminarayana R. Kammath27693a42019-06-24 00:51:47 -0500171 return PLDM_SUCCESS;
172}
John Wang58a0e062019-11-08 15:38:15 +0800173
174void CommandInterface::exec()
175{
176 auto [rc, requestMsg] = createRequestMsg();
177 if (rc != PLDM_SUCCESS)
178 {
179 std::cerr << "Failed to encode request message for " << pldmType << ":"
180 << commandName << " rc = " << rc << std::endl;
181 return;
182 }
183
184 std::cout << "Encode request successfully" << std::endl;
185
186 // Insert the PLDM message type and EID at the begining of the request msg.
187 requestMsg.insert(requestMsg.begin(), MCTP_MSG_TYPE_PLDM);
188 requestMsg.insert(requestMsg.begin(), PLDM_ENTITY_ID);
189
190 std::cout << "Request Message:" << std::endl;
191 printBuffer(requestMsg);
192
193 std::vector<uint8_t> responseMsg;
194 rc = mctpSockSendRecv(requestMsg, responseMsg);
195
196 if (rc != PLDM_SUCCESS)
197 {
198 std::cerr << "Failed to receive from socket: RC = " << rc << std::endl;
199 return;
200 }
201
202 std::cout << "Response Message:" << std::endl;
203 printBuffer(responseMsg);
204
205 auto responsePtr = reinterpret_cast<struct pldm_msg*>(
206 responseMsg.data() + 2 /*skip the mctp header*/);
207 parseResponseMsg(responsePtr, responseMsg.size() -
208 2 /*skip the mctp header*/ -
209 sizeof(pldm_msg_hdr));
210}
211
212} // namespace helper
213} // namespace pldmtool