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 :
11 : #include "sock_api.h"
12 : #include <arpa/inet.h>
13 : #include <netinet/tcp.h>
14 : #include "log/adx_log.h"
15 : #include "adx_msg.h"
16 : #include "mmpa_api.h"
17 : using namespace Adx;
18 :
19 : /**
20 : * @brief create sock server
21 : * @param [in] adxLocalChan: local channel string
22 : *
23 : * @return
24 : * sock fd
25 : */
26 4 : int32_t SockServerCreate(const std::string &adxLocalChan)
27 : {
28 4 : IDE_CTRL_VALUE_FAILED(!adxLocalChan.empty(), return -1, "local socket failed");
29 4 : int32_t sockFd = mmSocket(PF_LOCAL, SOCK_STREAM, 0);
30 4 : IDE_CTRL_VALUE_FAILED(sockFd >= 0, return sockFd, "local socket failed");
31 :
32 : struct sockaddr_un sockAddr;
33 4 : (void)memset_s(&sockAddr, sizeof(sockAddr), 0, sizeof(sockAddr));
34 4 : int32_t ret = strcpy_s(sockAddr.sun_path + 1, sizeof(sockAddr.sun_path) - 1, adxLocalChan.c_str());
35 4 : if (ret != EOK) {
36 1 : IDE_LOGE("local socket path copy failed");
37 1 : ADX_LOCAL_CLOSE_AND_SET_INVALID(sockFd);
38 1 : return sockFd;
39 : }
40 :
41 3 : sockAddr.sun_family = AF_LOCAL;
42 3 : ret = mmBind(sockFd, reinterpret_cast<mmSockAddr *>(&sockAddr),
43 3 : offsetof(struct sockaddr_un, sun_path) + 1 + adxLocalChan.size());
44 3 : if (ret < 0) {
45 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
46 1 : IDE_LOGE("local server bind exception info : %s",
47 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
48 1 : ADX_LOCAL_CLOSE_AND_SET_INVALID(sockFd);
49 1 : return sockFd;
50 : }
51 :
52 2 : ret = mmListen(sockFd, TCP_MAX_LISTEN_NUM);
53 2 : if (ret < 0) {
54 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
55 1 : IDE_LOGE("local server listen exception info : %s",
56 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
57 1 : ADX_LOCAL_CLOSE_AND_SET_INVALID(sockFd);
58 1 : return sockFd;
59 : }
60 :
61 1 : IDE_LOGD("local server init %d", sockFd);
62 1 : return sockFd;
63 : }
64 :
65 : /**
66 : * @brief destroy sock server
67 : * @param [in] sockFd: sock Fd
68 : *
69 : * @return
70 : * IDE_DAEMON_OK: destroy sock server success
71 : * IDE_DAEMON_ERROR: destroy sock server failed
72 : */
73 2 : int32_t SockServerDestroy(int32_t &sockFd)
74 : {
75 2 : if (sockFd < 0) {
76 1 : return IDE_DAEMON_ERROR;
77 : }
78 :
79 1 : mmClose(sockFd);
80 1 : sockFd = -1;
81 1 : return IDE_DAEMON_OK;
82 : }
83 :
84 : /**
85 : * @brief create sock client
86 : *
87 : * @return
88 : * sock fd
89 : */
90 2 : int32_t SockClientCreate()
91 : {
92 2 : int sockFd = mmSocket(PF_LOCAL, SOCK_STREAM, 0);
93 2 : IDE_CTRL_VALUE_FAILED(sockFd >= 0, return sockFd, "local socket failed");
94 2 : IDE_LOGI("SockClientCreate sockFd: %d", sockFd);
95 2 : return sockFd;
96 : }
97 :
98 : /**
99 : * @brief destroy sock client
100 : * @param [in] sockFd: sock Fd
101 : *
102 : * @return
103 : * IDE_DAEMON_OK: destroy sock client success
104 : * IDE_DAEMON_ERROR: destroy sock client failed
105 : */
106 1 : int32_t SockClientDestory(int32_t &sockFd)
107 : {
108 1 : IDE_CTRL_VALUE_FAILED(sockFd >= 0, return IDE_DAEMON_ERROR, "sockFd invalid");
109 :
110 1 : mmClose(sockFd);
111 1 : sockFd = -1;
112 1 : return IDE_DAEMON_OK;
113 : }
114 :
115 : /**
116 : * @brief call sock accept
117 : * @param [in] sockFd: sock Fd
118 : *
119 : * @return
120 : * clientFd
121 : */
122 2 : int32_t SockAccept(int32_t sockFd)
123 : {
124 2 : IDE_CTRL_VALUE_FAILED(sockFd >= 0, return sockFd, "local socket failed");
125 : mmSockAddr clientAddr;
126 2 : (void)memset_s(&clientAddr, sizeof(clientAddr), 0, sizeof(clientAddr));
127 2 : mmSocklen_t len = sizeof(mmSockAddr);
128 2 : int32_t clientFd = mmAccept(sockFd, &clientAddr, &len);
129 2 : if (clientFd < 0) {
130 1 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
131 1 : IDE_LOGE("local socket accept failed, info : %s",
132 : mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
133 : }
134 :
135 2 : return clientFd;
136 : }
137 :
138 : /**
139 : * @brief sock connect
140 : * @param [in] sockFd: sock Fd
141 : * @param [in] adxLocalChan: local channel string
142 : *
143 : * @return
144 : * sockFd: sock fd
145 : * IDE_DAEMON_ERROR: sock connect failed
146 : */
147 4 : int32_t SockConnect(int32_t sockFd, const std::string &adxLocalChan)
148 : {
149 4 : IDE_CTRL_VALUE_FAILED(sockFd >= 0, return IDE_DAEMON_ERROR, "local socket failed");
150 4 : IDE_CTRL_VALUE_FAILED(!adxLocalChan.empty(), return IDE_DAEMON_ERROR,
151 : "local socket failed");
152 : struct sockaddr_un sockAddr;
153 4 : (void)memset_s(&sockAddr, sizeof(sockAddr), 0, sizeof(sockAddr));
154 4 : int32_t ret = strcpy_s(sockAddr.sun_path + 1, sizeof(sockAddr.sun_path) - 1, adxLocalChan.c_str());
155 4 : if (ret != EOK) {
156 1 : IDE_LOGE("local socket strcpy_s failed");
157 1 : return IDE_DAEMON_ERROR;
158 : }
159 :
160 3 : sockAddr.sun_family = AF_LOCAL;
161 3 : ret = mmConnect(sockFd, reinterpret_cast<mmSockAddr *>(&sockAddr),
162 3 : offsetof(struct sockaddr_un, sun_path) + 1 + adxLocalChan.size());
163 3 : if (ret < 0) {
164 1 : IDE_LOGE("local socket connect failed");
165 1 : return IDE_DAEMON_ERROR;
166 : }
167 :
168 2 : IDE_LOGI("SockConnect ret: %d, sockFd: %d", ret, sockFd);
169 2 : return sockFd;
170 : }
171 :
172 : /**
173 : * @brief sock hal read
174 : * @param [in] fd: file descriptor
175 : * @param [in] readBuf: read buffer
176 : * @param [in] recvLen: receive length
177 : * @param [in] flag: read flag
178 : *
179 : * @return
180 : * recvLen: receive length
181 : * IDE_DAEMON_ERROR: sock hal read failed
182 : */
183 3 : static uint32_t SockHalRead(int32_t fd, IdeBuffT readBuf, int32_t recvLen, int32_t flag)
184 : {
185 3 : if (fd < 0 || readBuf == nullptr || recvLen <= 0) {
186 0 : return IDE_DAEMON_ERROR;
187 : }
188 :
189 3 : int32_t remainLen = recvLen;
190 : do {
191 72 : int32_t len = mmSocketRecv(fd, readBuf, remainLen, flag);
192 72 : IDE_LOGI("sock %d recv length %d, %d", fd, len, remainLen);
193 72 : if (len < 0 && mmGetErrorCode() == EINTR) {
194 0 : continue;
195 72 : } else if (len < 0) {
196 0 : char errBuf[MAX_ERRSTR_LEN + 1] = {0};
197 0 : IDE_LOGE("sock recv error, info : %s", mmGetErrorFormatMessage(mmGetErrorCode(), errBuf, MAX_ERRSTR_LEN));
198 0 : return IDE_DAEMON_ERROR;
199 : }
200 :
201 72 : remainLen -= len;
202 72 : } while (remainLen > 0);
203 :
204 3 : return static_cast<uint32_t>(recvLen);
205 : }
206 :
207 : /**
208 : * @brief check msg valid
209 : * @param [in] proto: msg proto
210 : *
211 : * @return
212 : * true: msg is valid
213 : * false: msg is invalid
214 : */
215 3 : static bool CheckMsgValid(const MsgProto &proto)
216 : {
217 3 : if (proto.headInfo != ADX_PROTO_MAGIC_VALUE) {
218 3 : return false;
219 : }
220 :
221 0 : if (proto.totalLen > INT32_MAX - sizeof(MsgProto)) {
222 0 : return false;
223 : }
224 :
225 0 : return true;
226 : }
227 :
228 : /**
229 : * @brief sock proto read
230 : * @param [in] fd: file descriptor
231 : * @param [in] readBuf: read buffer
232 : * @param [in] recvLen: receive length
233 : * @param [in] flag: read flag
234 : *
235 : * @return
236 : * recvTotalLen: receive total length
237 : * IDE_DAEMON_ERROR: sock proto read failed
238 : */
239 3 : static int32_t SockProtoRead(int32_t fd, IdeRecvBuffT readBuf, IdeI32Pt recvLen, int32_t flag)
240 : {
241 : MsgProto proto;
242 3 : (void)memset_s(&proto, sizeof(proto), 0, sizeof(proto));
243 3 : if (SockHalRead(fd, static_cast<IdeBuffT>(&proto), sizeof(MsgProto), flag) != sizeof(MsgProto)) {
244 0 : IDE_LOGE("sock recv proto head error");
245 0 : return IDE_DAEMON_ERROR;
246 : }
247 :
248 3 : if (CheckMsgValid(proto) == false) {
249 3 : IDE_LOGE("check proto head error");
250 3 : return IDE_DAEMON_ERROR;
251 : }
252 :
253 0 : IdeU8Pt buffer = (IdeU8Pt)ADX_SAFE_MALLOC(proto.totalLen + sizeof(MsgProto));
254 0 : if (buffer == nullptr) {
255 0 : IDE_LOGE("check proto malloc error");
256 0 : return IDE_DAEMON_ERROR;
257 : }
258 :
259 0 : int32_t recvTotalLen = proto.totalLen + sizeof(MsgProto);
260 0 : int ret = memcpy_s(buffer, recvTotalLen, &proto, sizeof(MsgProto));
261 0 : IDE_LOGI("recvTotalLen: %d, sizeof(MsgProto): %zu", recvTotalLen, sizeof(MsgProto));
262 0 : if (ret != EOK) {
263 0 : IDE_LOGE("check memcpy_s head error");
264 0 : ADX_SAFE_FREE(buffer);
265 0 : return IDE_DAEMON_ERROR;
266 : }
267 :
268 0 : if (proto.totalLen != 0) {
269 0 : if (SockHalRead(fd, buffer + sizeof(MsgProto), proto.totalLen, flag) != proto.totalLen) {
270 0 : IDE_LOGE("sock recv proto body error");
271 0 : ADX_SAFE_FREE(buffer);
272 0 : return IDE_DAEMON_ERROR;
273 : }
274 : }
275 0 : *readBuf = buffer;
276 0 : *recvLen = recvTotalLen;
277 0 : return recvTotalLen;
278 : }
279 :
280 : /**
281 : * @brief sock read
282 : * @param [in] fd: file descriptor
283 : * @param [in] readBuf: read buffer
284 : * @param [in] recvLen: receive length
285 : * @param [in] flag: read flag
286 : *
287 : * @return
288 : * IDE_DAEMON_OK: sock read success
289 : * IDE_DAEMON_ERROR: sock read failed
290 : */
291 3 : int32_t SockRead(int32_t fd, IdeRecvBuffT readBuf, IdeI32Pt recvLen, int32_t flag)
292 : {
293 3 : if (fd < 0 || readBuf == nullptr || recvLen == nullptr) {
294 0 : return IDE_DAEMON_ERROR;
295 : }
296 :
297 3 : if (SockProtoRead(fd, readBuf, recvLen, flag) < 0) {
298 3 : return IDE_DAEMON_ERROR;
299 : }
300 0 : return IDE_DAEMON_OK;
301 : }
302 :
303 : /**
304 : * @brief sock hal write
305 : * @param [in] fd: file descriptor
306 : * @param [in] writeBuf: write buffer
307 : * @param [in] writeLen: receive length
308 : * @param [in] flag: write flag
309 : *
310 : * @return
311 : * len: return len of mmSocketSend
312 : */
313 3 : static int32_t SockHalWrite(int32_t fd, IdeSendBuffT writeBuf, int32_t writeLen, int32_t flag)
314 : {
315 3 : int32_t len = 0;
316 : do {
317 3 : len = mmSocketSend(fd, const_cast<IdeBuffT>(writeBuf), writeLen, flag);
318 3 : } while (len < 0 && mmGetErrorCode() == EINTR);
319 3 : return len;
320 : }
321 :
322 : /**
323 : * @brief sock write
324 : * @param [in] fd: file descriptor
325 : * @param [in] writeBuf: write buffer
326 : * @param [in] writeLen: receive length
327 : * @param [in] flag: write flag
328 : *
329 : * @return
330 : * IDE_DAEMON_OK: sock write success
331 : * IDE_DAEMON_ERROR: sock write failed
332 : */
333 4 : int32_t SockWrite(int32_t fd, IdeSendBuffT writeBuf, int32_t len, int32_t flag)
334 : {
335 4 : if (fd < 0 || writeBuf == nullptr || len <= 0) {
336 1 : return IDE_DAEMON_ERROR;
337 : }
338 :
339 3 : if (SockHalWrite(fd, writeBuf, len, flag) < 0) {
340 1 : return IDE_DAEMON_ERROR;
341 : }
342 2 : return IDE_DAEMON_OK;
343 : }
344 :
345 : /**
346 : * @brief sock close for server accept
347 : * @param [in] sockFd: sock file descriptor
348 : *
349 : * @return
350 : * ret: return val of mmClose
351 : * IDE_DAEMON_ERROR: sockFd invalid
352 : */
353 2 : int32_t SockClose(int32_t &sockFd)
354 : {
355 2 : if (sockFd < 0) {
356 1 : return IDE_DAEMON_ERROR;
357 : }
358 :
359 1 : int32_t ret = mmClose(sockFd);
360 1 : sockFd = -1;
361 1 : return ret;
362 : }
|