summaryrefslogtreecommitdiff
path: root/nuttx/net/accept.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/net/accept.c')
-rw-r--r--nuttx/net/accept.c112
1 files changed, 65 insertions, 47 deletions
diff --git a/nuttx/net/accept.c b/nuttx/net/accept.c
index 122e67c43..3fea60b19 100644
--- a/nuttx/net/accept.c
+++ b/nuttx/net/accept.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/accept.c
*
- * Copyright (C) 2007 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@@ -289,7 +289,9 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
goto errout;
}
- /* Verify that a valid memory block has been provided to receive the address address */
+ /* Verify that a valid memory block has been provided to receive
+ * the address
+ */
#ifdef CONFIG_NET_IPv6
if (addr->sa_family != AF_INET6 || *addrlen < sizeof(struct sockaddr_in6))
@@ -301,7 +303,9 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
goto errout;
}
- /* Allocate a socket descriptor for the new connection now (so that it cannot fail later) */
+ /* Allocate a socket descriptor for the new connection now
+ * (so that it cannot fail later)
+ */
newfd = sockfd_allocate();
if (newfd < 0)
@@ -317,68 +321,79 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
goto errout_with_socket;
}
- /* Set the socket state to accepting */
+ /* Check the backlog to see if there is a connection already pending
+ * for this listener.
+ */
- psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);
+ save = irqsave();
+ conn = (struct uip_conn *)psock->s_conn;
- /* Perform the TCP accept operation */
+#ifdef CONFIG_NET_TCPBACKLOG
+ state.acpt_newconn = uip_backlogremove(conn);
+ if (!state.acpt_newconn)
+#endif
+ {
+ /* Set the socket state to accepting */
- /* Initialize the state structure. This is done with interrupts
- * disabled because we don't want anything to happen until we
- * are ready.
- */
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_ACCEPT);
- save = irqsave();
- state.acpt_addr = inaddr;
- state.acpt_newconn = NULL;
- state.acpt_result = OK;
- sem_init(&state.acpt_sem, 0, 0);
+ /* Perform the TCP accept operation */
- /* Set up the callback in the connection */
+ /* Initialize the state structure. This is done with interrupts
+ * disabled because we don't want anything to happen until we
+ * are ready.
+ */
- conn = (struct uip_conn *)psock->s_conn;
- conn->accept_private = (void*)&state;
- conn->accept = accept_interrupt;
+ state.acpt_addr = inaddr;
+ state.acpt_newconn = NULL;
+ state.acpt_result = OK;
+ sem_init(&state.acpt_sem, 0, 0);
- /* Wait for the send to complete or an error to occur: NOTES: (1)
- * sem_wait will also terminate if a signal is received, (2) interrupts
- * are disabled! They will be re-enabled while the task sleeps and
- * automatically re-enabled when the task restarts.
- */
+ /* Set up the callback in the connection */
- ret = sem_wait(&state.acpt_sem);
+ conn->accept_private = (void*)&state;
+ conn->accept = accept_interrupt;
- /* Make sure that no further interrupts are processed */
+ /* Wait for the send to complete or an error to occur: NOTES: (1)
+ * sem_wait will also terminate if a signal is received, (2) interrupts
+ * are disabled! They will be re-enabled while the task sleeps and
+ * automatically re-enabled when the task restarts.
+ */
- conn->accept_private = NULL;
- conn->accept = NULL;
+ ret = sem_wait(&state.acpt_sem);
- sem_destroy(&state. acpt_sem);
- irqrestore(save);
+ /* Make sure that no further interrupts are processed */
- /* Set the socket state to idle */
+ conn->accept_private = NULL;
+ conn->accept = NULL;
- psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
+ sem_destroy(&state. acpt_sem);
- /* Check for a errors. Errors are signaled by negative errno values
- * for the send length
- */
+ /* Set the socket state to idle */
- if (state.acpt_result != 0)
- {
- err = state.acpt_result;
- goto errout_with_socket;
- }
+ psock->s_flags = _SS_SETSTATE(psock->s_flags, _SF_IDLE);
- /* If sem_wait failed, then we were probably reawakened by a signal. In
- * this case, sem_wait will have set errno appropriately.
- */
+ /* Check for a errors. Errors are signaled by negative errno values
+ * for the send length
+ */
- if (ret < 0)
- {
- err = -ret;
- goto errout_with_socket;
+ if (state.acpt_result != 0)
+ {
+ err = state.acpt_result;
+ goto errout_with_irq;
+ }
+
+ /* If sem_wait failed, then we were probably reawakened by a signal. In
+ * this case, sem_wait will have set errno appropriately.
+ */
+
+ if (ret < 0)
+ {
+ err = -ret;
+ goto errout_with_irq;
+ }
}
+ irqrestore(save);
/* Initialize the socket structure and mark the socket as connected */
@@ -387,6 +402,9 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
pnewsock->s_flags |= _SF_CONNECTED;
return newfd;
+errout_with_irq:
+ irqrestore(save);
+
errout_with_socket:
sockfd_release(newfd);