diff options
Diffstat (limited to 'nuttx/net/accept.c')
-rw-r--r-- | nuttx/net/accept.c | 462 |
1 files changed, 0 insertions, 462 deletions
diff --git a/nuttx/net/accept.c b/nuttx/net/accept.c deleted file mode 100644 index 07e3f983e..000000000 --- a/nuttx/net/accept.c +++ /dev/null @@ -1,462 +0,0 @@ -/**************************************************************************** - * net/accept.c - * - * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt <gnutt@nuttx.org> - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include <nuttx/config.h> -#if defined(CONFIG_NET) && CONFIG_NSOCKET_DESCRIPTORS > 0 && defined(CONFIG_NET_TCP) - -#include <sys/types.h> -#include <sys/socket.h> - -#include <semaphore.h> -#include <string.h> -#include <errno.h> -#include <assert.h> -#include <debug.h> - -#include <arch/irq.h> - -#include "net_internal.h" - -/**************************************************************************** - * Definitions - ****************************************************************************/ - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct accept_s -{ - sem_t acpt_sem; /* Wait for interrupt event */ -#ifdef CONFIG_NET_IPv6 - FAR struct sockaddr_in6 *acpt_addr; /* Return connection adress */ -#else - FAR struct sockaddr_in *acpt_addr; /* Return connection adress */ -#endif - FAR struct uip_conn *acpt_newconn; /* The accepted connection */ - int acpt_result; /* The result of the wait */ -}; - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Function: accept_tcpsender - * - * Description: - * Getting the sender's address from the UDP packet - * - * Parameters: - * conn - The newly accepted TCP connection - * pstate - the recvfrom state structure - * - * Returned Value: - * None - * - * Assumptions: - * Running at the interrupt level - * - ****************************************************************************/ - -#ifdef CONFIG_NET_TCP -#ifdef CONFIG_NET_IPv6 -static inline void accept_tcpsender(FAR struct uip_conn *conn, - FAR struct sockaddr_in6 *addr) -{ - if (addr) - { - addr->sin_family = AF_INET6; - addr->sin_port = conn->rport; - uip_ipaddr_copy(addr->sin6_addr.s6_addr, conn->ripaddr); - } -} -#else -static inline void accept_tcpsender(FAR struct uip_conn *conn, - FAR struct sockaddr_in *addr) -{ - if (addr) - { - addr->sin_family = AF_INET; - addr->sin_port = conn->rport; - uip_ipaddr_copy(addr->sin_addr.s_addr, conn->ripaddr); - } -} -#endif /* CONFIG_NET_IPv6 */ -#endif /* CONFIG_NET_TCP */ - -/**************************************************************************** - * Function: accept_interrupt - * - * Description: - * Receive interrupt level callbacks when connections occur - * - * Parameters: - * listener The conection stucture of the listener - * conn The connection stucture that was just accepted - * - * Returned Value: - * None - * - * Assumptions: - * Running at the interrupt level - * - ****************************************************************************/ - -static int accept_interrupt(struct uip_conn *listener, struct uip_conn *conn) -{ - struct accept_s *pstate = (struct accept_s *)listener->accept_private; - int ret = -EINVAL; - - if (pstate) - { - /* Get the connection address */ - - accept_tcpsender(conn, pstate->acpt_addr); - - /* Save the connection structure */ - - pstate->acpt_newconn = conn; - pstate->acpt_result = OK; - - /* There should be a reference of one on the new connection */ - - DEBUGASSERT(conn->crefs == 1); - - /* Wake-up the waiting caller thread */ - - sem_post(&pstate->acpt_sem); - - /* Stop any further callbacks */ - - listener->accept_private = NULL; - listener->accept = NULL; - ret = OK; - } - - return ret; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Function: accept - * - * Description: - * The accept 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 - * allocates a new socket descriptor for the socket, which is returned. The - * newly created socket is no longer in the listening state. The original - * socket 'sockfd' is unaffected by this call. Per file descriptor flags - * are not inherited across an accept. - * - * The 'sockfd' argument is a socket descriptor that has been created with - * socket(), bound to a local address with bind(), and is listening for - * connections after a call to listen(). - * - * On return, the 'addr' structure is filled in with the address of the - * connecting entity. The 'addrlen' argument initially contains the size - * of the structure pointed to by 'addr'; on return it will contain the - * actual length of the address returned. - * - * If no pending connections are present on the queue, and the socket is - * not marked as non-blocking, accept blocks the caller until a connection - * is present. If the socket is marked non-blocking and no pending - * connections are present on the queue, accept returns EAGAIN. - * - * Parameters: - * sockfd The listening socket descriptior - * addr Receives the address of the connecting client - * addrlen Input: allocated size of 'addr', Return: returned size of 'addr' - * - * Returned Value: - * Returns -1 on error. If it succeeds, it returns a non-negative integer - * that is a descriptor for the accepted socket. - * - * EAGAIN or EWOULDBLOCK - * The socket is marked non-blocking and no connections are present to - * be accepted. - * EBADF - * The descriptor is invalid. - * ENOTSOCK - * The descriptor references a file, not a socket. - * EOPNOTSUPP - * The referenced socket is not of type SOCK_STREAM. - * EINTR - * The system call was interrupted by a signal that was caught before - * a valid connection arrived. - * ECONNABORTED - * A connection has been aborted. - * EINVAL - * Socket is not listening for connections. - * EMFILE - * The per-process limit of open file descriptors has been reached. - * ENFILE - * The system maximum for file descriptors has been reached. - * EFAULT - * The addr parameter is not in a writable part of the user address - * space. - * ENOBUFS or ENOMEM - * Not enough free memory. - * EPROTO - * Protocol error. - * EPERM - * Firewall rules forbid connection. - * - * Assumptions: - * - ****************************************************************************/ - -int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) -{ - FAR struct socket *psock = sockfd_socket(sockfd); - FAR struct socket *pnewsock; - FAR struct uip_conn *conn; - struct accept_s state; -#ifdef CONFIG_NET_IPv6 - FAR struct sockaddr_in6 *inaddr = (struct sockaddr_in6 *)addr; -#else - FAR struct sockaddr_in *inaddr = (struct sockaddr_in *)addr; -#endif - uip_lock_t save; - int newfd; - int err; - int ret; - - /* Verify that the sockfd corresponds to valid, allocated socket */ - - if (!psock || psock->s_crefs <= 0) - { - /* It is not a valid socket description. Distinguish between the cases - * where sockfd is a just valid and when it is a valid file descriptor used - * in the wrong context. - */ - -#if CONFIG_NFILE_DESCRIPTORS > 0 - if ((unsigned int)sockfd < CONFIG_NFILE_DESCRIPTORS) - { - err = ENOTSOCK; - } - else -#endif - { - err = EBADF; - } - goto errout; - } - - /* We have a socket descriptor, but it is a stream? */ - - if (psock->s_type != SOCK_STREAM) - { - err = EOPNOTSUPP; - goto errout; - } - - /* Is the socket listening for a connection? */ - - if (!_SS_ISLISTENING(psock->s_flags)) - { - err = EINVAL; - goto errout; - } - - /* Verify that a valid memory block has been provided to receive the - * address - */ - - if (addr) - { -#ifdef CONFIG_NET_IPv6 - if (*addrlen < sizeof(struct sockaddr_in6)) -#else - if (*addrlen < sizeof(struct sockaddr_in)) -#endif - { - err = EBADF; - goto errout; - } - } - - /* Allocate a socket descriptor for the new connection now (so that it - * cannot fail later) - */ - - newfd = sockfd_allocate(0); - if (newfd < 0) - { - err = ENFILE; - goto errout; - } - - pnewsock = sockfd_socket(newfd); - if (!pnewsock) - { - err = ENFILE; - goto errout_with_socket; - } - - /* Check the backlog to see if there is a connection already pending for - * this listener. - */ - - save = uip_lock(); - conn = (struct uip_conn *)psock->s_conn; - -#ifdef CONFIG_NET_TCPBACKLOG - state.acpt_newconn = uip_backlogremove(conn); - if (state.acpt_newconn) - { - /* Yes... get the address of the connected client */ - - nvdbg("Pending conn=%p\n", state.acpt_newconn); - accept_tcpsender(state.acpt_newconn, inaddr); - } - - /* In general, this uIP-based implementation will not support non-blocking - * socket operations... except in a few cases: Here for TCP accept with backlog - * enabled. If this socket is configured as non-blocking then return EAGAIN - * if there is no pending connection in the backlog. - */ - - else if (_SS_ISNONBLOCK(psock->s_flags)) - { - err = EAGAIN; - goto errout_with_lock; - } - else -#endif - { - /* Set the socket state to accepting */ - - psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT); - - /* Perform the TCP accept operation */ - - /* Initialize the state structure. This is done with interrupts - * disabled because we don't want anything to happen until we - * are ready. - */ - - state.acpt_addr = inaddr; - state.acpt_newconn = NULL; - state.acpt_result = OK; - sem_init(&state.acpt_sem, 0, 0); - - /* Set up the callback in the connection */ - - conn->accept_private = (void*)&state; - conn->accept = accept_interrupt; - - /* Wait for the send to complete or an error to occur: NOTES: (1) - * uip_lockedwait will also terminate if a signal is received, (2) interrupts - * may be disabled! They will be re-enabled while the task sleeps and - * automatically re-enabled when the task restarts. - */ - - ret = uip_lockedwait(&state.acpt_sem); - - /* Make sure that no further interrupts are processed */ - - conn->accept_private = NULL; - conn->accept = NULL; - - sem_destroy(&state. acpt_sem); - - /* Set the socket state to idle */ - - psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE); - - /* Check for a errors. Errors are signaled by negative errno values - * for the send length. - */ - - if (state.acpt_result != 0) - { - err = state.acpt_result; - goto errout_with_lock; - } - - /* If uip_lockedwait failed, then we were probably reawakened by a signal. In - * this case, uip_lockedwait will have set errno appropriately. - */ - - if (ret < 0) - { - err = -ret; - goto errout_with_lock; - } - } - - /* Initialize the socket structure and mark the socket as connected. - * (The reference count on the new connection structure was set in the - * interrupt handler). - */ - - pnewsock->s_type = SOCK_STREAM; - pnewsock->s_conn = state.acpt_newconn; - pnewsock->s_flags |= _SF_CONNECTED; - pnewsock->s_flags &= ~_SF_CLOSED; - - /* Begin monitoring for TCP connection events on the newly connected socket */ - - net_startmonitor(pnewsock); - uip_unlock(save); - return newfd; - -errout_with_lock: - uip_unlock(save); - -errout_with_socket: - sockfd_release(newfd); - -errout: - errno = err; - return ERROR; -} - -#endif /* CONFIG_NET && CONFIG_NSOCKET_DESCRIPTORS && CONFIG_NET_TCP */ |