Make net_close() nonblocking and free unestablished connections if no free connections available. From Max Holtzberg
This commit is contained in:
parent
d3fa588250
commit
4c884a5079
@ -5717,4 +5717,6 @@
|
||||
caused by the routing table. From Max Holtzberg (2013-10-6).
|
||||
* arch/arm/src/sama5/sam_lcdc.c and .h: Empty "skeleton" file that
|
||||
will eventually become an LCDC driver for the SAMA5 (2013-10-6).
|
||||
|
||||
* net/net_close.c, net/uip/uip_tcpcon, and include/nuttx/net/uip/uip-tcp.h:
|
||||
Make net_close() nonblocking and free unestablished connections if no
|
||||
free connections available. From Max Holtzber (2013-10-6).
|
||||
|
@ -6,7 +6,8 @@
|
||||
* of C macros that are used by uIP programs as well as internal uIP
|
||||
* structures, TCP/IP header structures and function declarations.
|
||||
*
|
||||
* Copyright (C) 2007, 2009-2010, 2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009-2010, 2012-2013 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This logic was leveraged from uIP which also has a BSD-style license:
|
||||
@ -168,8 +169,8 @@ struct uip_conn
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_NET_TCPBACKLOG
|
||||
struct uip_conn *blparent;
|
||||
struct uip_backlog_s *backlog;
|
||||
FAR struct uip_conn *blparent;
|
||||
FAR struct uip_backlog_s *backlog;
|
||||
#endif
|
||||
|
||||
/* Application callbacks:
|
||||
@ -196,14 +197,24 @@ struct uip_conn
|
||||
* dev->d_len should also be cleared).
|
||||
*/
|
||||
|
||||
struct uip_callback_s *list;
|
||||
FAR struct uip_callback_s *list;
|
||||
|
||||
/* Close callback. The socket close logic allocates this callback and lets
|
||||
* the connection handle closing itself. So the application won't be
|
||||
* blocked on the close call. The callback has to be freed together with
|
||||
* this connection structure.
|
||||
*/
|
||||
|
||||
FAR struct uip_callback_s *closecb;
|
||||
|
||||
/* accept() is called when the TCP logic has created a connection */
|
||||
|
||||
FAR void *accept_private;
|
||||
int (*accept)(FAR struct uip_conn *listener, struct uip_conn *conn);
|
||||
|
||||
/* connection_event() is called on any of the subset of connection-related events */
|
||||
/* connection_event() is called on any of the subset of connection-related
|
||||
* events.
|
||||
*/
|
||||
|
||||
FAR void *connection_private;
|
||||
void (*connection_event)(FAR struct uip_conn *conn, uint16_t flags);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/net_close.c
|
||||
*
|
||||
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -87,38 +87,41 @@ struct tcp_close_s
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCP
|
||||
static uint16_t netclose_interrupt(struct uip_driver_s *dev, void *pvconn,
|
||||
void *pvpriv, uint16_t flags)
|
||||
static uint16_t netclose_interrupt(FAR struct uip_driver_s *dev,
|
||||
FAR void *pvconn, FAR void *pvpriv,
|
||||
uint16_t flags)
|
||||
{
|
||||
struct tcp_close_s *pstate = (struct tcp_close_s *)pvpriv;
|
||||
FAR struct uip_conn *conn = (FAR struct uip_conn*)pvconn;
|
||||
|
||||
nllvdbg("flags: %04x\n", flags);
|
||||
DEBUGASSERT(conn != NULL);
|
||||
|
||||
if (pstate)
|
||||
nlldbg("flags: %04x\n", flags);
|
||||
|
||||
/* UIP_CLOSE: The remote host has closed the connection
|
||||
* UIP_ABORT: The remote host has aborted the connection
|
||||
* UIP_TIMEDOUT: The remote did not respond, the connection timed out
|
||||
*/
|
||||
|
||||
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
|
||||
{
|
||||
/* UIP_CLOSE: The remote host has closed the connection
|
||||
* UIP_ABORT: The remote host has aborted the connection
|
||||
/* The disconnection is complete */
|
||||
|
||||
conn->closecb->flags = 0;
|
||||
conn->closecb->priv = NULL;
|
||||
conn->closecb->event = NULL;
|
||||
|
||||
/* Free connection resources */
|
||||
|
||||
uip_tcpfree(conn);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Drop data received in this state and make sure that UIP_CLOSE
|
||||
* is set in the response
|
||||
*/
|
||||
|
||||
if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0)
|
||||
{
|
||||
/* The disconnection is complete */
|
||||
|
||||
pstate->cl_cb->flags = 0;
|
||||
pstate->cl_cb->priv = NULL;
|
||||
pstate->cl_cb->event = NULL;
|
||||
sem_post(&pstate->cl_sem);
|
||||
nllvdbg("Resuming\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Drop data received in this state and make sure that UIP_CLOSE
|
||||
* is set in the response
|
||||
*/
|
||||
|
||||
dev->d_len = 0;
|
||||
return (flags & ~UIP_NEWDATA) | UIP_CLOSE;
|
||||
}
|
||||
dev->d_len = 0;
|
||||
return (flags & ~UIP_NEWDATA) | UIP_CLOSE;
|
||||
}
|
||||
|
||||
return flags;
|
||||
@ -158,34 +161,25 @@ static inline void netclose_disconnect(FAR struct socket *psock)
|
||||
{
|
||||
struct uip_conn *conn = (struct uip_conn*)psock->s_conn;
|
||||
|
||||
DEBUGASSERT(conn->closecb == NULL);
|
||||
|
||||
/* Check for the case where the host beat us and disconnected first */
|
||||
|
||||
if (conn->tcpstateflags == UIP_ESTABLISHED)
|
||||
{
|
||||
/* Set up to receive TCP data event callbacks */
|
||||
/* This callback will be freed together with conn */
|
||||
|
||||
state.cl_cb = uip_tcpcallbackalloc(conn);
|
||||
if (state.cl_cb)
|
||||
conn->closecb = uip_tcpcallbackalloc(conn);
|
||||
if (conn->closecb)
|
||||
{
|
||||
state.cl_psock = psock;
|
||||
sem_init(&state.cl_sem, 0, 0);
|
||||
/* Set up to receive TCP data event callbacks */
|
||||
|
||||
state.cl_cb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT;
|
||||
state.cl_cb->priv = (void*)&state;
|
||||
state.cl_cb->event = netclose_interrupt;
|
||||
conn->closecb->flags = UIP_NEWDATA|UIP_POLL|UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT;
|
||||
conn->closecb->event = netclose_interrupt;
|
||||
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
/* Notify the device driver of the availaibilty of TX data */
|
||||
|
||||
netdev_txnotify(conn->ripaddr);
|
||||
|
||||
/* Wait for the disconnect event */
|
||||
|
||||
(void)uip_lockedwait(&state.cl_sem);
|
||||
|
||||
/* We are now disconnected */
|
||||
|
||||
sem_destroy(&state.cl_sem);
|
||||
uip_tcpcallbackfree(conn, state.cl_cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,17 +236,16 @@ int psock_close(FAR struct socket *psock)
|
||||
struct uip_conn *conn = psock->s_conn;
|
||||
|
||||
/* Is this the last reference to the connection structure (there
|
||||
* could be more if the socket was dup'ed.
|
||||
* could be more if the socket was dup'ed).
|
||||
*/
|
||||
|
||||
if (conn->crefs <= 1)
|
||||
{
|
||||
/* Yes... free the connection structure */
|
||||
/* Yes... then perform the disconnection now */
|
||||
|
||||
uip_unlisten(conn); /* No longer accepting connections */
|
||||
netclose_disconnect(psock); /* Break any current connections */
|
||||
conn->crefs = 0; /* No more references on the connection */
|
||||
uip_tcpfree(conn); /* Free uIP resources */
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/uip/uip_tcpconn.c
|
||||
*
|
||||
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2011, 2013 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Large parts of this file were leveraged from uIP logic:
|
||||
@ -36,10 +36,6 @@
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Compilation Switches
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
@ -221,23 +217,29 @@ struct uip_conn *uip_tcpalloc(void)
|
||||
|
||||
conn = (struct uip_conn *)dq_remfirst(&g_free_tcp_connections);
|
||||
|
||||
#if 0 /* Revisit */
|
||||
/* Is the free list empty? */
|
||||
|
||||
if (!conn)
|
||||
{
|
||||
/* As a fallback, check for connection structures in the TIME_WAIT
|
||||
* state. If no CLOSED connections are found, then take the oldest
|
||||
/* As a fallback, check for connection structures which are not
|
||||
* established yet.
|
||||
*
|
||||
* Search the active connection list for the oldest connection
|
||||
* that is not in the UIP_ESTABLISHED state.
|
||||
*/
|
||||
|
||||
struct uip_conn *tmp = g_active_tcp_connections.head;
|
||||
while (tmp)
|
||||
{
|
||||
/* Is this connectin in the UIP_TIME_WAIT state? */
|
||||
nllvdbg("conn: %p state: %02x\n", tmp, tmp->tcpstateflags);
|
||||
|
||||
if (tmp->tcpstateflags == UIP_TIME_WAIT)
|
||||
/* Is this connection in some state other than UIP_ESTABLISHED
|
||||
* state?
|
||||
*/
|
||||
|
||||
if (tmp->tcpstateflags != UIP_ESTABLISHED)
|
||||
{
|
||||
/* Is it the oldest one we have seen so far? */
|
||||
/* Yes.. Is it the oldest one we have seen so far? */
|
||||
|
||||
if (!conn || tmp->timer > conn->timer)
|
||||
{
|
||||
@ -252,11 +254,27 @@ struct uip_conn *uip_tcpalloc(void)
|
||||
tmp = tmp->node.flink;
|
||||
}
|
||||
|
||||
/* If we found one, remove it from the active connection list */
|
||||
/* Did we find a connection that we can re-use? */
|
||||
|
||||
dq_rem(&conn->node, &g_active_tcp_connections);
|
||||
if (conn != NULL)
|
||||
{
|
||||
nlldbg("Closing unestablished connection: %p\n", conn);
|
||||
|
||||
/* Yes... free it. This will remove the connection from the list
|
||||
* of active connections and release all resources held by the
|
||||
* connection.
|
||||
*
|
||||
* REVISIT: Could there be any higher level, socket interface
|
||||
* that needs to be informed that we did this to them?
|
||||
*/
|
||||
|
||||
uip_tcpfree(conn);
|
||||
|
||||
/* Now there is guaranteed to be one free connection. Get it! */
|
||||
|
||||
conn = (struct uip_conn *)dq_remfirst(&g_free_tcp_connections);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uip_unlock(flags);
|
||||
|
||||
@ -264,6 +282,7 @@ struct uip_conn *uip_tcpalloc(void)
|
||||
|
||||
if (conn)
|
||||
{
|
||||
memset(conn, 0, sizeof(struct uip_conn));
|
||||
conn->tcpstateflags = UIP_ALLOCATED;
|
||||
}
|
||||
|
||||
@ -294,6 +313,13 @@ void uip_tcpfree(struct uip_conn *conn)
|
||||
DEBUGASSERT(conn->crefs == 0);
|
||||
flags = uip_lock();
|
||||
|
||||
/* Check if there is an allocated close callback structure */
|
||||
|
||||
if (conn->closecb != NULL)
|
||||
{
|
||||
uip_tcpcallbackfree(conn, conn->closecb);
|
||||
}
|
||||
|
||||
/* UIP_ALLOCATED means that that the connection is not in the active list
|
||||
* yet.
|
||||
*/
|
||||
@ -354,7 +380,7 @@ void uip_tcpfree(struct uip_conn *conn)
|
||||
struct uip_conn *uip_tcpactive(struct uip_tcpip_hdr *buf)
|
||||
{
|
||||
struct uip_conn *conn = (struct uip_conn *)g_active_tcp_connections.head;
|
||||
in_addr_t srcipaddr = uip_ip4addr_conv(buf->srcipaddr);
|
||||
in_addr_t srcipaddr = uip_ip4addr_conv(buf->srcipaddr);
|
||||
|
||||
while (conn)
|
||||
{
|
||||
@ -421,7 +447,7 @@ struct uip_conn *uip_tcplistener(uint16_t portno)
|
||||
int i;
|
||||
|
||||
/* Check if this port number is in use by any active UIP TCP connection */
|
||||
|
||||
|
||||
for (i = 0; i < CONFIG_NET_TCP_CONNS; i++)
|
||||
{
|
||||
conn = &g_tcp_connections[i];
|
||||
@ -432,6 +458,7 @@ struct uip_conn *uip_tcplistener(uint16_t portno)
|
||||
return conn;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -484,6 +511,7 @@ struct uip_conn *uip_tcpaccept(struct uip_tcpip_hdr *buf)
|
||||
|
||||
dq_addlast(&conn->node, &g_active_tcp_connections);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
@ -569,7 +597,7 @@ int uip_tcpconnect(struct uip_conn *conn, const struct sockaddr_in *addr)
|
||||
uip_lock_t flags;
|
||||
int port;
|
||||
|
||||
/* The connection is expected to be in the UIP_ALLOCATED state.. i.e.,
|
||||
/* The connection is expected to be in the UIP_ALLOCATED state.. i.e.,
|
||||
* allocated via up_tcpalloc(), but not yet put into the active connections
|
||||
* list.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user