已合并
新增socket适配层接口,看门狗模块 #35
chenmy-git创建于 2024年8月3日
新增socket适配层接口,看门狗模块 #35
已合并
从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 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | + | ||
| 39 | + | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | + | ||
| 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 | + | ||
| 621 | + if (fd < 0) { | ||
| 622 | + return errno; | ||
| 623 | + } | ||
| 624 | + | ||
| 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 | + | ||
| 680 | + return inet_ntoa_r(tempAddr, buf, buflen); | ||
| 681 | + | ||
| 682 | + return inet_ntop(AF_INET, &tempAddr, buf, sizeof(tempAddr)); | ||
| 683 | + | ||
| 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 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 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 | + | ||
| 69 | + | ||
| 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 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +extern "C" { | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 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 | + | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||