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