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(
81 : const CommHandle& handle, CmdClassT type, MsgStatus status, 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(
89 10 : handle, sendDataMsgPtr.get(), sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
90 10 : if (ret != IDE_DAEMON_OK) {
91 4 : IDE_LOGE(
92 : "send message failed, ret: %d, session: %zu, length: %u bytes, please check peer end is alive", ret,
93 : handle.session, length);
94 4 : return IDE_DAEMON_CHANNEL_ERROR;
95 : }
96 :
97 6 : return IDE_DAEMON_NONE_ERROR;
98 10 : }
99 :
100 11 : MsgCode AdxMsgProto::GetStringMsgData(const CommHandle& handle, std::string& value)
101 : {
102 11 : MsgProto* req = nullptr;
103 11 : int32_t length = 0;
104 11 : int32_t blockType = COMM_OPT_NOBLOCK;
105 11 : if (handle.timeout == 0) {
106 0 : blockType = COMM_OPT_BLOCK;
107 11 : } else if (handle.timeout > 0) {
108 9 : blockType = handle.timeout;
109 : }
110 11 : int32_t ret = AdxCommOptManager::Instance().Read(handle, reinterpret_cast<IdeRecvBuffT>(&req), length, blockType);
111 11 : if ((ret == IDE_DAEMON_ERROR) || (req == nullptr) || (length <= 0)) {
112 8 : if (ret == DRV_ERROR_WAIT_TIMEOUT) {
113 1 : return IDE_DAEMON_HDC_TIMEOUT;
114 : }
115 7 : if (ret == IDE_DAEMON_SOCK_CLOSE) {
116 0 : return static_cast<MsgCode>(IDE_DAEMON_SOCK_CLOSE);
117 : }
118 7 : return IDE_DAEMON_CHANNEL_ERROR;
119 : }
120 :
121 3 : SharedPtr<MsgProto> msgPtr(req, IdeXfree);
122 3 : if (length <= static_cast<int32_t>(sizeof(MsgProto))) {
123 1 : IDE_LOGE("receive request length(%d bytes) exception", length);
124 1 : return IDE_DAEMON_INVALID_PARAM_ERROR;
125 : }
126 2 : req = nullptr;
127 2 : if (msgPtr->status == MsgStatus::MSG_STATUS_FILE_LOAD) {
128 0 : IDE_LOGE("receive request status(%d) exception", static_cast<int32_t>(MsgStatus::MSG_STATUS_FILE_LOAD));
129 0 : return IDE_DAEMON_UNKNOW_ERROR;
130 : }
131 2 : if (msgPtr->sliceLen + sizeof(MsgProto) != (uint32_t)length) {
132 1 : IDE_LOGE("receive request package(%u bytes) length(%d bytes) exception", msgPtr->sliceLen, length);
133 1 : return IDE_DAEMON_UNKNOW_ERROR;
134 : }
135 :
136 1 : value = std::string((IdeStringBuffer)msgPtr->data, msgPtr->sliceLen);
137 1 : return IDE_DAEMON_NONE_ERROR;
138 3 : }
139 :
140 3 : MsgCode AdxMsgProto::SendEventFile(const CommHandle& handle, CmdClassT type, uint16_t devId, int32_t fd)
141 : {
142 3 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
143 3 : MsgProto* msg = AdxMsgProto::CreateMsgPacket(type, devId, nullptr, MAX_PROTO_FILE_BUFFER_SIZE);
144 3 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return IDE_DAEMON_MALLOC_ERROR, "create message failed");
145 3 : std::unique_ptr<MsgProto, decltype(&IdeXfree)> sendDataMsgPtr(msg, IdeXfree);
146 3 : msg = nullptr;
147 :
148 3 : mmSsize_t pos = mmLseek(fd, 0L, SEEK_SET);
149 3 : IDE_CTRL_VALUE_FAILED(pos >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek set failed");
150 :
151 3 : mmSsize_t readLen = MAX_PROTO_FILE_BUFFER_SIZE;
152 3 : mmSsize_t len = mmRead(fd, sendDataMsgPtr->data, readLen);
153 3 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
154 3 : int32_t err = mmGetErrorCode();
155 3 : if ((len < 0) && (err == EIO)) {
156 1 : IDE_LOGW("An EIO exception occurred when reading files from the event_sched directory");
157 1 : len = 0;
158 : } else {
159 2 : IDE_CTRL_VALUE_FAILED(
160 : len >= 0, return IDE_DAEMON_UNKNOW_ERROR, "Failed to read file in the event_sched directory: info [%s]",
161 : mmGetErrorFormatMessage(err, errBuf, MAX_ERRSTR_LEN));
162 : }
163 :
164 2 : if (len > MAX_DEV_FILE_SIZE) {
165 0 : IDE_LOGW("read file success, but the size has exceeded the maximum size of the dev file.");
166 : }
167 2 : sendDataMsgPtr->status = MsgStatus::MSG_STATUS_FILE_LOAD;
168 2 : sendDataMsgPtr->totalLen = len;
169 2 : sendDataMsgPtr->offset = 0;
170 2 : sendDataMsgPtr->sliceLen = (uint32_t)len;
171 4 : int32_t ret = AdxCommOptManager::Instance().Write(
172 2 : handle, sendDataMsgPtr.get(), sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
173 2 : IDE_CTRL_VALUE_FAILED(
174 : ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR, "hand shake failed ret %d, please check server is alive",
175 : ret);
176 0 : RecvResponse(handle);
177 0 : return IDE_DAEMON_NONE_ERROR;
178 3 : }
179 :
180 1 : MsgCode AdxMsgProto::SendFile(const CommHandle& handle, CmdClassT type, uint16_t devId, int32_t fd)
181 : {
182 1 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
183 1 : MsgProto* msg = AdxMsgProto::CreateMsgPacket(type, devId, nullptr, MAX_PROTO_FILE_BUFFER_SIZE);
184 1 : IDE_CTRL_VALUE_FAILED(msg != nullptr, return IDE_DAEMON_MALLOC_ERROR, "create message failed");
185 1 : std::unique_ptr<MsgProto, decltype(&IdeXfree)> sendDataMsgPtr(msg, IdeXfree);
186 1 : msg = nullptr;
187 1 : mmSsize_t fileLength = mmLseek(fd, 0L, SEEK_END);
188 1 : IDE_CTRL_VALUE_FAILED(fileLength >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek end failed");
189 :
190 1 : mmSsize_t pos = mmLseek(fd, 0L, SEEK_SET);
191 1 : IDE_CTRL_VALUE_FAILED(pos >= 0, return IDE_DAEMON_UNKNOW_ERROR, "lseek set failed");
192 1 : mmSsize_t resLen = fileLength;
193 1 : sendDataMsgPtr->status = MsgStatus::MSG_STATUS_FILE_LOAD;
194 1 : sendDataMsgPtr->totalLen = fileLength;
195 1 : sendDataMsgPtr->offset = 0;
196 :
197 1 : if (resLen == 0) {
198 0 : sendDataMsgPtr->sliceLen = (uint32_t)fileLength;
199 0 : int32_t ret = AdxCommOptManager::Instance().Write(
200 0 : handle, sendDataMsgPtr.get(), sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
201 0 : IDE_CTRL_VALUE_FAILED(
202 : ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR,
203 : "send empty file failed ret %d, please check server is alive", ret);
204 : }
205 :
206 1 : while (resLen > 0) {
207 1 : mmSsize_t readLen =
208 1 : static_cast<uint32_t>(resLen) > MAX_PROTO_FILE_BUFFER_SIZE ? MAX_PROTO_FILE_BUFFER_SIZE : resLen;
209 1 : mmSsize_t len = mmRead(fd, sendDataMsgPtr->data, readLen);
210 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
211 2 : IDE_CTRL_VALUE_FAILED(
212 : len >= 0, return IDE_DAEMON_UNKNOW_ERROR, "read file failed : info [%s]",
213 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
214 1 : if (len > 0 && len <= readLen) {
215 1 : sendDataMsgPtr->sliceLen = (uint32_t)len;
216 2 : int32_t ret = AdxCommOptManager::Instance().Write(
217 1 : handle, sendDataMsgPtr.get(), sendDataMsgPtr->sliceLen + sizeof(MsgProto), COMM_OPT_BLOCK);
218 1 : IDE_CTRL_VALUE_FAILED(
219 : ret == IDE_DAEMON_OK, return IDE_DAEMON_CHANNEL_ERROR,
220 : "hand shake failed ret %d, please check server is alive", ret);
221 : }
222 0 : sendDataMsgPtr->offset += (uint32_t)len;
223 0 : resLen -= len;
224 : }
225 0 : RecvResponse(handle);
226 0 : return IDE_DAEMON_NONE_ERROR;
227 1 : }
228 :
229 0 : MsgCode AdxMsgProto::RecvFile(const CommHandle& handle, int32_t fd)
230 : {
231 0 : IDE_CTRL_VALUE_FAILED(fd >= 0, return IDE_DAEMON_INVALID_PARAM_ERROR, "create message failed");
232 0 : MsgProto* msg = nullptr;
233 0 : int32_t length = 0;
234 : while (true) {
235 0 : int32_t ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&msg, length, handle.timeout);
236 0 : IDE_CTRL_VALUE_FAILED(
237 : ret == IDE_DAEMON_OK && msg != nullptr, return IDE_DAEMON_CHANNEL_ERROR,
238 : "hand shake failed ret %d, read failed or timeout", ret);
239 0 : if (msg->msgType == MsgType::MSG_CTRL) { // check the message is ctrl or not
240 0 : IDE_LOGW("receive ctrl msg from device, stop receiving this file");
241 0 : IDE_XFREE_AND_SET_NULL(msg);
242 0 : return IDE_DAEMON_NONE_ERROR;
243 : }
244 0 : if (msg->sliceLen != 0 && msg->sliceLen <= MAX_PROTO_FILE_BUFFER_SIZE) {
245 0 : mmSsize_t len = mmWrite(fd, msg->data, msg->sliceLen);
246 0 : if (len < 0) {
247 0 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
248 0 : IDE_LOGE(
249 : "write file failed : info [%s]", mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
250 0 : IDE_XFREE_AND_SET_NULL(msg);
251 0 : return IDE_DAEMON_UNKNOW_ERROR;
252 : }
253 : }
254 :
255 0 : if (msg->totalLen == msg->sliceLen + msg->offset) {
256 0 : break;
257 : }
258 :
259 0 : IDE_XFREE_AND_SET_NULL(msg);
260 0 : }
261 :
262 0 : if (SendResponse(handle, msg->reqType, msg->devId, MsgStatus::MSG_STATUS_NONE_ERROR) != IDE_DAEMON_NONE_ERROR) {
263 0 : IDE_LOGW("send response exception");
264 0 : IDE_XFREE_AND_SET_NULL(msg);
265 0 : return IDE_DAEMON_CHANNEL_ERROR;
266 : }
267 :
268 0 : IDE_XFREE_AND_SET_NULL(msg);
269 0 : return IDE_DAEMON_NONE_ERROR;
270 : }
271 :
272 2 : MsgCode AdxMsgProto::SendResponse(const CommHandle& handle, uint16_t type, uint16_t devId, MsgStatus status)
273 : {
274 : MsgProto msg;
275 2 : (void)memset_s(&msg, sizeof(msg), 0, sizeof(msg));
276 2 : (void)CreateCtrlMsg(msg, status);
277 2 : msg.reqType = type;
278 2 : msg.devId = devId;
279 2 : int32_t ret = AdxCommOptManager::Instance().Write(handle, (IdeSendBuffT)&msg, sizeof(MsgProto), COMM_OPT_BLOCK);
280 2 : if (ret != IDE_DAEMON_OK) {
281 1 : IDE_LOGE("send response failed ret %d, please check peer is alive", ret);
282 1 : return IDE_DAEMON_CHANNEL_ERROR;
283 : }
284 :
285 1 : IDE_LOGI("device(%d) cmd(%d) response success", devId, type);
286 1 : return IDE_DAEMON_NONE_ERROR;
287 : }
288 :
289 2 : MsgCode AdxMsgProto::RecvResponse(const CommHandle& handle)
290 : {
291 2 : MsgProto* recvBuf = nullptr;
292 2 : int32_t length = 0;
293 2 : int32_t ret = AdxCommOptManager::Instance().Read(handle, (IdeRecvBuffT)&recvBuf, length, COMM_OPT_BLOCK);
294 2 : if (ret != IDE_DAEMON_OK || recvBuf == nullptr) {
295 0 : return IDE_DAEMON_CHANNEL_ERROR;
296 : }
297 :
298 2 : if (recvBuf->msgType == MsgType::MSG_CTRL && recvBuf->status == MsgStatus::MSG_STATUS_NONE_ERROR) {
299 2 : IDE_XFREE_AND_SET_NULL(recvBuf);
300 2 : return IDE_DAEMON_NONE_ERROR;
301 : }
302 :
303 0 : if (recvBuf->msgType == MsgType::MSG_CTRL && recvBuf->status == MsgStatus::MSG_STATUS_CACHE_FULL_ERROR) {
304 0 : IDE_XFREE_AND_SET_NULL(recvBuf);
305 0 : return IDE_DAEMON_DUMP_QUEUE_FULL;
306 : }
307 :
308 0 : IDE_XFREE_AND_SET_NULL(recvBuf);
309 0 : return IDE_DAEMON_UNKNOW_ERROR;
310 : }
311 : } // namespace Adx
|