diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index fb31d93158d..9302c6c4539 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -197,7 +197,6 @@ struct sock_intf_s CODE int (*si_close)(FAR struct socket *psock); CODE int (*si_ioctl)(FAR struct socket *psock, int cmd, FAR void *arg, size_t arglen); - CODE int (*si_socketpair)(FAR struct socket *psocks[2]); #ifdef CONFIG_NET_SENDFILE CODE ssize_t (*si_sendfile)(FAR struct socket *psock, FAR struct file *infile, FAR off_t *offset, @@ -1424,27 +1423,6 @@ int psock_vfcntl(FAR struct socket *psock, int cmd, va_list ap); int psock_fcntl(FAR struct socket *psock, int cmd, ...); -/**************************************************************************** - * Name: psock_socketpair - * - * Description: - * Create an unbound pair of connected sockets in a specified domain, of a - * specified type, under the protocol optionally specified by the protocol - * argument. The two sockets shall be identical. The file descriptors used - * in referencing the created sockets shall be returned in - * sv[0] and sv[1]. - * - * Input Parameters: - * domain (see sys/socket.h) - * type (see sys/socket.h) - * protocol (see sys/socket.h) - * psocks A pointer to a user allocated socket structure to be paired. - * - ****************************************************************************/ - -int psock_socketpair(int domain, int type, int protocol, - FAR struct socket *psocks[2]); - /**************************************************************************** * Name: netdev_register * diff --git a/libs/libc/net/Make.defs b/libs/libc/net/Make.defs index 48617263d66..c32eb10e974 100644 --- a/libs/libc/net/Make.defs +++ b/libs/libc/net/Make.defs @@ -26,7 +26,7 @@ CSRCS += lib_inetntop.c lib_inetpton.c CSRCS += lib_etherntoa.c lib_etheraton.c ifeq ($(CONFIG_NET),y) -CSRCS += lib_shutdown.c +CSRCS += lib_shutdown.c lib_socketpair.c endif ifeq ($(CONFIG_NET_LOOPBACK),y) diff --git a/libs/libc/net/lib_socketpair.c b/libs/libc/net/lib_socketpair.c new file mode 100644 index 00000000000..3bae979f8ff --- /dev/null +++ b/libs/libc/net/lib_socketpair.c @@ -0,0 +1,186 @@ +/**************************************************************************** + * libs/libc/net/lib_socketpair.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 +#include +#include +#include +#include +#include +#include + +/**************************************************************************** + * Public Type Declarations + ****************************************************************************/ + +union sockaddr_u +{ + struct sockaddr addr; + struct sockaddr_in inaddr; + struct sockaddr_in6 in6addr; +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void init_loop_addr(int domain, FAR union sockaddr_u *addr, + FAR socklen_t *len) +{ + if (domain == AF_INET6) + { + struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT; + + memset(&addr->in6addr, 0, sizeof(addr->in6addr)); + addr->in6addr.sin6_family = domain; + addr->in6addr.sin6_addr = init_sin6_addr; + *len = sizeof(addr->in6addr); + } + else + { + memset(&addr->inaddr, 0, sizeof(addr->inaddr)); + addr->inaddr.sin_family = domain; + addr->inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + *len = sizeof(addr->inaddr); + } +} + +static int create_socket(int domain, int type, int protocol, + FAR union sockaddr_u *addr, FAR socklen_t *len) +{ + int socketfd; + + socketfd = socket(domain, type, protocol); + if (socketfd < 0) + { + return socketfd; + } + + init_loop_addr(domain, addr, len); + if (bind(socketfd, &addr->addr, *len) == 0) + { + if (getsockname(socketfd, &addr->addr, len) == 0) + { + return socketfd; + } + } + + close(socketfd); + return -1; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: socketpair + * + * Description: + * Create an unbound pair of connected sockets in a specified domain, of a + * specified type, under the protocol optionally specified by the protocol + * argument. The two sockets shall be identical. The file descriptors used + * in referencing the created sockets shall be returned in + * sv[0] and sv[1]. + * + ****************************************************************************/ + +int socketpair(int domain, int type, int protocol, int sv[2]) +{ + union sockaddr_u addr[2]; + socklen_t len; + + if (domain != AF_UNIX && domain != AF_INET && domain != AF_INET6) + { + set_errno(EAFNOSUPPORT); + return -1; + } + + if (sv == NULL) + { + set_errno(EINVAL); + return -1; + } + + if (domain == AF_UNIX) + { + domain = AF_INET; + } + + sv[0] = create_socket(domain, type, protocol, &addr[0], &len); + sv[1] = create_socket(domain, type, protocol, &addr[1], &len); + if (sv[0] < 0 || sv[1] < 0) + { + goto err; + } + + if (type == SOCK_DGRAM) + { + if (connect(sv[0], &addr[1].addr, len) < 0) + { + goto err; + } + + if (connect(sv[1], &addr[0].addr, len) < 0) + { + goto err; + } + } + else + { + int listener = sv[0]; + + if (listen(listener, 2) < 0) + { + goto err; + } + + if (connect(sv[1], &addr[0].addr, len) < 0) + { + goto err; + } + + sv[0] = accept(listener, &addr[0].addr, &len); + close(listener); + if (sv[0] < 0) + { + goto err; + } + } + + return 0; + +err: + if (sv[0] != -1) + { + close(sv[0]); + } + + if (sv[1] != -1) + { + close(sv[1]); + } + + return -1; +} diff --git a/net/inet/inet_sockif.c b/net/inet/inet_sockif.c index b37df49a20e..4486b563edb 100644 --- a/net/inet/inet_sockif.c +++ b/net/inet/inet_sockif.c @@ -32,7 +32,6 @@ #include #include -#include #include #include "tcp/tcp.h" @@ -45,17 +44,6 @@ #ifdef HAVE_INET_SOCKETS -/**************************************************************************** - * Private Type Definitions - ****************************************************************************/ - -union sockaddr_u -{ - struct sockaddr addr; - struct sockaddr_in inaddr; - struct sockaddr_in6 in6addr; -}; - /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -90,7 +78,6 @@ static ssize_t inet_recvmsg(FAR struct socket *psock, FAR struct msghdr *msg, int flags); static int inet_ioctl(FAR struct socket *psock, int cmd, FAR void *arg, size_t arglen); -static int inet_socketpair(FAR struct socket *psocks[2]); #ifdef CONFIG_NET_SENDFILE static ssize_t inet_sendfile(FAR struct socket *psock, FAR struct file *infile, FAR off_t *offset, @@ -116,8 +103,7 @@ static const struct sock_intf_s g_inet_sockif = inet_sendmsg, /* si_sendmsg */ inet_recvmsg, /* si_recvmsg */ inet_close, /* si_close */ - inet_ioctl, /* si_ioctl */ - inet_socketpair /* si_socketpair */ + inet_ioctl /* si_ioctl */ #ifdef CONFIG_NET_SENDFILE , inet_sendfile /* si_sendfile */ @@ -1342,130 +1328,6 @@ static int inet_ioctl(FAR struct socket *psock, int cmd, return -EINVAL; } -/**************************************************************************** - * Name: inet_socketpair - * - * Description: - * Create a pair of connected sockets between psocks[2] - * - * Parameters: - * psocks A reference to the socket structure of the socket pair - * - ****************************************************************************/ - -static int inet_socketpair(FAR struct socket *psocks[2]) -{ - FAR struct socket *pserver; - FAR struct socket server; - union sockaddr_u addr[2]; - socklen_t len; - int ret; - - /* Set the sock address to localhost */ - -#ifdef CONFIG_NET_IPv6 - if (psocks[0]->s_domain == AF_INET6) - { - struct in6_addr init_sin6_addr = IN6ADDR_LOOPBACK_INIT; - - len = sizeof(addr[0].in6addr); - memset(&addr[0], 0, len); - addr[0].in6addr.sin6_family = psocks[0]->s_domain; - addr[0].in6addr.sin6_addr = init_sin6_addr; - } - else -#endif - { - len = sizeof(addr[0].inaddr); - memset(&addr[0], 0, len); - addr[0].inaddr.sin_family = psocks[0]->s_domain; - addr[0].inaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - } - - memcpy(&addr[1], &addr[0], len); - - ret = psock_bind(psocks[0], &addr[0].addr, len); - if (ret < 0) - { - return ret; - } - - psock_getsockname(psocks[0], &addr[0].addr, &len); - - /* For SOCK_STREAM, Use proxy service handle to make temporary - * pserver process, psocks[1] will be replaced with a new accept handle - */ - - if (psocks[0]->s_type == SOCK_STREAM) - { - ret = psock_socket(psocks[1]->s_domain, psocks[1]->s_type, - psocks[1]->s_proto, &server); - if (ret < 0) - { - return ret; - } - - pserver = &server; - } - else - { - pserver = psocks[1]; - } - - ret = psock_bind(pserver, &addr[1].addr, len); - if (ret < 0) - { - goto errout; - } - - psock_getsockname(pserver, &addr[1].addr, &len); - - if (psocks[0]->s_type == SOCK_DGRAM) - { - ret = psock_connect(psocks[0], &addr[1].addr, len); - if (ret < 0) - { - goto errout; - } - - ret = psock_connect(pserver, &addr[0].addr, len); - if (ret < 0) - { - goto errout; - } - } - else - { - ret = psock_listen(pserver, 2); - if (ret < 0) - { - goto errout; - } - - ret = psock_connect(psocks[0], &addr[1].addr, len); - if (ret < 0) - { - goto errout; - } - - /* Release the resource of psocks[1], accept will replace - * this handle - */ - - psock_close(psocks[1]); - - ret = psock_accept(pserver, &addr[1].addr, &len, psocks[1]); - } - -errout: - if (pserver->s_type == SOCK_STREAM) - { - psock_close(pserver); - } - - return ret; -} - /**************************************************************************** * Name: inet_sendfile * diff --git a/net/socket/Make.defs b/net/socket/Make.defs index f71a42c3b5a..431868afd03 100644 --- a/net/socket/Make.defs +++ b/net/socket/Make.defs @@ -22,7 +22,7 @@ SOCK_CSRCS += bind.c connect.c getsockname.c getpeername.c SOCK_CSRCS += recv.c recvfrom.c send.c sendto.c -SOCK_CSRCS += socket.c socketpair.c net_close.c +SOCK_CSRCS += socket.c net_close.c SOCK_CSRCS += recvmsg.c sendmsg.c SOCK_CSRCS += net_dup2.c net_sockif.c net_poll.c net_vfcntl.c SOCK_CSRCS += net_fstat.c diff --git a/net/socket/socketpair.c b/net/socket/socketpair.c deleted file mode 100644 index 1f4b6bac347..00000000000 --- a/net/socket/socketpair.c +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** - * net/socket/socketpair.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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: socketpair - * - * Description: - * Create an unbound pair of connected sockets in a specified domain, of a - * specified type, under the protocol optionally specified by the protocol - * argument. The two sockets shall be identical. The file descriptors used - * in referencing the created sockets shall be returned in - * sv[0] and sv[1]. - * - * Input Parameters: - * domain - (see sys/socket.h) - * type - (see sys/socket.h) - * protocol - (see sys/socket.h) - * psocks - The array to catch the pair descriptors - * - ****************************************************************************/ - -int psock_socketpair(int domain, int type, int protocol, - FAR struct socket *psocks[2]) -{ - int ret; - - /* Initialize the socket structure */ - - ret = psock_socket(domain, type, protocol, psocks[0]); - if (ret < 0) - { - return ret; - } - - if (psocks[0]->s_sockif->si_socketpair == NULL) - { - ret = -EAFNOSUPPORT; - goto errsock; - } - - ret = psock_socket(domain, type, protocol, psocks[1]); - if (ret < 0) - { - goto errsock; - } - - /* Perform socketpair process */ - - ret = psocks[0]->s_sockif->si_socketpair(psocks); - if (ret == 0) - { - return ret; - } - - psock_close(psocks[1]); -errsock: - psock_close(psocks[0]); - return ret; -} - -/**************************************************************************** - * Name: socketpair - * - * Description: - * Create an unbound pair of connected sockets in a specified domain, of a - * specified type, under the protocol optionally specified by the protocol - * argument. The two sockets shall be identical. The file descriptors used - * in referencing the created sockets shall be returned in - * sv[0] and sv[1]. - * - * Input Parameters: - * domain - (see sys/socket.h) - * type - (see sys/socket.h) - * protocol - (see sys/socket.h) - * sv[2] - The user provided array in which to catch the pair - descriptors - * - ****************************************************************************/ - -int socketpair(int domain, int type, int protocol, int sv[2]) -{ - FAR struct socket *psocks[2]; - int oflags = O_RDWR; - int i = 0; - int ret; - - if (sv == NULL) - { - ret = -EINVAL; - goto errout; - } - - for (i = 0; i < 2; i++) - { - psocks[i] = kmm_zalloc(sizeof(*psocks[i])); - if (psocks[i] == NULL) - { - ret = -ENOMEM; - goto errout_with_alloc; - } - } - - ret = psock_socketpair(domain, type, protocol, psocks); - if (ret < 0) - { - goto errout_with_alloc; - } - - if (type & SOCK_CLOEXEC) - { - oflags |= O_CLOEXEC; - } - - /* Allocate a socket descriptor */ - - for (i = 0; i < 2; i++) - { - sv[i] = sockfd_allocate(psocks[i], oflags); - if (sv[i] < 0) - { - ret = sv[i]; - goto errout_with_psock; - } - } - - return OK; - -errout_with_psock: - while (i-- > 0) - { - nx_close(sv[i]); - } - - i = 2; -errout_with_alloc: - while (i-- > 0) - { - kmm_free(psocks[i]); - } - -errout: - set_errno(-ret); - return ERROR; -}