diff --git a/components/dfs/Kconfig b/components/dfs/Kconfig index 87b346026d..0ec3ad7464 100644 --- a/components/dfs/Kconfig +++ b/components/dfs/Kconfig @@ -28,7 +28,7 @@ if RT_USING_DFS config RT_USING_DFS_ELMFAT bool "Enable elm-chan fatfs" - default y + default n help FatFs is a generic FAT/exFAT file system module for small embedded systems. @@ -95,14 +95,6 @@ if RT_USING_DFS bool "Using devfs for device objects" default y - config RT_USING_DFS_NET - bool "Enable BSD socket operated by file system API" - select RT_USING_LWIP - select RT_USING_POSIX - default n - help - Let BSD socket operated by file system API, such as read/write and involveed in select/poll POSIX APIs. - config RT_USING_DFS_ROMFS bool "Enable ReadOnly file system on flash" default n diff --git a/components/dfs/filesystems/net/SConscript b/components/dfs/filesystems/net/SConscript deleted file mode 100644 index 0b5e45c090..0000000000 --- a/components/dfs/filesystems/net/SConscript +++ /dev/null @@ -1,17 +0,0 @@ -# RT-Thread building script for component - -from building import * - -cwd = GetCurrentDir() -src = Glob('*.c') -CPPPATH = [cwd] - -if not GetDepend('HAVE_SYS_SELECT_H'): - CPPPATH += [cwd + '/select'] - -if not GetDepend('HAVE_SYS_SOCKET_H'): - CPPPATH += [cwd + '/socket'] - -group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_NET'], CPPPATH = CPPPATH) - -Return('group') diff --git a/components/dfs/filesystems/net/net_sockets.c b/components/dfs/filesystems/net/net_sockets.c deleted file mode 100644 index 5e598c331a..0000000000 --- a/components/dfs/filesystems/net/net_sockets.c +++ /dev/null @@ -1,362 +0,0 @@ -/* - * File : lwip_sockets.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Change Logs: - * Date Author Notes - * 2015-02-17 Bernard First version - */ - -#include -#include -#include -#include - -#include "dfs_net.h" - -static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) -{ - int s; - struct lwip_sock *sock; - uint32_t event = 0; - SYS_ARCH_DECL_PROTECT(lev); - - LWIP_UNUSED_ARG(len); - - /* Get socket */ - if (conn) - { - s = conn->socket; - if (s < 0) - { - /* Data comes in right away after an accept, even though - * the server task might not have created a new socket yet. - * Just count down (or up) if that's the case and we - * will use the data later. Note that only receive events - * can happen before the new socket is set up. */ - SYS_ARCH_PROTECT(lev); - if (conn->socket < 0) - { - if (evt == NETCONN_EVT_RCVPLUS) - { - conn->socket--; - } - SYS_ARCH_UNPROTECT(lev); - return; - } - s = conn->socket; - SYS_ARCH_UNPROTECT(lev); - } - - sock = lwip_tryget_socket(s); - if (!sock) - { - return; - } - } - else - { - return; - } - - SYS_ARCH_PROTECT(lev); - /* Set event as required */ - switch (evt) - { - case NETCONN_EVT_RCVPLUS: - sock->rcvevent++; - break; - case NETCONN_EVT_RCVMINUS: - sock->rcvevent--; - break; - case NETCONN_EVT_SENDPLUS: - sock->sendevent = 1; - break; - case NETCONN_EVT_SENDMINUS: - sock->sendevent = 0; - break; - case NETCONN_EVT_ERROR: - sock->errevent = 1; - break; - default: - LWIP_ASSERT("unknown event", 0); - break; - } - - if (sock->lastdata || sock->rcvevent > 0) event |= POLLIN; - if (sock->sendevent) event |= POLLOUT; - if (sock->errevent) event |= POLLERR; - - SYS_ARCH_UNPROTECT(lev); - - if (event) - { - rt_wqueue_wakeup(&sock->wait_head, (void*)event); - } -} - -int accept(int s, struct sockaddr *addr, socklen_t *addrlen) -{ - int new_client = -1; - int sock = dfs_net_getsocket(s); - - new_client = lwip_accept(sock, addr, addrlen); - if (new_client != -1) - { - /* this is a new socket, create it in file system fd */ - int fd; - struct dfs_fd *d; - struct lwip_sock *lwsock; - - /* allocate a fd */ - fd = fd_new(); - if (fd < 0) - { - rt_set_errno(-ENOMEM); - lwip_close(sock); - - return -1; - } - d = fd_get(fd); - - /* this is a socket fd */ - d->type = FT_SOCKET; - d->path = RT_NULL; - - d->fops = dfs_net_get_fops(); - /* initialize wait head */ - lwsock = lwip_tryget_socket(new_client); - rt_wqueue_init(&(lwsock->wait_head)); - - d->flags = O_RDWR; /* set flags as read and write */ - d->size = 0; - d->pos = 0; - - /* set socket to the data of dfs_fd */ - d->data = (void *) new_client; - - /* release the ref-count of fd */ - fd_put(d); - - return fd; - } - - return new_client; -} -RTM_EXPORT(accept); - -int bind(int s, const struct sockaddr *name, socklen_t namelen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_bind(sock, name, namelen); -} -RTM_EXPORT(bind); - -int shutdown(int s, int how) -{ - int sock; - struct dfs_fd *d; - - d = fd_get(s); - if (d == RT_NULL) - { - rt_set_errno(-EBADF); - - return -1; - } - - sock = dfs_net_getsocket(s); - if (lwip_shutdown(sock, how) == 0) - { - /* socket has been closed, delete it from file system fd */ - fd_put(d); - fd_put(d); - - return 0; - } - - return -1; -} -RTM_EXPORT(shutdown); - -int getpeername(int s, struct sockaddr *name, socklen_t *namelen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_getpeername(sock, name, namelen); -} -RTM_EXPORT(getpeername); - -int getsockname(int s, struct sockaddr *name, socklen_t *namelen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_getsockname(sock, name, namelen); -} -RTM_EXPORT(getsockname); - -int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_getsockopt(sock, level, optname, optval, optlen); -} -RTM_EXPORT(getsockopt); - -int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) -{ - int sock = dfs_net_getsocket(s); - -#if LWIP_VERSION_MAJOR < 2U -#error "Your lwIP version is not supported. Please using lwIP 2.0.0+." -#endif - - return lwip_setsockopt(sock, level, optname, optval, optlen); -} -RTM_EXPORT(setsockopt); - -int connect(int s, const struct sockaddr *name, socklen_t namelen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_connect(sock, name, namelen); -} -RTM_EXPORT(connect); - -int listen(int s, int backlog) -{ - int sock = dfs_net_getsocket(s); - - return lwip_listen(sock, backlog); -} -RTM_EXPORT(listen); - -int recv(int s, void *mem, size_t len, int flags) -{ - int sock = dfs_net_getsocket(s); - - return lwip_recv(sock, mem, len, flags); -} -RTM_EXPORT(recv); - -int recvfrom(int s, void *mem, size_t len, int flags, - struct sockaddr *from, socklen_t *fromlen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_recvfrom(sock, mem, len, flags, from, fromlen); -} -RTM_EXPORT(recvfrom); - -int send(int s, const void *dataptr, size_t size, int flags) -{ - int sock = dfs_net_getsocket(s); - - return lwip_send(sock, dataptr, size, flags); -} -RTM_EXPORT(send); - -int sendto(int s, const void *dataptr, size_t size, int flags, - const struct sockaddr *to, socklen_t tolen) -{ - int sock = dfs_net_getsocket(s); - - return lwip_sendto(sock, dataptr, size, flags, to, tolen); -} -RTM_EXPORT(sendto); - -int socket(int domain, int type, int protocol) -{ - /* create a BSD socket */ - int fd; - int sock; - struct dfs_fd *d; - struct lwip_sock *lwsock; - - /* allocate a fd */ - fd = fd_new(); - if (fd < 0) - { - rt_set_errno(-ENOMEM); - - return -1; - } - d = fd_get(fd); - - /* create socket in lwip and then put it to the dfs_fd */ - sock = lwip_socket(domain, type, protocol); - if (sock >= 0) - { - /* this is a socket fd */ - d->type = FT_SOCKET; - d->path = NULL; - - d->fops = dfs_net_get_fops(); - - d->flags = O_RDWR; /* set flags as read and write */ - d->size = 0; - d->pos = 0; - - /* set socket to the data of dfs_fd */ - d->data = (void *) sock; - - lwsock = lwip_tryget_socket(sock); - rt_wqueue_init(&(lwsock->wait_head)); - lwsock->conn->callback = event_callback; - } - else - { - /* release fd */ - fd_put(d); - fd_put(d); - - rt_set_errno(-ENOMEM); - - return -1; - } - - /* release the ref-count of fd */ - fd_put(d); - - return fd; -} -RTM_EXPORT(socket); - -int closesocket(int s) -{ - int sock = dfs_net_getsocket(s); - struct dfs_fd *d; - - d = fd_get(s); - - /* socket has been closed, delete it from file system fd */ - fd_put(d); - fd_put(d); - - return lwip_close(sock); -} -RTM_EXPORT(closesocket); - -int ioctlsocket(int s, long cmd, void *arg) -{ - int sock = dfs_net_getsocket(s); - - return lwip_ioctl(sock, cmd, arg); -} -RTM_EXPORT(ioctlsocket); diff --git a/components/net/Kconfig b/components/net/Kconfig index 620d831c03..d2191af2e6 100644 --- a/components/net/Kconfig +++ b/components/net/Kconfig @@ -1,4 +1,44 @@ -menu "Network stack" +menu "Network" + +menu "Socket abstraction layer" + +config RT_USING_SAL + bool "Enable socket abstraction layer" + default n + select RT_USING_DFS + + if RT_USING_SAL + + menu "protocol stack implement" + + config SAL_USING_LWIP + bool "Support lwIP stack" + default y if RT_USING_LWIP + default n + depends on RT_USING_LWIP + + config SAL_USING_AT + bool "Support AT Commands stack" + default y if RT_USING_AT_SOCKET + default n + depends on RT_USING_AT_SOCKET + endmenu + + config SAL_USING_POSIX + bool "Enable BSD socket operated by file system API" + select RT_USING_LIBC + select RT_USING_POSIX + default n + help + Let BSD socket operated by file system API, such as read/write and involveed in select/poll POSIX APIs. + + config SAL_PROTO_FAMILIES_NUM + int "the number of protocol family" + default 4 + + endif + +endmenu menu "light weight TCP/IP stack" config RT_USING_LWIP @@ -227,7 +267,6 @@ config LWIP_USING_DHCPD default 1.1.1.1 endif endif - endif diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h index f07e9d51f5..55a123ec6a 100644 --- a/components/net/lwip-1.4.1/src/lwipopts.h +++ b/components/net/lwip-1.4.1/src/lwipopts.h @@ -371,7 +371,7 @@ * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. * (only used if you use sockets.c) */ -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX #define LWIP_COMPAT_SOCKETS 0 #else #ifndef LWIP_COMPAT_SOCKETS diff --git a/components/net/lwip-2.0.2/SConscript b/components/net/lwip-2.0.2/SConscript index 761681c57d..0fc63f4b26 100644 --- a/components/net/lwip-2.0.2/SConscript +++ b/components/net/lwip-2.0.2/SConscript @@ -67,7 +67,7 @@ path = [GetCurrentDir() + '/src', GetCurrentDir() + '/src/arch/include', GetCurrentDir() + '/src/include/netif'] -if not GetDepend('RT_USING_POSIX') or not GetDepend('RT_USING_DFS_NET'): +if not GetDepend('RT_USING_POSIX') or not GetDepend('SAL_USING_POSIX'): path += [GetCurrentDir() + '/src/include/posix'] if GetDepend(['RT_LWIP_SNMP']): diff --git a/components/net/lwip-2.0.2/src/api/sockets.c b/components/net/lwip-2.0.2/src/api/sockets.c index 1a99f48fa4..1d0fb0dd19 100644 --- a/components/net/lwip-2.0.2/src/api/sockets.c +++ b/components/net/lwip-2.0.2/src/api/sockets.c @@ -197,7 +197,7 @@ static void sockaddr_to_ipaddr_port(const struct sockaddr* sockaddr, ip_addr_t* #endif #include -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX #include #endif @@ -222,7 +222,7 @@ struct lwip_sock { /** counter of how many threads are waiting for this socket using select */ SELWAIT_T select_waiting; -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX rt_wqueue_t wait_head; #endif }; diff --git a/components/net/lwip-2.0.2/src/lwipopts.h b/components/net/lwip-2.0.2/src/lwipopts.h index 988b9668db..ce41a12136 100644 --- a/components/net/lwip-2.0.2/src/lwipopts.h +++ b/components/net/lwip-2.0.2/src/lwipopts.h @@ -405,7 +405,7 @@ * LWIP_COMPAT_SOCKETS==1: Enable BSD-style sockets functions names. * (only used if you use sockets.c) */ -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX #define LWIP_COMPAT_SOCKETS 0 #else #ifndef LWIP_COMPAT_SOCKETS diff --git a/components/net/sal_socket/SConscript b/components/net/sal_socket/SConscript new file mode 100644 index 0000000000..c1cdafab72 --- /dev/null +++ b/components/net/sal_socket/SConscript @@ -0,0 +1,31 @@ +# RT-Thread building script for component + +from building import * + +cwd = GetCurrentDir() + +src = Glob('src/*.c') +src += Glob('socket/*.c') + +CPPPATH = [cwd + '/include'] +CPPPATH += [cwd + '/include/dfs_net'] +CPPPATH += [cwd + '/include/socket'] + +if GetDepend('SAL_USING_LWIP'): + src += Glob('impl/af_inet_lwip.c') + +if GetDepend('SAL_USING_AT'): + src += Glob('impl/af_inet_at.c') + +if GetDepend('SAL_USING_POSIX'): + src += Glob('dfs_net/*.c') + + if not GetDepend('HAVE_SYS_SELECT_H'): + CPPPATH += [cwd + '/include/dfs_net/sys_select'] + + if not GetDepend('HAVE_SYS_SOCKET_H'): + CPPPATH += [cwd + '/include/socket/sys_socket'] + +group = DefineGroup('SAL', src, depend = ['RT_USING_SAL'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/dfs/filesystems/net/dfs_net.c b/components/net/sal_socket/dfs_net/dfs_net.c similarity index 60% rename from components/dfs/filesystems/net/dfs_net.c rename to components/net/sal_socket/dfs_net/dfs_net.c index 67f8fe8a7f..ee9b685f8c 100644 --- a/components/dfs/filesystems/net/dfs_net.c +++ b/components/net/sal_socket/dfs_net/dfs_net.c @@ -1,7 +1,7 @@ /* * File : dfs_net.c * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015-2016, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,33 +22,29 @@ * 2015-02-17 Bernard First version * 2016-05-07 Bernard Rename dfs_lwip to dfs_net * 2018-03-09 Bernard Fix the last data issue in poll. + * 2018-05-24 ChenYong Add socket abstraction layer */ #include + #include -#include -#include -#include +#include -#include #include -#include -#include "dfs_net.h" - int dfs_net_getsocket(int fd) { - int sock; + int socket; struct dfs_fd *_dfs_fd; _dfs_fd = fd_get(fd); if (_dfs_fd == NULL) return -1; - if (_dfs_fd->type != FT_SOCKET) sock = -1; - else sock = (int)_dfs_fd->data; + if (_dfs_fd->type != FT_SOCKET) socket = -1; + else socket = (int)_dfs_fd->data; fd_put(_dfs_fd); /* put this dfs fd */ - return sock; + return socket; } static int dfs_net_ioctl(struct dfs_fd* file, int cmd, void* args) @@ -58,69 +54,30 @@ static int dfs_net_ioctl(struct dfs_fd* file, int cmd, void* args) static int dfs_net_read(struct dfs_fd* file, void *buf, size_t count) { - int sock; + int socket = (int) file->data; - sock = (int)file->data; - count = lwip_read(sock, buf, count); - - return count; + return sal_recvfrom(socket, buf, count, 0, NULL, NULL); } static int dfs_net_write(struct dfs_fd *file, const void *buf, size_t count) { - int sock; - - sock = (int)file->data; - count = lwip_write(sock, buf, count); + int socket = (int) file->data; - return count; + return sal_sendto(socket, buf, count, 0, NULL, 0); } static int dfs_net_close(struct dfs_fd* file) { - int sock; - int result; - - sock = (int)file->data; - result = lwip_close(sock); - - if (result == 0) return RT_EOK; - - return -result; + int socket = (int) file->data; + + return sal_closesocket(socket); } static int dfs_net_poll(struct dfs_fd *file, struct rt_pollreq *req) { - int sfd; - int mask = 0; - struct lwip_sock *sock; + extern int sal_poll(struct dfs_fd *file, struct rt_pollreq *req); - sfd = (int)file->data; - - sock = lwip_tryget_socket(sfd); - if (sock != NULL) - { - rt_base_t level; - - rt_poll_add(&sock->wait_head, req); - - level = rt_hw_interrupt_disable(); - if (sock->lastdata || sock->rcvevent) - { - mask |= POLLIN; - } - if (sock->sendevent) - { - mask |= POLLOUT; - } - if (sock->errevent) - { - mask |= POLLERR; - } - rt_hw_interrupt_enable(level); - } - - return mask; + return sal_poll(file, req); } const struct dfs_file_ops _net_fops = @@ -140,4 +97,3 @@ const struct dfs_file_ops *dfs_net_get_fops(void) { return &_net_fops; } - diff --git a/components/net/sal_socket/impl/af_inet_at.c b/components/net/sal_socket/impl/af_inet_at.c new file mode 100644 index 0000000000..8ddb236e84 --- /dev/null +++ b/components/net/sal_socket/impl/af_inet_at.c @@ -0,0 +1,125 @@ +/* + * File : af_inet_at.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-06-06 ChenYong First version + */ + +#include +#include + +#include + +#ifdef SAL_USING_POSIX +#include +#endif + +#ifdef SAL_USING_POSIX +static int at_poll(struct dfs_fd *file, struct rt_pollreq *req) +{ + int mask = 0; + struct at_socket *sock; + struct sal_socket *sal_sock; + + sal_sock = sal_get_socket((int) file->data); + if(!sal_sock) + { + return -1; + } + + sock = at_get_socket((int)sal_sock->user_data); + if (sock != NULL) + { + rt_base_t level; + + rt_poll_add(&sock->wait_head, req); + + level = rt_hw_interrupt_disable(); + if (sock->rcvevent) + { + mask |= POLLIN; + } + if (sock->sendevent) + { + mask |= POLLOUT; + } + if (sock->errevent) + { + mask |= POLLERR; + } + rt_hw_interrupt_enable(level); + } + + return mask; +} +#endif + +static const struct proto_ops at_inet_stream_ops = +{ + at_socket, + at_closesocket, + at_bind, + NULL, + at_connect, + NULL, + at_sendto, + at_recvfrom, + at_getsockopt, + at_setsockopt, + at_shutdown, + NULL, + NULL, + NULL, + +#ifdef SAL_USING_POSIX + at_poll, +#else + NULL, +#endif /* SAL_USING_POSIX */ +}; + +static int at_create(struct sal_socket *socket, int type, int protocol) +{ + RT_ASSERT(socket); + + //TODO Check type & protocol + + socket->ops = &at_inet_stream_ops; + + return 0; +} + +static const struct proto_family at_inet_family_ops = { + AF_AT, + AF_INET, + at_create, + at_gethostbyname, + NULL, + at_freeaddrinfo, + at_getaddrinfo, +}; + +int at_inet_init(void) +{ + sal_proto_family_register(&at_inet_family_ops); + + return 0; +} +INIT_COMPONENT_EXPORT(at_inet_init); diff --git a/components/net/sal_socket/impl/af_inet_lwip.c b/components/net/sal_socket/impl/af_inet_lwip.c new file mode 100644 index 0000000000..deb9239bf4 --- /dev/null +++ b/components/net/sal_socket/impl/af_inet_lwip.c @@ -0,0 +1,302 @@ +/* + * File : af_inet_lwip.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-17 ChenYong First version + */ + +#include + +#include +#include +#include +#include + +#ifdef SAL_USING_POSIX +#include +#endif + +#include + +#if LWIP_VERSION < 0x2000000 +#define SELWAIT_T int +#else +#ifndef SELWAIT_T +#define SELWAIT_T u8_t +#endif +#endif + +/* + * Re-define lwip socket + * + * NOTE: please make sure the definitions same in lwip::net_socket.c + */ +struct lwip_sock { + /** sockets currently are built on netconns, each socket has one netconn */ + struct netconn *conn; + /** data that was left from the previous read */ + void *lastdata; + /** offset in the data that was left from the previous read */ + u16_t lastoffset; + /** number of times data was received, set by event_callback(), + tested by the receive and select functions */ + s16_t rcvevent; + /** number of times data was ACKed (free send buffer), set by event_callback(), + tested by select */ + u16_t sendevent; + /** error happened for this socket, set by event_callback(), tested by select */ + u16_t errevent; + /** last error that occurred on this socket */ +#if LWIP_VERSION < 0x2000000 + int err; +#else + u8_t err; +#endif + /** counter of how many threads are waiting for this socket using select */ + SELWAIT_T select_waiting; + +#ifdef SAL_USING_POSIX + rt_wqueue_t wait_head; +#endif +}; + +extern struct lwip_sock *lwip_tryget_socket(int s); + +static void event_callback(struct netconn *conn, enum netconn_evt evt, u16_t len) +{ + int s; + struct lwip_sock *sock; + uint32_t event = 0; + SYS_ARCH_DECL_PROTECT(lev); + + LWIP_UNUSED_ARG(len); + + /* Get socket */ + if (conn) + { + s = conn->socket; + if (s < 0) + { + /* Data comes in right away after an accept, even though + * the server task might not have created a new socket yet. + * Just count down (or up) if that's the case and we + * will use the data later. Note that only receive events + * can happen before the new socket is set up. */ + SYS_ARCH_PROTECT(lev); + if (conn->socket < 0) + { + if (evt == NETCONN_EVT_RCVPLUS) + { + conn->socket--; + } + SYS_ARCH_UNPROTECT(lev); + return; + } + s = conn->socket; + SYS_ARCH_UNPROTECT(lev); + } + + sock = lwip_tryget_socket(s); + if (!sock) + { + return; + } + } + else + { + return; + } + + SYS_ARCH_PROTECT(lev); + /* Set event as required */ + switch (evt) + { + case NETCONN_EVT_RCVPLUS: + sock->rcvevent++; + break; + case NETCONN_EVT_RCVMINUS: + sock->rcvevent--; + break; + case NETCONN_EVT_SENDPLUS: + sock->sendevent = 1; + break; + case NETCONN_EVT_SENDMINUS: + sock->sendevent = 0; + break; + case NETCONN_EVT_ERROR: + sock->errevent = 1; + break; + default: + LWIP_ASSERT("unknown event", 0); + break; + } + + if (sock->lastdata || sock->rcvevent > 0) + event |= POLLIN; + if (sock->sendevent) + event |= POLLOUT; + if (sock->errevent) + event |= POLLERR; + + SYS_ARCH_UNPROTECT(lev); + + if (event) + { +#ifdef SAL_USING_POSIX + rt_wqueue_wakeup(&sock->wait_head, (void*) event); +#endif + } +} + +static int inet_socket(int domain, int type, int protocol) +{ + int socket; + + socket = lwip_socket(domain, type, protocol); + if (socket >= 0) + { + struct lwip_sock *lwsock; + + lwsock = lwip_tryget_socket(socket); + lwsock->conn->callback = event_callback; + +#ifdef SAL_USING_POSIX + rt_wqueue_init(&lwsock->wait_head); +#endif + + } + + return socket; +} + +static int inet_accept(int socket, struct sockaddr *addr, socklen_t *addrlen) +{ + int new_socket; + + new_socket = lwip_accept(socket, addr, addrlen); + if (new_socket >= 0) + { + struct lwip_sock *lwsock; + + lwsock = lwip_tryget_socket(new_socket); + +#ifdef SAL_USING_POSIX + rt_wqueue_init(&lwsock->wait_head); +#endif + } + + return new_socket; +} + +static int inet_getsockname(int socket, struct sockaddr *name, socklen_t *namelen) +{ +#if LWIP_VERSION_MAJOR < 2U + rt_kprintf("ERROR: Your lwIP version is not supported. Please using lwIP 2.0.0+.\n"); + RT_ASSERT(LWIP_VERSION_MAJOR >= 2U); +#endif + + return lwip_getsockname(socket, name, namelen); +} + +static int inet_poll(struct dfs_fd *file, struct rt_pollreq *req) +{ + int mask = 0; + struct lwip_sock *sock; + struct sal_socket *sal_sock; + + sal_sock = sal_get_socket((int) file->data); + if(!sal_sock) + { + return -1; + } + + sock = lwip_tryget_socket((int)sal_sock->user_data); + if (sock != NULL) + { + rt_base_t level; + + rt_poll_add(&sock->wait_head, req); + + level = rt_hw_interrupt_disable(); + if (sock->lastdata || sock->rcvevent) + { + mask |= POLLIN; + } + if (sock->sendevent) + { + mask |= POLLOUT; + } + if (sock->errevent) + { + mask |= POLLERR; + } + rt_hw_interrupt_enable(level); + } + + return mask; +} + +static const struct proto_ops lwip_inet_stream_ops = { + inet_socket, + lwip_close, + lwip_bind, + lwip_listen, + lwip_connect, + inet_accept, + lwip_sendto, + lwip_recvfrom, + lwip_getsockopt, + //TODO fix on 1.4.1 + lwip_setsockopt, + lwip_shutdown, + lwip_getpeername, + inet_getsockname, + lwip_ioctl, + inet_poll, +}; + +static int inet_create(struct sal_socket *socket, int type, int protocol) +{ + RT_ASSERT(socket); + + //TODO Check type & protocol + + socket->ops = &lwip_inet_stream_ops; + + return 0; +} + +static const struct proto_family lwip_inet_family_ops = { + AF_INET, + AF_INET, + inet_create, + lwip_gethostbyname, + lwip_gethostbyname_r, + lwip_freeaddrinfo, + lwip_getaddrinfo, +}; + +int lwip_inet_init(void) +{ + sal_proto_family_register(&lwip_inet_family_ops); + + return 0; +} +INIT_COMPONENT_EXPORT(lwip_inet_init); diff --git a/components/dfs/filesystems/net/dfs_net.h b/components/net/sal_socket/include/dfs_net/dfs_net.h similarity index 97% rename from components/dfs/filesystems/net/dfs_net.h rename to components/net/sal_socket/include/dfs_net/dfs_net.h index 647e6b5f3a..2a21fe3858 100644 --- a/components/dfs/filesystems/net/dfs_net.h +++ b/components/net/sal_socket/include/dfs_net/dfs_net.h @@ -30,7 +30,7 @@ extern "C" { #endif -#include +#include const struct dfs_file_ops* dfs_net_get_fops(void); int dfs_net_getsocket(int fd); diff --git a/components/dfs/filesystems/net/select/sys/select.h b/components/net/sal_socket/include/dfs_net/sys_select/sys/select.h similarity index 94% rename from components/dfs/filesystems/net/select/sys/select.h rename to components/net/sal_socket/include/dfs_net/sys_select/sys/select.h index ce91583904..c2e2d54d3a 100644 --- a/components/dfs/filesystems/net/select/sys/select.h +++ b/components/net/sal_socket/include/dfs_net/sys_select/sys/select.h @@ -1,7 +1,7 @@ /* * File : select.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/components/net/sal_socket/include/sal.h b/components/net/sal_socket/include/sal.h new file mode 100644 index 0000000000..8a9dd61b67 --- /dev/null +++ b/components/net/sal_socket/include/sal.h @@ -0,0 +1,101 @@ +/* + * File : sal.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-17 ChenYong First version + */ + +#ifndef SAL_H__ +#define SAL_H__ + +#include +#include + +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef uint32_t socklen_t; +#endif + +/* sal socket magic word */ +#define SAL_SOCKET_MAGIC 0x5A10 + +/* The maximum number of sockets structure */ +#define SAL_SOCKETS_NUM DFS_FD_MAX + +/* The maximum number of protocol families */ +#ifndef SAL_PROTO_FAMILIES_NUM +#define SAL_PROTO_FAMILIES_NUM 4 +#endif + +/* sal socket offset */ +#ifndef SAL_SOCKET_OFFSET +#define SAL_SOCKET_OFFSET 0 +#endif + +struct proto_ops +{ + int (*socket) (int domain, int type, int protocol); + int (*closesocket)(int s); + int (*bind) (int s, const struct sockaddr *name, socklen_t namelen); + int (*listen) (int s, int backlog); + int (*connect) (int s, const struct sockaddr *name, socklen_t namelen); + int (*accept) (int s, struct sockaddr *addr, socklen_t *addrlen); + int (*sendto) (int s, const void *data, size_t size, int flags, const struct sockaddr *to, socklen_t tolen); + int (*recvfrom) (int s, void *mem, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); + int (*getsockopt) (int s, int level, int optname, void *optval, socklen_t *optlen); + int (*setsockopt) (int s, int level, int optname, const void *optval, socklen_t optlen); + int (*shutdown) (int s, int how); + int (*getpeername)(int s, struct sockaddr *name, socklen_t *namelen); + int (*getsockname)(int s, struct sockaddr *name, socklen_t *namelen); + int (*ioctlsocket)(int s, long cmd, void *arg); + int (*poll) (struct dfs_fd *file, struct rt_pollreq *req); +}; + +struct sal_socket +{ + uint32_t magic; /* sal socket magic word */ + + int socket; /* sal socket descriptor */ + int domain; + int type; + int protocol; + + const struct proto_ops *ops; /* socket options */ + void *user_data; /* specific sal socket data */ +}; + +struct proto_family +{ + int family; /* primary protocol families type*/ + int sec_family; /* secondary protocol families type*/ + int (*create)(struct sal_socket *sal_socket, int type, int protocol); /* register socket options */ + + struct hostent* (*gethostbyname) (const char *name); + int (*gethostbyname_r)(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); + void (*freeaddrinfo) (struct addrinfo *ai); + int (*getaddrinfo) (const char *nodename, const char *servname, const struct addrinfo *hints, struct addrinfo **res); +}; + +/* SAL socket initialization */ +int sal_init(void); + +int sal_proto_family_register(const struct proto_family *pf); +struct sal_socket *sal_get_socket(int sock); + +#endif /* SAL_H__ */ diff --git a/components/net/sal_socket/include/sal_ipaddr.h b/components/net/sal_socket/include/sal_ipaddr.h new file mode 100644 index 0000000000..814d1d16e9 --- /dev/null +++ b/components/net/sal_socket/include/sal_ipaddr.h @@ -0,0 +1,138 @@ +/* + * File : sal_ipaddr.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-18 ChenYong First version + */ +#ifndef SAL_IPADDR_H__ +#define SAL_IPADDR_H__ + +#include "sal_type.h" + +/** IPv4 only: set the IP address given as an u32_t */ +#define ip4_addr_set_u32(dest_ipaddr, src_u32) ((dest_ipaddr)->addr = (src_u32)) +/** IPv4 only: get the IP address as an u32_t */ +#define ip4_addr_get_u32(src_ipaddr) ((src_ipaddr)->addr) + +#define IP4ADDR_STRLEN_MAX 16 + +/* These macros should be calculated by the preprocessor and are used + with compile-time constants only (so that there is no little-endian + overhead at runtime). */ +#define PP_HTONS(x) ((((x) & 0x00ffUL) << 8) | (((x) & 0xff00UL) >> 8)) +#define PP_NTOHS(x) PP_HTONS(x) +#define PP_HTONL(x) ((((x) & 0x000000ffUL) << 24) | \ + (((x) & 0x0000ff00UL) << 8) | \ + (((x) & 0x00ff0000UL) >> 8) | \ + (((x) & 0xff000000UL) >> 24)) +#define PP_NTOHL(x) PP_HTONL(x) + +#define htons(x) (u16_t)PP_HTONS(x) +#define ntohs(x) (u16_t)PP_NTOHS(x) +#define htonl(x) (u32_t)PP_HTONL(x) +#define ntohl(x) (u32_t)PP_NTOHL(x) + +/* If your port already typedef's in_addr_t, define IN_ADDR_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_addr_t) && !defined(IN_ADDR_T_DEFINED) +typedef u32_t in_addr_t; +#endif + +struct in_addr +{ + in_addr_t s_addr; +}; + +struct in6_addr +{ + union + { + u32_t u32_addr[4]; + u8_t u8_addr[16]; + } un; +#define s6_addr un.u8_addr +}; + +enum sal_ip_addr_type +{ + /** IPv4 */ + IPADDR_TYPE_V4 = 0U, + /** IPv6 */ + IPADDR_TYPE_V6 = 6U, + /** IPv4+IPv6 ("dual-stack") */ + IPADDR_TYPE_ANY = 46U +}; + +typedef struct ip4_addr +{ + u32_t addr; +} ip4_addr_t; + +typedef struct ip6_addr +{ + u32_t addr[4]; +} ip6_addr_t; + +typedef struct _ip_addr +{ + union + { + ip6_addr_t ip6; + ip4_addr_t ip4; + } u_addr; + /** @ref sal_ip_addr_type */ + u8_t type; +} ip_addr_t; + +/** 255.255.255.255 */ +#define IPADDR_NONE ((u32_t)0xffffffffUL) +/** 127.0.0.1 */ +#define IPADDR_LOOPBACK ((u32_t)0x7f000001UL) +/** 0.0.0.0 */ +#define IPADDR_ANY ((u32_t)0x00000000UL) +/** 255.255.255.255 */ +#define IPADDR_BROADCAST ((u32_t)0xffffffffUL) + +/** 255.255.255.255 */ +#define INADDR_NONE IPADDR_NONE +/** 127.0.0.1 */ +#define INADDR_LOOPBACK IPADDR_LOOPBACK +/** 0.0.0.0 */ +#define INADDR_ANY IPADDR_ANY +/** 255.255.255.255 */ +#define INADDR_BROADCAST IPADDR_BROADCAST + +#define IPADDR_BROADCAST_STRING "255.255.255.255" + +in_addr_t sal_ipaddr_addr(const char *cp); +int sal_ip4addr_aton(const char *cp, ip4_addr_t *addr); +char *sal_ip4addr_ntoa(const ip4_addr_t *addr); +char *sal_ip4addr_ntoa_r(const ip4_addr_t *addr, char *buf, int buflen); + +#define inet_addr(cp) sal_ipaddr_addr(cp) +#define inet_aton(cp,addr) sal_ip4addr_aton(cp,(ip4_addr_t*)addr) +#define inet_ntoa(addr) sal_ip4addr_ntoa((const ip4_addr_t*)&(addr)) +#define inet_ntoa_r(addr, buf, buflen) sal_ip4addr_ntoa_r((const ip4_addr_t*)&(addr), buf, buflen) + +#ifdef __cplusplus +} +#endif + +#endif /* SAL_IPADDR_H__ */ diff --git a/components/net/sal_socket/include/sal_netdb.h b/components/net/sal_socket/include/sal_netdb.h new file mode 100644 index 0000000000..12f7abe6b7 --- /dev/null +++ b/components/net/sal_socket/include/sal_netdb.h @@ -0,0 +1,91 @@ +/* + * File : sal_netdb.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-24 ChenYong First version + */ +#ifndef SAL_NETDB_H__ +#define SAL_NETDB_H__ + +#include + +#define EAI_NONAME 200 +#define EAI_SERVICE 201 +#define EAI_FAIL 202 +#define EAI_MEMORY 203 +#define EAI_FAMILY 204 + +#define HOST_NOT_FOUND 210 +#define NO_DATA 211 +#define NO_RECOVERY 212 +#define TRY_AGAIN 213 + +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_NUMERICSERV 0x08 +#define AI_V4MAPPED 0x10 +#define AI_ALL 0x20 +#define AI_ADDRCONFIG 0x40 + +/* input flags for structure addrinfo */ +#define AI_PASSIVE 0x01 +#define AI_CANONNAME 0x02 +#define AI_NUMERICHOST 0x04 +#define AI_NUMERICSERV 0x08 +#define AI_V4MAPPED 0x10 +#define AI_ALL 0x20 +#define AI_ADDRCONFIG 0x40 + +#define DNS_MAX_NAME_LENGTH 256 + +struct hostent { + char *h_name; /* Official name of the host. */ + char **h_aliases; /* A pointer to an array of pointers to alternative host names, + terminated by a null pointer. */ + int h_addrtype; /* Address type. */ + int h_length; /* The length, in bytes, of the address. */ + char **h_addr_list; /* A pointer to an array of pointers to network addresses (in + network byte order) for the host, terminated by a null pointer. */ +#define h_addr h_addr_list[0] /* for backward compatibility */ +}; + +struct addrinfo { + int ai_flags; /* Input flags. */ + int ai_family; /* Address family of socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol of socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address of socket. */ + char *ai_canonname; /* Canonical name of service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; + +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); +void sal_freeaddrinfo(struct addrinfo *ai); +int sal_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res); + +#endif /* SAL_NETDB_H__ */ diff --git a/components/net/sal_socket/include/sal_socket.h b/components/net/sal_socket/include/sal_socket.h new file mode 100644 index 0000000000..0261561613 --- /dev/null +++ b/components/net/sal_socket/include/sal_socket.h @@ -0,0 +1,166 @@ +/* + * File : sal_socket.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-24 ChenYong First version + */ + +#ifndef SAL_SOCKET_H__ +#define SAL_SOCKET_H__ + +#include "sal_ipaddr.h" + +#if !defined(socklen_t) && !defined(SOCKLEN_T_DEFINED) +typedef uint32_t socklen_t; +#endif + +#if !defined(sa_family_t) && !defined(SA_FAMILY_T_DEFINED) +typedef uint8_t sa_family_t; +#endif + +/* If your port already typedef's in_port_t, define IN_PORT_T_DEFINED + to prevent this code from redefining it. */ +#if !defined(in_port_t) && !defined(IN_PORT_T_DEFINED) +typedef uint16_t in_port_t; +#endif + +/* Socket protocol types (TCP/UDP/RAW) */ +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define SOCK_RAW 3 + +#define SOCK_MAX (SOCK_RAW + 1) + +/* + * Option flags per-socket. These must match the SOF_ flags in ip.h (checked in init.c) + */ +#define SO_REUSEADDR 0x0004 /* Allow local address reuse */ +#define SO_KEEPALIVE 0x0008 /* keep connections alive */ +#define SO_BROADCAST 0x0020 /* permit to send and to receive broadcast messages (see IP_SOF_BROADCAST option) */ + +/* + * Additional options, not kept in so_options. + */ +#define SO_DEBUG 0x0001 /* Unimplemented: turn on debugging info recording */ +#define SO_ACCEPTCONN 0x0002 /* socket has had listen() */ +#define SO_DONTROUTE 0x0010 /* Unimplemented: just use interface addresses */ +#define SO_USELOOPBACK 0x0040 /* Unimplemented: bypass hardware when possible */ +#define SO_LINGER 0x0080 /* linger on close if data present */ +#define SO_DONTLINGER ((int)(~SO_LINGER)) +#define SO_OOBINLINE 0x0100 /* Unimplemented: leave received OOB data in line */ +#define SO_REUSEPORT 0x0200 /* Unimplemented: allow local address & port reuse */ +#define SO_SNDBUF 0x1001 /* Unimplemented: send buffer size */ +#define SO_RCVBUF 0x1002 /* receive buffer size */ +#define SO_SNDLOWAT 0x1003 /* Unimplemented: send low-water mark */ +#define SO_RCVLOWAT 0x1004 /* Unimplemented: receive low-water mark */ +#define SO_SNDTIMEO 0x1005 /* send timeout */ +#define SO_RCVTIMEO 0x1006 /* receive timeout */ +#define SO_ERROR 0x1007 /* get error status and clear */ +#define SO_TYPE 0x1008 /* get socket type */ +#define SO_CONTIMEO 0x1009 /* Unimplemented: connect timeout */ +#define SO_NO_CHECK 0x100a /* don't create UDP checksum */ + +/* + * Level number for (get/set)sockopt() to apply to socket itself. + */ +#define SOL_SOCKET 0xfff /* options for socket level */ + +#define AF_UNSPEC 0 +#define AF_INET 2 +#define AF_INET6 10 +#define AF_CAN 29 /* Controller Area Network */ +#define AF_AT 45 /* AT socket */ +#define PF_INET AF_INET +#define PF_INET6 AF_INET6 +#define PF_UNSPEC AF_UNSPEC +#define PF_CAN AF_CAN +#define PF_AT AF_AT + +#define AF_MAX (AF_AT + 1) /* For now.. */ + +#define IPPROTO_IP 0 +#define IPPROTO_ICMP 1 +#define IPPROTO_TCP 6 +#define IPPROTO_UDP 17 +#define IPPROTO_IPV6 41 +#define IPPROTO_ICMPV6 58 +#define IPPROTO_UDPLITE 136 +#define IPPROTO_RAW 255 + +/* Flags we can use with send and recv. */ +#define MSG_PEEK 0x01 /* Peeks at an incoming message */ +#define MSG_WAITALL 0x02 /* Unimplemented: Requests that the function block until the full amount of data requested can be returned */ +#define MSG_OOB 0x04 /* Unimplemented: Requests out-of-band data. The significance and semantics of out-of-band data are protocol-specific */ +#define MSG_DONTWAIT 0x08 /* Nonblocking i/o for this operation only */ +#define MSG_MORE 0x10 /* Sender will send more */ + +/* + * Options for level IPPROTO_TCP + */ +#define TCP_NODELAY 0x01 /* don't delay send to coalesce packets */ +#define TCP_KEEPALIVE 0x02 /* send KEEPALIVE probes when idle for pcb->keep_idle milliseconds */ +#define TCP_KEEPIDLE 0x03 /* set pcb->keep_idle - Same as TCP_KEEPALIVE, but use seconds for get/setsockopt */ +#define TCP_KEEPINTVL 0x04 /* set pcb->keep_intvl - Use seconds for get/setsockopt */ +#define TCP_KEEPCNT 0x05 /* set pcb->keep_cnt - Use number of probes sent for get/setsockopt */ + +struct sockaddr { + uint8_t sa_len; + sa_family_t sa_family; + char sa_data[14]; +}; + +/* members are in network byte order */ +struct sockaddr_in { + uint8_t sin_len; + sa_family_t sin_family; + in_port_t sin_port; + struct in_addr sin_addr; +#define SIN_ZERO_LEN 8 + char sin_zero[SIN_ZERO_LEN]; +}; + +struct sockaddr_storage { + uint8_t s2_len; + sa_family_t ss_family; + char s2_data1[2]; + uint32_t s2_data2[3]; +#if SAL_IPV6 + u32_t s2_data3[3]; +#endif /* SAL_IPV6 */ +}; + +int sal_accept(int socket, struct sockaddr *addr, socklen_t *addrlen); +int sal_bind(int socket, const struct sockaddr *name, socklen_t namelen); +int sal_shutdown(int socket, int how); +int sal_getpeername (int socket, struct sockaddr *name, socklen_t *namelen); +int sal_getsockname (int socket, struct sockaddr *name, socklen_t *namelen); +int sal_getsockopt (int socket, int level, int optname, void *optval, socklen_t *optlen); +int sal_setsockopt (int socket, int level, int optname, const void *optval, socklen_t optlen); +int sal_connect(int socket, const struct sockaddr *name, socklen_t namelen); +int sal_listen(int socket, int backlog); +int sal_recvfrom(int socket, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen); +int sal_sendto(int socket, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen); +int sal_socket(int domain, int type, int protocol); +int sal_closesocket(int socket); +int sal_ioctlsocket(int socket, long cmd, void *arg); + +#endif /* SAL_SOCKET_H__ */ diff --git a/components/net/sal_socket/include/sal_type.h b/components/net/sal_socket/include/sal_type.h new file mode 100644 index 0000000000..0446d5f4e1 --- /dev/null +++ b/components/net/sal_socket/include/sal_type.h @@ -0,0 +1,40 @@ +/* + * File : sal_type.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-17 ChenYong First version + */ + +#ifndef SAL_TYPE_H__ +#define SAL_TYPE_H__ + +#include +#include + +typedef int8_t err_t; +typedef uint8_t u8_t; +typedef int8_t s8_t; +typedef uint16_t u16_t; +typedef int16_t s16_t; +typedef uint32_t u32_t; +typedef int32_t s32_t; +typedef uintptr_t mem_ptr_t; + +#endif /* SAL_TYPE_H__ */ diff --git a/components/dfs/filesystems/net/arpa/inet.h b/components/net/sal_socket/include/socket/arpa/inet.h similarity index 92% rename from components/dfs/filesystems/net/arpa/inet.h rename to components/net/sal_socket/include/socket/arpa/inet.h index 395f3489ba..e7d856d434 100644 --- a/components/dfs/filesystems/net/arpa/inet.h +++ b/components/net/sal_socket/include/socket/arpa/inet.h @@ -1,7 +1,7 @@ /* * File : inet.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,6 @@ #ifndef INET_H__ #define INET_H__ -#include +#include #endif diff --git a/components/dfs/filesystems/net/netdb.h b/components/net/sal_socket/include/socket/netdb.h similarity index 90% rename from components/dfs/filesystems/net/netdb.h rename to components/net/sal_socket/include/socket/netdb.h index bf509c371a..c1ffbb826c 100644 --- a/components/dfs/filesystems/net/netdb.h +++ b/components/net/sal_socket/include/socket/netdb.h @@ -1,7 +1,7 @@ /* * File : netdb.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ * Change Logs: * Date Author Notes * 2015-02-17 Bernard First version + * 2108-05-24 ChenYong Add socket abstraction layer */ #ifndef NETDB_H__ @@ -29,7 +30,7 @@ extern "C" { #endif -#include +#include struct hostent *gethostbyname(const char *name); diff --git a/components/dfs/filesystems/net/netinet/in.h b/components/net/sal_socket/include/socket/netinet/in.h similarity index 92% rename from components/dfs/filesystems/net/netinet/in.h rename to components/net/sal_socket/include/socket/netinet/in.h index 24fe8b5409..d01a9b3f89 100644 --- a/components/dfs/filesystems/net/netinet/in.h +++ b/components/net/sal_socket/include/socket/netinet/in.h @@ -1,7 +1,7 @@ /* * File : in.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,7 +25,7 @@ #ifndef IN_H__ #define IN_H__ -#include +#include #ifndef IN6_IS_ADDR_MULTICAST #define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff) diff --git a/components/dfs/filesystems/net/netinet/tcp.h b/components/net/sal_socket/include/socket/netinet/tcp.h similarity index 92% rename from components/dfs/filesystems/net/netinet/tcp.h rename to components/net/sal_socket/include/socket/netinet/tcp.h index c157b0bb38..aafb0f15d0 100644 --- a/components/dfs/filesystems/net/netinet/tcp.h +++ b/components/net/sal_socket/include/socket/netinet/tcp.h @@ -1,7 +1,7 @@ /* * File : tcp.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,6 @@ #ifndef TCP_H__ #define TCP_H__ -#include +#include #endif diff --git a/components/dfs/filesystems/net/netinet/udp.h b/components/net/sal_socket/include/socket/netinet/udp.h similarity index 92% rename from components/dfs/filesystems/net/netinet/udp.h rename to components/net/sal_socket/include/socket/netinet/udp.h index 6eef3ee774..4b84755e68 100644 --- a/components/dfs/filesystems/net/netinet/udp.h +++ b/components/net/sal_socket/include/socket/netinet/udp.h @@ -1,7 +1,7 @@ /* * File : udp.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,6 @@ #ifndef UDP_H__ #define UDP_H__ -#include +#include #endif diff --git a/components/dfs/filesystems/net/socket/sys/socket.h b/components/net/sal_socket/include/socket/sys_socket/sys/socket.h similarity index 55% rename from components/dfs/filesystems/net/socket/sys/socket.h rename to components/net/sal_socket/include/socket/sys_socket/sys/socket.h index 4ed96fe222..2b0357ff81 100644 --- a/components/dfs/filesystems/net/socket/sys/socket.h +++ b/components/net/sal_socket/include/socket/sys_socket/sys/socket.h @@ -1,7 +1,7 @@ /* * File : socket.h * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2015, RT-Thread Development Team + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,74 +20,18 @@ * Change Logs: * Date Author Notes * 2015-02-17 Bernard First version + * 2018-05-17 ChenYong Add socket abstraction layer */ -#ifndef SOCKET_H__ -#define SOCKET_H__ +#ifndef SYS_SOCKET_H_ +#define SYS_SOCKET_H_ + +#include #ifdef __cplusplus extern "C" { #endif -#include -#include -#include -#include - -#include - -#if LWIP_VERSION < 0x2000000 -typedef uint16_t sa_family_t; -typedef uint16_t in_port_t; - -struct sockaddr_storage -{ - sa_family_t ss_family; /* Address family */ - char ss_data[14]; /* 14-bytes of address data */ -}; -#endif - -#if LWIP_VERSION < 0x2000000 -#define SELWAIT_T int -#else -#ifndef SELWAIT_T -#define SELWAIT_T u8_t -#endif -#endif - -/* - * Re-define lwip socket - * - * NOTE: please make sure the definitions same in lwip::net_socket.c - */ -struct lwip_sock { - /** sockets currently are built on netconns, each socket has one netconn */ - struct netconn *conn; - /** data that was left from the previous read */ - void *lastdata; - /** offset in the data that was left from the previous read */ - u16_t lastoffset; - /** number of times data was received, set by event_callback(), - tested by the receive and select functions */ - s16_t rcvevent; - /** number of times data was ACKed (free send buffer), set by event_callback(), - tested by select */ - u16_t sendevent; - /** error happened for this socket, set by event_callback(), tested by select */ - u16_t errevent; - /** last error that occurred on this socket */ -#if LWIP_VERSION < 0x2000000 - int err; -#else - u8_t err; -#endif - /** counter of how many threads are waiting for this socket using select */ - SELWAIT_T select_waiting; - - rt_wqueue_t wait_head; -}; -struct lwip_sock *lwip_tryget_socket(int s); - int accept(int s, struct sockaddr *addr, socklen_t *addrlen); int bind(int s, const struct sockaddr *name, socklen_t namelen); int shutdown(int s, int how); @@ -111,4 +55,4 @@ int ioctlsocket(int s, long cmd, void *arg); } #endif -#endif +#endif /* _SYS_SOCKET_H_ */ diff --git a/components/dfs/filesystems/net/net_netdb.c b/components/net/sal_socket/socket/net_netdb.c similarity index 81% rename from components/dfs/filesystems/net/net_netdb.c rename to components/net/sal_socket/socket/net_netdb.c index 1e14dfb093..5acab36403 100644 --- a/components/dfs/filesystems/net/net_netdb.c +++ b/components/net/sal_socket/socket/net_netdb.c @@ -1,5 +1,5 @@ /* - * File : netdb.c + * File : net_netdb.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2015, RT-Thread Development Team * @@ -20,26 +20,28 @@ * Change Logs: * Date Author Notes * 2015-02-17 Bernard First version + * 2108-05-24 ChenYong Add socket abstraction layer */ -#include "netdb.h" -#include +#include + +#include struct hostent *gethostbyname(const char *name) { - return lwip_gethostbyname(name); + return sal_gethostbyname(name); } RTM_EXPORT(gethostbyname); int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop) { - return lwip_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); + return sal_gethostbyname_r(name, ret, buf, buflen, result, h_errnop); } void freeaddrinfo(struct addrinfo *ai) { - lwip_freeaddrinfo(ai); + sal_freeaddrinfo(ai); } RTM_EXPORT(freeaddrinfo); @@ -48,6 +50,6 @@ int getaddrinfo(const char *nodename, const struct addrinfo *hints, struct addrinfo **res) { - return lwip_getaddrinfo(nodename, servname, hints, res); + return sal_getaddrinfo(nodename, servname, hints, res); } RTM_EXPORT(getaddrinfo); diff --git a/components/net/sal_socket/socket/net_sockets.c b/components/net/sal_socket/socket/net_sockets.c new file mode 100644 index 0000000000..f181ee14d5 --- /dev/null +++ b/components/net/sal_socket/socket/net_sockets.c @@ -0,0 +1,284 @@ +/* + * File : net_sockets.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-02-17 Bernard First version + * 2018-05-17 ChenYong Add socket abstraction layer + */ + +#include +#include +#include +#include + +#include + +int accept(int s, struct sockaddr *addr, socklen_t *addrlen) +{ + int new_socket = -1; + int socket = dfs_net_getsocket(s); + + new_socket = sal_accept(socket, addr, addrlen); + if (new_socket != -1) + { + /* this is a new socket, create it in file system fd */ + int fd; + struct dfs_fd *d; + + /* allocate a fd */ + fd = fd_new(); + if (fd < 0) + { + rt_set_errno(-ENOMEM); + sal_closesocket(socket); + + return -1; + } + + d = fd_get(fd); + if(d) + { + /* this is a socket fd */ + d->type = FT_SOCKET; + d->path = NULL; + + d->fops = dfs_net_get_fops(); + + d->flags = O_RDWR; /* set flags as read and write */ + d->size = 0; + d->pos = 0; + + /* set socket to the data of dfs_fd */ + d->data = (void *) new_socket; + + /* release the ref-count of fd */ + fd_put(d); + + return fd; + } + + return -1; + } + + return -1; +} +RTM_EXPORT(accept); + +int bind(int s, const struct sockaddr *name, socklen_t namelen) +{ + int socket = dfs_net_getsocket(s); + + return sal_bind(socket, name, namelen); +} +RTM_EXPORT(bind); + +int shutdown(int s, int how) +{ + int socket; + struct dfs_fd *d; + + d = fd_get(s); + if (d == NULL) + { + rt_set_errno(-EBADF); + + return -1; + } + + socket = dfs_net_getsocket(s); + if (sal_shutdown(socket, how) == 0) + { + /* socket has been closed, delete it from file system fd */ + fd_put(d); + fd_put(d); + + return 0; + } + + return -1; + +} +RTM_EXPORT(shutdown); + +int getpeername(int s, struct sockaddr *name, socklen_t *namelen) +{ + int socket = dfs_net_getsocket(s); + + return sal_getpeername(socket, name, namelen); +} +RTM_EXPORT(getpeername); + +int getsockname(int s, struct sockaddr *name, socklen_t *namelen) +{ + int socket = dfs_net_getsocket(s); + + return sal_getsockname(socket, name, namelen); +} +RTM_EXPORT(getsockname); + +int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen) +{ + int socket = dfs_net_getsocket(s); + + return sal_getsockopt(socket, level, optname, optval, optlen); +} +RTM_EXPORT(getsockopt); + +int setsockopt(int s, int level, int optname, const void *optval, socklen_t optlen) +{ + int socket = dfs_net_getsocket(s); + + return sal_setsockopt(socket, level, optname, optval, optlen); +} +RTM_EXPORT(setsockopt); + +int connect(int s, const struct sockaddr *name, socklen_t namelen) +{ + int socket = dfs_net_getsocket(s); + + return sal_connect(socket, name, namelen); +} +RTM_EXPORT(connect); + +int listen(int s, int backlog) +{ + int socket = dfs_net_getsocket(s); + + return sal_listen(socket, backlog); +} +RTM_EXPORT(listen); + +int recv(int s, void *mem, size_t len, int flags) +{ + int socket = dfs_net_getsocket(s); + + return sal_recvfrom(socket, mem, len, flags, NULL, NULL); +} +RTM_EXPORT(recv); + +int recvfrom(int s, void *mem, size_t len, int flags, + struct sockaddr *from, socklen_t *fromlen) +{ + int socket = dfs_net_getsocket(s); + + return sal_recvfrom(socket, mem, len, flags, from, fromlen); +} +RTM_EXPORT(recvfrom); + +int send(int s, const void *dataptr, size_t size, int flags) +{ + int socket = dfs_net_getsocket(s); + + return sal_sendto(socket, dataptr, size, flags, NULL, 0); +} +RTM_EXPORT(send); + +int sendto(int s, const void *dataptr, size_t size, int flags, + const struct sockaddr *to, socklen_t tolen) +{ + int socket = dfs_net_getsocket(s); + + return sal_sendto(socket, dataptr, size, flags, to, tolen); +} +RTM_EXPORT(sendto); + +int socket(int domain, int type, int protocol) +{ + /* create a BSD socket */ + int fd; + int socket; + struct dfs_fd *d; + + /* allocate a fd */ + fd = fd_new(); + if (fd < 0) + { + rt_set_errno(-ENOMEM); + + return -1; + } + d = fd_get(fd); + + /* create socket and then put it to the dfs_fd */ + socket = sal_socket(domain, type, protocol); + if (socket >= 0) + { + /* this is a socket fd */ + d->type = FT_SOCKET; + d->path = NULL; + + d->fops = dfs_net_get_fops(); + + d->flags = O_RDWR; /* set flags as read and write */ + d->size = 0; + d->pos = 0; + + /* set socket to the data of dfs_fd */ + d->data = (void *) socket; + } + else + { + /* release fd */ + fd_put(d); + fd_put(d); + + rt_set_errno(-ENOMEM); + + return -1; + } + + /* release the ref-count of fd */ + fd_put(d); + + return fd; +} +RTM_EXPORT(socket); + +int closesocket(int s) +{ + int socket = dfs_net_getsocket(s); + struct dfs_fd *d; + + d = fd_get(s); + if(!d) + { + return -1; + } + + if (sal_closesocket(socket) == 0) + { + /* socket has been closed, delete it from file system fd */ + fd_put(d); + fd_put(d); + + return 0; + } + + return -1; +} +RTM_EXPORT(closesocket); + +int ioctlsocket(int s, long cmd, void *arg) +{ + int socket = dfs_net_getsocket(s); + + return sal_ioctlsocket(socket, cmd, arg); +} +RTM_EXPORT(ioctlsocket); diff --git a/components/net/sal_socket/src/sal_ipaddr.c b/components/net/sal_socket/src/sal_ipaddr.c new file mode 100644 index 0000000000..0060ccec45 --- /dev/null +++ b/components/net/sal_socket/src/sal_ipaddr.c @@ -0,0 +1,271 @@ +/* + * File : sal_ipaddr.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-18 ChenYong First version + */ + +#include +#include + +/* 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 new file mode 100644 index 0000000000..71aaa2c658 --- /dev/null +++ b/components/net/sal_socket/src/sal_socket.c @@ -0,0 +1,730 @@ +/* + * File : sal_socket.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2018-05-23 ChenYong First version + */ + +#include +#include + +#include +#include +#include + +#define DBG_ENABLE +#define DBG_SECTION_NAME "SAL_SOC" +#define DBG_LEVEL DBG_INFO +#define DBG_COLOR +#include + +/* the socket table used to dynamic allocate sockets */ +struct sal_socket_table +{ + uint32_t max_socket; + struct sal_socket **sockets; +}; + +/* The global array of available protocol families */ +static struct 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; + +/** + * SAL (Socket Abstraction Layer) initialization. + * + * @return result + * >= 0: initialize success + */ +int sal_init(void) +{ + if(init_ok) + { + LOG_D("Socket Abstraction Layer is already initialized."); + return 0; + } + + /* clean sal socket table */ + memset(&socket_table, 0, sizeof(socket_table)); + /* 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 the current protocol family to the global array of protocol families. + * + * @param pf protocol families structure + * + * @return 0 : protocol families structure index + * -1 : the global array of available protocol families is full + */ +int sal_proto_family_register(const struct proto_family *pf) +{ + rt_base_t level; + int idx; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); + + /* 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].gethostbyname = pf->gethostbyname; + proto_families[idx].gethostbyname_r = pf->gethostbyname_r; + proto_families[idx].freeaddrinfo = pf->freeaddrinfo; + proto_families[idx].getaddrinfo = pf->getaddrinfo; + + /* enable interrupt */ + rt_hw_interrupt_enable(level); + + return 0; +} + +/** + * this function will get socket structure by sal socket descriptor + * + * @param socket sal socket index + * + * @return socket structure 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 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 socket structure and set socket options + * + * @param family protocol family + * @param type socket type + * @param protocol transfer Protocol + * @param res socket structure address + * + * @return 0 : socket initialize success + * -1 : input the wrong family + * -2 : input the wrong socket type + * -3 : get protocol family structure 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 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 structure */ + 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 FD with 4 step length */ + cnt = st->max_socket + 4; + 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_malloc(sizeof(struct sal_socket)); + if (st->sockets[idx] == RT_NULL) + { + idx = st->max_socket; + } + } + +__result: + return idx; + +} + +/** + * this function will return a empty sal socket structure address + * + * @return sal socket structure address + */ +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; + +__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_socket; + struct sal_socket *new_sock; + + /* allocate a new socket structure and registered socket options */ + new_socket = socket_new(); + if (new_socket < 0) + { + return -1; + } + new_sock = sal_get_socket(new_socket); + + retval = socket_init(sock->domain, sock->type, sock->protocol, &new_sock); + if (retval < 0) + { + 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_sock->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) + { + memset(sock, 0x00, sizeof(struct sal_socket)); + 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; + } + + return sock->ops->setsockopt((int) sock->user_data, level, optname, optval, optlen); +} + +int sal_connect(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->connect == RT_NULL) + { + return -RT_ENOSYS; + } + + return sock->ops->connect((int) sock->user_data, name, namelen); +} + +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; + } + + return sock->ops->recvfrom((int) sock->user_data, mem, len, flags, from, fromlen); +} + +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; + } + + return sock->ops->sendto((int) sock->user_data, dataptr, size, flags, to, tolen); +} + +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) + { + 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) + { + memset(sock, 0x00, sizeof(struct sal_socket)); + 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); +} + +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); +} + +struct hostent *sal_gethostbyname(const char *name) +{ + int i; + + for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + { + if (proto_families[i].gethostbyname) + { + return proto_families[i].gethostbyname(name); + } + } + + 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; + + for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + { + if (proto_families[i].gethostbyname_r) + { + return proto_families[i].gethostbyname_r(name, ret, buf, buflen, result, h_errnop); + } + } + + return -1; +} + +void sal_freeaddrinfo(struct addrinfo *ai) +{ + int i; + + for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + { + if (proto_families[i].freeaddrinfo) + { + proto_families[i].freeaddrinfo(ai); + return; + } + } +} + +int sal_getaddrinfo(const char *nodename, + const char *servname, + const struct addrinfo *hints, + struct addrinfo **res) +{ + int i; + + for (i = 0; i < SAL_PROTO_FAMILIES_NUM; ++i) + { + if (proto_families[i].getaddrinfo) + { + return proto_families[i].getaddrinfo(nodename, servname, hints, res); + } + } + + return -1; +} diff --git a/examples/network/chargen.c b/examples/network/chargen.c index 7db47da76f..218449b845 100644 --- a/examples/network/chargen.c +++ b/examples/network/chargen.c @@ -1,13 +1,13 @@ #include #include -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX #include // only dfs_net #include #else #define read lwip_read #define write lwip_write -#endif /* RT_USING_DFS_NET */ +#endif /* SAL_USING_POSIX */ #include "netdb.h" diff --git a/include/libc/libc_fdset.h b/include/libc/libc_fdset.h index 057cc7fed2..74c4ba1cb2 100644 --- a/include/libc/libc_fdset.h +++ b/include/libc/libc_fdset.h @@ -35,7 +35,7 @@ #else -#ifdef RT_USING_DFS_NET +#ifdef SAL_USING_POSIX #ifdef FD_SETSIZE #undef FD_SETSIZE diff --git a/include/rtdebug.h b/include/rtdebug.h index 417ba70185..040d19e684 100644 --- a/include/rtdebug.h +++ b/include/rtdebug.h @@ -29,8 +29,8 @@ #error "POSIX poll/select, stdin need file system(RT_USING_DFS) and device file system(RT_USING_DFS_DEVFS)" #endif -#if defined(RT_USING_LWIP) && !defined(RT_USING_DFS_NET) -#error "POSIX poll/select, stdin need file BSD socket API(RT_USING_DFS_NET)" +#if defined(RT_USING_LWIP) && !defined(SAL_USING_POSIX) +#error "POSIX poll/select, stdin need file BSD socket API(SAL_USING_POSIX)" #endif #if !defined(RT_USING_LIBC)