You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2021/10/26 13:01:59 UTC
[incubator-nuttx] 01/02: arch/sim: add native socket support based
on usrsock
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit b90d0941380512ce81f36fb4ad68288dafa3e772
Author: chao.an <an...@xiaomi.com>
AuthorDate: Sun Aug 29 17:52:02 2021 +0800
arch/sim: add native socket support based on usrsock
Signed-off-by: chao.an <an...@xiaomi.com>
---
arch/sim/Kconfig | 17 +-
arch/sim/src/Makefile | 5 +
arch/sim/src/nuttx-names.in | 9 +
arch/sim/src/sim/up_idle.c | 4 +
arch/sim/src/sim/up_initialize.c | 6 +
arch/sim/src/sim/up_internal.h | 7 +
arch/sim/src/sim/up_usrsock.c | 443 +++++++++++++++++++++++++++++++
arch/sim/src/sim/up_usrsock_host.c | 515 +++++++++++++++++++++++++++++++++++++
arch/sim/src/sim/up_usrsock_host.h | 317 +++++++++++++++++++++++
9 files changed, 1321 insertions(+), 2 deletions(-)
diff --git a/arch/sim/Kconfig b/arch/sim/Kconfig
index 5cc6a33..ea2d962 100644
--- a/arch/sim/Kconfig
+++ b/arch/sim/Kconfig
@@ -127,15 +127,28 @@ config SIM_WALLTIME_SIGNAL
endchoice
+choice
+ prompt "Simulated Network Interface"
+ default SIM_NETDEV
+ depends on NET
+ optional
+
config SIM_NETDEV
bool "Simulated Network Device"
- default y
select ARCH_HAVE_NETDEV_STATISTICS
select SCHED_LPWORK
- depends on NET_ETHERNET
+ select NET_ETHERNET
---help---
Build in support for a simulated network device.
+config SIM_NETUSRSOCK
+ bool "Simulated Network Device with Native Stack via usrsock"
+ select NET_USRSOCK
+ ---help---
+ Built-in support for a simulated network device using native stack via usrsock
+
+endchoice
+
if SIM_NETDEV
choice
diff --git a/arch/sim/src/Makefile b/arch/sim/src/Makefile
index a106114..71a8c4c 100644
--- a/arch/sim/src/Makefile
+++ b/arch/sim/src/Makefile
@@ -170,6 +170,11 @@ else ifeq ($(CONFIG_SIM_NETDEV_VPNKIT),y)
HOSTSRCS += protocol.c negotiate.c
endif
+ifeq ($(CONFIG_SIM_NETUSRSOCK),y)
+ HOSTSRCS += up_usrsock_host.c
+ CSRCS += up_usrsock.c
+endif
+
ifeq ($(CONFIG_SIM_HCISOCKET),y)
HOSTSRCS += up_hcisocket_host.c
CSRCS += up_hcisocket.c
diff --git a/arch/sim/src/nuttx-names.in b/arch/sim/src/nuttx-names.in
index 4b576d2..2c43b3a 100644
--- a/arch/sim/src/nuttx-names.in
+++ b/arch/sim/src/nuttx-names.in
@@ -31,6 +31,7 @@
#endif
NXSYMBOLS(__cxa_atexit)
+NXSYMBOLS(accept)
NXSYMBOLS(atexit)
NXSYMBOLS(bind)
NXSYMBOLS(calloc)
@@ -45,13 +46,18 @@ NXSYMBOLS(dup)
NXSYMBOLS(exit)
NXSYMBOLS(fchmod)
NXSYMBOLS(fchown)
+NXSYMBOLS(fcntl)
NXSYMBOLS(free)
NXSYMBOLS(fstat)
NXSYMBOLS(fsync)
NXSYMBOLS(ftruncate)
NXSYMBOLS(futimens)
+NXSYMBOLS(getpeername)
+NXSYMBOLS(getsockname)
+NXSYMBOLS(getsockopt)
NXSYMBOLS(if_nametoindex)
NXSYMBOLS(ioctl)
+NXSYMBOLS(listen)
NXSYMBOLS(longjmp)
NXSYMBOLS(lseek)
NXSYMBOLS(malloc)
@@ -87,14 +93,17 @@ NXSYMBOLS(read)
NXSYMBOLS(readdir)
NXSYMBOLS(readv)
NXSYMBOLS(realloc)
+NXSYMBOLS(recvfrom)
NXSYMBOLS(rename)
NXSYMBOLS(rewinddir)
NXSYMBOLS(rmdir)
NXSYMBOLS(sched_yield)
NXSYMBOLS(select)
NXSYMBOLS(sendmsg)
+NXSYMBOLS(sendto)
NXSYMBOLS(setitimer)
NXSYMBOLS(setjmp)
+NXSYMBOLS(setsockopt)
NXSYMBOLS(shutdown)
NXSYMBOLS(sigaction)
NXSYMBOLS(sigaddset)
diff --git a/arch/sim/src/sim/up_idle.c b/arch/sim/src/sim/up_idle.c
index be66287..abd80f6 100644
--- a/arch/sim/src/sim/up_idle.c
+++ b/arch/sim/src/sim/up_idle.c
@@ -90,6 +90,10 @@ void up_idle(void)
netdriver_loop();
#endif
+#ifdef CONFIG_SIM_NETUSRSOCK
+ usrsock_loop();
+#endif
+
#ifdef CONFIG_RPTUN
up_rptun_loop();
#endif
diff --git a/arch/sim/src/sim/up_initialize.c b/arch/sim/src/sim/up_initialize.c
index ea5f031..1af2c6a 100644
--- a/arch/sim/src/sim/up_initialize.c
+++ b/arch/sim/src/sim/up_initialize.c
@@ -246,6 +246,12 @@ void up_initialize(void)
netdriver_init(); /* Our "real" network driver */
#endif
+#ifdef CONFIG_SIM_NETUSRSOCK
+ /* Register the usrsock native socket device */
+
+ usrsock_init();
+#endif
+
#ifdef CONFIG_NET_LOOPBACK
/* Initialize the local loopback device */
diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h
index f8ef29c..c2ae3e2 100644
--- a/arch/sim/src/sim/up_internal.h
+++ b/arch/sim/src/sim/up_internal.h
@@ -316,6 +316,13 @@ void netdriver_setmacaddr(unsigned char *macaddr);
void netdriver_setmtu(int mtu);
void netdriver_loop(void);
+/* up_usrsock.c *************************************************************/
+
+#ifdef CONFIG_SIM_NETUSRSOCK
+int usrsock_init(void);
+void usrsock_loop(void);
+#endif
+
/* up_rptun.c ***************************************************************/
#ifdef CONFIG_RPTUN
diff --git a/arch/sim/src/sim/up_usrsock.c b/arch/sim/src/sim/up_usrsock.c
new file mode 100644
index 0000000..5cd0185
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock.c
@@ -0,0 +1,443 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <poll.h>
+#include <syslog.h>
+#include <string.h>
+
+#include <nuttx/fs/fs.h>
+#include <nuttx/net/usrsock.h>
+
+#include "up_usrsock_host.h"
+
+/****************************************************************************
+ * Private Type Declarations
+ ****************************************************************************/
+
+struct usrsock_s
+{
+ struct file usock;
+ uint8_t data[4096];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+typedef int (*usrsock_handler_t)(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct usrsock_s g_usrsock;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int usrsock_send(FAR struct usrsock_s *usrsock,
+ FAR const void *buf, size_t len)
+{
+ FAR uint8_t *data = (FAR uint8_t *)buf;
+ ssize_t ret;
+
+ while (len > 0)
+ {
+ ret = file_write(&usrsock->usock, data, len);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ data += ret;
+ len -= ret;
+ }
+
+ return 0;
+}
+
+static int usrsock_send_ack(FAR struct usrsock_s *usrsock,
+ uint8_t xid, int32_t result)
+{
+ struct usrsock_message_req_ack_s ack;
+
+ ack.head.msgid = USRSOCK_MESSAGE_RESPONSE_ACK;
+ ack.head.flags = (result == -EINPROGRESS);
+
+ ack.xid = xid;
+ ack.result = result;
+
+ return usrsock_send(usrsock, &ack, sizeof(ack));
+}
+
+static int usrsock_send_dack(FAR struct usrsock_s *usrsock,
+ FAR struct usrsock_message_datareq_ack_s *ack,
+ uint8_t xid, int32_t result,
+ uint16_t valuelen,
+ uint16_t valuelen_nontrunc)
+{
+ ack->reqack.head.msgid = USRSOCK_MESSAGE_RESPONSE_DATA_ACK;
+ ack->reqack.head.flags = 0;
+
+ ack->reqack.xid = xid;
+ ack->reqack.result = result;
+
+ if (result < 0)
+ {
+ result = 0;
+ valuelen = 0;
+ valuelen_nontrunc = 0;
+ }
+ else if (valuelen > valuelen_nontrunc)
+ {
+ valuelen = valuelen_nontrunc;
+ }
+
+ ack->valuelen = valuelen;
+ ack->valuelen_nontrunc = valuelen_nontrunc;
+
+ return usrsock_send(usrsock, ack, sizeof(*ack) + valuelen + result);
+}
+
+static int usrsock_send_event(FAR struct usrsock_s *usrsock,
+ int16_t usockid, uint16_t events)
+{
+ struct usrsock_message_socket_event_s event;
+
+ event.head.msgid = USRSOCK_MESSAGE_SOCKET_EVENT;
+ event.head.flags = USRSOCK_MESSAGE_FLAG_EVENT;
+
+ event.usockid = usockid;
+ event.events = events;
+
+ return usrsock_send(usrsock, &event, sizeof(event));
+}
+
+static int usrsock_socket_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_socket_s *req = data;
+ int fd = usrsock_host_socket(req->domain, req->type, req->protocol);
+
+ usrsock_send_ack(usrsock, req->head.xid, fd);
+ if (fd > 0)
+ {
+ usrsock_send_event(usrsock, fd, USRSOCK_EVENT_SENDTO_READY);
+ }
+
+ return fd;
+}
+
+static int usrsock_close_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_close_s *req = data;
+ int ret = usrsock_host_close(req->usockid);
+
+ return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_connect_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_connect_s *req = data;
+ int ret = usrsock_host_connect(req->usockid,
+ (FAR const struct sockaddr *)(req + 1),
+ req->addrlen);
+
+ return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_sendto_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_sendto_s *req = data;
+ int ret = usrsock_host_sendto(req->usockid,
+ (FAR const void *)(req + 1) + req->addrlen,
+ req->buflen, req->flags,
+ req->addrlen ?
+ (FAR const struct sockaddr *)(req + 1) :
+ NULL, req->addrlen);
+
+ usrsock_send_ack(usrsock, req->head.xid, ret);
+ if (ret > 0)
+ {
+ ret = usrsock_send_event(usrsock, req->usockid,
+ USRSOCK_EVENT_SENDTO_READY);
+ }
+
+ return ret;
+}
+
+static int usrsock_recvfrom_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_recvfrom_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ socklen_t outaddrlen = req->max_addrlen;
+ socklen_t inaddrlen = req->max_addrlen;
+ size_t buflen = req->max_buflen;
+ int ret;
+
+ ack = (struct usrsock_message_datareq_ack_s *)usrsock->data;
+ if (sizeof(*ack) + inaddrlen + buflen > sizeof(usrsock->data))
+ {
+ buflen = sizeof(usrsock->data) - sizeof(*ack) - inaddrlen;
+ }
+
+ ret = usrsock_host_recvfrom(req->usockid,
+ (FAR void *)(ack + 1) + inaddrlen,
+ buflen, req->flags,
+ outaddrlen ?
+ (FAR struct sockaddr *)(ack + 1) : NULL,
+ outaddrlen ? &outaddrlen : NULL);
+ if (ret > 0 && outaddrlen < inaddrlen)
+ {
+ memcpy((FAR void *)(ack + 1) + outaddrlen,
+ (FAR void *)(ack + 1) + inaddrlen, ret);
+ }
+
+ return usrsock_send_dack(usrsock, ack, req->head.xid,
+ ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_setsockopt_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_setsockopt_s *req = data;
+ int ret = usrsock_host_setsockopt(req->usockid, req->level,
+ req->option, req + 1, req->valuelen);
+
+ return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_getsockopt_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_getsockopt_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ socklen_t optlen = req->max_valuelen;
+ int ret;
+
+ ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+ ret = usrsock_host_getsockopt(req->usockid,
+ req->level, req->option,
+ ack + 1, &optlen);
+
+ return usrsock_send_dack(usrsock, ack, req->head.xid,
+ ret, optlen, optlen);
+}
+
+static int usrsock_getsockname_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_getsockname_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ socklen_t outaddrlen = req->max_addrlen;
+ socklen_t inaddrlen = req->max_addrlen;
+ int ret;
+
+ ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+ ret = usrsock_host_getsockname(req->usockid,
+ (FAR struct sockaddr *)(ack + 1), &outaddrlen);
+
+ return usrsock_send_dack(usrsock, ack, req->head.xid,
+ ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_getpeername_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_getpeername_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ socklen_t outaddrlen = req->max_addrlen;
+ socklen_t inaddrlen = req->max_addrlen;
+ int ret;
+
+ ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+ ret = usrsock_host_getpeername(req->usockid,
+ (FAR struct sockaddr *)(ack + 1), &outaddrlen);
+
+ return usrsock_send_dack(usrsock, ack, req->head.xid,
+ ret, inaddrlen, outaddrlen);
+}
+
+static int usrsock_bind_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_bind_s *req = data;
+ int ret = usrsock_host_bind(req->usockid,
+ (FAR const struct sockaddr *)(req + 1),
+ req->addrlen);
+
+ return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_listen_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_listen_s *req = data;
+ int ret = usrsock_host_listen(req->usockid, req->backlog);
+
+ return usrsock_send_ack(usrsock, req->head.xid, ret);
+}
+
+static int usrsock_accept_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_accept_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ socklen_t outaddrlen = req->max_addrlen;
+ socklen_t inaddrlen = req->max_addrlen;
+ int sockfd;
+ int ret;
+
+ ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+ sockfd = usrsock_host_accept(req->usockid,
+ outaddrlen ?
+ (FAR struct sockaddr *)(ack + 1) : NULL,
+ outaddrlen ? &outaddrlen : NULL);
+ if (sockfd > 0)
+ {
+ /* Append index as usockid to the payload */
+
+ if (outaddrlen <= inaddrlen)
+ {
+ *(FAR int16_t *)((FAR void *)(ack + 1) + outaddrlen) = sockfd;
+ }
+ else
+ {
+ *(FAR int16_t *)((FAR void *)(ack + 1) + inaddrlen) = sockfd;
+ }
+
+ ret = sizeof(int16_t); /* Return usockid size */
+ }
+ else
+ {
+ ret = sockfd;
+ }
+
+ usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+ inaddrlen, outaddrlen);
+ if (ret > 0)
+ {
+ usrsock_send_event(usrsock, sockfd, USRSOCK_EVENT_SENDTO_READY);
+ }
+
+ return ret;
+}
+
+static int usrsock_ioctl_handler(FAR struct usrsock_s *usrsock,
+ FAR const void *data, size_t len)
+{
+ FAR const struct usrsock_request_ioctl_s *req = data;
+ FAR struct usrsock_message_datareq_ack_s *ack;
+ int ret;
+
+ ack = (FAR struct usrsock_message_datareq_ack_s *)usrsock->data;
+ memcpy(ack + 1, req + 1, req->arglen);
+ ret = usrsock_host_ioctl(req->usockid, req->cmd,
+ (unsigned long)(ack + 1));
+
+ return usrsock_send_dack(usrsock, ack, req->head.xid, ret,
+ req->arglen, req->arglen);
+}
+
+static const usrsock_handler_t g_usrsock_handler[] =
+{
+ [USRSOCK_REQUEST_SOCKET] = usrsock_socket_handler,
+ [USRSOCK_REQUEST_CLOSE] = usrsock_close_handler,
+ [USRSOCK_REQUEST_CONNECT] = usrsock_connect_handler,
+ [USRSOCK_REQUEST_SENDTO] = usrsock_sendto_handler,
+ [USRSOCK_REQUEST_RECVFROM] = usrsock_recvfrom_handler,
+ [USRSOCK_REQUEST_SETSOCKOPT] = usrsock_setsockopt_handler,
+ [USRSOCK_REQUEST_GETSOCKOPT] = usrsock_getsockopt_handler,
+ [USRSOCK_REQUEST_GETSOCKNAME] = usrsock_getsockname_handler,
+ [USRSOCK_REQUEST_GETPEERNAME] = usrsock_getpeername_handler,
+ [USRSOCK_REQUEST_BIND] = usrsock_bind_handler,
+ [USRSOCK_REQUEST_LISTEN] = usrsock_listen_handler,
+ [USRSOCK_REQUEST_ACCEPT] = usrsock_accept_handler,
+ [USRSOCK_REQUEST_IOCTL] = usrsock_ioctl_handler,
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int usrsock_event_callback(int16_t usockid, uint16_t events)
+{
+ return usrsock_send_event(&g_usrsock, usockid, events);
+}
+
+int usrsock_init(void)
+{
+ return file_open(&g_usrsock.usock, "/dev/usrsock", O_RDWR);
+}
+
+void usrsock_loop(void)
+{
+ FAR struct usrsock_request_common_s *common;
+ uint8_t data[4096];
+ int ret;
+ struct pollfd pfd =
+ {
+ .ptr = &g_usrsock.usock,
+ .events = POLLIN | POLLFILE,
+ };
+
+ ret = poll(&pfd, 1, 0);
+ if (ret > 0)
+ {
+ ret = file_read(&g_usrsock.usock, data, sizeof(data));
+ if (ret > 0)
+ {
+ common = (FAR struct usrsock_request_common_s *)data;
+
+ if (common->reqid >= 0 &&
+ common->reqid < USRSOCK_REQUEST__MAX)
+ {
+ ret = g_usrsock_handler[common->reqid](&g_usrsock,
+ data, ret);
+ if (ret < 0)
+ {
+ syslog(LOG_ERR, "Usrsock request %d failed: %d\n",
+ common->reqid, ret);
+ }
+ }
+ else
+ {
+ syslog(LOG_ERR, "Invalid request id: %d\n",
+ common->reqid);
+ }
+ }
+ }
+
+ usrsock_host_loop();
+}
diff --git a/arch/sim/src/sim/up_usrsock_host.c b/arch/sim/src/sim/up_usrsock_host.c
new file mode 100644
index 0000000..d6428fc
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock_host.c
@@ -0,0 +1,515 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock_host.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <syslog.h>
+
+#include <netinet/in.h>
+
+#include "up_usrsock_host.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static int g_active_maxfd = -1;
+static fd_set g_active_read_fds;
+static fd_set g_active_write_fds;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void usrsock_host_clear_fd(int fd, fd_set *fds)
+{
+ if (FD_ISSET(fd, fds))
+ {
+ FD_CLR(fd, fds);
+
+ if (fd == g_active_maxfd)
+ {
+ while (fd--)
+ {
+ if (FD_ISSET(fd, &g_active_read_fds))
+ {
+ break;
+ }
+ else if (FD_ISSET(fd, &g_active_write_fds))
+ {
+ break;
+ }
+ }
+
+ g_active_maxfd = fd;
+ }
+ }
+}
+
+static void usrsock_host_set_fd(int fd, fd_set *fds)
+{
+ if (!FD_ISSET(fd, fds))
+ {
+ FD_SET(fd, fds);
+ if (fd > g_active_maxfd)
+ {
+ g_active_maxfd = fd;
+ }
+ }
+}
+
+static void sockaddr_to_native(const struct nuttx_sockaddr *addr,
+ const nuttx_socklen_t addrlen,
+ struct sockaddr *naddr,
+ socklen_t *naddrlen)
+{
+ naddr->sa_family = addr->sa_family;
+ memcpy(naddr->sa_data, addr->sa_data, sizeof(naddr->sa_data));
+
+ *naddrlen = addrlen;
+}
+
+static void sockaddr_to_nuttx(const struct sockaddr *naddr,
+ const socklen_t naddrlen,
+ struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen)
+{
+ addr->sa_family = naddr->sa_family;
+ memcpy(addr->sa_data, naddr->sa_data, sizeof(addr->sa_data));
+
+ *addrlen = naddrlen;
+}
+
+static void sock_nonblock(int socket, int enable)
+{
+ if (enable)
+ {
+ fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK);
+ }
+ else
+ {
+ fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK);
+ }
+}
+
+static int usrsock_host_sockopt(int sockfd, int level, int optname,
+ const void *optval, nuttx_socklen_t *optlen,
+ bool set)
+{
+ int ret = -EINVAL;
+
+ if (level == NUTTX_SOL_SOCKET)
+ {
+ level = SOL_SOCKET;
+ }
+ else if (level == NUTTX_IPPROTO_TCP)
+ {
+ level = IPPROTO_TCP;
+ }
+ else if (level == NUTTX_IPPROTO_UDP)
+ {
+ level = IPPROTO_UDP;
+ }
+ else if (level == NUTTX_IPPROTO_IP)
+ {
+ level = IPPROTO_IP;
+ }
+ else
+ {
+ return ret;
+ }
+
+ if (optname == NUTTX_SO_REUSEADDR)
+ {
+ optname = SO_REUSEADDR;
+ }
+ else if (optname == NUTTX_SO_ERROR)
+ {
+ optname = SO_ERROR;
+ }
+ else
+ {
+ syslog(LOG_ERR, "Invalid optname: %x\n", optname);
+ return ret;
+ }
+
+ if (set)
+ {
+ ret = setsockopt(sockfd, level, optname, optval, *optlen);
+ }
+ else
+ {
+ ret = getsockopt(sockfd, level, optname, (void *)optval, optlen);
+ }
+
+ return ret < 0 ? -errno : 0;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int usrsock_host_socket(int domain, int type, int protocol)
+{
+ int ret;
+
+ if (domain == NUTTX_PF_INET)
+ {
+ domain = PF_INET;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ if (type == NUTTX_SOCK_STREAM)
+ {
+ type = SOCK_STREAM;
+ }
+ else if (type == NUTTX_SOCK_DGRAM)
+ {
+ type = SOCK_DGRAM;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ if (protocol == NUTTX_IPPROTO_IP)
+ {
+ protocol = IPPROTO_IP;
+ }
+ else if (protocol == NUTTX_IPPROTO_ICMP)
+ {
+ protocol = IPPROTO_ICMP;
+ }
+ else if (protocol == NUTTX_IPPROTO_TCP)
+ {
+ protocol = IPPROTO_TCP;
+ }
+ else if (protocol == NUTTX_IPPROTO_UDP)
+ {
+ protocol = IPPROTO_UDP;
+ }
+ else
+ {
+ return -EINVAL;
+ }
+
+ ret = socket(domain, type, protocol);
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ sock_nonblock(ret, true);
+ usrsock_host_set_fd(ret, &g_active_read_fds);
+
+ return ret;
+}
+
+int usrsock_host_close(int sockfd)
+{
+ usrsock_host_clear_fd(sockfd, &g_active_read_fds);
+ usrsock_host_clear_fd(sockfd, &g_active_write_fds);
+
+ return close(sockfd);
+}
+
+int usrsock_host_connect(int sockfd,
+ const struct nuttx_sockaddr *addr,
+ nuttx_socklen_t addrlen)
+{
+ struct sockaddr naddr;
+ socklen_t naddrlen;
+ int ret;
+
+ sockaddr_to_native(addr, addrlen, &naddr, &naddrlen);
+
+ sock_nonblock(sockfd, false);
+ ret = connect(sockfd, &naddr, naddrlen);
+ sock_nonblock(sockfd, true);
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+ return ret;
+}
+
+ssize_t usrsock_host_sendto(int sockfd, const void *buf,
+ size_t len, int flags,
+ const struct nuttx_sockaddr *dest_addr,
+ nuttx_socklen_t addrlen)
+{
+ struct sockaddr naddr;
+ socklen_t naddrlen;
+ int ret;
+
+ if (dest_addr && addrlen >= sizeof(*dest_addr))
+ {
+ sockaddr_to_native(dest_addr, addrlen, &naddr, &naddrlen);
+ ret = sendto(sockfd, buf, len, flags, &naddr, naddrlen);
+ }
+ else
+ {
+ ret = sendto(sockfd, buf, len, flags, NULL, 0);
+ }
+
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ {
+ usrsock_host_set_fd(sockfd, &g_active_write_fds);
+ }
+ else
+ {
+ usrsock_event_callback(sockfd, NUTTX_USRSOCK_EVENT_REMOTE_CLOSED);
+ }
+ }
+
+ return ret >= 0 ? ret : -errno;
+}
+
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct nuttx_sockaddr *src_addr,
+ nuttx_socklen_t *addrlen)
+{
+ struct sockaddr naddr;
+ socklen_t naddrlen;
+ int ret;
+
+ if (src_addr && addrlen && *addrlen >= sizeof(*src_addr))
+ {
+ sockaddr_to_native(src_addr, *addrlen, &naddr, &naddrlen);
+ ret = recvfrom(sockfd, buf, len, flags, &naddr, &naddrlen);
+ }
+ else
+ {
+ ret = recvfrom(sockfd, buf, len, flags, NULL, NULL);
+ }
+
+ if (ret <= 0)
+ {
+ if (ret == 0 || errno != EAGAIN)
+ {
+ usrsock_event_callback(sockfd, NUTTX_USRSOCK_EVENT_REMOTE_CLOSED);
+ }
+
+ return -errno;
+ }
+
+ if (src_addr && addrlen && *addrlen >= sizeof(*src_addr))
+ {
+ sockaddr_to_nuttx(&naddr, naddrlen, src_addr, addrlen);
+ }
+
+ usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+ return ret;
+}
+
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+ const void *optval, nuttx_socklen_t optlen)
+{
+ return usrsock_host_sockopt(sockfd, level, optname,
+ optval, &optlen, true);
+}
+
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+ void *optval, nuttx_socklen_t *optlen)
+{
+ return usrsock_host_sockopt(sockfd, level, optname,
+ optval, optlen, false);
+}
+
+int usrsock_host_getsockname(int sockfd,
+ struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen)
+{
+ socklen_t naddrlen = sizeof(struct sockaddr);
+ struct sockaddr naddr;
+ int ret;
+
+ ret = getsockname(sockfd, &naddr, &naddrlen);
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ if (addr && addrlen && *addrlen >= sizeof(*addr))
+ {
+ sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+ }
+
+ return ret;
+}
+
+int usrsock_host_getpeername(int sockfd,
+ struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen)
+{
+ socklen_t naddrlen = sizeof(struct sockaddr);
+ struct sockaddr naddr;
+ int ret;
+
+ ret = getpeername(sockfd, &naddr, &naddrlen);
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ if (addr && addrlen && *addrlen >= sizeof(*addr))
+ {
+ sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+ }
+
+ return ret;
+}
+
+int usrsock_host_bind(int sockfd,
+ const struct nuttx_sockaddr *addr,
+ nuttx_socklen_t addrlen)
+{
+ struct sockaddr naddr;
+ socklen_t naddrlen;
+
+ sockaddr_to_native(addr, addrlen, &naddr, &naddrlen);
+
+ return bind(sockfd, &naddr, naddrlen) < 0 ? -errno : 0;
+}
+
+int usrsock_host_listen(int sockfd, int backlog)
+{
+ int ret;
+
+ ret = listen(sockfd, backlog);
+ if (ret < 0)
+ {
+ return -errno;
+ }
+
+ usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+ return ret;
+}
+
+int usrsock_host_accept(int sockfd, struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen)
+{
+ struct sockaddr naddr;
+ socklen_t naddrlen;
+ int ret;
+
+ ret = accept(sockfd, &naddr, &naddrlen);
+ if (ret <= 0)
+ {
+ return -errno;
+ }
+
+ if (addr && addrlen && *addrlen >= sizeof(*addr))
+ {
+ sockaddr_to_nuttx(&naddr, naddrlen, addr, addrlen);
+ }
+
+ sock_nonblock(ret, true);
+ usrsock_host_set_fd(ret, &g_active_read_fds);
+ usrsock_host_set_fd(sockfd, &g_active_read_fds);
+
+ return ret;
+}
+
+int usrsock_host_ioctl(int fd, unsigned long request, ...)
+{
+ return 0;
+}
+
+void usrsock_host_loop(void)
+{
+ struct timeval timeout;
+ fd_set write_fds;
+ fd_set read_fds;
+ uint16_t events;
+ int ret;
+ int i;
+
+ if (g_active_maxfd <= 0)
+ {
+ return;
+ }
+
+ memset(&timeout, 0x0, sizeof(timeout));
+ memcpy(&read_fds, &g_active_read_fds, sizeof(read_fds));
+ memcpy(&write_fds, &g_active_write_fds, sizeof(write_fds));
+
+ ret = select(g_active_maxfd + 1, &read_fds, &write_fds, NULL, &timeout);
+ if (ret == 0)
+ {
+ return;
+ }
+
+ for (i = 0; i <= g_active_maxfd; i++)
+ {
+ events = 0;
+
+ if (FD_ISSET(i, &read_fds))
+ {
+ usrsock_host_clear_fd(i, &g_active_read_fds);
+ events |= NUTTX_USRSOCK_EVENT_RECVFROM_AVAIL;
+ }
+
+ if (FD_ISSET(i, &write_fds))
+ {
+ usrsock_host_clear_fd(i, &g_active_write_fds);
+ events |= NUTTX_USRSOCK_EVENT_SENDTO_READY;
+ }
+
+ if (events)
+ {
+ usrsock_event_callback(i, events);
+
+ if (--ret == 0)
+ {
+ break;
+ }
+ }
+ }
+}
diff --git a/arch/sim/src/sim/up_usrsock_host.h b/arch/sim/src/sim/up_usrsock_host.h
new file mode 100644
index 0000000..1374d2c
--- /dev/null
+++ b/arch/sim/src/sim/up_usrsock_host.h
@@ -0,0 +1,317 @@
+/****************************************************************************
+ * arch/sim/src/sim/up_usrsock_host.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H
+#define __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#ifndef __SIM__
+# include <sys/socket.h>
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#ifdef __SIM__
+
+#define NUTTX_IPPROTO_IP 0
+#define NUTTX_IPPROTO_HOPOPTS 0
+#define NUTTX_IPPROTO_ICMP 1
+#define NUTTX_IPPROTO_IGMP 2
+#define NUTTX_IPPROTO_IPIP 4
+#define NUTTX_IPPROTO_TCP 6
+#define NUTTX_IPPROTO_EGP 8
+#define NUTTX_IPPROTO_PUP 12
+#define NUTTX_IPPROTO_UDP 17
+#define NUTTX_IPPROTO_IDP 22
+#define NUTTX_IPPROTO_TP 29
+#define NUTTX_IPPROTO_DCCP 33
+#define NUTTX_IPPROTO_IPV6 41
+#define NUTTX_IPPROTO_ROUTING 43
+#define NUTTX_IPPROTO_FRAGMENT 44
+#define NUTTX_IPPROTO_RSVP 46
+#define NUTTX_IPPROTO_GRE 47
+#define NUTTX_IPPROTO_ESP 50
+#define NUTTX_IPPROTO_AH 51
+#define NUTTX_IPPROTO_ICMP6 58
+#define NUTTX_IPPROTO_NONE 59
+#define NUTTX_IPPROTO_DSTOPTS 60
+#define NUTTX_IPPROTO_MTP 92
+#define NUTTX_IPPROTO_ENCAP 98
+#define NUTTX_IPPROTO_BEETPH 94
+#define NUTTX_IPPROTO_PIM 103
+#define NUTTX_IPPROTO_COMP 108
+#define NUTTX_IPPROTO_SCTP 132
+#define NUTTX_IPPROTO_UDPLITE 136
+#define NUTTX_IPPROTO_MPLS 137
+#define NUTTX_IPPROTO_RAW 255
+
+#define NUTTX_PF_UNSPEC 0
+#define NUTTX_PF_UNIX 1
+#define NUTTX_PF_LOCAL 1
+#define NUTTX_PF_INET 2
+#define NUTTX_PF_INET6 10
+#define NUTTX_PF_NETLINK 16
+#define NUTTX_PF_ROUTE NUTTX_PF_NETLINK
+#define NUTTX_PF_PACKET 17
+#define NUTTX_PF_CAN 29
+#define NUTTX_PF_BLUETOOTH 31
+#define NUTTX_PF_IEEE802154 36
+#define NUTTX_PF_PKTRADIO 64
+#define NUTTX_PF_RPMSG 65
+
+#define NUTTX_AF_UNSPEC NUTTX_PF_UNSPEC
+#define NUTTX_AF_UNIX NUTTX_PF_UNIX
+#define NUTTX_AF_LOCAL NUTTX_PF_LOCAL
+#define NUTTX_AF_INET NUTTX_PF_INET
+#define NUTTX_AF_INET6 NUTTX_PF_INET6
+#define NUTTX_AF_NETLINK NUTTX_PF_NETLINK
+#define NUTTX_AF_ROUTE NUTTX_PF_ROUTE
+#define NUTTX_AF_PACKET NUTTX_PF_PACKET
+#define NUTTX_AF_CAN NUTTX_PF_CAN
+#define NUTTX_AF_BLUETOOTH NUTTX_PF_BLUETOOTH
+#define NUTTX_AF_IEEE802154 NUTTX_PF_IEEE802154
+#define NUTTX_AF_PKTRADIO NUTTX_PF_PKTRADIO
+#define NUTTX_AF_RPMSG NUTTX_PF_RPMSG
+
+#define NUTTX_SOCK_UNSPEC 0
+#define NUTTX_SOCK_STREAM 1
+#define NUTTX_SOCK_DGRAM 2
+#define NUTTX_SOCK_RAW 3
+#define NUTTX_SOCK_RDM 4
+#define NUTTX_SOCK_SEQPACKET 5
+#define NUTTX_SOCK_PACKET 10
+#define NUTTX_SOCK_CLOEXEC 02000000
+#define NUTTX_SOCK_NONBLOCK 00004000
+
+#define NUTTX_SOCK_MAX (NUTTX_SOCK_PACKET + 1)
+#define NUTTX_SOCK_TYPE_MASK 0xf
+
+#define NUTTX_MSG_OOB 0x0001
+#define NUTTX_MSG_PEEK 0x0002
+#define NUTTX_MSG_DONTROUTE 0x0004
+#define NUTTX_MSG_CTRUNC 0x0008
+#define NUTTX_MSG_PROXY 0x0010
+#define NUTTX_MSG_TRUNC 0x0020
+#define NUTTX_MSG_DONTWAIT 0x0040
+#define NUTTX_MSG_EOR 0x0080
+#define NUTTX_MSG_WAITALL 0x0100
+#define NUTTX_MSG_FIN 0x0200
+#define NUTTX_MSG_SYN 0x0400
+#define NUTTX_MSG_CONFIRM 0x0800
+#define NUTTX_MSG_RST 0x1000
+#define NUTTX_MSG_ERRQUEUE 0x2000
+#define NUTTX_MSG_NOSIGNAL 0x4000
+#define NUTTX_MSG_MORE 0x8000
+
+#define NUTTX_SOL_SOCKET 1
+#define NUTTX_SO_ACCEPTCONN 0
+#define NUTTX_SO_BROADCAST 1
+#define NUTTX_SO_DEBUG 2
+#define NUTTX_SO_DONTROUTE 3
+#define NUTTX_SO_ERROR 4
+#define NUTTX_SO_KEEPALIVE 5
+#define NUTTX_SO_LINGER 6
+#define NUTTX_SO_OOBINLINE 7
+#define NUTTX_SO_RCVBUF 8
+#define NUTTX_SO_RCVLOWAT 9
+#define NUTTX_SO_RCVTIMEO 10
+#define NUTTX_SO_REUSEADDR 11
+#define NUTTX_SO_SNDBUF 12
+#define NUTTX_SO_SNDLOWAT 13
+#define NUTTX_SO_SNDTIMEO 14
+#define NUTTX_SO_TYPE 15
+#define NUTTX_SO_TIMESTAMP 16
+
+#define NUTTX_SO_SNDBUFFORCE 32
+#define NUTTX_SO_RCVBUFFORCE 33
+#define NUTTX_SO_RXQ_OVFL 40
+
+#define NUTTX_SOL_IP NUTTX_IPPROTO_IP
+#define NUTTX_SOL_IPV6 NUTTX_IPPROTO_IPV6
+#define NUTTX_SOL_TCP NUTTX_IPPROTO_TCP
+#define NUTTX_SOL_UDP NUTTX_IPPROTO_UDP
+
+#define NUTTX_SOL_HCI 0
+#define NUTTX_SOL_L2CAP 6
+#define NUTTX_SOL_SCO 17
+#define NUTTX_SOL_RFCOMM 18
+
+#define NUTTX___SO_PROTOCOL 16
+
+#define NUTTX_SHUT_RD 1
+#define NUTTX_SHUT_WR 2
+#define NUTTX_SHUT_RDWR 3
+
+#define NUTTX_SCM_RIGHTS 0x01
+#define NUTTX_SCM_CREDENTIALS 0x02
+#define NUTTX_SCM_SECURITY 0x03
+
+#define NUTTX_IP_MULTICAST_IF (NUTTX__SO_PROTOCOL + 1)
+#define NUTTX_IP_MULTICAST_TTL (NUTTX__SO_PROTOCOL + 2)
+#define NUTTX_IP_MULTICAST_LOOP (NUTTX__SO_PROTOCOL + 3)
+#define NUTTX_IP_ADD_MEMBERSHIP (NUTTX__SO_PROTOCOL + 4)
+#define NUTTX_IP_DROP_MEMBERSHIP (NUTTX__SO_PROTOCOL + 5)
+#define NUTTX_IP_UNBLOCK_SOURCE (NUTTX__SO_PROTOCOL + 6)
+#define NUTTX_IP_BLOCK_SOURCE (NUTTX__SO_PROTOCOL + 7)
+#define NUTTX_IP_ADD_SOURCE_MEMBERSHIP (NUTTX__SO_PROTOCOL + 8)
+#define NUTTX_IP_DROP_SOURCE_MEMBERSHIP (NUTTX__SO_PROTOCOL + 9)
+#define NUTTX_IP_MSFILTER (NUTTX__SO_PROTOCOL + 10)
+#define NUTTX_IP_MULTICAST_ALL (NUTTX__SO_PROTOCOL + 11)
+#define NUTTX_IP_PKTINFO (NUTTX__SO_PROTOCOL + 12)
+#define NUTTX_IP_TOS (NUTTX__SO_PROTOCOL + 13)
+#define NUTTX_IP_TTL (NUTTX__SO_PROTOCOL + 14)
+
+/* Event message flags */
+
+#define NUTTX_USRSOCK_EVENT_ABORT (1 << 1)
+#define NUTTX_USRSOCK_EVENT_SENDTO_READY (1 << 2)
+#define NUTTX_USRSOCK_EVENT_RECVFROM_AVAIL (1 << 3)
+#define NUTTX_USRSOCK_EVENT_REMOTE_CLOSED (1 << 4)
+
+/****************************************************************************
+ * Type Definitions
+ ****************************************************************************/
+
+typedef unsigned int nuttx_socklen_t;
+
+#ifdef CONFIG_NET_IPv6
+struct nuttx_sockaddr_storage
+{
+ sa_family_t ss_family; /* Address family */
+ char ss_data[26]; /* 26-bytes of address data */
+};
+#else
+struct nuttx_sockaddr_storage
+{
+ sa_family_t ss_family; /* Address family */
+ char ss_data[14]; /* 14-bytes of address data */
+};
+#endif
+
+struct nuttx_sockaddr
+{
+ sa_family_t sa_family; /* Address family: See AF_* definitions */
+ char sa_data[14]; /* 14-bytes data (actually variable length) */
+};
+
+struct nuttx_linger
+{
+ int l_onoff; /* Indicates whether linger option is enabled. */
+ int l_linger; /* Linger time, in seconds. */
+};
+
+struct nuttx_iovec
+{
+ void *iov_base; /* Base address of I/O memory region */
+ size_t iov_len; /* Size of the memory pointed to by iov_base */
+};
+
+struct nuttx_msghdr
+{
+ void *msg_name; /* Socket name */
+ socklen_t msg_namelen; /* Length of name */
+ struct nuttx_iovec *msg_iov; /* Data blocks */
+ unsigned long msg_iovlen; /* Number of blocks */
+ void *msg_control; /* Per protocol magic
+ * (eg BSD file descriptor passing)
+ */
+ unsigned long msg_controllen; /* Length of cmsg list */
+ unsigned int msg_flags;
+};
+
+struct nuttx_cmsghdr
+{
+ unsigned long cmsg_len; /* Data byte count, including hdr */
+ int cmsg_level; /* Originating protocol */
+ int cmsg_type; /* Protocol-specific type */
+};
+
+#endif /* __SIM__ */
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#ifdef __SIM__
+int usrsock_event_callback(int16_t usockid, uint16_t events);
+
+int usrsock_host_socket(int domain, int type, int protocol);
+int usrsock_host_close(int sockfd);
+int usrsock_host_connect(int sockfd, const struct nuttx_sockaddr *addr,
+ nuttx_socklen_t addrlen);
+ssize_t usrsock_host_sendto(int sockfd, const void *buf, size_t len,
+ int flags,
+ const struct nuttx_sockaddr *dest_addr,
+ nuttx_socklen_t addrlen);
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct nuttx_sockaddr *src_addr,
+ nuttx_socklen_t *addrlen);
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+ const void *optval, nuttx_socklen_t optlen);
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+ void *optval, nuttx_socklen_t *optlen);
+int usrsock_host_getsockname(int sockfd,
+ struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen);
+int usrsock_host_getpeername(int sockfd,
+ struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen);
+int usrsock_host_bind(int sockfd, const struct nuttx_sockaddr *addr,
+ nuttx_socklen_t addrlen);
+int usrsock_host_listen(int sockfd, int backlog);
+int usrsock_host_accept(int sockfd, struct nuttx_sockaddr *addr,
+ nuttx_socklen_t *addrlen);
+int usrsock_host_ioctl(int fd, unsigned long request, ...);
+#else
+int usrsock_host_socket(int domain, int type, int protocol);
+int usrsock_host_close(int sockfd);
+int usrsock_host_connect(int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen);
+ssize_t usrsock_host_sendto(int sockfd, const void *buf, size_t len,
+ int flags,
+ const struct sockaddr *dest_addr,
+ socklen_t addrlen);
+ssize_t usrsock_host_recvfrom(int sockfd, void *buf, size_t len, int flags,
+ struct sockaddr *src_addr,
+ socklen_t *addrlen);
+int usrsock_host_setsockopt(int sockfd, int level, int optname,
+ const void *optval, socklen_t optlen);
+int usrsock_host_getsockopt(int sockfd, int level, int optname,
+ void *optval, socklen_t *optlen);
+int usrsock_host_getsockname(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen);
+int usrsock_host_getpeername(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen);
+int usrsock_host_bind(int sockfd, const struct sockaddr *addr,
+ socklen_t addrlen);
+int usrsock_host_listen(int sockfd, int backlog);
+int usrsock_host_accept(int sockfd, struct sockaddr *addr,
+ socklen_t *addrlen);
+int usrsock_host_ioctl(int fd, unsigned long request, ...);
+
+void usrsock_host_loop(void);
+#endif /* __SIM__ */
+
+#endif /* __ARCH_SIM_SRC_SIM_UP_USRSOCK_HOST_H */