summaryrefslogtreecommitdiff
path: root/components/net/sal_socket
diff options
context:
space:
mode:
authorchenyong <[email protected]>2018-07-17 20:29:33 +0800
committerchenyong <[email protected]>2018-07-18 13:34:13 +0800
commit8cda48a1323dc3cb1f947eb86d895595ebc30b38 (patch)
tree2adcb7fef3f4e735196973821aa298e5f6af98e7 /components/net/sal_socket
parent4ca1d03bdffef9e79456df3e696b7efb7f5b79aa (diff)
[net][sal] Add SAL (socket abstraction layer) framework
Diffstat (limited to 'components/net/sal_socket')
-rw-r--r--components/net/sal_socket/SConscript31
-rw-r--r--components/net/sal_socket/dfs_net/dfs_net.c99
-rw-r--r--components/net/sal_socket/impl/af_inet_at.c125
-rw-r--r--components/net/sal_socket/impl/af_inet_lwip.c302
-rw-r--r--components/net/sal_socket/include/dfs_net/dfs_net.h43
-rw-r--r--components/net/sal_socket/include/dfs_net/sys_select/sys/select.h30
-rw-r--r--components/net/sal_socket/include/sal.h101
-rw-r--r--components/net/sal_socket/include/sal_ipaddr.h138
-rw-r--r--components/net/sal_socket/include/sal_netdb.h91
-rw-r--r--components/net/sal_socket/include/sal_socket.h166
-rw-r--r--components/net/sal_socket/include/sal_type.h40
-rw-r--r--components/net/sal_socket/include/socket/arpa/inet.h30
-rw-r--r--components/net/sal_socket/include/socket/netdb.h49
-rw-r--r--components/net/sal_socket/include/socket/netinet/in.h34
-rw-r--r--components/net/sal_socket/include/socket/netinet/tcp.h30
-rw-r--r--components/net/sal_socket/include/socket/netinet/udp.h30
-rw-r--r--components/net/sal_socket/include/socket/sys_socket/sys/socket.h58
-rw-r--r--components/net/sal_socket/socket/net_netdb.c55
-rw-r--r--components/net/sal_socket/socket/net_sockets.c284
-rw-r--r--components/net/sal_socket/src/sal_ipaddr.c271
-rw-r--r--components/net/sal_socket/src/sal_socket.c730
21 files changed, 2737 insertions, 0 deletions
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/net/sal_socket/dfs_net/dfs_net.c b/components/net/sal_socket/dfs_net/dfs_net.c
new file mode 100644
index 0000000000..ee9b685f8c
--- /dev/null
+++ b/components/net/sal_socket/dfs_net/dfs_net.c
@@ -0,0 +1,99 @@
+/*
+ * File : dfs_net.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
+ * 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 <rtthread.h>
+
+#include <dfs.h>
+#include <dfs_net.h>
+
+#include <sys/socket.h>
+
+int dfs_net_getsocket(int fd)
+{
+ int socket;
+ struct dfs_fd *_dfs_fd;
+
+ _dfs_fd = fd_get(fd);
+ if (_dfs_fd == NULL) return -1;
+
+ if (_dfs_fd->type != FT_SOCKET) socket = -1;
+ else socket = (int)_dfs_fd->data;
+
+ fd_put(_dfs_fd); /* put this dfs fd */
+ return socket;
+}
+
+static int dfs_net_ioctl(struct dfs_fd* file, int cmd, void* args)
+{
+ return -EIO;
+}
+
+static int dfs_net_read(struct dfs_fd* file, void *buf, size_t count)
+{
+ int socket = (int) file->data;
+
+ 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 socket = (int) file->data;
+
+ return sal_sendto(socket, buf, count, 0, NULL, 0);
+}
+
+static int dfs_net_close(struct dfs_fd* file)
+{
+ int socket = (int) file->data;
+
+ return sal_closesocket(socket);
+}
+
+static int dfs_net_poll(struct dfs_fd *file, struct rt_pollreq *req)
+{
+ extern int sal_poll(struct dfs_fd *file, struct rt_pollreq *req);
+
+ return sal_poll(file, req);
+}
+
+const struct dfs_file_ops _net_fops =
+{
+ NULL, /* open */
+ dfs_net_close,
+ dfs_net_ioctl,
+ dfs_net_read,
+ dfs_net_write,
+ NULL,
+ NULL, /* lseek */
+ NULL, /* getdents */
+ dfs_net_poll,
+};
+
+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 <netdb.h>
+#include <sal.h>
+
+#include <at_socket.h>
+
+#ifdef SAL_USING_POSIX
+#include <dfs_poll.h>
+#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 <rtthread.h>
+
+#include <lwip/sockets.h>
+#include <lwip/netdb.h>
+#include <lwip/api.h>
+#include <lwip/init.h>
+
+#ifdef SAL_USING_POSIX
+#include <dfs_poll.h>
+#endif
+
+#include <sal.h>
+
+#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/net/sal_socket/include/dfs_net/dfs_net.h b/components/net/sal_socket/include/dfs_net/dfs_net.h
new file mode 100644
index 0000000000..2a21fe3858
--- /dev/null
+++ b/components/net/sal_socket/include/dfs_net/dfs_net.h
@@ -0,0 +1,43 @@
+/*
+ * File : dfs_net.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2015-2016, 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
+ * 2016-05-05 Bernard rename dfs_lwip to dfs_net.
+ */
+
+#ifndef DFS_NET_H__
+#define DFS_NET_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <dfs_file.h>
+
+const struct dfs_file_ops* dfs_net_get_fops(void);
+int dfs_net_getsocket(int fd);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/components/net/sal_socket/include/dfs_net/sys_select/sys/select.h b/components/net/sal_socket/include/dfs_net/sys_select/sys/select.h
new file mode 100644
index 0000000000..c2e2d54d3a
--- /dev/null
+++ b/components/net/sal_socket/include/dfs_net/sys_select/sys/select.h
@@ -0,0 +1,30 @@
+/*
+ * File : select.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
+ * 2015-05-02 Bernard First version
+ */
+
+#ifndef SELECT_H__
+#define SELECT_H__
+
+#include <dfs_select.h>
+
+#endif
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 <dfs_file.h>
+#include <rtdevice.h>
+
+#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 <sal_socket.h>
+
+#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 <stdlib.h>
+#include <stdint.h>
+
+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/net/sal_socket/include/socket/arpa/inet.h b/components/net/sal_socket/include/socket/arpa/inet.h
new file mode 100644
index 0000000000..e7d856d434
--- /dev/null
+++ b/components/net/sal_socket/include/socket/arpa/inet.h
@@ -0,0 +1,30 @@
+/*
+ * File : inet.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
+ * 2015-02-17 Bernard First version
+ */
+
+#ifndef INET_H__
+#define INET_H__
+
+#include <sal_ipaddr.h>
+
+#endif
diff --git a/components/net/sal_socket/include/socket/netdb.h b/components/net/sal_socket/include/socket/netdb.h
new file mode 100644
index 0000000000..c1ffbb826c
--- /dev/null
+++ b/components/net/sal_socket/include/socket/netdb.h
@@ -0,0 +1,49 @@
+/*
+ * File : 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
+ * 2015-02-17 Bernard First version
+ * 2108-05-24 ChenYong Add socket abstraction layer
+ */
+
+#ifndef NETDB_H__
+#define NETDB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sal_netdb.h>
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/components/net/sal_socket/include/socket/netinet/in.h b/components/net/sal_socket/include/socket/netinet/in.h
new file mode 100644
index 0000000000..d01a9b3f89
--- /dev/null
+++ b/components/net/sal_socket/include/socket/netinet/in.h
@@ -0,0 +1,34 @@
+/*
+ * File : in.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
+ * 2015-02-17 Bernard First version
+ */
+
+#ifndef IN_H__
+#define IN_H__
+
+#include <sys/socket.h>
+
+#ifndef IN6_IS_ADDR_MULTICAST
+#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *) (a))[0] == 0xff)
+#endif
+
+#endif
diff --git a/components/net/sal_socket/include/socket/netinet/tcp.h b/components/net/sal_socket/include/socket/netinet/tcp.h
new file mode 100644
index 0000000000..aafb0f15d0
--- /dev/null
+++ b/components/net/sal_socket/include/socket/netinet/tcp.h
@@ -0,0 +1,30 @@
+/*
+ * File : tcp.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
+ * 2015-02-17 Bernard First version
+ */
+
+#ifndef TCP_H__
+#define TCP_H__
+
+#include <sys/socket.h>
+
+#endif
diff --git a/components/net/sal_socket/include/socket/netinet/udp.h b/components/net/sal_socket/include/socket/netinet/udp.h
new file mode 100644
index 0000000000..4b84755e68
--- /dev/null
+++ b/components/net/sal_socket/include/socket/netinet/udp.h
@@ -0,0 +1,30 @@
+/*
+ * File : udp.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
+ * 2015-02-17 Bernard First version
+ */
+
+#ifndef UDP_H__
+#define UDP_H__
+
+#include <sys/socket.h>
+
+#endif
diff --git a/components/net/sal_socket/include/socket/sys_socket/sys/socket.h b/components/net/sal_socket/include/socket/sys_socket/sys/socket.h
new file mode 100644
index 0000000000..2b0357ff81
--- /dev/null
+++ b/components/net/sal_socket/include/socket/sys_socket/sys/socket.h
@@ -0,0 +1,58 @@
+/*
+ * File : 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
+ * 2015-02-17 Bernard First version
+ * 2018-05-17 ChenYong Add socket abstraction layer
+ */
+
+#ifndef SYS_SOCKET_H_
+#define SYS_SOCKET_H_
+
+#include <sal_socket.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+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);
+int getpeername (int s, struct sockaddr *name, socklen_t *namelen);
+int getsockname (int s, struct sockaddr *name, socklen_t *namelen);
+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 connect(int s, const struct sockaddr *name, socklen_t namelen);
+int listen(int s, int backlog);
+int recv(int s, void *mem, size_t len, int flags);
+int recvfrom(int s, void *mem, size_t len, int flags,
+ struct sockaddr *from, socklen_t *fromlen);
+int send(int s, const void *dataptr, size_t size, int flags);
+int sendto(int s, const void *dataptr, size_t size, int flags,
+ const struct sockaddr *to, socklen_t tolen);
+int socket(int domain, int type, int protocol);
+int closesocket(int s);
+int ioctlsocket(int s, long cmd, void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SOCKET_H_ */
diff --git a/components/net/sal_socket/socket/net_netdb.c b/components/net/sal_socket/socket/net_netdb.c
new file mode 100644
index 0000000000..5acab36403
--- /dev/null
+++ b/components/net/sal_socket/socket/net_netdb.c
@@ -0,0 +1,55 @@
+/*
+ * File : net_netdb.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
+ * 2108-05-24 ChenYong Add socket abstraction layer
+ */
+
+#include <rtthread.h>
+
+#include <netdb.h>
+
+struct hostent *gethostbyname(const char *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 sal_gethostbyname_r(name, ret, buf, buflen, result, h_errnop);
+}
+
+void freeaddrinfo(struct addrinfo *ai)
+{
+ sal_freeaddrinfo(ai);
+}
+RTM_EXPORT(freeaddrinfo);
+
+int getaddrinfo(const char *nodename,
+ const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **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 <dfs.h>
+#include <dfs_file.h>
+#include <dfs_poll.h>
+#include <dfs_net.h>
+
+#include <sys/socket.h>
+
+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 <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
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 <rtthread.h>
+#include <rthw.h>
+
+#include <sal_socket.h>
+#include <sal_netdb.h>
+#include <sal.h>
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME "SAL_SOC"
+#define DBG_LEVEL DBG_INFO
+#define DBG_COLOR
+#include <rtdbg.h>
+
+/* 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;
+}