diff options
| author | yangjie11 <[email protected]> | 2020-11-18 09:56:35 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2020-11-18 09:56:35 +0800 |
| commit | d4a682e8d97fa131e5a8d795f8c5451d55cdd5b0 (patch) | |
| tree | 4773b40cb012475c5daf74bfd55707e141477669 /components/net/sal_socket/src | |
| parent | 2b98f4720c827ae1850df78299f6b273d568c8c7 (diff) | |
| parent | 2ef3c9d861f55253620996a94831a4be31ca6620 (diff) | |
Merge pull request #3 from RT-Thread/master
sync
Diffstat (limited to 'components/net/sal_socket/src')
| -rw-r--r-- | components/net/sal_socket/src/sal_ipaddr.c | 257 | ||||
| -rw-r--r-- | components/net/sal_socket/src/sal_socket.c | 844 |
2 files changed, 493 insertions, 608 deletions
diff --git a/components/net/sal_socket/src/sal_ipaddr.c b/components/net/sal_socket/src/sal_ipaddr.c deleted file mode 100644 index 6477a8ad64..0000000000 --- a/components/net/sal_socket/src/sal_ipaddr.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * 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); -} diff --git a/components/net/sal_socket/src/sal_socket.c b/components/net/sal_socket/src/sal_socket.c index dba8e66254..ec0519df02 100644 --- a/components/net/sal_socket/src/sal_socket.c +++ b/components/net/sal_socket/src/sal_socket.c @@ -11,6 +11,7 @@ #include <rtthread.h> #include <rthw.h> +#include <sys/time.h> #include <sal_socket.h> #include <sal_netdb.h> @@ -18,11 +19,17 @@ #include <sal_tls.h> #endif #include <sal.h> +#include <netdev.h> -#define DBG_ENABLE -#define DBG_SECTION_NAME "SAL_SOC" -#define DBG_LEVEL DBG_INFO -#define DBG_COLOR +#include <ipc/workqueue.h> + +/* check system workqueue stack size */ +#if RT_SYSTEM_WORKQUEUE_STACKSIZE < 1536 +#error "The system workqueue stack size must more than 1536 bytes" +#endif + +#define DBG_TAG "sal.skt" +#define DBG_LVL DBG_INFO #include <rtdbg.h> #define SOCKET_TABLE_STEP_LEN 4 @@ -39,8 +46,6 @@ struct sal_socket_table 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; @@ -51,25 +56,50 @@ static rt_bool_t init_ok = RT_FALSE; #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)) \ - { \ +do { \ + if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, name)){ \ return proto_tls->ops->name((sock)->user_data_tls, (optval), (optlen)); \ } \ }while(0) \ +#define SAL_SOCKET_OBJ_GET(sock, socket) \ +do { \ + (sock) = sal_get_socket(socket); \ + if ((sock) == RT_NULL) { \ + return -1; \ + } \ +}while(0) \ + +#define SAL_NETDEV_IS_UP(netdev) \ +do { \ + if (!netdev_is_up(netdev)) { \ + return -1; \ + } \ +}while(0) \ + +#define SAL_NETDEV_SOCKETOPS_VALID(netdev, pf, ops) \ +do { \ + (pf) = (struct sal_proto_family *) netdev->sal_user_data; \ + if ((pf)->skt_ops->ops == RT_NULL){ \ + return -1; \ + } \ +}while(0) \ + +#define SAL_NETDEV_NETDBOPS_VALID(netdev, pf, ops) \ + ((netdev) && netdev_is_up(netdev) && \ + ((pf) = (struct sal_proto_family *) (netdev)->sal_user_data) != RT_NULL && \ + (pf)->netdb_ops->ops) \ /** * SAL (Socket Abstraction Layer) initialize. * * @return result 0: initialize success - * -1: initialize failed + * -1: initialize failed */ int sal_init(void) { int cn; - + if (init_ok) { LOG_D("Socket Abstraction Layer is already initialized."); @@ -85,7 +115,7 @@ int sal_init(void) 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); @@ -96,153 +126,177 @@ int sal_init(void) } 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) +/* check SAL network interface device internet status */ +static void check_netdev_internet_up_work(struct rt_work *work, void *work_data) { - RT_ASSERT(pt); - proto_tls = (struct sal_proto_tls *) pt; +#define SAL_INTERNET_VERSION 0x00 +#define SAL_INTERNET_BUFF_LEN 12 +#define SAL_INTERNET_TIMEOUT (2) - return 0; -} -#endif +#define SAL_INTERNET_HOST "link.rt-thread.org" +#define SAL_INTERNET_PORT 8101 -/** - * 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; +#define SAL_INTERNET_MONTH_LEN 4 +#define SAL_INTERNET_DATE_LEN 16 - /* disable interrupt */ - level = rt_hw_interrupt_disable(); + int index, sockfd = -1, result = 0; + struct sockaddr_in server_addr; + struct hostent *host; + struct timeval timeout; + struct netdev *netdev = (struct netdev *)work_data; + socklen_t addr_len = sizeof(struct sockaddr_in); + char send_data[SAL_INTERNET_BUFF_LEN], recv_data = 0; + struct rt_delayed_work *delay_work = (struct rt_delayed_work *)work; - /* check protocol family is already registered */ - for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++) + const char month[][SAL_INTERNET_MONTH_LEN] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + char date[SAL_INTERNET_DATE_LEN]; + int moth_num = 0; + + struct sal_proto_family *pf = (struct sal_proto_family *) netdev->sal_user_data; + const struct sal_socket_ops *skt_ops; + + if (work) { - 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; - } + rt_free(delay_work); } - /* find an empty protocol family entry */ - for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM && proto_families[idx].create; idx++); + /* get network interface socket operations */ + if (pf == RT_NULL || pf->skt_ops == RT_NULL) + { + result = -RT_ERROR; + goto __exit; + } - /* can't find an empty protocol family entry */ - if (idx == SAL_PROTO_FAMILIES_NUM) + host = (struct hostent *) pf->netdb_ops->gethostbyname(SAL_INTERNET_HOST); + if (host == RT_NULL) { - /* enable interrupt */ - rt_hw_interrupt_enable(level); - return -1; + result = -RT_ERROR; + goto __exit; } - proto_families[idx].family = pf->family; - proto_families[idx].sec_family = pf->sec_family; - proto_families[idx].create = pf->create; + skt_ops = pf->skt_ops; + if ((sockfd = skt_ops->socket(AF_INET, SOCK_DGRAM, 0)) < 0) + { + result = -RT_ERROR; + goto __exit; + } - 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; + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(SAL_INTERNET_PORT); + server_addr.sin_addr = *((struct in_addr *)host->h_addr); + rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); - /* enable interrupt */ - rt_hw_interrupt_enable(level); + timeout.tv_sec = SAL_INTERNET_TIMEOUT; + timeout.tv_usec = 0; - return 0; -} + /* set receive and send timeout */ + skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (void *) &timeout, sizeof(timeout)); + skt_ops->setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, (void *) &timeout, sizeof(timeout)); -/** - * 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; + /* get build moth value*/ + rt_memset(date, 0x00, SAL_INTERNET_DATE_LEN); + rt_snprintf(date, SAL_INTERNET_DATE_LEN, "%s", __DATE__); - RT_ASSERT(family > 0 && family < AF_MAX); - - for(idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++) + for (index = 0; index < sizeof(month) / SAL_INTERNET_MONTH_LEN; index++) { - if (proto_families[idx].family == family && proto_families[idx].create) + if (rt_memcmp(date, month[index], SAL_INTERNET_MONTH_LEN - 1) == 0) { - rt_memset(&proto_families[idx], 0x00, sizeof(struct sal_proto_family)); - - return idx; + moth_num = index + 1; + break; } } - return -1; + /* not find build month */ + if (moth_num == 0 || moth_num > sizeof(month) / SAL_INTERNET_MONTH_LEN) + { + result = -RT_ERROR; + goto __exit; + } + + rt_memset(send_data, 0x00, SAL_INTERNET_BUFF_LEN); + send_data[0] = SAL_INTERNET_VERSION; + for (index = 0; index < netdev->hwaddr_len; index++) + { + send_data[index + 1] = netdev->hwaddr[index] + moth_num; + } + send_data[9] = RT_VERSION; + send_data[10] = RT_SUBVERSION; + send_data[11] = RT_REVISION; + + skt_ops->sendto(sockfd, send_data, SAL_INTERNET_BUFF_LEN, 0, + (struct sockaddr *)&server_addr, sizeof(struct sockaddr)); + + result = skt_ops->recvfrom(sockfd, &recv_data, sizeof(recv_data), 0, (struct sockaddr *)&server_addr, &addr_len); + if (result < 0) + { + goto __exit; + } + + if (recv_data == RT_FALSE) + { + result = -RT_ERROR; + goto __exit; + } + +__exit: + if (result > 0) + { + LOG_D("Set network interface device(%s) internet status up.", netdev->name); + netdev->flags |= NETDEV_FLAG_INTERNET_UP; + } + else + { + LOG_D("Set network interface device(%s) internet status down.", netdev->name); + netdev->flags &= ~NETDEV_FLAG_INTERNET_UP; + } + + if (sockfd >= 0) + { + skt_ops->closesocket(sockfd); + } } /** - * This function will judge whether protocol family is registered + * This function will check SAL network interface device internet status. * - * @param family protocol family number - * - * @return 1: protocol family is registered - * 0: protocol family is not registered + * @param netdev the network interface device to check */ -rt_bool_t sal_proto_family_is_registered(int family) +int sal_check_netdev_internet_up(struct netdev *netdev) { - int idx = 0; + /* workqueue for network connect */ + struct rt_delayed_work *net_work = RT_NULL; - RT_ASSERT(family > 0 && family < AF_MAX); + RT_ASSERT(netdev); - for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++) + net_work = (struct rt_delayed_work *)rt_calloc(1, sizeof(struct rt_delayed_work)); + if (net_work == RT_NULL) { - if (proto_families[idx].family == family && proto_families[idx].create) - { - return RT_TRUE; - } + LOG_W("No memory for network interface device(%s) delay work.", netdev->name); + return -1; } - return RT_FALSE; + rt_delayed_work_init(net_work, check_netdev_internet_up_work, (void *)netdev); + rt_work_submit(&(net_work->work), RT_TICK_PER_SECOND); + + return 0; } /** - * This function will get protocol family object by family number. + * This function will register TLS protocol to the global TLS protocol. * - * @param family protocol family number + * @param pt TLS protocol object * - * @return protocol family object + * @return 0: TLS protocol object register success */ -struct sal_proto_family *sal_proto_family_find(int family) +#ifdef SAL_USING_TLS +int sal_proto_tls_register(const struct sal_proto_tls *pt) { - 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]; - } - } + RT_ASSERT(pt); + proto_tls = (struct sal_proto_tls *) pt; - return RT_NULL; + return 0; } +#endif /** * This function will get sal socket object by sal socket descriptor. @@ -262,10 +316,7 @@ struct sal_socket *sal_get_socket(int socket) socket = socket - SAL_SOCKET_OFFSET; /* check socket structure valid or not */ - if (st->sockets[socket]->magic != SAL_SOCKET_MAGIC) - { - return RT_NULL; - } + RT_ASSERT(st->sockets[socket]->magic == SAL_SOCKET_MAGIC); return st->sockets[socket]; } @@ -297,33 +348,35 @@ static void sal_unlock(void) } /** - * This function will get protocol family structure by family type - * - * @param family protocol family + * This function will clean the netdev. * - * @return protocol family structure address + * @note please don't invoke it on ISR. */ -static struct sal_proto_family *get_proto_family(int family) +int sal_netdev_cleanup(struct netdev *netdev) { - int idx; + int idx = 0, find_dev; - for (idx = 0; idx < SAL_PROTO_FAMILIES_NUM; idx++) + do { - if (proto_families[idx].family == family && proto_families[idx].create) + find_dev = 0; + sal_lock(); + for (idx = 0; idx < socket_table.max_socket; idx++) { - return &proto_families[idx]; + if (socket_table.sockets[idx] && socket_table.sockets[idx]->netdev == netdev) + { + find_dev = 1; + break; + } } - } - /* 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) + sal_unlock(); + if (find_dev) { - return &proto_families[idx]; + rt_thread_mdelay(100); } } + while (find_dev); - return RT_NULL; + return 0; } /** @@ -337,13 +390,16 @@ static struct sal_proto_family *get_proto_family(int family) * @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 + * -3 : get network interface failed */ static int socket_init(int family, int type, int protocol, struct sal_socket **res) { + struct sal_socket *sock; struct sal_proto_family *pf; + struct netdev *netdv_def = netdev_default; + struct netdev *netdev = RT_NULL; + rt_bool_t flag = RT_FALSE; if (family < 0 || family > AF_MAX) { @@ -360,16 +416,28 @@ static int socket_init(int family, int type, int protocol, struct sal_socket **r sock->type = type; sock->protocol = protocol; - /* get socket protocol family object */ - if ((pf = get_proto_family(family)) == RT_NULL) + if (netdv_def && netdev_is_up(netdv_def)) { - return -3; + /* check default network interface device protocol family */ + pf = (struct sal_proto_family *) netdv_def->sal_user_data; + if (pf != RT_NULL && pf->skt_ops && (pf->family == family || pf->sec_family == family)) + { + sock->netdev = netdv_def; + flag = RT_TRUE; + } } - /* registered the current socket options */ - if (pf->create(sock, type, protocol) != 0) + if (flag == RT_FALSE) { - return -4; + /* get network interface device by protocol family */ + netdev = netdev_get_by_family(family); + if (netdev == RT_NULL) + { + LOG_E("not find network interface device by protocol family(%d).", family); + return -3; + } + + sock->netdev = netdev; } return 0; @@ -383,9 +451,9 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket) 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 */ @@ -424,7 +492,15 @@ static int socket_alloc(struct sal_socket_table *st, int f_socket) __result: return idx; +} +static void socket_free(struct sal_socket_table *st, int idx) +{ + struct sal_socket *sock; + + sock = st->sockets[idx]; + st->sockets[idx] = RT_NULL; + rt_free(sock); } static int socket_new(void) @@ -448,7 +524,7 @@ static int socket_new(void) sock = st->sockets[idx]; sock->socket = idx + SAL_SOCKET_OFFSET; sock->magic = SAL_SOCKET_MAGIC; - sock->ops = RT_NULL; + sock->netdev = RT_NULL; sock->user_data = RT_NULL; #ifdef SAL_USING_TLS sock->user_data_tls = RT_NULL; @@ -459,23 +535,42 @@ __result: return idx + SAL_SOCKET_OFFSET; } -int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) +static void socket_delete(int socket) { - int new_socket; struct sal_socket *sock; + struct sal_socket_table *st = &socket_table; + int idx; - sock = sal_get_socket(socket); - if (!sock) + idx = socket - SAL_SOCKET_OFFSET; + if (idx < 0 || idx >= (int) st->max_socket) { - return -1; + return; } + sal_lock(); + sock = sal_get_socket(socket); + RT_ASSERT(sock != RT_NULL); + sock->magic = 0; + sock->netdev = RT_NULL; + socket_free(st, idx); + sal_unlock(); +} - if (sock->ops->accept == RT_NULL) - { - return -RT_ENOSYS; - } +int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) +{ + int new_socket; + struct sal_socket *sock; + struct sal_proto_family *pf; + + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - new_socket = sock->ops->accept((int) sock->user_data, addr, addrlen); + /* check the network interface is up status */ + SAL_NETDEV_IS_UP(sock->netdev); + + /* check the network interface socket operations */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, accept); + + new_socket = pf->skt_ops->accept((int) sock->user_data, addr, addrlen); if (new_socket != -1) { int retval; @@ -484,23 +579,25 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) /* allocate a new socket structure and registered socket options */ new_sal_socket = socket_new(); - if (new_sal_socket < 0) + new_sock = sal_get_socket(new_sal_socket); + if (new_sock == RT_NULL) { - sock->ops->closesocket(new_socket); + pf->skt_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); + pf->skt_ops->closesocket(new_socket); rt_memset(new_sock, 0x00, sizeof(struct sal_socket)); + /* socket init failed, delete socket */ + socket_delete(new_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 */ + /* socket structure user_data used to store the acquired new socket */ new_sock->user_data = (void *) new_socket; return new_sal_socket; @@ -509,40 +606,87 @@ int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) return -1; } +static void sal_sockaddr_to_ipaddr(const struct sockaddr *name, ip_addr_t *local_ipaddr) +{ + const struct sockaddr_in *svr_addr = (const struct sockaddr_in *) name; + +#if NETDEV_IPV4 && NETDEV_IPV6 + local_ipaddr->u_addr.ip4.addr = svr_addr->sin_addr.s_addr; + local_ipaddr->type = IPADDR_TYPE_V4; +#elif NETDEV_IPV4 + local_ipaddr->addr = svr_addr->sin_addr.s_addr; +#elif NETDEV_IPV6 +#error "not only support IPV6" +#endif /* NETDEV_IPV4 && NETDEV_IPV6*/ +} + int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen) { struct sal_socket *sock; + struct sal_proto_family *pf; + ip_addr_t input_ipaddr; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + RT_ASSERT(name); + + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->bind == RT_NULL) + /* bind network interface by ip address */ + sal_sockaddr_to_ipaddr(name, &input_ipaddr); + + /* check input ipaddr is default netdev ipaddr */ + if (!ip_addr_isany_val(input_ipaddr)) { - return -RT_ENOSYS; + struct sal_proto_family *input_pf = RT_NULL, *local_pf = RT_NULL; + struct netdev *new_netdev = RT_NULL; + + new_netdev = netdev_get_by_ipaddr(&input_ipaddr); + if (new_netdev == RT_NULL) + { + return -1; + } + + /* get input and local ip address proto_family */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, local_pf, bind); + SAL_NETDEV_SOCKETOPS_VALID(new_netdev, input_pf, bind); + + /* check the network interface protocol family type */ + if (input_pf->family != local_pf->family) + { + int new_socket = -1; + + /* protocol family is different, close old socket and create new socket by input ip address */ + local_pf->skt_ops->closesocket(socket); + + new_socket = input_pf->skt_ops->socket(input_pf->family, sock->type, sock->protocol); + if (new_socket < 0) + { + return -1; + } + sock->netdev = new_netdev; + sock->user_data = (void *) new_socket; + } } - return sock->ops->bind((int) sock->user_data, name, namelen); + /* check and get protocol families by the network interface device */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, bind); + return pf->skt_ops->bind((int) sock->user_data, name, namelen); } int sal_shutdown(int socket, int how) { struct sal_socket *sock; + struct sal_proto_family *pf; + int error = 0; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->shutdown == RT_NULL) - { - return -RT_ENOSYS; - } + /* shutdown operation not need to check network interface status */ + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, shutdown); - if (sock->ops->shutdown((int) sock->user_data, how) == 0) + if (pf->skt_ops->shutdown((int) sock->user_data, how) == 0) { #ifdef SAL_USING_TLS if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket)) @@ -553,82 +697,69 @@ int sal_shutdown(int socket, int how) } } #endif - rt_free(sock); - socket_table.sockets[socket] = RT_NULL; - return 0; + error = 0; + } + else + { + error = -1; } - return -1; + + return error; } int sal_getpeername(int socket, struct sockaddr *name, socklen_t *namelen) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->getpeername == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getpeername); - return sock->ops->getpeername((int) sock->user_data, name, namelen); + return pf->skt_ops->getpeername((int) sock->user_data, name, namelen); } int sal_getsockname(int socket, struct sockaddr *name, socklen_t *namelen) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->getsockname == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockname); - return sock->ops->getsockname((int) sock->user_data, name, namelen); + return pf->skt_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; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->getsockopt == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, getsockopt); - return sock->ops->getsockopt((int) sock->user_data, level, optname, optval, optlen); + return pf->skt_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; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->setsockopt == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, setsockopt); #ifdef SAL_USING_TLS if (level == SOL_TLS) @@ -659,30 +790,28 @@ int sal_setsockopt(int socket, int level, int optname, const void *optval, sockl } else { - return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen); + return pf->skt_ops->setsockopt((int) sock->user_data, level, optname, optval, optlen); } #else - return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen); + return pf->skt_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; + struct sal_proto_family *pf; int ret; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->connect == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface is up status */ + SAL_NETDEV_IS_UP(sock->netdev); + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, connect); - ret = sock->ops->connect((int) sock->user_data, name, namelen); + ret = pf->skt_ops->connect((int) sock->user_data, name, namelen); #ifdef SAL_USING_TLS if (ret >= 0 && SAL_SOCKOPS_PROTO_TLS_VALID(sock, connect)) { @@ -690,7 +819,7 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) { return -1; } - + return ret; } #endif @@ -701,90 +830,82 @@ int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen) int sal_listen(int socket, int backlog) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->listen == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, listen); - return sock->ops->listen((int) sock->user_data, backlog); + return pf->skt_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 sockaddr *from, socklen_t *fromlen) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->recvfrom == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface is up status */ + SAL_NETDEV_IS_UP(sock->netdev); + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, recvfrom); #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); + return pf->skt_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); + return pf->skt_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) + const struct sockaddr *to, socklen_t tolen) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->sendto == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface is up status */ + SAL_NETDEV_IS_UP(sock->netdev); + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, sendto); #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); + return pf->skt_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); + return pf->skt_ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen); #endif } @@ -793,6 +914,7 @@ int sal_socket(int domain, int type, int protocol) int retval; int socket, proto_socket; struct sal_socket *sock; + struct sal_proto_family *pf; /* allocate a new socket and registered socket options */ socket = socket_new(); @@ -800,29 +922,37 @@ int sal_socket(int domain, int type, int protocol) { return -1; } + + /* get sal socket object by socket descriptor */ sock = sal_get_socket(socket); + if (sock == RT_NULL) + { + socket_delete(socket); + return -1; + } + /* Initialize sal socket object */ retval = socket_init(domain, type, protocol, &sock); if (retval < 0) { LOG_E("SAL socket protocol family input failed, return error %d.", retval); + socket_delete(socket); return -1; } - if (sock->ops->socket == RT_NULL) - { - return -RT_ENOSYS; - } + /* valid the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket); - proto_socket = sock->ops->socket(domain, type, protocol); + proto_socket = pf->skt_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); + sock->user_data_tls = proto_tls->ops->socket(socket); if (sock->user_data_tls == RT_NULL) { + socket_delete(socket); return -1; } } @@ -830,26 +960,24 @@ int sal_socket(int domain, int type, int protocol) sock->user_data = (void *) proto_socket; return sock->socket; } - + socket_delete(socket); return -1; } int sal_closesocket(int socket) { struct sal_socket *sock; + struct sal_proto_family *pf; + int error = 0; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->closesocket == RT_NULL) - { - return -RT_ENOSYS; - } + /* clsoesocket operation not need to vaild network interface status */ + /* valid the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, socket); - if (sock->ops->closesocket((int) sock->user_data) == 0) + if (pf->skt_ops->closesocket((int) sock->user_data) == 0) { #ifdef SAL_USING_TLS if (SAL_SOCKOPS_PROTO_TLS_VALID(sock, closesocket)) @@ -860,67 +988,68 @@ int sal_closesocket(int socket) } } #endif - rt_free(sock); - socket_table.sockets[socket] = RT_NULL; - return 0; + error = 0; + } + else + { + error = -1; } - return -1; + /* delete socket */ + socket_delete(socket); + + return error; } int sal_ioctlsocket(int socket, long cmd, void *arg) { struct sal_socket *sock; + struct sal_proto_family *pf; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->ioctlsocket == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, ioctlsocket); - return sock->ops->ioctlsocket((int) sock->user_data, cmd, arg); + return pf->skt_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; + struct sal_proto_family *pf; int socket = (int) file->data; - sock = sal_get_socket(socket); - if (!sock) - { - return -1; - } + /* get the socket object by socket descriptor */ + SAL_SOCKET_OBJ_GET(sock, socket); - if (sock->ops->poll == RT_NULL) - { - return -RT_ENOSYS; - } + /* check the network interface is up status */ + SAL_NETDEV_IS_UP(sock->netdev); + /* check the network interface socket opreation */ + SAL_NETDEV_SOCKETOPS_VALID(sock->netdev, pf, poll); - return sock->ops->poll(file, req); + return pf->skt_ops->poll(file, req); } #endif struct hostent *sal_gethostbyname(const char *name) { - int i; - struct hostent *hst; + struct netdev *netdev = netdev_default; + struct sal_proto_family *pf; - for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname)) { - if (proto_families[i].ops && proto_families[i].ops->gethostbyname) + return pf->netdb_ops->gethostbyname(name); + } + else + { + /* get the first network interface device with up status */ + netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP); + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname)) { - hst = proto_families[i].ops->gethostbyname(name); - if (hst != RT_NULL) - { - return hst; - } + return pf->netdb_ops->gethostbyname(name); } } @@ -928,19 +1057,22 @@ struct hostent *sal_gethostbyname(const char *name) } int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf, - size_t buflen, struct hostent **result, int *h_errnop) + size_t buflen, struct hostent **result, int *h_errnop) { - int i, res; + struct netdev *netdev = netdev_default; + struct sal_proto_family *pf; - for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname_r)) + { + return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop); + } + else { - if (proto_families[i].ops && proto_families[i].ops->gethostbyname_r) + /* get the first network interface device with up status */ + netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP); + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, gethostbyname_r)) { - res = proto_families[i].ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop); - if (res == 0) - { - return res; - } + return pf->netdb_ops->gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } } @@ -948,21 +1080,24 @@ int sal_gethostbyname_r(const char *name, struct hostent *ret, char *buf, } int sal_getaddrinfo(const char *nodename, - const char *servname, - const struct addrinfo *hints, - struct addrinfo **res) + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) { - int i, ret; + struct netdev *netdev = netdev_default; + struct sal_proto_family *pf; - for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, getaddrinfo)) + { + return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res); + } + else { - if (proto_families[i].ops && proto_families[i].ops->getaddrinfo) + /* get the first network interface device with up status */ + netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP); + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, getaddrinfo)) { - ret = proto_families[i].ops->getaddrinfo(nodename, servname, hints, res); - if (ret == 0) - { - return ret; - } + return pf->netdb_ops->getaddrinfo(nodename, servname, hints, res); } } @@ -971,14 +1106,21 @@ int sal_getaddrinfo(const char *nodename, void sal_freeaddrinfo(struct addrinfo *ai) { - int i; + struct netdev *netdev = netdev_default; + struct sal_proto_family *pf; - for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, freeaddrinfo)) { - if (proto_families[i].ops && proto_families[i].ops->freeaddrinfo) + pf->netdb_ops->freeaddrinfo(ai); + } + else + { + /* get the first network interface device with up status */ + netdev = netdev_get_first_by_flags(NETDEV_FLAG_UP); + if (SAL_NETDEV_NETDBOPS_VALID(netdev, pf, freeaddrinfo)) { - proto_families[i].ops->freeaddrinfo(ai); - return; + pf->netdb_ops->freeaddrinfo(ai); } } } + |
