summaryrefslogtreecommitdiff
path: root/components/net/sal_socket/impl
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/impl
parent4ca1d03bdffef9e79456df3e696b7efb7f5b79aa (diff)
[net][sal] Add SAL (socket abstraction layer) framework
Diffstat (limited to 'components/net/sal_socket/impl')
-rw-r--r--components/net/sal_socket/impl/af_inet_at.c125
-rw-r--r--components/net/sal_socket/impl/af_inet_lwip.c302
2 files changed, 427 insertions, 0 deletions
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);