From 48c9d1033659603663f6e35587cf27045a130e0d Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Fri, 18 Nov 2022 18:16:19 +0800 Subject: [PATCH] net_socket: add accept4 function Signed-off-by: zhanghongyu --- drivers/usrsock/usrsock_rpmsg_server.c | 7 +-- drivers/video/vnc/vnc_server.c | 2 +- include/nuttx/net/net.h | 4 +- include/sys/socket.h | 2 + include/sys/syscall_lookup.h | 1 + net/inet/inet_sockif.c | 5 +- net/socket/accept.c | 63 ++++++++++++++++++++++---- syscall/syscall.csv | 1 + 8 files changed, 69 insertions(+), 16 deletions(-) diff --git a/drivers/usrsock/usrsock_rpmsg_server.c b/drivers/usrsock/usrsock_rpmsg_server.c index 2795a55e3c..56d423efcb 100644 --- a/drivers/usrsock/usrsock_rpmsg_server.c +++ b/drivers/usrsock/usrsock_rpmsg_server.c @@ -785,13 +785,10 @@ static int usrsock_rpmsg_accept_handler(FAR struct rpmsg_endpoint *ept, nxrmutex_unlock(&priv->mutex); ret = psock_accept(&priv->socks[req->usockid], outaddrlen ? (FAR struct sockaddr *)(ack + 1) : NULL, - outaddrlen ? &outaddrlen : NULL, &priv->socks[i]); + outaddrlen ? &outaddrlen : NULL, &priv->socks[i], + SOCK_NONBLOCK); if (ret >= 0) { - int nonblock = 1; - - psock_ioctl(&priv->socks[i], FIONBIO, &nonblock); - /* Append index as usockid to the payload */ if (outaddrlen <= inaddrlen) diff --git a/drivers/video/vnc/vnc_server.c b/drivers/video/vnc/vnc_server.c index fada149e33..f0d79158f8 100644 --- a/drivers/video/vnc/vnc_server.c +++ b/drivers/video/vnc/vnc_server.c @@ -185,7 +185,7 @@ static int vnc_connect(FAR struct vnc_session_s *session, int port) ginfo("Accepting connection for Display %d\n", session->display); - ret = psock_accept(&session->listen, NULL, NULL, &session->connect); + ret = psock_accept(&session->listen, NULL, NULL, &session->connect, 0); if (ret < 0) { goto errout_with_listener; diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index bdabcbaf83..5e5cec7b0f 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -700,6 +700,7 @@ int psock_listen(FAR struct socket *psock, int backlog); * addrlen Input: allocated size of 'addr', Return: returned size of * 'addr' * newsock Location to return the accepted socket information. + * flags The flags used for initialization * * Returned Value: * Returns zero (OK) on success. On failure, it returns a negated errno @@ -734,7 +735,8 @@ int psock_listen(FAR struct socket *psock, int backlog); ****************************************************************************/ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, - FAR socklen_t *addrlen, FAR struct socket *newsock); + FAR socklen_t *addrlen, FAR struct socket *newsock, + int flags); /**************************************************************************** * Name: psock_connect diff --git a/include/sys/socket.h b/include/sys/socket.h index 28cd271491..d54c38f542 100644 --- a/include/sys/socket.h +++ b/include/sys/socket.h @@ -387,6 +387,8 @@ int connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen); int listen(int sockfd, int backlog); int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen); +int accept4(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen, + int flags); ssize_t send(int sockfd, FAR const void *buf, size_t len, int flags); ssize_t sendto(int sockfd, FAR const void *buf, size_t len, int flags, diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index fdfbb710a9..5a75cb4dd0 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -348,6 +348,7 @@ SYSCALL_LOOKUP(munmap, 2) #ifdef CONFIG_NET SYSCALL_LOOKUP(accept, 3) + SYSCALL_LOOKUP(accept4, 4) SYSCALL_LOOKUP(bind, 3) SYSCALL_LOOKUP(connect, 3) SYSCALL_LOOKUP(getpeername, 3) diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index 85f12a0521..7c2b30cfcb 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -1936,6 +1936,8 @@ static int inet_socketpair(FAR struct socket *psocks[2]) #if defined(CONFIG_NET_TCP) if (psocks[0]->s_type == SOCK_STREAM) { + FAR struct socket_conn_s *conn = psocks[1]->s_conn; + ret = psock_listen(pserver, 2); if (ret < 0) { @@ -1954,7 +1956,8 @@ static int inet_socketpair(FAR struct socket *psocks[2]) psock_close(psocks[1]); - ret = psock_accept(pserver, &addr[1].addr, &len, psocks[1]); + ret = psock_accept(pserver, &addr[1].addr, &len, psocks[1], + conn->s_flags & _SF_NONBLOCK ? SOCK_NONBLOCK : 0); } #endif /* CONFIG_NET_TCP */ diff --git a/net/socket/accept.c b/net/socket/accept.c index 14491128c3..c0a2cc0eb3 100644 --- a/net/socket/accept.c +++ b/net/socket/accept.c @@ -78,6 +78,7 @@ * addrlen Input: allocated size of 'addr', Return: returned size * of 'addr' * newsock Location to return the accepted socket information. + * flags The flags used for initialization * * Returned Value: * Returns 0 (OK) on success. On failure, it returns a negated errno value @@ -111,7 +112,8 @@ ****************************************************************************/ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, - FAR socklen_t *addrlen, FAR struct socket *newsock) + FAR socklen_t *addrlen, FAR struct socket *newsock, + int flags) { FAR struct socket_conn_s *conn; int ret; @@ -148,6 +150,10 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, conn = newsock->s_conn; conn->s_flags |= _SF_CONNECTED; conn->s_flags &= ~_SF_CLOSED; + if (flags & SOCK_NONBLOCK) + { + conn->s_flags |= _SF_NONBLOCK; + } } else { @@ -159,10 +165,10 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, } /**************************************************************************** - * Name: accept + * Name: accept4 * * Description: - * The accept function is used with connection-based socket types + * The accept4 function is used with connection-based socket types * (SOCK_STREAM, SOCK_SEQPACKET and SOCK_RDM). It extracts the first * connection request on the queue of pending connections, creates a new * connected socket with mostly the same properties as 'sockfd', and @@ -190,6 +196,7 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, * addr Receives the address of the connecting client * addrlen Input: allocated size of 'addr', * Return: returned size of 'addr' + * flags The flags used for initialization * * Returned Value: * Returns -1 on error. If it succeeds, it returns a non-negative integer @@ -227,18 +234,26 @@ int psock_accept(FAR struct socket *psock, FAR struct sockaddr *addr, * ****************************************************************************/ -int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +int accept4(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen, + int flags) { - FAR struct socket *psock; + FAR struct socket *psock = NULL; FAR struct socket *newsock; + int oflags = O_RDWR; int errcode; int newfd; int ret; - /* accept() is a cancellation point */ + /* accept4() is a cancellation point */ enter_cancellation_point(); + if (flags & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) + { + errcode = EINVAL; + goto errout; + } + /* Get the underlying socket structure */ ret = sockfd_socket(sockfd, &psock); @@ -258,7 +273,7 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) goto errout; } - ret = psock_accept(psock, addr, addrlen, newsock); + ret = psock_accept(psock, addr, addrlen, newsock, flags); if (ret < 0) { errcode = -ret; @@ -269,7 +284,17 @@ int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) * cannot fail later) */ - newfd = sockfd_allocate(newsock, O_RDWR); + if (flags & SOCK_CLOEXEC) + { + oflags |= O_CLOEXEC; + } + + if (flags & SOCK_NONBLOCK) + { + oflags |= O_NONBLOCK; + } + + newfd = sockfd_allocate(newsock, oflags); if (newfd < 0) { errcode = ENFILE; @@ -291,3 +316,25 @@ errout: _SO_SETERRNO(psock, errcode); return ERROR; } + +/**************************************************************************** + * Name: accept + * + * Description: + * The accept() call is identical to accept4() with a zero flags. + * + * Input Parameters: + * sockfd The listening socket descriptor + * addr Receives the address of the connecting client + * addrlen Input: allocated size of 'addr', + * Return: returned size of 'addr' + * + * Returned Value: + * (see accept4) + * + ****************************************************************************/ + +int accept(int sockfd, FAR struct sockaddr *addr, FAR socklen_t *addrlen) +{ + return accept4(sockfd, addr, addrlen, 0); +} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index ecf735fe89..042f276060 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -1,6 +1,7 @@ "_exit","unistd.h","","noreturn","int" "_assert","assert.h","","void","FAR const char *","int" "accept","sys/socket.h","defined(CONFIG_NET)","int","int","FAR struct sockaddr *","FAR socklen_t *" +"accept4","sys/socket.h","defined(CONFIG_NET)","int","int","FAR struct sockaddr *","FAR socklen_t *","int" "adjtime","sys/time.h","defined(CONFIG_CLOCK_TIMEKEEPING)","int","FAR const struct timeval *","FAR struct timeval *" "aio_cancel","aio.h","defined(CONFIG_FS_AIO)","int","int","FAR struct aiocb *" "aio_fsync","aio.h","defined(CONFIG_FS_AIO)","int","int","FAR struct aiocb *"