From 9fe041fff5ece21226684692458bae406f6eb067 Mon Sep 17 00:00:00 2001
From: patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>
Date: Thu, 20 Nov 2008 21:50:55 +0000
Subject: [PATCH] Completed integration of TCP connection backlog and
 poll()/select() for connections

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1295 42af7a65-404d-4744-a932-0658087f49c3
---
 ChangeLog                    |  1 +
 Documentation/NuttX.html     |  1 +
 TODO                         |  6 ------
 examples/poll/net_listener.c |  8 +++++--
 net/accept.c                 | 42 ++++++++++++++++++++++--------------
 net/uip/uip-callback.c       |  2 +-
 net/uip/uip-listen.c         |  2 +-
 net/uip/uip-tcpbacklog.c     | 20 +++++++++++++++--
 net/uip/uip-tcpcallback.c    |  2 +-
 9 files changed, 55 insertions(+), 29 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index c880ef3e28..2e6cae02e1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -579,4 +579,5 @@
 	* Implemented support for connection backlog.  The size of the backlog is specified by the
 	  second argument of the standard listen() API.  Hooks are provided to support poll()/select()
 	  waiting for connections, with a subsequent call to accept() to use the backlogged connection.
+	* Fixed a minor bug in accept().  It should allow the address and addresslen values to be NULL
 
diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html
index 3dd0d53fab..a5eb01a82a 100644
--- a/Documentation/NuttX.html
+++ b/Documentation/NuttX.html
@@ -1215,6 +1215,7 @@ nuttx-0.3.19 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 	* Implemented support for connection backlog.  The size of the backlog is specified by the
 	  second argument of the standard listen() API.  Hooks are provided to support poll()/select()
 	  waiting for connections, with a subsequent call to accept() to use the backlogged connection.
+	* Fixed a minor bug in accept().  It should allow the address and addresslen values to be NULL
 
 pascal-0.1.3 2008-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
 
diff --git a/TODO b/TODO
index e90e10e9c9..9ea6c61b7a 100644
--- a/TODO
+++ b/TODO
@@ -220,12 +220,6 @@ o Network (net/, netutils/)
   Status:      Open, depends on UDP read-ahead support
   Priority:    Medium
 
-  Description: poll()/select() does not detect incoming connections.  As a result
-               they are not useful for implementing servers in the usual way.
-  Status:      Open.
-  Priority:    High.  There is a work-around (compare examples/poll/net_reader.c
-               to examples/poll/net_listener.c).
-
 o USB (drivers/usbdev)
   ^^^^^^^^^^^^^^^^^^^^
 
diff --git a/examples/poll/net_listener.c b/examples/poll/net_listener.c
index bc9840cd80..957f48fc06 100644
--- a/examples/poll/net_listener.c
+++ b/examples/poll/net_listener.c
@@ -181,11 +181,13 @@ static inline boolean net_connection(struct net_listener_s *nls)
   for (;;)
 #endif
     {
-      message("net_listener: Accepting accepting connection on sd=%d\n", nls->listensd);
+      message("net_listener: Accepting new connection on sd=%d\n", nls->listensd);
+
       sd = accept(nls->listensd, NULL, NULL);
       if (sd < 0)
         {
-          message("net_listener: accept failed: %d\n", sd);
+          message("net_listener: accept failed: %d\n", errno);
+
           if (errno != EINTR)
             {
               return FALSE;
@@ -195,6 +197,8 @@ static inline boolean net_connection(struct net_listener_s *nls)
         {
           /* Add the new connection to the master set */
 
+          message("net_listener: Connection accepted for sd=%d\n", sd);
+
           FD_SET(sd, &nls->master);
           if (sd > nls->mxsd)
             {
diff --git a/net/accept.c b/net/accept.c
index 3fea60b192..f4c54e5f34 100644
--- a/net/accept.c
+++ b/net/accept.c
@@ -99,14 +99,14 @@ struct accept_s
  ****************************************************************************/
 
 #ifdef CONFIG_NET_TCP
-static inline void accept_tcpsender(struct uip_conn *conn, struct accept_s *pstate)
-{
- #ifdef CONFIG_NET_IPv6
-  FAR struct sockaddr_in6 *addr = pstate->acpt_addr;
+#ifdef CONFIG_NET_IPv6
+static inline void accept_tcpsender(FAR struct uip_conn *conn,
+                                    FAR struct sockaddr_in6 *addr)
 #else
-  FAR struct sockaddr_in *addr  = pstate->acpt_addr;
+static inline void accept_tcpsender(FAR struct uip_conn *conn,
+                                    FAR struct sockaddr_in *addr)
 #endif
-
+{
   if (addr)
     {
       addr->sin_family = AF_INET;
@@ -143,7 +143,7 @@ static int accept_interrupt(struct uip_conn *listener, struct uip_conn *conn)
     {
       /* Get the connection address */
 
-      accept_tcpsender(conn, pstate);
+      accept_tcpsender(conn, pstate->acpt_addr);
 
       /* Save the connection structure */
 
@@ -293,15 +293,18 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
    * the address
    */
 
+  if (addr)
+    {
 #ifdef CONFIG_NET_IPv6
-  if (addr->sa_family != AF_INET6 || *addrlen < sizeof(struct sockaddr_in6))
+      if (addr->sa_family != AF_INET6 || *addrlen < sizeof(struct sockaddr_in6))
 #else
-  if (addr->sa_family != AF_INET || *addrlen < sizeof(struct sockaddr_in))
+      if (addr->sa_family != AF_INET || *addrlen < sizeof(struct sockaddr_in))
 #endif
-  {
-      err = EBADF;
-      goto errout;
-  }
+        {
+          err = EBADF;
+          goto errout;
+        }
+    }
 
   /* Allocate a socket descriptor for the new connection now
    * (so that it cannot fail later)
@@ -330,7 +333,14 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
 
 #ifdef CONFIG_NET_TCPBACKLOG
   state.acpt_newconn = uip_backlogremove(conn);
-  if (!state.acpt_newconn)
+  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);
+    }
+  else
 #endif
     {
       /* Set the socket state to accepting */
@@ -380,7 +390,7 @@ int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
       if (state.acpt_result != 0)
         {
           err = state.acpt_result;
-         goto errout_with_irq;
+          goto errout_with_irq;
         }
 
       /* If sem_wait failed, then we were probably reawakened by a signal. In
@@ -409,7 +419,7 @@ errout_with_socket:
   sockfd_release(newfd);
 
 errout:
-  *get_errno_ptr() = err;
+  errno = err;
   return ERROR;
 }
 
diff --git a/net/uip/uip-callback.c b/net/uip/uip-callback.c
index 9a2ad78161..27f3a522e1 100644
--- a/net/uip/uip-callback.c
+++ b/net/uip/uip-callback.c
@@ -208,7 +208,7 @@ void uip_callbackfree(FAR struct uip_callback_s *cb, FAR struct uip_callback_s *
  ****************************************************************************/
 
 uint16 uip_callbackexecute(FAR struct uip_driver_s *dev, void *pvconn, uint16 flags,
-                          FAR struct uip_callback_s *list)
+                           FAR struct uip_callback_s *list)
 {
   FAR struct uip_callback_s *next;
   irqstate_t save;
diff --git a/net/uip/uip-listen.c b/net/uip/uip-listen.c
index b5e17a6bf5..9ab3eae720 100644
--- a/net/uip/uip-listen.c
+++ b/net/uip/uip-listen.c
@@ -259,7 +259,7 @@ int uip_accept(struct uip_driver_s *dev, struct uip_conn *conn, uint16 portno)
           ret =  uip_backlogadd(listener, conn);
           if (ret == OK)
             {
-              (void)uip_tcpcallback(dev, conn, UIP_BACKLOG);
+              (void)uip_tcpcallback(dev, listener, UIP_BACKLOG);
             }
         }
 #endif
diff --git a/net/uip/uip-tcpbacklog.c b/net/uip/uip-tcpbacklog.c
index 152d374ba4..2562707eed 100644
--- a/net/uip/uip-tcpbacklog.c
+++ b/net/uip/uip-tcpbacklog.c
@@ -84,6 +84,8 @@ int uip_backlogcreate(FAR struct uip_conn *conn, int nblg)
   int offset;
   int i;
 
+  nvdbg("conn=%p nblg=%d\n", conn, nblg);
+
 #ifdef CONFIG_DEBUG
   if (!conn)
     {
@@ -114,6 +116,7 @@ int uip_backlogcreate(FAR struct uip_conn *conn, int nblg)
       bls = (FAR struct uip_backlog_s *)zalloc(size);
       if (!bls)
         {
+          ndbg("Failed to allocate backlog\n");
           return -ENOMEM;
         }
 
@@ -164,6 +167,8 @@ int uip_backlogdestroy(FAR struct uip_conn *conn)
   FAR struct uip_blcontainer_s *blc;
   FAR struct uip_conn          *blconn;
 
+  nvdbg("conn=%p\n", conn);
+
 #ifdef CONFIG_DEBUG
   if (!conn)
     {
@@ -222,6 +227,8 @@ int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn)
   FAR struct uip_blcontainer_s *blc;
   int ret = -EINVAL;
 
+  nvdbg("conn=%p blconn=%p\n", conn, blconn);
+
 #ifdef CONFIG_DEBUG
   if (!conn)
     {
@@ -237,6 +244,7 @@ int uip_backlogadd(FAR struct uip_conn *conn, FAR struct uip_conn *blconn)
        blc = (FAR struct uip_blcontainer_s *)dq_remfirst(&bls->bl_free);
        if (!blc)
          {
+           ndbg("Failed to allocate container\n");
            ret = -ENOMEM;
          }
        else
@@ -277,8 +285,9 @@ struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn)
       return NULL;
     }
 #endif
+
   bls = conn->backlog;
-  if (bls && blconn)
+  if (bls)
     {
        /* Remove the a container at the head of the pending connection list
         * (FIFO)
@@ -296,6 +305,8 @@ struct uip_conn *uip_backlogremove(FAR struct uip_conn *conn)
            dq_addlast(&blc->bc_node, &bls->bl_free);
          }
     }
+
+  nvdbg("conn=%p, returning %p\n", conn, blconn);
   return blconn;
 }
 
@@ -317,12 +328,15 @@ int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn)
   FAR struct uip_backlog_s     *bls;
   FAR struct uip_blcontainer_s *blc;
 
+  nvdbg("conn=%p blconn=%p\n", conn, blconn);
+
 #ifdef CONFIG_DEBUG
   if (!conn)
     {
-      return NULL;
+      return -EINVAL;
     }
 #endif
+
   bls = conn->backlog;
   if (bls)
     {
@@ -340,6 +354,8 @@ int uip_backlogdelete(FAR struct uip_conn *conn, FAR struct uip_conn *blconn)
                 return OK;
               }
           }
+
+        ndbg("Failed to find pending connection\n");
         return -EINVAL;
     }
   return OK;
diff --git a/net/uip/uip-tcpcallback.c b/net/uip/uip-tcpcallback.c
index 71a2696d97..1ee61ad29d 100644
--- a/net/uip/uip-tcpcallback.c
+++ b/net/uip/uip-tcpcallback.c
@@ -254,7 +254,7 @@ uint16 uip_tcpcallback(struct uip_driver_s *dev, struct uip_conn *conn, uint16 f
    *                 (In UIP_NEWDATA is cleared bu UIP_SNDACK is not set, then
    *                 dev->d_len should also be cleared).
    */
- 
+
   ret = uip_callbackexecute(dev, conn, flags, conn->list);
 
   /* There may be no new data handler in place at them moment that the new
-- 
GitLab