初始提交

This commit is contained in:
2025-06-27 00:32:57 +08:00
commit e40bb2ba8a
5134 changed files with 2158460 additions and 0 deletions

View File

@@ -0,0 +1,257 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-05-18 ChenYong First version
*/
#include <sal_ipaddr.h>
#include <rtthread.h>
/* Here for now until needed in other places in lwIP */
#ifndef isprint
#define in_range(c, lo, up) ((u8_t)c >= lo && (u8_t)c <= up)
#define isprint(c) in_range(c, 0x20, 0x7f)
#define isdigit(c) in_range(c, '0', '9')
#define isxdigit(c) (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
#define islower(c) in_range(c, 'a', 'z')
#define isspace(c) (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
#endif
/**
* Check whether "cp" is a valid ascii representation
* of an Internet address and convert to a binary address.
* Returns 1 if the address is valid, 0 if not.
* This replaces inet_addr, the return value from which
* cannot distinguish between failure and a local broadcast address.
*
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
* @param addr pointer to which to save the ip address in network order
* @return 1 if cp could be converted to addr, 0 on failure
*/
int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr)
{
u32_t val;
u8_t base;
char c;
u32_t parts[4];
u32_t *pp = parts;
c = *cp;
for (;;)
{
/*
* Collect number up to ``.''.
* Values are specified as for C:
* 0x=hex, 0=octal, 1-9=decimal.
*/
if (!isdigit(c))
{
return 0;
}
val = 0;
base = 10;
if (c == '0')
{
c = *++cp;
if (c == 'x' || c == 'X')
{
base = 16;
c = *++cp;
}
else
{
base = 8;
}
}
for (;;)
{
if (isdigit(c))
{
val = (val * base) + (u32_t) (c - '0');
c = *++cp;
}
else if (base == 16 && isxdigit(c))
{
val = (val << 4) | (u32_t) (c + 10 - (islower(c) ? 'a' : 'A'));
c = *++cp;
}
else
{
break;
}
}
if (c == '.')
{
/*
* Internet format:
* a.b.c.d
* a.b.c (with c treated as 16 bits)
* a.b (with b treated as 24 bits)
*/
if (pp >= parts + 3)
{
return 0;
}
*pp++ = val;
c = *++cp;
}
else
{
break;
}
}
/*
* Check for trailing characters.
*/
if (c != '\0' && !isspace(c))
{
return 0;
}
/*
* Concoct the address according to
* the number of parts specified.
*/
switch (pp - parts + 1)
{
case 0:
return 0; /* initial nondigit */
case 1: /* a -- 32 bits */
break;
case 2: /* a.b -- 8.24 bits */
if (val > 0xffffffUL)
{
return 0;
}
if (parts[0] > 0xff)
{
return 0;
}
val |= parts[0] << 24;
break;
case 3: /* a.b.c -- 8.8.16 bits */
if (val > 0xffff)
{
return 0;
}
if ((parts[0] > 0xff) || (parts[1] > 0xff))
{
return 0;
}
val |= (parts[0] << 24) | (parts[1] << 16);
break;
case 4: /* a.b.c.d -- 8.8.8.8 bits */
if (val > 0xff)
{
return 0;
}
if ((parts[0] > 0xff) || (parts[1] > 0xff) || (parts[2] > 0xff))
{
return 0;
}
val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
break;
default:
RT_ASSERT(0);
break;
}
if (addr)
{
ip4_addr_set_u32(addr, htonl(val));
}
return 1;
}
/**
* Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
*
* @param addr ip address in network order to convert
* @param buf target buffer where the string is stored
* @param buflen length of buf
* @return either pointer to buf which now holds the ASCII
* representation of addr or NULL if buf was too small
*/
char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen)
{
u32_t s_addr;
char inv[3];
char *rp;
u8_t *ap;
u8_t rem;
u8_t n;
u8_t i;
int len = 0;
s_addr = ip4_addr_get_u32(addr);
rp = buf;
ap = (u8_t *) &s_addr;
for (n = 0; n < 4; n++)
{
i = 0;
do
{
rem = *ap % (u8_t) 10;
*ap /= (u8_t) 10;
inv[i++] = (char) ('0' + rem);
} while (*ap);
while (i--)
{
if (len++ >= buflen)
{
return NULL;
}
*rp++ = inv[i];
}
if (len++ >= buflen)
{
return NULL;
}
*rp++ = '.';
ap++;
}
*--rp = 0;
return buf;
}
/**
* Convert numeric IP address into decimal dotted ASCII representation.
* returns ptr to static buffer; not reentrant!
*
* @param addr ip address in network order to convert
* @return pointer to a global static (!) buffer that holds the ASCII
* representation of addr
*/
char *sal_ip4addr_ntoa(const ip4_addr_t *addr)
{
static char str[IP4ADDR_STRLEN_MAX];
return sal_ip4addr_ntoa_r(addr, str, IP4ADDR_STRLEN_MAX);
}
/**
* Ascii internet address interpretation routine.
* The value returned is in network order.
*
* @param cp IP address in ascii representation (e.g. "127.0.0.1")
* @return ip address in network order
*/
in_addr_t sal_ipaddr_addr(const char *cp)
{
ip4_addr_t val;
if (sal_ip4addr_aton(cp, &val)) {
return ip4_addr_get_u32(&val);
}
return (IPADDR_NONE);
}

View File

@@ -0,0 +1,984 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-05-23 ChenYong First version
* 2018-11-12 ChenYong Add TLS support
*/
#include <rtthread.h>
#include <rthw.h>
#include <sal_socket.h>
#include <sal_netdb.h>
#ifdef SAL_USING_TLS
#include <sal_tls.h>
#endif
#include <sal.h>
#define DBG_ENABLE
#define DBG_SECTION_NAME "SAL_SOC"
#define DBG_LEVEL DBG_INFO
#define DBG_COLOR
#include <rtdbg.h>
#define SOCKET_TABLE_STEP_LEN 4
/* the socket table used to dynamic allocate sockets */
struct sal_socket_table
{
uint32_t max_socket;
struct sal_socket **sockets;
};
#ifdef SAL_USING_TLS
/* The global TLS protocol options */
static struct sal_proto_tls *proto_tls;
#endif
/* The global array of available protocol families */
static struct sal_proto_family proto_families[SAL_PROTO_FAMILIES_NUM];
/* The global socket table */
static struct sal_socket_table socket_table;
static struct rt_mutex sal_core_lock;
static rt_bool_t init_ok = RT_FALSE;
#define IS_SOCKET_PROTO_TLS(sock) (((sock)->protocol == PROTOCOL_TLS) || \
((sock)->protocol == PROTOCOL_DTLS))
#define SAL_SOCKOPS_PROTO_TLS_VALID(sock, name) (proto_tls && (proto_tls->ops->name) && IS_SOCKET_PROTO_TLS(sock))
#define SAL_SOCKOPT_PROTO_TLS_EXEC(sock, name, optval, optlen) \
do \
{ \
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)) \
{ \
return proto_tls->ops->name((sock)->user_data_tls, (optval), (optlen)); \
} \
}while(0) \
/**
* SAL (Socket Abstraction Layer) initialize.
*
* @return result 0: initialize success
* -1: initialize failed
*/
int sal_init(void)
{
int cn;
if (init_ok)
{
LOG_D("Socket Abstraction Layer is already initialized.");
return 0;
}
/* init sal socket table */
cn = SOCKET_TABLE_STEP_LEN < SAL_SOCKETS_NUM ? SOCKET_TABLE_STEP_LEN : SAL_SOCKETS_NUM;
socket_table.max_socket = cn;
socket_table.sockets = rt_calloc(1, cn * sizeof(struct sal_socket *));
if (socket_table.sockets == RT_NULL)
{
LOG_E("No memory for socket table.\n");
return -1;
}
/* create sal socket lock */
rt_mutex_init(&sal_core_lock, "sal_lock", RT_IPC_FLAG_FIFO);
LOG_I("Socket Abstraction Layer initialize success.");
init_ok = RT_TRUE;
return 0;
}
INIT_COMPONENT_EXPORT(sal_init);
/**
* This function will register TLS protocol to the global TLS protocol.
*
* @param pt TLS protocol object
*
* @return 0: TLS protocol object register success
*/
#ifdef SAL_USING_TLS
int sal_proto_tls_register(const struct sal_proto_tls *pt)
{
RT_ASSERT(pt);
proto_tls = (struct sal_proto_tls *) pt;
return 0;
}
#endif
/**
* This function will register protocol family to the global array of protocol families.
*
* @param pf protocol family object
*
* @return 0: protocol family object register success
* -1: the global array of available protocol families is full
*/
int sal_proto_family_register(const struct sal_proto_family *pf)
{
rt_base_t level;
int idx;
/* disable interrupt */
level = rt_hw_interrupt_disable();
/* check protocol family is already registered */
for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == pf->family && proto_families[idx].create)
{
/* enable interrupt */
rt_hw_interrupt_enable(level);
LOG_E("%s protocol family is already registered!", pf->family);
return -1;
}
}
/* find an empty protocol family entry */
for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM && proto_families[idx].create; idx++);
/* can't find an empty protocol family entry */
if (idx == SAL_PROTO_FAMILIES_NUM)
{
/* enable interrupt */
rt_hw_interrupt_enable(level);
return -1;
}
proto_families[idx].family = pf->family;
proto_families[idx].sec_family = pf->sec_family;
proto_families[idx].create = pf->create;
proto_families[idx].ops = pf->ops;
proto_families[idx].ops->gethostbyname = pf->ops->gethostbyname;
proto_families[idx].ops->gethostbyname_r = pf->ops->gethostbyname_r;
proto_families[idx].ops->freeaddrinfo = pf->ops->freeaddrinfo;
proto_families[idx].ops->getaddrinfo = pf->ops->getaddrinfo;
/* enable interrupt */
rt_hw_interrupt_enable(level);
return 0;
}
/**
* This function removes a previously registered protocol family object.
*
* @param pf protocol family object
*
* @return >=0 : unregister protocol family index
* -1 : unregister failed
*/
int sal_proto_family_unregister(int family)
{
int idx = 0;
RT_ASSERT(family > 0 && family < AF_MAX);
for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == family && proto_families[idx].create)
{
rt_memset(&proto_families[idx], 0x00, sizeof(struct sal_proto_family));
return idx;
}
}
return -1;
}
/**
* This function will judge whether protocol family is registered
*
* @param family protocol family number
*
* @return 1: protocol family is registered
* 0: protocol family is not registered
*/
rt_bool_t sal_proto_family_is_registered(int family)
{
int idx = 0;
RT_ASSERT(family > 0 && family < AF_MAX);
for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == family && proto_families[idx].create)
{
return RT_TRUE;
}
}
return RT_FALSE;
}
/**
* This function will get protocol family object by family number.
*
* @param family protocol family number
*
* @return protocol family object
*/
struct sal_proto_family *sal_proto_family_find(int family)
{
int idx = 0;
RT_ASSERT(family > 0 && family < AF_MAX);
for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == family && proto_families[idx].create)
{
return &proto_families[idx];
}
}
return RT_NULL;
}
/**
* This function will get sal socket object by sal socket descriptor.
*
* @param socket sal socket index
*
* @return sal socket object of the current sal socket index
*/
struct sal_socket *sal_get_socket(int socket)
{
struct sal_socket_table *st = &socket_table;
if (socket < 0 || socket >= (int) st->max_socket)
{
return RT_NULL;
}
socket = socket - SAL_SOCKET_OFFSET;
/* check socket structure valid or not */
if (st->sockets[socket]->magic != SAL_SOCKET_MAGIC)
{
return RT_NULL;
}
return st->sockets[socket];
}
/**
* This function will lock sal socket.
*
* @note please don't invoke it on ISR.
*/
static void sal_lock(void)
{
rt_err_t result;
result = rt_mutex_take(&sal_core_lock, RT_WAITING_FOREVER);
if (result != RT_EOK)
{
RT_ASSERT(0);
}
}
/**
* This function will lock sal socket.
*
* @note please don't invoke it on ISR.
*/
static void sal_unlock(void)
{
rt_mutex_release(&sal_core_lock);
}
/**
* This function will get protocol family structure by family type
*
* @param family protocol family
*
* @return protocol family structure address
*/
static struct sal_proto_family *get_proto_family(int family)
{
int idx;
for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].family == family && proto_families[idx].create)
{
return &proto_families[idx];
}
}
/* compare the secondary protocol families when primary protocol families find failed */
for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++)
{
if (proto_families[idx].sec_family == family && proto_families[idx].create)
{
return &proto_families[idx];
}
}
return RT_NULL;
}
/**
* This function will initialize sal socket object and set socket options
*
* @param family protocol family
* @param type socket type
* @param protocol transfer Protocol
* @param res sal socket object address
*
* @return 0 : socket initialize success
* -1 : input the wrong family
* -2 : input the wrong socket type
* -3 : get protocol family object failed
* -4 : set socket options failed
*/
static int socket_init(int family, int type, int protocol, struct sal_socket **res)
{
struct sal_socket *sock;
struct sal_proto_family *pf;
if (family < 0 || family > AF_MAX)
{
return -1;
}
if (type < 0 || type > SOCK_MAX)
{
return -2;
}
sock = *res;
sock->domain = family;
sock->type = type;
sock->protocol = protocol;
/* get socket protocol family object */
if ((pf = get_proto_family(family)) == RT_NULL)
{
return -3;
}
/* registered the current socket options */
if (pf->create(sock, type, protocol) != 0)
{
return -4;
}
return 0;
}
static int socket_alloc(struct sal_socket_table *st, int f_socket)
{
int idx;
/* find an empty socket entry */
for (idx = f_socket; idx < (int) st->max_socket; idx++)
{
if (st->sockets[idx] == RT_NULL)
break;
if (st->sockets[idx]->ops == RT_NULL)
break;
}
/* allocate a larger sockte container */
if (idx == (int) st->max_socket && st->max_socket < SAL_SOCKETS_NUM)
{
int cnt, index;
struct sal_socket **sockets;
/* increase the number of socket with 4 step length */
cnt = st->max_socket + SOCKET_TABLE_STEP_LEN;
cnt = cnt > SAL_SOCKETS_NUM ? SAL_SOCKETS_NUM : cnt;
sockets = rt_realloc(st->sockets, cnt * sizeof(struct sal_socket *));
if (sockets == RT_NULL)
goto __result; /* return st->max_socket */
/* clean the new allocated fds */
for (index = st->max_socket; index < cnt; index++)
{
sockets[index] = RT_NULL;
}
st->sockets = sockets;
st->max_socket = cnt;
}
/* allocate 'struct sal_socket' */
if (idx < (int) st->max_socket && st->sockets[idx] == RT_NULL)
{
st->sockets[idx] = rt_calloc(1, sizeof(struct sal_socket));
if (st->sockets[idx] == RT_NULL)
{
idx = st->max_socket;
}
}
__result:
return idx;
}
static int socket_new(void)
{
struct sal_socket *sock;
struct sal_socket_table *st = &socket_table;
int idx;
sal_lock();
/* find an empty sal socket entry */
idx = socket_alloc(st, 0);
/* can't find an empty sal socket entry */
if (idx == (int) st->max_socket)
{
idx = -(1 + SAL_SOCKET_OFFSET);
goto __result;
}
sock = st->sockets[idx];
sock->socket = idx + SAL_SOCKET_OFFSET;
sock->magic = SAL_SOCKET_MAGIC;
sock->ops = RT_NULL;
sock->user_data = RT_NULL;
#ifdef SAL_USING_TLS
sock->user_data_tls = RT_NULL;
#endif
__result:
sal_unlock();
return idx + SAL_SOCKET_OFFSET;
}
int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen)
{
int new_socket;
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->accept == RT_NULL)
{
return -RT_ENOSYS;
}
new_socket = sock->ops->accept((int) sock->user_data, addr, addrlen);
if (new_socket != -1)
{
int retval;
int new_sal_socket;
struct sal_socket *new_sock;
/* allocate a new socket structure and registered socket options */
new_sal_socket = socket_new();
if (new_sal_socket < 0)
{
sock->ops->closesocket(new_socket);
return -1;
}
new_sock = sal_get_socket(new_sal_socket);
retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock);
if (retval < 0)
{
sock->ops->closesocket(new_socket);
rt_memset(new_sock, 0x00, sizeof(struct sal_socket));
LOG_E("New socket registered failed, return error %d.", retval);
return -1;
}
/* socket struct user_data used to store the acquired new socket */
new_sock->user_data = (void *) new_socket;
return new_sal_socket;
}
return -1;
}
int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->bind == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->bind((int) sock->user_data, name, namelen);
}
int sal_shutdown(int socket, int how)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->shutdown == RT_NULL)
{
return -RT_ENOSYS;
}
if (sock->ops->shutdown((int) sock->user_data, how) == 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
{
if (proto_tls->ops->closesocket(sock->user_data_tls) < 0)
{
return -1;
}
}
#endif
rt_free(sock);
socket_table.sockets[socket] = RT_NULL;
return 0;
}
return -1;
}
int sal_getpeername(int socket, struct sockaddr *name, socklen_t *namelen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->getpeername == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->getpeername((int) sock->user_data, name, namelen);
}
int sal_getsockname(int socket, struct sockaddr *name, socklen_t *namelen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->getsockname == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->getsockname((int) sock->user_data, name, namelen);
}
int sal_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->getsockopt == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->getsockopt((int) sock->user_data, level, optname, optval, optlen);
}
int sal_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->setsockopt == RT_NULL)
{
return -RT_ENOSYS;
}
#ifdef SAL_USING_TLS
if (level == SOL_TLS)
{
switch (optname)
{
case TLS_CRET_LIST:
SAL_SOCKOPT_PROTO_TLS_EXEC(sock, set_cret_list, optval, optlen);
break;
case TLS_CIPHERSUITE_LIST:
SAL_SOCKOPT_PROTO_TLS_EXEC(sock, set_ciphersurite, optval, optlen);
break;
case TLS_PEER_VERIFY:
SAL_SOCKOPT_PROTO_TLS_EXEC(sock, set_peer_verify, optval, optlen);
break;
case TLS_DTLS_ROLE:
SAL_SOCKOPT_PROTO_TLS_EXEC(sock, set_dtls_role, optval, optlen);
break;
default:
return -1;
}
return 0;
}
else
{
return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
}
#else
return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen);
#endif /* SAL_USING_TLS */
}
int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen)
{
struct sal_socket *sock;
int ret;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->connect == RT_NULL)
{
return -RT_ENOSYS;
}
ret = sock->ops->connect((int) sock->user_data, name, namelen);
#ifdef SAL_USING_TLS
if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect))
{
if (proto_tls->ops->connect(sock->user_data_tls) < 0)
{
return -1;
}
return ret;
}
#endif
return ret;
}
int sal_listen(int socket, int backlog)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->listen == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->listen((int) sock->user_data, backlog);
}
int sal_recvfrom(int socket, void *mem, size_t len, int flags,
struct sockaddr *from, socklen_t *fromlen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->recvfrom == RT_NULL)
{
return -RT_ENOSYS;
}
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, recv))
{
int ret;
if ((ret = proto_tls->ops->recv(sock->user_data_tls, mem, len)) < 0)
{
return -1;
}
return ret;
}
else
{
return sock->ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
}
#else
return sock->ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen);
#endif
}
int sal_sendto(int socket, const void *dataptr, size_t size, int flags,
const struct sockaddr *to, socklen_t tolen)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->sendto == RT_NULL)
{
return -RT_ENOSYS;
}
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, send))
{
int ret;
if ((ret = proto_tls->ops->send(sock->user_data_tls, dataptr, size)) < 0)
{
return -1;
}
return ret;
}
else
{
return sock->ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
}
#else
return sock->ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen);
#endif
}
int sal_socket(int domain, int type, int protocol)
{
int retval;
int socket, proto_socket;
struct sal_socket *sock;
/* allocate a new socket and registered socket options */
socket = socket_new();
if (socket < 0)
{
return -1;
}
sock = sal_get_socket(socket);
retval = socket_init(domain, type, protocol, &sock);
if (retval < 0)
{
LOG_E("SAL socket protocol family input failed, return error %d.", retval);
return -1;
}
if (sock->ops->socket == RT_NULL)
{
return -RT_ENOSYS;
}
proto_socket = sock->ops->socket(domain, type, protocol);
if (proto_socket >= 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, socket))
{
sock->user_data_tls = proto_tls->ops->socket(proto_socket);
if (sock->user_data_tls == RT_NULL)
{
return -1;
}
}
#endif
sock->user_data = (void *) proto_socket;
return sock->socket;
}
return -1;
}
int sal_closesocket(int socket)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->closesocket == RT_NULL)
{
return -RT_ENOSYS;
}
if (sock->ops->closesocket((int) sock->user_data) == 0)
{
#ifdef SAL_USING_TLS
if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket))
{
if (proto_tls->ops->closesocket(sock->user_data_tls) < 0)
{
return -1;
}
}
#endif
rt_free(sock);
socket_table.sockets[socket] = RT_NULL;
return 0;
}
return -1;
}
int sal_ioctlsocket(int socket, long cmd, void *arg)
{
struct sal_socket *sock;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->ioctlsocket == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->ioctlsocket((int) sock->user_data, cmd, arg);
}
#ifdef SAL_USING_POSIX
int sal_poll(struct dfs_fd *file, struct rt_pollreq *req)
{
struct sal_socket *sock;
int socket = (int) file->data;
sock = sal_get_socket(socket);
if (!sock)
{
return -1;
}
if (sock->ops->poll == RT_NULL)
{
return -RT_ENOSYS;
}
return sock->ops->poll(file, req);
}
#endif
struct hostent *sal_gethostbyname(const char *name)
{
int i;
struct hostent *hst;
for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
{
if (proto_families[i].ops && proto_families[i].ops->gethostbyname)
{
hst = proto_families[i].ops->gethostbyname(name);
if (hst != RT_NULL)
{
return hst;
}
}
}
return RT_NULL;
}
int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf,
size_t buflen, struct hostent **result, int *h_errnop)
{
int i, res;
for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
{
if (proto_families[i].ops && proto_families[i].ops->gethostbyname_r)
{
res = proto_families[i].ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
if (res == 0)
{
return res;
}
}
}
return -1;
}
int sal_getaddrinfo(const char *nodename,
const char *servname,
const struct addrinfo *hints,
struct addrinfo **res)
{
int i, ret;
for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
{
if (proto_families[i].ops && proto_families[i].ops->getaddrinfo)
{
ret = proto_families[i].ops->getaddrinfo(nodename, servname, hints, res);
if (ret == 0)
{
return ret;
}
}
}
return -1;
}
void sal_freeaddrinfo(struct addrinfo *ai)
{
int i;
for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i)
{
if (proto_families[i].ops && proto_families[i].ops->freeaddrinfo)
{
proto_families[i].ops->freeaddrinfo(ai);
return;
}
}
}