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 <spudmonkey@racsa.co.cr> * 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 <spudmonkey@racsa.co.cr> 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