* Copyright (c) 2024-2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "iotc_socket.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>
#include "securec.h"
#include "iotc_errcode.h"
#include "iotc_network.h"
#include "iotc_mem.h"
#include "iotc_log.h"
#include <sys/time.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#endif
#define MS_PER_SEC 1000
#define US_PER_MS 1000
#define MAX_IP_LEN 40
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#define IPV6_ADDR_LEN 28
#define MAX_ADDR_LE _IPV6_ADDR_LEN
#define MAX_DNS_RES_NUM 10
typedef struct AddrInfoInner {
IotcAddrInfo hiAddr;
struct addrinfo *addr;
} AddrInfoInner;
typedef struct {
IotcSocketOption option;
int32_t (*setOptionFunc)(int32_t fd, const void *value, uint32_t len);
} OptionItem;
typedef struct {
int32_t hiType;
int32_t sockType;
} SocketTypePair;
static const SocketTypePair AF_MAP[] = {
{IOTC_SOCKET_DOMAIN_AF_INET, AF_INET},
{IOTC_SOCKET_DOMAIN_AF_INET6, AF_INET6},
{IOTC_SOCKET_DOMAIN_UNSPEC, AF_UNSPEC},
};
static const SocketTypePair AP_MAP[] = {
{IOTC_SOCKET_PROTO_IP, IPPROTO_IP},
{IOTC_SOCKET_PROTO_TCP, IPPROTO_TCP},
{IOTC_SOCKET_PROTO_UDP, IPPROTO_UDP},
};
static const SocketTypePair AS_MAP[] = {
{IOTC_SOCKET_TYPE_STREAM, SOCK_STREAM},
{IOTC_SOCKET_TYPE_DGRAM, SOCK_DGRAM},
{IOTC_SOCKET_TYPE_RAW, SOCK_RAW},
};
static int32_t AiFamily2Socket(int32_t af)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AF_MAP); ++i) {
if (AF_MAP[i].hiType == af) {
return AF_MAP[i].sockType;
}
}
return af;
}
static int32_t Socket2AiFamily(int32_t af)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AF_MAP); ++i) {
if (AF_MAP[i].sockType == af) {
return AF_MAP[i].hiType;
}
}
return af;
}
static int32_t AiProtocal2Socket(int32_t ap)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AP_MAP); ++i) {
if (AP_MAP[i].hiType == ap) {
return AP_MAP[i].sockType;
}
}
return ap;
}
static int32_t Socket2AiProtocal(int32_t ap)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AP_MAP); ++i) {
if (AP_MAP[i].sockType == ap) {
return AP_MAP[i].hiType;
}
}
return ap;
}
static int32_t AiSocket2Socket(int32_t as)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AS_MAP); ++i) {
if (AS_MAP[i].hiType == as) {
return AS_MAP[i].sockType;
}
}
return as;
}
static int32_t Socket2AiSocket(int32_t as)
{
for (uint32_t i = 0; i < ARRAY_SIZE(AS_MAP); ++i) {
if (AS_MAP[i].sockType == as) {
return AS_MAP[i].hiType;
}
}
return as;
}
static void GetIotcAddrInfo(IotcAddrInfo *out, struct addrinfo *in,
int32_t level, int32_t maxLevel)
{
if ((level > maxLevel) || (in == NULL) || (out == NULL)) {
return;
}
out->aiFlags = in->ai_flags;
out->aiFamily = Socket2AiFamily(in->ai_family);
out->aiProtocol = Socket2AiProtocal(in->ai_protocol);
out->aiSocktype = Socket2AiSocket(in->ai_socktype);
out->aiAddr = (IotcSockaddr *)in->ai_addr;
out->aiCanonname = in->ai_canonname;
if (in->ai_next != NULL) {
out->aiNext = (IotcAddrInfo *)IotcMalloc(sizeof(IotcAddrInfo));
if (out->aiNext == NULL) {
IOTC_LOGE("malloc error");
} else {
(void)memset_s(out->aiNext, sizeof(IotcAddrInfo), 0, sizeof(IotcAddrInfo));
GetIotcAddrInfo(out->aiNext, in->ai_next, level + 1, maxLevel);
}
}
return;
}
static void FreeIotcAddrInfo(IotcAddrInfo *addr)
{
if (addr->aiNext != NULL) {
FreeIotcAddrInfo(addr->aiNext);
addr->aiNext = NULL;
}
IotcFree(addr);
}
static void FreeAddrInfoInner(AddrInfoInner *addrInner)
{
if (addrInner->addr != NULL) {
freeaddrinfo(addrInner->addr);
addrInner->addr = NULL;
}
FreeIotcAddrInfo((IotcAddrInfo *)addrInner);
}
static IotcAddrInfo *GetAddrInfoInner(struct addrinfo *addr)
{
if (addr == NULL) {
return NULL;
}
AddrInfoInner *addrInner = (AddrInfoInner *)IotcMalloc(sizeof(AddrInfoInner));
if (addrInner == NULL) {
IOTC_LOGE("malloc error");
freeaddrinfo(addr);
return NULL;
}
(void)memset_s(addrInner, sizeof(AddrInfoInner), 0, sizeof(AddrInfoInner));
GetIotcAddrInfo(&addrInner->hiAddr, addr, 1, MAX_DNS_RES_NUM);
addrInner->addr = addr;
return (IotcAddrInfo *)addrInner;
}
int32_t IotcGetAddrInfo(const char *nodename, const char *servname,
const IotcAddrInfo *hints, IotcAddrInfo **result)
{
if ((nodename == NULL) || (result == NULL)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
struct addrinfo *resInfo = NULL;
struct addrinfo *hintsInfoP = NULL;
struct addrinfo hintsInfo;
IOTC_LOGD("get addinfo %s", nodename);
if (hints != NULL) {
if (memcpy_s(&hintsInfo, sizeof(struct addrinfo), hints, sizeof(IotcAddrInfo)) != EOK) {
IOTC_LOGE("memcpy error");
return IOTC_ERR_SECUREC_MEMCPY;
}
hintsInfo.ai_family = AiFamily2Socket(hintsInfo.ai_family);
hintsInfo.ai_protocol = AiProtocal2Socket(hintsInfo.ai_protocol);
hintsInfo.ai_socktype = AiSocket2Socket(hintsInfo.ai_socktype);
hintsInfoP = &hintsInfo;
}
int32_t ret = getaddrinfo(nodename, servname, hintsInfoP, &resInfo);
if ((ret != 0) || (resInfo == NULL)) {
IOTC_LOGD("getaddrinfo failed, ret %d", ret);
return IOTC_ADAPTER_SOCKET_ERR_DNS;
}
*result = GetAddrInfoInner(resInfo);
return IOTC_OK;
}
void IotcFreeAddrInfo(IotcAddrInfo *addrInfo)
{
if (addrInfo == NULL) {
IOTC_LOGE("invalid param");
return;
}
FreeAddrInfoInner((AddrInfoInner *)addrInfo);
return;
}
int32_t IotcSocket(IotcSocketDomain domain, IotcSocketType type, IotcSocketProto proto)
{
int32_t af = AiFamily2Socket(domain);
int32_t st = AiSocket2Socket(type);
int32_t ap = AiProtocal2Socket(proto);
return socket(af, st, ap);
}
void IotcClose(int32_t fd)
{
(void)close(fd);
return;
}
static int32_t SetFcntl(int32_t fd, bool isBlock)
{
int32_t flags = fcntl(fd, F_GETFL, 0);
if (flags < 0) {
IOTC_LOGE("fcntl get failed, ret %d", flags);
return IOTC_ADAPTER_SOCKET_ERR_FCNTL;
}
if (isBlock) {
flags &= (~O_NONBLOCK);
} else {
flags |= O_NONBLOCK;
}
if (fcntl(fd, F_SETFL, flags) < 0) {
IOTC_LOGE("fcntl set failed");
return IOTC_ADAPTER_SOCKET_ERR_FCNTL;
}
return IOTC_OK;
}
static int32_t SetSocketOptionNonblock(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
return SetFcntl(fd, false);
}
static int32_t SetSocketOptionBlock(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
return SetFcntl(fd, true);
}
static int32_t SetSocketTimeout(int32_t fd, uint32_t timeout, bool isRead)
{
struct timeval tv;
int32_t flag = isRead ? SO_RCVTIMEO : SO_SNDTIMEO;
tv.tv_sec = timeout / MS_PER_SEC;
tv.tv_usec = timeout % MS_PER_SEC * US_PER_MS;
if (setsockopt(fd, SOL_SOCKET, flag, &tv, sizeof(struct timeval)) != 0) {
IOTC_LOGE("set [%d][%u] failed", flag, timeout);
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionReadTimeout(int32_t fd, const void *value, uint32_t len)
{
if (len < sizeof(uint32_t)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
uint32_t timeout = *(const uint32_t *)value;
return SetSocketTimeout(fd, timeout, true);
}
static int32_t SetSocketOptionSendTimeout(int32_t fd, const void *value, uint32_t len)
{
if (len < sizeof(uint32_t)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
uint32_t timeout = *(const uint32_t *)value;
return SetSocketTimeout(fd, timeout, false);
}
static int32_t SetSocketOptionEnableReuseAddr(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 1;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("set reuse addr failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionDisableReuseAddr(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 0;
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("close reuse addr failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketMultiGroup(int32_t fd, const void *value, uint32_t len, bool isAdd)
{
#if IOTC_CONF_LITEOS_M_SUPPORT
return IOTC_ERR_NOT_SUPPORT;
#else
if (value == NULL || len < sizeof(IotcSocketMultiAddr)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
IotcSocketMultiAddr *addr = (IotcSocketMultiAddr *)value;
if (addr->local == NULL || addr->multi == NULL) {
IOTC_LOGE("invalid ip");
return IOTC_ERR_PARAM_INVALID;
}
struct ip_mreq group;
(void)memset_s(&group, sizeof(struct ip_mreq), 0, sizeof(struct ip_mreq));
group.imr_multiaddr.s_addr = IotcInetAddr(addr->multi);
group.imr_interface.s_addr = IotcInetAddr(addr->local);
int32_t flag = isAdd ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
int32_t ret = setsockopt(fd, IPPROTO_IP, flag, (void *)&group, sizeof(group));
if (ret != 0) {
IOTC_LOGE("set opt %d failed %d %d", flag, ret, IotcGetSocketErrno(fd));
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
#endif
}
static int32_t SetSocketOptionAddMultiGroup(int32_t fd, const void *value, uint32_t len)
{
return SetSocketMultiGroup(fd, value, len, true);
}
static int32_t SetSocketOptionDropMultiGroup(int32_t fd, const void *value, uint32_t len)
{
return SetSocketMultiGroup(fd, value, len, false);
}
static int32_t SetSocketOptionEnableBroadcast(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 1;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("set broadcast failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionDisableBroadcast(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 0;
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("close broadcast failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionEnableMultiLoop(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 1;
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("set loop failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionDisableMultiLoop(int32_t fd, const void *value, uint32_t len)
{
(void)value;
(void)len;
int32_t opt = 0;
if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&opt, sizeof(opt)) != 0) {
IOTC_LOGE("set loop failed");
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionSendBuffer(int32_t fd, const void *value, uint32_t len)
{
if (len < sizeof(uint32_t)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
uint32_t bufferLen = *(uint32_t *)value;
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&bufferLen, sizeof(bufferLen)) != 0) {
IOTC_LOGE("set sendbuf %u failed", bufferLen);
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
static int32_t SetSocketOptionReadBuffer(int32_t fd, const void *value, uint32_t len)
{
if (len < sizeof(uint32_t)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
uint32_t bufferLen = *(uint32_t *)value;
if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&bufferLen, sizeof(bufferLen)) != 0) {
IOTC_LOGE("set recvbuf %u failed", bufferLen);
return IOTC_ADAPTER_SOCKET_ERR_SET_OPT;
}
return IOTC_OK;
}
int32_t IotcSetSocketOpt(int32_t fd, IotcSocketOption option, const void *value, uint32_t len)
{
static const OptionItem optionList[] = {
{IOTC_SOCKET_OPTION_SETFL_BLOCK, SetSocketOptionBlock},
{IOTC_SOCKET_OPTION_SETFL_NONBLOCK, SetSocketOptionNonblock},
{IOTC_SOCKET_OPTION_READ_TIMEOUT, SetSocketOptionReadTimeout},
{IOTC_SOCKET_OPTION_SEND_TIMEOUT, SetSocketOptionSendTimeout},
{IOTC_SOCKET_OPTION_ENABLE_REUSEADDR, SetSocketOptionEnableReuseAddr},
{IOTC_SOCKET_OPTION_DISABLE_REUSEADDR, SetSocketOptionDisableReuseAddr},
{IOTC_SOCKET_OPTION_ADD_MULTI_GROUP, SetSocketOptionAddMultiGroup},
{IOTC_SOCKET_OPTION_DROP_MULTI_GROUP, SetSocketOptionDropMultiGroup},
{IOTC_SOCKET_OPTION_ENABLE_BROADCAST, SetSocketOptionEnableBroadcast},
{IOTC_SOCKET_OPTION_DISABLE_BROADCAST, SetSocketOptionDisableBroadcast},
{IOTC_SOCKET_OPTION_ENABLE_MULTI_LOOP, SetSocketOptionEnableMultiLoop},
{IOTC_SOCKET_OPTION_DISABLE_MULTI_LOOP, SetSocketOptionDisableMultiLoop},
{IOTC_SOCKET_OPTION_SEND_BUFFER, SetSocketOptionSendBuffer},
{IOTC_SOCKET_OPTION_READ_BUFFER, SetSocketOptionReadBuffer},
};
for (uint32_t i = 0; i < (sizeof(optionList) / sizeof(OptionItem)); ++i) {
if (option == optionList[i].option) {
return optionList[i].setOptionFunc(fd, value, len);
}
}
IOTC_LOGW("unsupport option %d", option);
return IOTC_ERR_NOT_SUPPORT;
}
int32_t IotcBind(int32_t fd, const IotcSockaddr *addr, uint32_t addrLen)
{
(void)addrLen;
if (addr == NULL) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
struct sockaddr addrIn;
addrIn.sa_family = AiFamily2Socket(addr->saFamily);
if (memcpy_s(addrIn.sa_data, sizeof(addrIn.sa_data), addr->saData, sizeof(addr->saData)) != EOK) {
IOTC_LOGE("memcpy error");
return IOTC_ERR_SECUREC_MEMCPY;
}
return bind(fd, &addrIn, sizeof(struct sockaddr));
}
int32_t IotcConnect(int32_t fd, const IotcSockaddr *addr, uint32_t addrLen)
{
(void)addrLen;
if (addr == NULL) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
struct sockaddr addrIn;
addrIn.sa_family = AiFamily2Socket(addr->saFamily);
if (memcpy_s(addrIn.sa_data, sizeof(addrIn.sa_data), addr->saData, sizeof(addr->saData)) != EOK) {
IOTC_LOGE("memcpy error");
return IOTC_ERR_SECUREC_MEMCPY;
}
return connect(fd, &addrIn, sizeof(struct sockaddr));
}
int32_t IotcRecv(int32_t fd, uint8_t *buf, uint32_t len)
{
return recv(fd, buf, len, MSG_DONTWAIT);
}
int32_t IotcSend(int32_t fd, const uint8_t *buf, uint32_t len)
{
return send(fd, buf, len, MSG_DONTWAIT);
}
int32_t IotcRecvFrom(int32_t fd, uint8_t *buf, uint32_t len, IotcSockaddr *from, uint32_t *fromLen)
{
if ((from == NULL) || (fromLen == NULL) || (buf == NULL)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
struct sockaddr addr;
(void)memset_s(&addr, sizeof(struct sockaddr), 0, sizeof(struct sockaddr));
int32_t ret = recvfrom(fd, buf, len, 0, &addr, (socklen_t *)fromLen);
from->saFamily = addr.sa_family;
if (memcpy_s(from->saData, sizeof(from->saData), addr.sa_data, sizeof(addr.sa_data)) != EOK) {
IOTC_LOGE("memcpy error");
return IOTC_ERR_SECUREC_MEMCPY;
}
return ret;
}
int32_t IotcSendTo(int32_t fd, const uint8_t *buf, uint32_t len, const IotcSockaddr *to, uint32_t toLen)
{
if ((to == NULL) || (buf == NULL)) {
IOTC_LOGE("invalid param");
return IOTC_ERR_PARAM_INVALID;
}
struct sockaddr addr;
(void)memset_s(&addr, sizeof(struct sockaddr), 0, sizeof(struct sockaddr));
addr.sa_family = AiFamily2Socket(to->saFamily);
if (memcpy_s(addr.sa_data, sizeof(addr.sa_data), to->saData, sizeof(to->saData)) != EOK) {
IOTC_LOGE("memcpy error");
return IOTC_ERR_SECUREC_MEMCPY;
}
return sendto(fd, buf, len, 0, &addr, toLen);
}
static void GetFdSet(IotcFdSet *set, fd_set *fdSet, int32_t *maxfd)
{
if ((set == NULL) || (set->fdSet == NULL)) {
return;
}
(void)memset_s(fdSet, sizeof(fd_set), 0, sizeof(fd_set));
for (uint32_t i = 0; i < set->num; ++i) {
if (set->fdSet[i] >= 0) {
FD_SET(set->fdSet[i], fdSet);
*maxfd = MAX(*maxfd, set->fdSet[i]);
}
}
}
static void FdIsSet(IotcFdSet *set, fd_set *fdSet)
{
if (set == NULL) {
return;
}
for (uint32_t i = 0; i < set->num; ++i) {
if (FD_ISSET(set->fdSet[i], fdSet) == 0) {
set->fdSet[i] = -1;
}
}
return;
}
int32_t IotcSelect(IotcFdSet *readSet, IotcFdSet *writeSet, IotcFdSet *exceptSet, uint32_t ms)
{
int32_t maxFd = -1;
fd_set read;
fd_set write;
fd_set except;
GetFdSet(readSet, &read, &maxFd);
GetFdSet(writeSet, &write, &maxFd);
GetFdSet(exceptSet, &except, &maxFd);
struct timeval timeout;
timeout.tv_sec = ms / MS_PER_SEC;
timeout.tv_usec = ms % MS_PER_SEC * US_PER_MS;
int32_t ret = select(maxFd + 1, (readSet == NULL) ? NULL : &read,
(writeSet == NULL) ? NULL : &write,
(exceptSet == NULL) ? NULL : &except, &timeout);
if (ret <= 0) {
return ret;
}
FdIsSet(readSet, &read);
FdIsSet(writeSet, &write);
FdIsSet(exceptSet, &except);
return ret;
}
int32_t IotcGetSocketErrno(int32_t fd)
{
#if defined(errno)
if (fd < 0) {
return errno;
}
#endif
int32_t socketErr;
uint32_t len = sizeof(socklen_t);
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &socketErr, (socklen_t *)&len) != 0) {
IOTC_LOGE("get socket errno error");
return IOTC_ADAPTER_SOCKET_ERR_GET_OPT;
}
switch (socketErr) {
case EINTR:
return IOTC_SOCKET_ERRNO_EINTR;
case EAGAIN:
return IOTC_SOCKET_ERRNO_EAGAIN;
case EINPROGRESS:
return IOTC_SOCKET_ERRNO_EINPROGRESS;
default:
break;
}
return socketErr;
}
uint32_t IotcHtonl(uint32_t hl)
{
return htonl(hl);
}
uint32_t IotcNtohl(uint32_t nl)
{
return ntohl(nl);
}
uint16_t IotcHtons(uint16_t hs)
{
return htons(hs);
}
uint16_t IotcNtohs(uint16_t ns)
{
return ntohs(ns);
}
int32_t IotcInetAton(const char *ip, uint32_t *addr)
{
return inet_aton(ip, (struct in_addr *)addr);
}
uint32_t IotcInetAddr(const char *ip)
{
return inet_addr(ip);
}
const char *IotcInetNtoa(uint32_t addr, char *buf, uint32_t buflen)
{
struct in_addr tempAddr;
tempAddr.s_addr = IotcHtonl(addr);
#if IOTC_CONF_ADAPTER_SOCKET_LWIP_SUPPORT
return inet_ntoa_r(tempAddr, buf, buflen);
#else
return inet_ntop(AF_INET, &tempAddr, buf, buflen);
#endif
}