From 6cc69bfa5100230776910d8f1d463b113df5f561 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 6 Oct 2013 09:48:54 -0600 Subject: Make net_close() nonblocking and free unestablished connections if no free connections available. From Max Holtzberg --- nuttx/net/net_close.c | 87 +++++++++++++++++++++++---------------------------- 1 file changed, 40 insertions(+), 47 deletions(-) (limited to 'nuttx/net/net_close.c') diff --git a/nuttx/net/net_close.c b/nuttx/net/net_close.c index 10f7e199e..6e14cafb0 100644 --- a/nuttx/net/net_close.c +++ b/nuttx/net/net_close.c @@ -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 * * 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 */ - if ((flags & (UIP_CLOSE|UIP_ABORT)) != 0) - { - /* The disconnection is complete */ + conn->closecb->flags = 0; + conn->closecb->priv = NULL; + conn->closecb->event = NULL; - 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 - */ + /* Free connection resources */ - dev->d_len = 0; - return (flags & ~UIP_NEWDATA) | UIP_CLOSE; - } + uip_tcpfree(conn); + } + 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; } 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 { -- cgit v1.2.3