Completed integration of TCP connection backlog and poll()/select() for connections
git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1295 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
parent
5d5d883446
commit
870d58f99b
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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)
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue