已合并
新增socket适配层接口,看门狗模块 #35
chenmy-git创建于 2024年8月3日
新增socket适配层接口,看门狗模块 #35
已合并
chenmy-git创建于 2024年8月3日
从refs/pull/35/head合入到master
共 4 个文件变更+1100-0
@@ -0,0 +1,684 @@
1+/*
2+ * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+#include "adapter_socket.h"
16+#include <stdio.h>
17+#include <stdlib.h>
18+#include <stdbool.h>
19+#include <string.h>
20+#include <sys/socket.h>
21+#include <netdb.h>
22+#include "securec.h"
23+#include "iotc_errcode.h"
24+#include "adapter_network.h"
25+#include "adapter_mem.h"
26+#include "adapter_log.h"
27+ 
28+#if !IOTC_CONF_ADAPTER_SOCKET_LWIP_SUPPORT
29+#include <arpa/inet.h>
30+#include <unistd.h>
31+#include <fcntl.h>
32+#endif
33+ 
34+#ifndef ARRAY_SIZE
35+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
36+#endif
37+#define MS_PER_SEC 1000
38+#define US_PER_MS 1000
39+#define MAX_IP_LEN 40
40+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
41+#define IPV6_ADDR_LEN 28
42+#define MAX_ADDR_LE _IPV6_ADDR_LEN
43+#define MAX_DNS_RES_NUM 10
44+ 
45+typedef struct AddrInfoInner {
46+ AdapterAddrInfo hiAddr;
47+ struct addrinfo *addr;
48+} AddrInfoInner;
49+ 
50+typedef struct {
51+ AdapterSocketOption option;
52+ int32_t (*setOptionFunc)(int32_t fd, const void *value, uint32_t len);
53+} OptionItem;
54+ 
55+typedef struct {
56+ int32_t hiType;
57+ int32_t sockType;
58+} SocketTypePair;
59+ 
60+static const SocketTypePair AF_MAP[] = {
61+ {ADAPTER_SOCKET_DOMAIN_AF_INET, AF_INET},
62+ {ADAPTER_SOCKET_DOMAIN_AF_INET6, AF_INET6},
63+ {ADAPTER_SOCKET_DOMAIN_UNSPEC, AF_UNSPEC},
64+};
65+ 
66+static const SocketTypePair AP_MAP[] = {
67+ {ADAPTER_SOCKET_PROTO_IP, IPPROTO_IP},
68+ {ADAPTER_SOCKET_PROTO_TCP, IPPROTO_TCP},
69+ {ADAPTER_SOCKET_PROTO_UDP, IPPROTO_UDP},
70+};
71+ 
72+static const SocketTypePair AS_MAP[] = {
73+ {ADAPTER_SOCKET_TYPE_STREAM, SOCK_STREAM},
74+ {ADAPTER_SOCKET_TYPE_DGRAM, SOCK_DGRAM},
75+ {ADAPTER_SOCKET_TYPE_RAW, SOCK_RAW},
76+};
77+ 
78+static int32_t AiFamily2Socket(int32_t af)
79+{
80+ for (uint32_t i = 0; i < ARRAY_SIZE(AF_MAP); ++i) {
81+ if (AF_MAP[i].hiType == af) {
82+ return AF_MAP[i].sockType;
83+ }
84+ }
85+ return af;
86+}
87+ 
88+static int32_t Socket2AiFamily(int32_t af)
89+{
90+ for (uint32_t i = 0; i < ARRAY_SIZE(AF_MAP); ++i) {
91+ if (AF_MAP[i].sockType == af) {
92+ return AF_MAP[i].hiType;
93+ }
94+ }
95+ return af;
96+}
97+ 
98+static int32_t AiProtocal2Socket(int32_t ap)
99+{
100+ for (uint32_t i = 0; i < ARRAY_SIZE(AP_MAP); ++i) {
101+ if (AP_MAP[i].hiType == ap) {
102+ return AP_MAP[i].sockType;
103+ }
104+ }
105+ return ap;
106+}
107+ 
108+static int32_t Socket2AiProtocal(int32_t ap)
109+{
110+ for (uint32_t i = 0; i < ARRAY_SIZE(AP_MAP); ++i) {
111+ if (AP_MAP[i].sockType == ap) {
112+ return AP_MAP[i].hiType;
113+ }
114+ }
115+ return ap;
116+}
117+ 
118+static int32_t AiSocket2Socket(int32_t as)
119+{
120+ for (uint32_t i = 0; i < ARRAY_SIZE(AS_MAP); ++i) {
121+ if (AS_MAP[i].hiType == as) {
122+ return AS_MAP[i].sockType;
123+ }
124+ }
125+ return as;
126+}
127+ 
128+static int32_t Socket2AiSocket(int32_t as)
129+{
130+ for (uint32_t i = 0; i < ARRAY_SIZE(AS_MAP); ++i) {
131+ if (AS_MAP[i].sockType == as) {
132+ return AS_MAP[i].hiType;
133+ }
134+ }
135+ return as;
136+}
137+ 
138+static void GetAdapterAddrInfo(AdapterAddrInfo *out, struct addrinfo *in,
139+ int32_t level, int32_t maxLevel)
140+{
141+ if ((level > maxLevel) || (in == NULL) || (out == NULL)) {
142+ return;
143+ }
144+ 
145+ out->aiFlags = in->ai_flags;
146+ out->aiFamily = Socket2AiFamily(in->ai_family);
147+ out->aiProtocol = Socket2AiProtocal(in->ai_protocol);
148+ out->aiSocktype = Socket2AiSocket(in->ai_socktype);
149+ out->aiAddr = (AdapterSockaddr *)in->ai_addr;
150+ out->aiCanonname = in->ai_canonname;
151+ 
152+ if (in->ai_next != NULL) {
153+ out->aiNext = (AdapterAddrInfo *)AdapterMalloc(sizeof(AdapterAddrInfo));
154+ if (out->aiNext == NULL) {
155+ ADAPTER_LOGE("malloc error");
156+ } else {
157+ (void)memset_s(out->aiNext, sizeof(AdapterAddrInfo), 0, sizeof(AdapterAddrInfo));
158+ GetAdapterAddrInfo(out->aiNext, in->ai_next, level + 1, maxLevel);
159+ }
160+ }
161+ return;
162+}
163+ 
164+static void FreeAdapterAddrInfo(AdapterAddrInfo *addr)
165+{
166+ if (addr->aiNext != NULL) {
167+ FreeAdapterAddrInfo(addr->aiNext);
168+ addr->aiNext = NULL;
169+ }
170+ AdapterFree(addr);
171+}
172+ 
173+static void FreeAddrInfoInner(AddrInfoInner *addrInner)
174+{
175+ if (addrInner->addr != NULL) {
176+ freeaddrinfo(addrInner->addr);
177+ addrInner->addr = NULL;
178+ }
179+ FreeAdapterAddrInfo((AdapterAddrInfo *)addrInner);
180+}
181+ 
182+static AdapterAddrInfo *GetAddrInfoInner(struct addrinfo *addr)
183+{
184+ if (addr == NULL) {
185+ return NULL;
186+ }
187+ AddrInfoInner *addrInner = (AddrInfoInner *)AdapterMalloc(sizeof(AddrInfoInner));
188+ if (addrInner == NULL) {
189+ ADAPTER_LOGE("malloc error");
190+ freeaddrinfo(addr);
191+ return NULL;
192+ }
193+ (void)memset_s(addrInner, sizeof(AddrInfoInner), 0, sizeof(AddrInfoInner));
194+ GetAdapterAddrInfo(&addrInner->hiAddr, addr, 1, MAX_DNS_RES_NUM);
195+ addrInner->addr = addr;
196+ return (AdapterAddrInfo *)addrInner;
197+}
198+ 
199+int32_t AdapterGetAddrInfo(const char *nodename, const char *servname,
200+ const AdapterAddrInfo *hints, AdapterAddrInfo **result)
201+{
202+ if ((nodename == NULL) || (result == NULL)) {
203+ ADAPTER_LOGE("invalid param");
204+ return IOTC_ERR_PARAM_INVALID;
205+ }
206+ 
207+ struct addrinfo *resInfo = NULL;
208+ struct addrinfo *hintsInfoP = NULL;
209+ struct addrinfo hintsInfo;
210+ ADAPTER_LOGD("get addinfo %s", nodename);
211+ if (hints != NULL) {
212+ if (memcpy_s(&hintsInfo, sizeof(struct addrinfo), hints, sizeof(AdapterAddrInfo)) != EOK) {
213+ ADAPTER_LOGE("memcpy error");
214+ return IOTC_ERR_SECUREC_MEMCPY;
215+ }
216+ hintsInfo.ai_family = AiFamily2Socket(hintsInfo.ai_family);
217+ hintsInfo.ai_protocol = AiProtocal2Socket(hintsInfo.ai_protocol);
218+ hintsInfo.ai_socktype = AiSocket2Socket(hintsInfo.ai_socktype);
219+ hintsInfoP = &hintsInfo;
220+ }
221+ 
222+ int32_t ret = getaddrinfo(nodename, servname, hintsInfoP, &resInfo);
223+ if ((ret != 0) || (resInfo == NULL)) {
224+ ADAPTER_LOGD("getaddrinfo failed, ret %d", ret);
225+ return IOTC_ADAPTER_SOCKET_ERR_DNS;
226+ }
227+ 
228+ *result = GetAddrInfoInner(resInfo);
229+ return IOTC_OK;
230+}
231+ 
232+void AdapterFreeAddrInfo(AdapterAddrInfo *addrInfo)
233+{
234+ if (addrInfo == NULL) {
235+ ADAPTER_LOGE("invalid param");
236+ return;
237+ }
238+ FreeAddrInfoInner((AddrInfoInner *)addrInfo);
239+ return;
240+}
241+ 
242+int32_t AdapterSocket(AdapterSocketDomain domain, AdapterSocketType type, AdapterSocketProto proto)
243+{
244+ int32_t af = AiFamily2Socket(domain);
245+ int32_t st = AiSocket2Socket(type);
246+ int32_t ap = AiProtocal2Socket(proto);
247+ 
248+ return socket(af, st, ap);
249+}
250+ 
251+void AdapterClose(int32_t fd)
252+{
253+ (void)close(fd);
254+ return;
255+}
256+ 
257+static int32_t SetFcntl(int32_t fd, bool isBlock)
258+{
259+ int32_t flags = fcntl(fd, F_GETFL, 0);
260+ if (flags < 0) {
261+ ADAPTER_LOGE("fcntl get failed, ret %d", flags);
262+ return IOTC_ADAPTER_SOCKET_ERR_FCNTL;
263+ }
264+ if (isBlock) {
265+ flags &= (~O_NONBLOCK);
266+ } else {
267+ flags |= O_NONBLOCK;
268+ }
269+ if (fcntl(fd, F_SETFL, flags) < 0) {
270+ ADAPTER_LOGE("fcntl set failed");
271+ return IOTC_ADAPTER_SOCKET_ERR_FCNTL;
272+ }
273+ return IOTC_OK;
274+}
275+ 
276+static int32_t SetSocketOptionNonblock(int32_t fd, const void *value, uint32_t len)
277+{
278+ (void)value;
279+ (void)len;
280+ 
281+ return SetFcntl(fd, false);
282+}
283+ 
284+static int32_t SetSocketOptionBlock(int32_t fd, const void *value, uint32_t len)
285+{
286+ (void)value;
287+ (void)len;
288+ 
289+ return SetFcntl(fd, true);
290+}
291+ 
292+static int32_t SetSocketTimeout(int32_t fd, uint32_t timeout, bool isRead)
293+{
294+ struct timeval tv;
295+ int32_t flag = isRead ? SO_RCVTIMEO : SO_SNDTIMEO;
296+ 
297+ tv.tv_sec = timeout / MS_PER_SEC;
298+ tv.tv_usec = timeout % MS_PER_SEC * US_PER_MS;
299+ if (setsockopt(fd, SOL_SOCKET, flag, &tv, sizeof(struct timeval)) != 0) {
300+ ADAPTER_LOGE("set [%d][%u] failed", flag, timeout);
301+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
302+ }
303+ return IOTC_OK;
304+}
305+ 
306+static int32_t SetSocketOptionReadTimeout(int32_t fd, const void *value, uint32_t len)
307+{
308+ if (len < sizeof(uint32_t)) {
309+ ADAPTER_LOGE("invalid param");
310+ return IOTC_ERR_PARAM_INVALID;
311+ }
312+ uint32_t timeout = *(const uint32_t *)value;
313+ 
314+ return SetSocketTimeout(fd, timeout, true);
315+}
316+ 
317+static int32_t SetSocketOptionSendTimeout(int32_t fd, const void *value, uint32_t len)
318+{
319+ if (len < sizeof(uint32_t)) {
320+ ADAPTER_LOGE("invalid param");
321+ return IOTC_ERR_PARAM_INVALID;
322+ }
323+ uint32_t timeout = *(const uint32_t *)value;
324+ 
325+ return SetSocketTimeout(fd, timeout, false);
326+}
327+ 
328+static int32_t SetSocketOptionEnableReuseAddr(int32_t fd, const void *value, uint32_t len)
329+{
330+ (void)value;
331+ (void)len;
332+ int32_t opt = 1;
333+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) != 0) {
334+ ADAPTER_LOGE("set reuse addr failed");
335+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
336+ }
337+ return IOTC_OK;
338+}
339+ 
340+static int32_t SetSocketOptionDisableReuseAddr(int32_t fd, const void *value, uint32_t len)
341+{
342+ (void)value;
343+ (void)len;
344+ int32_t opt = 0;
345+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) != 0) {
346+ ADAPTER_LOGE("close reuse addr failed");
347+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
348+ }
349+ return IOTC_OK;
350+}
351+ 
352+static int32_t SetSocketMultiGroup(int32_t fd, const void *value, uint32_t len, bool isAdd)
353+{
354+ if (value == NULL || len < sizeof(AdapterSocketMultiAddr)) {
355+ ADAPTER_LOGE("invalid param");
356+ return IOTC_ERR_PARAM_INVALID;
357+ }
358+ AdapterSocketMultiAddr *addr = (AdapterSocketMultiAddr *)value;
359+ if (addr->local == NULL || addr->multi == NULL) {
360+ ADAPTER_LOGE("invalid ip");
361+ return IOTC_ERR_PARAM_INVALID;
362+ }
363+ 
364+ struct ip_mreq group;
365+ (void)memset_s(&group, sizeof(struct ip_mreq), 0, sizeof(struct ip_mreq));
366+ group.imr_multiaddr.s_addr = AdapterInetAddr(addr->multi);
367+ group.imr_interface.s_addr = AdapterInetAddr(addr->local);
368+ 
369+ int32_t flag = isAdd ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
370+ int32_t ret = setsockopt(fd, IPPROTO_IP, flag, (void *)&group, sizeof(group));
371+ if (ret != 0) {
372+ ADAPTER_LOGE("set opt %d failed %d %d", flag, ret, AdapterGetSocketErrno(fd));
373+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
374+ }
375+ return IOTC_OK;
376+}
377+ 
378+static int32_t SetSocketOptionAddMultiGroup(int32_t fd, const void *value, uint32_t len)
379+{
380+ return SetSocketMultiGroup(fd, value, len, true);
381+}
382+ 
383+static int32_t SetSocketOptionDropMultiGroup(int32_t fd, const void *value, uint32_t len)
384+{
385+ return SetSocketMultiGroup(fd, value, len, false);
386+}
387+ 
388+static int32_t SetSocketOptionEnableBroadcast(int32_t fd, const void *value, uint32_t len)
389+{
390+ (void)value;
391+ (void)len;
392+ int32_t opt = 1;
393+ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)) != 0) {
394+ ADAPTER_LOGE("set broadcast failed");
395+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
396+ }
397+ return IOTC_OK;
398+}
399+ 
400+static int32_t SetSocketOptionDisableBroadcast(int32_t fd, const void *value, uint32_t len)
401+{
402+ (void)value;
403+ (void)len;
404+ int32_t opt = 0;
405+ if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)) != 0) {
406+ ADAPTER_LOGE("close broadcast failed");
407+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
408+ }
409+ return IOTC_OK;
410+}
411+ 
412+static int32_t SetSocketOptionEnableMultiLoop(int32_t fd, const void *value, uint32_t len)
413+{
414+ (void)value;
415+ (void)len;
416+ int32_t opt = 1;
417+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&opt, sizeof(opt)) != 0) {
418+ ADAPTER_LOGE("set loop failed");
419+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
420+ }
421+ return IOTC_OK;
422+}
423+ 
424+static int32_t SetSocketOptionDisableMultiLoop(int32_t fd, const void *value, uint32_t len)
425+{
426+ (void)value;
427+ (void)len;
428+ int32_t opt = 0;
429+ if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&opt, sizeof(opt)) != 0) {
430+ ADAPTER_LOGE("set loop failed");
431+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
432+ }
433+ return IOTC_OK;
434+}
435+ 
436+static int32_t SetSocketOptionSendBuffer(int32_t fd, const void *value, uint32_t len)
437+{
438+ if (len < sizeof(uint32_t)) {
439+ ADAPTER_LOGE("invalid param");
440+ return IOTC_ERR_PARAM_INVALID;
441+ }
442+ uint32_t bufferLen = *(uint32_t *)value;
443+ if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&bufferLen, sizeof(bufferLen)) != 0) {
444+ ADAPTER_LOGE("set sendbuf %u failed", bufferLen);
445+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
446+ }
447+ return IOTC_OK;
448+}
449+ 
450+static int32_t SetSocketOptionReadBuffer(int32_t fd, const void *value, uint32_t len)
451+{
452+ if (len < sizeof(uint32_t)) {
453+ ADAPTER_LOGE("invalid param");
454+ return IOTC_ERR_PARAM_INVALID;
455+ }
456+ uint32_t bufferLen = *(uint32_t *)value;
457+ if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&bufferLen, sizeof(bufferLen)) != 0) {
458+ ADAPTER_LOGE("set recvbuf %u failed", bufferLen);
459+ return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
460+ }
461+ return IOTC_OK;
462+}
463+ 
464+int32_t AdapterSetSocketOpt(int32_t fd, AdapterSocketOption option, const void *value, uint32_t len)
465+{
466+ static const OptionItem optionList[] = {
467+ {ADAPTER_SOCKET_OPTION_SETFL_BLOCK, SetSocketOptionBlock},
468+ {ADAPTER_SOCKET_OPTION_SETFL_NONBLOCK, SetSocketOptionNonblock},
469+ {ADAPTER_SOCKET_OPTION_READ_TIMEOUT, SetSocketOptionReadTimeout},
470+ {ADAPTER_SOCKET_OPTION_SEND_TIMEOUT, SetSocketOptionSendTimeout},
471+ {ADAPTER_SOCKET_OPTION_ENABLE_REUSEADDR, SetSocketOptionEnableReuseAddr},
472+ {ADAPTER_SOCKET_OPTION_DISABLE_REUSEADDR, SetSocketOptionDisableReuseAddr},
473+ {ADAPTER_SOCKET_OPTION_ADD_MULTI_GROUP, SetSocketOptionAddMultiGroup},
474+ {ADAPTER_SOCKET_OPTION_DROP_MULTI_GROUP, SetSocketOptionDropMultiGroup},
475+ {ADAPTER_SOCKET_OPTION_ENABLE_BROADCAST, SetSocketOptionEnableBroadcast},
476+ {ADAPTER_SOCKET_OPTION_DISABLE_BROADCAST, SetSocketOptionDisableBroadcast},
477+ {ADAPTER_SOCKET_OPTION_ENABLE_MULTI_LOOP, SetSocketOptionEnableMultiLoop},
478+ {ADAPTER_SOCKET_OPTION_DISABLE_MULTI_LOOP, SetSocketOptionDisableMultiLoop},
479+ {ADAPTER_SOCKET_OPTION_SEND_BUFFER, SetSocketOptionSendBuffer},
480+ {ADAPTER_SOCKET_OPTION_READ_BUFFER, SetSocketOptionReadBuffer},
481+ };
482+ for (uint32_t i = 0; i < (sizeof(optionList) / sizeof(OptionItem)); ++i) {
483+ if (option == optionList[i].option) {
484+ return optionList[i].setOptionFunc(fd, value, len);
485+ }
486+ }
487+ ADAPTER_LOGW("unsupport option %d", option);
488+ return IOTC_ERR_NOT_SUPPORT;
489+}
490+ 
491+int32_t AdapterBind(int32_t fd, const AdapterSockaddr *addr, uint32_t addrLen)
492+{
493+ (void)addrLen;
494+ if (addr == NULL) {
495+ ADAPTER_LOGE("invalid param");
496+ return IOTC_ERR_PARAM_INVALID;
497+ }
498+ struct sockaddr addrIn;
499+ addrIn.sa_family = AiFamily2Socket(addr->saFamily);
500+ if (memcpy_s(addrIn.sa_data, sizeof(addrIn.sa_data), addr->saData, sizeof(addr->saData)) != EOK) {
501+ ADAPTER_LOGE("memcpy error");
502+ return IOTC_ERR_SECUREC_MEMCPY;
503+ }
504+ return bind(fd, &addrIn, sizeof(struct sockaddr));
505+}
506+ 
507+int32_t AdapterConnect(int32_t fd, const AdapterSockaddr *addr, uint32_t addrLen)
508+{
509+ (void)addrLen;
510+ if (addr == NULL) {
511+ ADAPTER_LOGE("invalid param");
512+ return IOTC_ERR_PARAM_INVALID;
513+ }
514+ struct sockaddr addrIn;
515+ addrIn.sa_family = AiFamily2Socket(addr->saFamily);
516+ if (memcpy_s(addrIn.sa_data, sizeof(addrIn.sa_data), addr->saData, sizeof(addr->saData)) != EOK) {
517+ ADAPTER_LOGE("memcpy error");
518+ return IOTC_ERR_SECUREC_MEMCPY;
519+ }
520+ return connect(fd, &addrIn, sizeof(struct sockaddr));
521+}
522+ 
523+int32_t AdapterRecv(int32_t fd, uint8_t *buf, uint32_t len)
524+{
525+ return recv(fd, buf, len, MSG_DONTWAIT);
526+}
527+ 
528+int32_t AdapterSend(int32_t fd, const uint8_t *buf, uint32_t len)
529+{
530+ return send(fd, buf, len, MSG_DONTWAIT);
531+}
532+ 
533+int32_t AdapterRecvFrom(int32_t fd, uint8_t *buf, uint32_t len, AdapterSockaddr *from, uint32_t *fromLen)
534+{
535+ if ((from == NULL) || (fromLen == NULL) || (buf == NULL)) {
536+ ADAPTER_LOGE("invalid param");
537+ return IOTC_ERR_PARAM_INVALID;
538+ }
539+ struct sockaddr addr;
540+ (void)memset_s(&addr, sizeof(struct sockaddr), 0, sizeof(struct sockaddr));
541+ int32_t ret = recvfrom(fd, buf, len, 0, &addr, (socklen_t *)fromLen);
542+ from->saFamily = addr.sa_family;
543+ if (memcpy_s(from->saData, sizeof(from->saData), addr.sa_data, sizeof(addr.sa_data)) != EOK) {
544+ ADAPTER_LOGE("memcpy error");
545+ return IOTC_ERR_SECUREC_MEMCPY;
546+ }
547+ return ret;
548+}
549+ 
550+int32_t AdapterSendTo(int32_t fd, const uint8_t *buf, uint32_t len, const AdapterSockaddr *to, uint32_t toLen)
551+{
552+ if ((to == NULL) || (buf == NULL)) {
553+ ADAPTER_LOGE("invalid param");
554+ return IOTC_ERR_PARAM_INVALID;
555+ }
556+ struct sockaddr addr;
557+ (void)memset_s(&addr, sizeof(struct sockaddr), 0, sizeof(struct sockaddr));
558+ addr.sa_family = AiFamily2Socket(to->saFamily);
559+ if (memcpy_s(addr.sa_data, sizeof(addr.sa_data), to->saData, sizeof(to->saData)) != EOK) {
560+ ADAPTER_LOGE("memcpy error");
561+ return IOTC_ERR_SECUREC_MEMCPY;
562+ }
563+ return sendto(fd, buf, len, 0, &addr, toLen);
564+}
565+ 
566+static void GetFdSet(AdapterFdSet *set, fd_set *fdSet, int32_t *maxfd)
567+{
568+ if ((set == NULL) || (set->fdSet == NULL)) {
569+ return;
570+ }
571+ 
572+ (void)memset_s(fdSet, sizeof(fd_set), 0, sizeof(fd_set));
573+ for (uint32_t i = 0; i < set->num; ++i) {
574+ if (set->fdSet[i] >= 0) {
575+ FD_SET(set->fdSet[i], fdSet);
576+ *maxfd = MAX(*maxfd, set->fdSet[i]);
577+ }
578+ }
579+}
580+ 
581+static void FdIsSet(AdapterFdSet *set, fd_set *fdSet)
582+{
583+ if (set == NULL) {
584+ return;
585+ }
586+ 
587+ for (uint32_t i = 0; i < set->num; ++i) {
588+ if (FD_ISSET(set->fdSet[i], fdSet) == 0) {
589+ set->fdSet[i] = -1;
590+ }
591+ }
592+ return;
593+}
594+ 
595+int32_t AdapterSelect(AdapterFdSet *readSet, AdapterFdSet *writeSet, AdapterFdSet *exceptSet, uint32_t ms)
596+{
597+ int32_t maxFd = -1;
598+ fd_set read, write, except;
599+ GetFdSet(readSet, &read, &maxFd);
600+ GetFdSet(writeSet, &write, &maxFd);
601+ GetFdSet(exceptSet, &except, &maxFd);
602+ 
603+ struct timeval timeout;
604+ timeout.tv_sec = ms / MS_PER_SEC;
605+ timeout.tv_usec = ms % MS_PER_SEC * US_PER_MS;
606+ int32_t ret = select(maxFd + 1, (readSet == NULL) ? NULL : &read,
607+ (writeSet == NULL) ? NULL : &write,
608+ (exceptSet == NULL) ? NULL : &except, &timeout);
609+ if (ret <= 0) {
610+ return ret;
611+ }
612+ FdIsSet(readSet, &read);
613+ FdIsSet(writeSet, &write);
614+ FdIsSet(exceptSet, &except);
615+ return ret;
616+}
617+ 
618+int32_t AdapterGetSocketErrno(int32_t fd)
619+{
620+#if defined(errno)
621+ if (fd < 0) {
622+ return errno;
623+ }
624+#endif
625+ int32_t socketErr;
626+ uint32_t len = sizeof(socklen_t);
627+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &socketErr, (socklen_t *)&len) != 0) {
628+ ADAPTER_LOGE("get socket errno error");
629+ return IOTC_ADAPTER_SOCKET_ERR_GET_OPT;
630+ }
631+ 
632+ switch (socketErr) {
633+ case EINTR:
634+ return ADAPTER_SOCKET_ERRNO_EINTR;
635+ case EAGAIN:
636+ return ADAPTER_SOCKET_ERRNO_EAGAIN;
637+ case EINPROGRESS:
638+ return ADAPTER_SOCKET_ERRNO_EINPROGRESS;
639+ default:
640+ break;
641+ }
642+ return socketErr;
643+}
644+ 
645+uint32_t AdapterHtonl(uint32_t hl)
646+{
647+ return htonl(hl);
648+}
649+ 
650+uint32_t AdapterNtohl(uint32_t nl)
651+{
652+ return ntohl(nl);
653+}
654+ 
655+uint16_t AdapterHtons(uint16_t hs)
656+{
657+ return htons(hs);
658+}
659+ 
660+uint16_t AdapterNtohs(uint16_t ns)
661+{
662+ return ntohs(ns);
663+}
664+ 
665+int32_t AdapterInetAton(const char *ip, uint32_t *addr)
666+{
667+ return inet_aton(ip, (struct in_addr *)addr);
668+}
669+ 
670+uint32_t AdapterInetAddr(const char *ip)
671+{
672+ return inet_addr(ip);
673+}
674+ 
675+const char *AdapterInetNtoa(uint32_t addr, char *buf, uint32_t buflen)
676+{
677+ struct in_addr tempAddr;
678+ tempAddr.s_addr = addr;
679+#if IOTC_CONF_ADAPTER_SOCKET_LWIP_SUPPORT
680+ return inet_ntoa_r(tempAddr, buf, buflen);
681+#else
682+ return inet_ntop(AF_INET, &tempAddr, buf, sizeof(tempAddr));
683+#endif
684+}
@@ -0,0 +1,26 @@
1+#
2+# Copyright (c) 2024 Huawei Device Co., Ltd.
3+# Licensed under the Apache License, Version 2.0 (the "License");
4+# you may not use this file except in compliance with the License.
5+# You may obtain a copy of the License at
6+#
7+# http://www.apache.org/licenses/LICENSE-2.0
8+#
9+# Unless required by applicable law or agreed to in writing, software
10+# distributed under the License is distributed on an "AS IS" BASIS,
11+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+# See the License for the specific language governing permissions and
13+# limitations under the License.
14+ 
15+set(IOTC_SRC_LIST
16+ ${IOTC_SRC_LIST}
17+ ${CMAKE_CURRENT_SOURCE_DIR}/dfx_anonymize.c
18+ ${CMAKE_CURRENT_SOURCE_DIR}/dfx_watch_dog.c
19+ PARENT_SCOPE
20+)
21+ 
22+set(IOTC_INC_LIST
23+ ${IOTC_INC_LIST}
24+ ${CMAKE_CURRENT_SOURCE_DIR}/include
25+ PARENT_SCOPE
26+)
@@ -0,0 +1,335 @@
1+/*
2+ * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+#include "dfx_watch_dog.h"
16+#include <stdbool.h>
17+#include <stdio.h>
18+#include "securec.h"
19+#include "adapter_os.h"
20+#include "iotc_errcode.h"
21+#include "utils_list.h"
22+#include "utils_mutex_ex.h"
23+#include "utils_assert.h"
24+ 
25+#ifndef DFX_WATCH_DOG_SCHEDULE_INTERVAL
26+#define DFX_WATCH_DOG_SCHEDULE_INTERVAL UTILS_SEC_TO_MS(2)
27+#endif
28+ 
29+#define DFX_WATCH_DOG_API_WAIT_TIME UTILS_SEC_TO_MS(30)
30+ 
31+#define DFX_WATCH_DOG_TASK_NAME "iotc_watchdog"
32+#define DFX_WATCH_DOG_DEFAULT_TASK_STACK_SIZE (2 * 1024)
33+#define DFX_WATCH_DOG_TASK_NAME_LEN 128
34+ 
35+typedef struct {
36+ bool flag;
37+ uint32_t timeoutMs;
38+ uint32_t runningMs;
39+ DfxWatchDogTimeoutHandler hdl;
40+ const char *name;
41+ AdapterTaskId *id;
42+ ListEntry list;
43+} WatchdogNode;
44+ 
45+typedef struct {
46+ const char *name;
47+ AdapterTaskId *id;
48+ ListEntry list;
49+} RecordNode;
50+ 
51+typedef struct {
52+ AdapterTaskId *id;
53+ bool isRunning;
54+ ListEntry watchDogList;
55+ ListEntry recordList;
56+ UtilsExMutex *mutex;
57+ AdapterSemId *sem;
58+} WatchdogContext;
59+ 
60+static uint32_t g_taskSize = DFX_WATCH_DOG_DEFAULT_TASK_STACK_SIZE;
61+static DfxWatchDogTimeoutHandler g_commHdl = NULL;
62+static WatchdogContext *GetWatchDogCtx(void)
63+{
64+ static WatchdogContext ctx;
65+ return &ctx;
66+}
67+ 
68+#define WATCH_DOG_LOCK() (void)UtilsExMutexLock(GetWatchDogCtx()->mutex)
69+#define WATCH_DOG_UNLOCK() UtilsExMutexUnlock(GetWatchDogCtx()->mutex)
70+
71+static bool WatchDogProc(void)
72+{
73+ bool isRunning = true;
74+ DfxWatchDogTimeoutHandler func = NULL;
75+ WATCH_DOG_LOCK();
76+ isRunning = GetWatchDogCtx()->isRunning;
77+ if (!isRunning) {
78+ WATCH_DOG_UNLOCK();
79+ return isRunning;
80+ }
81+ 
82+ bool timeout = false;
83+ ListEntry *item = NULL;
84+ LIST_FOR_EACH_ITEM(item, &GetWatchDogCtx()->watchDogList) {
85+ WatchdogNode *node = CONTAINER_OF(item, WatchdogNode, list);
86+ if (node->timeoutMs == 0 || !node->flag) {
87+ continue;
88+ } else if (node->timeoutMs > node->runningMs) {
89+ node->runningMs += DFX_WATCH_DOG_SCHEDULE_INTERVAL;
90+ } else {
91+ node->runningMs = 0;
92+ IOTC_LOGF("Watchdog[%s,%u] timeout", node->name, node->timeoutMs);
93+ func = node->hdl;
94+ timeout = true;
95+ break;
96+ }
97+ }
98+ WATCH_DOG_UNLOCK();
99+ if (timeout) {
100+ DfxDumpAllTask();
101+ if (func == NULL) {
102+ IOTC_LOGI("use comm hdl");
103+ func = g_commHdl;
104+ }
105+ if (func != NULL) {
106+ IOTC_LOGI("watch dog hdl process");
107+ func();
108+ }
109+ }
110+ return isRunning;
111+}
112+ 
113+static void WatchDogTaskBody(void *arg)
114+{
115+ NOT_USED(arg);
116+ GetWatchDogCtx()->isRunning = true;
117+ bool isRunning = true;
118+ do {
119+ AdapterSleepMs(DFX_WATCH_DOG_SCHEDULE_INTERVAL);
120+ isRunning = WatchDogProc();
121+ } while (isRunning);
122+ 
123+ WATCH_DOG_LOCK();
124+ if (GetWatchDogCtx()->sem != NULL) {
125+ AdapterPostSem(GetWatchDogCtx()->sem);
126+ }
127+ 
128+ WATCH_DOG_UNLOCK();
129+ IOTC_LOGN("Watch Dog task exit");
130+ AdapterDeleteTask(NULL);
131+}
132+ 
133+int32_t DfxWatchDogInit(void)
134+{
135+ (void)memset_s(GetWatchDogCtx(), sizeof(WatchdogContext), 0, sizeof(WatchdogContext));
136+ LIST_INIT(&GetWatchDogCtx()->watchDogList);
137+ LIST_INIT(&GetWatchDogCtx()->recordList);
138+ GetWatchDogCtx()->mutex = UtilsCreateExMutex();
139+ if (GetWatchDogCtx()->mutex == NULL) {
140+ return IOTC_CORE_COMM_UTILS_ERR_EX_MUTEX_CREATE;
141+ }
142+ 
143+ AdapterTaskParam taskParam = {
144+ .func = WatchDogTaskBody,
145+ .prio = ADAPTER_TASK_PRIORITY_MID,
146+ .stackSize = g_taskSize,
147+ .arg = NULL,
148+ .name = DFX_WATCH_DOG_TASK_NAME,
149+ };
150+ GetWatchDogCtx()->id = AdapterCreateTask(&taskParam);
151+ if (GetWatchDogCtx()->id == NULL) {
152+ IOTC_LOGW("WatchDog task create fail %u", g_taskSize);
153+ UtilsDestroyExMutex(&GetWatchDogCtx()->mutex);
154+ return IOTC_ADAPTER_OS_ERR_CREATE_TASK;
155+ }
156+ 
157+ return IOTC_OK;
158+}
159+ 
160+void DfxWatchDogDeinit(void)
161+{
162+ int32_t ret;
163+ if (GetWatchDogCtx()->isRunning) {
164+ WATCH_DOG_LOCK();
165+ GetWatchDogCtx()->sem = AdapterCreateSem(0);
166+ GetWatchDogCtx()->isRunning = false;
167+ WATCH_DOG_UNLOCK();
168+ if (GetWatchDogCtx()->sem != NULL) {
169+ ret = AdapterWaitSem(GetWatchDogCtx()->sem, DFX_WATCH_DOG_API_WAIT_TIME);
170+ if (ret != IOTC_OK) {
171+ IOTC_LOGW("wait sem error %d", ret);
172+ }
173+ WATCH_DOG_LOCK();
174+ AdapterDestroySem(GetWatchDogCtx()->sem);
175+ GetWatchDogCtx()->sem = NULL;
176+ WATCH_DOG_UNLOCK();
177+ } else {
178+ IOTC_LOGF("create sem error");
179+ }
180+ }
181+ 
182+ ListEntry *item = NULL;
183+ ListEntry *next = NULL;
184+ LIST_FOR_EACH_ITEM_SAFE(item, next, &GetWatchDogCtx()->recordList) {
185+ RecordNode *node = CONTAINER_OF(item, RecordNode, list);
186+ LIST_REMOVE(item);
187+ AdapterFree(node);
188+ }
189+ 
190+ LIST_FOR_EACH_ITEM_SAFE(item, next, &GetWatchDogCtx()->watchDogList) {
191+ WatchdogNode *node = CONTAINER_OF(item, WatchdogNode, list);
192+ LIST_REMOVE(item);
193+ AdapterFree(node);
194+ }
195+ 
196+ if (GetWatchDogCtx()->mutex != NULL) {
197+ UtilsDestroyExMutex(&GetWatchDogCtx()->mutex);
198+ }
199+ 
200+ (void)memset_s(GetWatchDogCtx(), sizeof(WatchdogContext), 0, sizeof(WatchdogContext));
201+ return;
202+}
203+ 
204+int32_t DfxAddWatchDog(uint32_t timeoutMs, DfxWatchDogTimeoutHandler hdl, const char *name)
205+{
206+ CHECK_RETURN_LOGW(timeoutMs != 0 && name != NULL, IOTC_ERR_PARAM_INVALID, "param invalid");
207+ WatchdogNode *newNode = (WatchdogNode *)AdapterMalloc(sizeof(WatchdogNode));
208+ if (newNode == NULL) {
209+ IOTC_LOGE("malloc");
210+ return IOTC_ADAPTER_MEM_ERR_MALLOC;
211+ }
212+ (void)memset_s(newNode, sizeof(WatchdogNode), 0, sizeof(WatchdogNode));
213+ 
214+ newNode->name = name;
215+ newNode->timeoutMs = timeoutMs;
216+ newNode->hdl = hdl;
217+ AdapterTaskId *id = AdapterGetCurrentTaskId();
218+ newNode->id = id;
219+ 
220+ WATCH_DOG_LOCK();
221+ LIST_INSERT_BEFORE(&newNode->list, &GetWatchDogCtx()->watchDogList);
222+ WATCH_DOG_UNLOCK();
223+ 
224+ IOTC_LOGN("WatchDog[%s/%u/%u] add succ", NON_NULL_STR(name), timeoutMs, UtilsGetTaskIdShort(id));
225+ return IOTC_OK;
226+}
227+ 
228+int32_t DfxFeedWatchDog(void)
229+{
230+ AdapterTaskId *id = AdapterGetCurrentTaskId();
231+ int32_t ret = IOTC_CORE_COMM_DFX_WATCH_DOG_ERR_FEED;
232+ WATCH_DOG_LOCK();
233+ ListEntry *item = NULL;
234+ LIST_FOR_EACH_ITEM(item, &GetWatchDogCtx()->watchDogList) {
235+ WatchdogNode *node = CONTAINER_OF(item, WatchdogNode, list);
236+ if (node->id != id) {
237+ continue;
238+ }
239+ node->flag = true;
240+ node->runningMs = 0;
241+ ret = IOTC_OK;
242+ break;
243+ }
244+ WATCH_DOG_UNLOCK();
245+ if (ret == IOTC_OK) {
246+ return ret;
247+ }
248+ 
249+ IOTC_LOGE("WatchDog[%u] feed fail", UtilsGetTaskIdShort(id));
250+ return ret;
251+}
252+ 
253+void DfxDelWatchDog(void)
254+{
255+ AdapterTaskId *id = AdapterGetCurrentTaskId();
256+ WATCH_DOG_LOCK();
257+ ListEntry *item = NULL;
258+ ListEntry *next = NULL;
259+ LIST_FOR_EACH_ITEM_SAFE(item, next, &GetWatchDogCtx()->watchDogList) {
260+ WatchdogNode *node = CONTAINER_OF(item, WatchdogNode, list);
261+ if (node->id != id) {
262+ continue;
263+ }
264+ IOTC_LOGN("WatchDog[%s/%u] del succ", NON_NULL_STR(node->name), UtilsGetTaskIdShort(node->id));
265+ LIST_REMOVE(item);
266+ AdapterFree(node);
267+ break;
268+ }
269+ WATCH_DOG_UNLOCK();
270+}
271+ 
272+void DfxRecordNoDogTask(const char *name)
273+{
274+ CHECK_V_RETURN_LOGW(name != NULL, "param invalid");
275+ RecordNode *newNode = (RecordNode *)AdapterMalloc(sizeof(RecordNode));
276+ if (newNode == NULL) {
277+ IOTC_LOGE("malloc");
278+ return;
279+ }
280+ (void)memset_s(newNode, sizeof(RecordNode), 0, sizeof(RecordNode));
281+ newNode->name = name;
282+ newNode->id = AdapterGetCurrentTaskId();
283+ WATCH_DOG_LOCK();
284+ LIST_INSERT_BEFORE(&newNode->list, &GetWatchDogCtx()->recordList);
285+ WATCH_DOG_UNLOCK();
286+ return;
287+}
288+ 
289+void DfxDelNoDogTaskRecord(void)
290+{
291+ AdapterTaskId *id = AdapterGetCurrentTaskId();
292+ 
293+ WATCH_DOG_LOCK();
294+ ListEntry *item = NULL;
295+ ListEntry *next = NULL;
296+ LIST_FOR_EACH_ITEM_SAFE(item, next, &GetWatchDogCtx()->watchDogList) {
297+ RecordNode *node = CONTAINER_OF(item, RecordNode, list);
298+ if (node->id == id) {
299+ IOTC_LOGN("NoDog[%s/%p] del succ", NON_NULL_STR(node->name), UtilsGetTaskIdShort(node->id));
300+ LIST_REMOVE(item);
301+ AdapterFree(node);
302+ return;
303+ }
304+ }
305+ WATCH_DOG_UNLOCK();
306+ return;
307+}
308+ 
309+void DfxSetWatchDogTaskSize(uint32_t size)
310+{
311+ g_taskSize = size;
312+ IOTC_LOGI("watch dog task size %u", size);
313+}
314+ 
315+void DfxDumpAllTask(void)
316+{
317+ WATCH_DOG_LOCK();
318+ ListEntry *item = NULL;
319+ LIST_FOR_EACH_ITEM(item, &GetWatchDogCtx()->watchDogList) {
320+ WatchdogNode *node = CONTAINER_OF(item, WatchdogNode, list);
321+ IOTC_LOGN("watch dog task [%s/%u/%u/%u/%d]", NON_NULL_STR(node->name), UtilsGetTaskIdShort(node->id),
322+ node->timeoutMs, node->runningMs, node->flag);
323+ }
324+ LIST_FOR_EACH_ITEM(item, &GetWatchDogCtx()->recordList) {
325+ RecordNode *node = CONTAINER_OF(item, RecordNode, list);
326+ IOTC_LOGN("record task [%s/%u/%u/%u]", NON_NULL_STR(node->name), UtilsGetTaskIdShort(node->id));
327+ }
328+ 
329+ WATCH_DOG_UNLOCK();
330+}
331+ 
332+void DfxWatchDogRegCommTimeoutHandler(DfxWatchDogTimeoutHandler hdl)
333+{
334+ g_commHdl = hdl;
335+}
@@ -0,0 +1,55 @@
1+/*
2+ * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3+ * Licensed under the Apache License, Version 2.0 (the "License");
4+ * you may not use this file except in compliance with the License.
5+ * You may obtain a copy of the License at
6+ *
7+ * http://www.apache.org/licenses/LICENSE-2.0
8+ *
9+ * Unless required by applicable law or agreed to in writing, software
10+ * distributed under the License is distributed on an "AS IS" BASIS,
11+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+ * See the License for the specific language governing permissions and
13+ * limitations under the License.
14+ */
15+#ifndef DFX_WATCH_DOG_H
16+#define DFX_WATCH_DOG_H
17+ 
18+#include <stdint.h>
19+#include <stddef.h>
20+ 
21+#ifdef __cplusplus
22+extern "C" {
23+#endif
24+ 
25+#ifndef IOTC_CONF_WATCH_DOG_TIMEOUT
26+#define IOTC_CONF_WATCH_DOG_TIMEOUT (1 * 60 * 1000)
27+#endif
28+ 
29+typedef void (*DfxWatchDogTimeoutHandler)(void);
30+ 
31+int32_t DfxWatchDogInit(void);
32+ 
33+void DfxWatchDogDeinit(void);
34+ 
35+int32_t DfxAddWatchDog(uint32_t timeoutMs, DfxWatchDogTimeoutHandler hdl, const char *name);
36+ 
37+int32_t DfxFeedWatchDog(void);
38+ 
39+void DfxWatchDogRegCommTimeoutHandler(DfxWatchDogTimeoutHandler hdl);
40+ 
41+void DfxDelWatchDog(void);
42+ 
43+void DfxRecordNoDogTask(const char *name);
44+ 
45+void DfxDelNoDogTaskRecord(void);
46+ 
47+void DfxSetWatchDogTaskSize(uint32_t size);
48+ 
49+void DfxDumpAllTask(void);
50+ 
51+#ifdef __cplusplus
52+}
53+#endif
54+ 
55+#endif /* DFX_WATCH_DOG_H */