arch/sim: add native socket support based on usrsock

Signed-off-by: chao.an <anchao@xiaomi.com>
This commit is contained in:
chao.an 2021-08-29 17:52:02 +08:00 committed by Xiang Xiao
parent c9d784a238
commit b90d094138
9 changed files with 1321 additions and 2 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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();
}

View File

@ -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;
}
}
}
}

View File

@ -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 */