Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 : #include "adx_msg_proto.h"
11 : #include "securec.h"
12 : #include "mmpa_api.h"
13 : #include "ascend_hal.h"
14 : #include "memory_utils.h"
15 : #include "log/adx_log.h"
16 : #include "adx_comm_opt_manager.h"
17 : namespace Adx {
18 : static const uint32_t MAX_PROTO_FILE_BUFFER_SIZE = 512000; // 500kb
19 : static const int32_t MAX_DEV_FILE_SIZE = 4096; // 4k
20 :
21 80 : MsgProto *AdxMsgProto::CreateMsgPacket(CmdClassT type, uint16_t devId, IdeSendBuffT data, uint32_t length)
22 : {
23 80 : MsgProto *msg = AdxMsgProto::CreateDataMsg(data, length);
24 80 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return nullptr, "create message failed");
25 79 : msg->devId = devId;
26 79 : msg->reqType = type;
27 79 : return msg;
28 : }
29 :
30 80 : MsgProto *AdxMsgProto::CreateMsgByType(MsgType type, IdeSendBuffT data, uint32_t length)
31 : {
32 80 : MsgProto *msg = nullptr;
33 80 : if (length > UINT32_MAX - sizeof(MsgProto)) {
34 0 : return nullptr;
35 : }
36 :
37 80 : if (type == MsgType::MSG_CTRL || type == MsgType::MSG_DATA) {
38 80 : uint32_t mallocLen = length + sizeof(MsgProto);
39 80 : msg = reinterpret_cast<MsgProto *>(IdeXmalloc(mallocLen));
40 80 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return nullptr, "malloc memory failed");
41 80 : if (data != nullptr) { // send buffer(data) not nullptr copy data to message
42 31 : int32_t ret = memcpy_s(msg->data, length, data, length);
43 31 : if (ret != EOK) {
44 1 : IDE_LOGE("create msg mem copy failed");
45 1 : IDE_XFREE_AND_SET_NULL(msg);
46 1 : return nullptr;
47 : }
48 : }
49 :
50 79 : msg->msgType = type;
51 79 : msg->sliceLen = length;
52 79 : msg->totalLen = length;
53 79 : IDE_LOGD("adx_msg_proto CreateMsgByType length is %u bytes", length);
54 79 : msg->headInfo = ADX_PROTO_MAGIC_VALUE;
55 79 : msg->headVer = ADX_PROTO_VERSION;
56 79 : msg->order = 0;
57 79 : return msg;
58 : }
59 :
60 0 : return nullptr;
61 : }
62 :
63 80 : MsgProto *AdxMsgProto::CreateDataMsg(IdeSendBuffT data, uint32_t length)
64 : {
65 80 : return CreateMsgByType(MsgType::MSG_DATA, data, length);
66 : }
67 :
68 4 : int32_t AdxMsgProto::CreateCtrlMsg(MsgProto &proto, MsgStatus status)
69 : {
70 4 : proto.headInfo = ADX_PROTO_MAGIC_VALUE;
71 4 : proto.headVer = ADX_PROTO_VERSION;
72 4 : proto.order = 0;
73 4 : proto.sliceLen = 0;
74 4 : proto.totalLen = 0;
75 4 : proto.msgType = MsgType::MSG_CTRL;
76 4 : proto.status = status;
77 4 : return IDE_DAEMON_OK;
78 : }
79 :
80 11 : MsgCode AdxMsgProto::SendMsgData(const CommHandle &handle, CmdClassT type, MsgStatus status,
81 : IdeSendBuffT data, uint32_t length)
82 : {
83 11 : MsgProto *msg = AdxMsgProto::CreateMsgPacket(type, 0, data, length);
84 11 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return IDE_DAEMON_MALLOC_ERROR, "create message failed");
85 10 : std::unique_ptr<MsgProto, decltype(&IdeXfree)> sendDataMsgPtr(msg, IdeXfree);
86 10 : sendDataMsgPtr->status = status;
87 10 : msg = nullptr;
88 20 : int32_t ret = AdxCommOptManager::Instance().Write(handle, sendDataMsgPtr.get(),
89 10 : sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
90 10 : if (ret != IDE_DAEMON_OK) {
91 4 : IDE_LOGE("send message failed, ret: %d, session: %zu, length: %u bytes, please check peer end is alive",
92 : ret, handle.session, length);
93 4 : return IDE_DAEMON_CHANNEL_ERROR;
94 : }
95 :
96 6 : return IDE_DAEMON_NONE_ERROR;
97 10 : }
98 :
99 11 : MsgCode AdxMsgProto::GetStringMsgData(const CommHandle &handle, std::string &value)
100 : {
101 11 : MsgProto *req = nullptr;
102 11 : int32_t length = 0;
103 11 : int32_t blockType = COMM_OPT_NOBLOCK;
104 11 : if (handle.timeout == 0) {
105 0 : blockType = COMM_OPT_BLOCK;
106 11 : } else if (handle.timeout > 0) {
107 9 : blockType = handle.timeout;
108 : }
109 11 : int32_t ret = AdxCommOptManager::Instance().Read(handle, reinterpret_cast<IdeRecvBuffT>(&req), length, blockType);
110 11 : if ((ret == IDE_DAEMON_ERROR) || (req == nullptr) || (length <= 0)) {
111 8 : if (ret == DRV_ERROR_WAIT_TIMEOUT) {
112 1 : return IDE_DAEMON_HDC_TIMEOUT;
113 : }
114 7 : if (ret == IDE_DAEMON_SOCK_CLOSE) {
115 0 : return static_cast<MsgCode>(IDE_DAEMON_SOCK_CLOSE);
116 : }
117 7 : return IDE_DAEMON_CHANNEL_ERROR;
118 : }
119 :
120 3 : SharedPtr<MsgProto> msgPtr(req, IdeXfree);
121 3 : if (length <= static_cast<int32_t>(sizeof(MsgProto))) {
122 1 : IDE_LOGE("receive request length(%d bytes) exception", length);
123 1 : return IDE_DAEMON_INVALID_PARAM_ERROR;
124 : }
125 2 : req = nullptr;
126 2 : if (msgPtr->status == MsgStatus::MSG_STATUS_FILE_LOAD) {
127 0 : IDE_LOGE("receive request status(%d) exception", static_cast<int32_t>(MsgStatus::MSG_STATUS_FILE_LOAD));
128 0 : return IDE_DAEMON_UNKNOW_ERROR;
129 : }
130 2 : if (msgPtr->sliceLen + sizeof(MsgProto) != (uint32_t)length) {
131 1 : IDE_LOGE("receive request package(%u bytes) length(%d bytes) exception", msgPtr->sliceLen, length);
132 1 : return IDE_DAEMON_UNKNOW_ERROR;
133 : }
134 :
135 1 : value = std::string((IdeStringBuffer)msgPtr->data, msgPtr->sliceLen);
136 1 : return IDE_DAEMON_NONE_ERROR;
137 3 : }
138 :
139 3 : MsgCode AdxMsgProto::SendEventFile(const CommHandle &handle, CmdClassT type, uint16_t devId, int32_t fd)
140 : {
141 3 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
142 3 : MsgProto *msg = AdxMsgProto::CreateMsgPacket(type, devId, nullptr, MAX_PROTO_FILE_BUFFER_SIZE);
143 3 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return IDE_DAEMON_MALLOC_ERROR, "create message failed");
144 3 : std::unique_ptr<MsgProto, decltype(&IdeXfree)> sendDataMsgPtr(msg, IdeXfree);
145 3 : msg = nullptr;
146 :
147 3 : mmSsize_t pos = mmLseek(fd, 0L, SEEK_SET);
148 3 : IDE_CTRL_VALUE_FAILED(pos >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek set failed");
149 :
150 3 : mmSsize_t readLen = MAX_PROTO_FILE_BUFFER_SIZE;
151 3 : mmSsize_t len = mmRead(fd, sendDataMsgPtr->data, readLen);
152 3 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
153 3 : int32_t err = mmGetErrorCode();
154 3 : if ((len < 0) && (err == EIO)) {
155 1 : IDE_LOGW("An EIO exception occurred when reading files from the event_sched directory");
156 1 : len = 0;
157 : } else {
158 2 : IDE_CTRL_VALUE_FAILED(len >= 0, return IDE_DAEMON_UNKNOW_ERROR,
159 : "Failed to read file in the event_sched directory: info [%s]",
160 : mmGetErrorFormatMessage(err, errBuf, MAX_ERRSTR_LEN));
161 : }
162 :
163 2 : if (len > MAX_DEV_FILE_SIZE) {
164 0 : IDE_LOGW("read file success, but the size has exceeded the maximum size of the dev file.");
165 : }
166 2 : sendDataMsgPtr->status = MsgStatus::MSG_STATUS_FILE_LOAD;
167 2 : sendDataMsgPtr->totalLen = len;
168 2 : sendDataMsgPtr->offset = 0;
169 2 : sendDataMsgPtr->sliceLen = (uint32_t)len;
170 4 : int32_t ret = AdxCommOptManager::Instance().Write(handle, sendDataMsgPtr.get(),
171 2 : sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
172 2 : IDE_CTRL_VALUE_FAILED(ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR,
173 : "hand shake failed ret %d, please check server is alive", ret);
174 0 : RecvResponse(handle);
175 0 : return IDE_DAEMON_NONE_ERROR;
176 3 : }
177 :
178 1 : MsgCode AdxMsgProto::SendFile(const CommHandle &handle, CmdClassT type, uint16_t devId, int32_t fd)
179 : {
180 1 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
181 1 : MsgProto *msg = AdxMsgProto::CreateMsgPacket(type, devId, nullptr, MAX_PROTO_FILE_BUFFER_SIZE);
182 1 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return IDE_DAEMON_MALLOC_ERROR, "create message failed");
183 1 : std::unique_ptr<MsgProto, decltype(&IdeXfree)> sendDataMsgPtr(msg, IdeXfree);
184 1 : msg = nullptr;
185 1 : mmSsize_t fileLength = mmLseek(fd, 0L, SEEK_END);
186 1 : IDE_CTRL_VALUE_FAILED(fileLength >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek end failed");
187 :
188 1 : mmSsize_t pos = mmLseek(fd, 0L, SEEK_SET);
189 1 : IDE_CTRL_VALUE_FAILED(pos >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek set failed");
190 1 : mmSsize_t resLen = fileLength;
191 1 : sendDataMsgPtr->status = MsgStatus::MSG_STATUS_FILE_LOAD;
192 1 : sendDataMsgPtr->totalLen = fileLength;
193 1 : sendDataMsgPtr->offset = 0;
194 :
195 1 : if (resLen == 0) {
196 0 : sendDataMsgPtr->sliceLen = (uint32_t)fileLength;
197 0 : int32_t ret = AdxCommOptManager::Instance().Write(handle, sendDataMsgPtr.get(),
198 0 : sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
199 0 : IDE_CTRL_VALUE_FAILED(ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR,
200 : "send empty file failed ret %d, please check server is alive", ret);
201 : }
202 :
203 1 : while (resLen > 0) {
204 1 : mmSsize_t readLen = static_cast<uint32_t>(resLen) > MAX_PROTO_FILE_BUFFER_SIZE ?
205 : MAX_PROTO_FILE_BUFFER_SIZE : resLen;
206 1 : mmSsize_t len = mmRead(fd, sendDataMsgPtr->data, readLen);
207 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
208 2 : IDE_CTRL_VALUE_FAILED(len >= 0, return IDE_DAEMON_UNKNOW_ERROR,
209 : "read file failed : info [%s]", mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
210 1 : if (len > 0 && len <= readLen) {
211 1 : sendDataMsgPtr->sliceLen = (uint32_t)len;
212 2 : int32_t ret = AdxCommOptManager::Instance().Write(handle, sendDataMsgPtr.get(),
213 1 : sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
214 1 : IDE_CTRL_VALUE_FAILED(ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR,
215 : "hand shake failed ret %d, please check server is alive", ret);
216 : }
217 0 : sendDataMsgPtr->offset += (uint32_t)len;
218 0 : resLen -= len;
219 : }
220 0 : RecvResponse(handle);
221 0 : return IDE_DAEMON_NONE_ERROR;
222 1 : }
223 :
224 0 : MsgCode AdxMsgProto::RecvFile(const CommHandle &handle, int32_t fd)
225 : {
226 0 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
227 0 : MsgProto *msg = nullptr;
228 0 : int32_t length = 0;
229 : while (true) {
230 0 : int32_t ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&msg,
231 0 : length, handle.timeout);
232 0 : IDE_CTRL_VALUE_FAILED(ret == IDE_DAEMON_OK && msg != nullptr, return IDE_DAEMON_CHANNEL_ERROR,
233 : "hand shake failed ret %d, read failed or timeout", ret);
234 0 : if (msg->msgType == MsgType::MSG_CTRL) { // check the message is ctrl or not
235 0 : IDE_LOGW("receive ctrl msg from device, stop receiving this file");
236 0 : IDE_XFREE_AND_SET_NULL(msg);
237 0 : return IDE_DAEMON_NONE_ERROR;
238 : }
239 0 : if (msg->sliceLen != 0 && msg->sliceLen <= MAX_PROTO_FILE_BUFFER_SIZE) {
240 0 : mmSsize_t len = mmWrite(fd, msg->data, msg->sliceLen);
241 0 : if (len < 0) {
242 0 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
243 0 : IDE_LOGE("write file failed : info [%s]",
244 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
245 0 : IDE_XFREE_AND_SET_NULL(msg);
246 0 : return IDE_DAEMON_UNKNOW_ERROR;
247 : }
248 : }
249 :
250 0 : if (msg->totalLen == msg->sliceLen + msg->offset) {
251 0 : break;
252 : }
253 :
254 0 : IDE_XFREE_AND_SET_NULL(msg);
255 0 : }
256 :
257 0 : if (SendResponse(handle, msg->reqType, msg->devId, MsgStatus::MSG_STATUS_NONE_ERROR) !=
258 : IDE_DAEMON_NONE_ERROR) {
259 0 : IDE_LOGW("send response exception");
260 0 : IDE_XFREE_AND_SET_NULL(msg);
261 0 : return IDE_DAEMON_CHANNEL_ERROR;
262 : }
263 :
264 0 : IDE_XFREE_AND_SET_NULL(msg);
265 0 : return IDE_DAEMON_NONE_ERROR;
266 : }
267 :
268 2 : MsgCode AdxMsgProto::SendResponse(const CommHandle &handle, uint16_t type,
269 : uint16_t devId, MsgStatus status)
270 : {
271 : MsgProto msg;
272 2 : (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
273 2 : (void)CreateCtrlMsg(msg, status);
274 2 : msg.reqType = type;
275 2 : msg.devId = devId;
276 2 : int32_t ret = AdxCommOptManager::Instance().Write(handle, (IdeSendBuffT)&msg, sizeof(MsgProto), COMM_OPT_BLOCK);
277 2 : if (ret != IDE_DAEMON_OK) {
278 1 : IDE_LOGE("send response failed ret %d, please check peer is alive", ret);
279 1 : return IDE_DAEMON_CHANNEL_ERROR;
280 : }
281 :
282 1 : IDE_LOGI("device(%d) cmd(%d) response success", devId, type);
283 1 : return IDE_DAEMON_NONE_ERROR;
284 : }
285 :
286 2 : MsgCode AdxMsgProto::RecvResponse(const CommHandle &handle)
287 : {
288 2 : MsgProto *recvBuf = nullptr;
289 2 : int32_t length = 0;
290 2 : int32_t ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&recvBuf, length, COMM_OPT_BLOCK);
291 2 : if (ret != IDE_DAEMON_OK || recvBuf == nullptr) {
292 0 : return IDE_DAEMON_CHANNEL_ERROR;
293 : }
294 :
295 2 : if (recvBuf->msgType == MsgType::MSG_CTRL && recvBuf->status == MsgStatus::MSG_STATUS_NONE_ERROR) {
296 2 : IDE_XFREE_AND_SET_NULL(recvBuf);
297 2 : return IDE_DAEMON_NONE_ERROR;
298 : }
299 :
300 0 : if (recvBuf->msgType == MsgType::MSG_CTRL && recvBuf->status == MsgStatus::MSG_STATUS_CACHE_FULL_ERROR) {
301 0 : IDE_XFREE_AND_SET_NULL(recvBuf);
302 0 : return IDE_DAEMON_DUMP_QUEUE_FULL;
303 : }
304 :
305 0 : IDE_XFREE_AND_SET_NULL(recvBuf);
306 0 : return IDE_DAEMON_UNKNOW_ERROR;
307 : }
308 : }
|