Skip to content

Commit

Permalink
/net/inet: Simplify design of change in last commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
gregory-nutt committed Jul 1, 2019
1 parent de5a616 commit 077d164
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 41 deletions.
6 changes: 2 additions & 4 deletions net/inet/Make.defs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@

# PF_INET/PF_INET6 socket address families

SOCK_CSRCS += inet_txdrain.c

ifeq ($(CONFIG_NET_IPv4),y)
SOCK_CSRCS += inet_sockif.c inet_recvfrom.c inet_close.c
SOCK_CSRCS += inet_globals.c
Expand All @@ -52,10 +54,6 @@ ifeq ($(CONFIG_NET_IPv6),y)
SOCK_CSRCS += ipv6_setsockopt.c ipv6_getsockname.c ipv6_getpeername.c
endif

ifeq ($(CONFIG_NET_SOLINGER),y)
SOCK_CSRCS += inet_txdrain.c
endif

# Include inet build support

DEPPATH += --dep-path inet
Expand Down
5 changes: 1 addition & 4 deletions net/inet/inet.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,7 @@ int inet_close(FAR struct socket *psock);
* Name: inet_txdrain
*
* Description:
* Wait for any buffered Tx data to be sent from the socket. This is part
* of the implementation of SO_LINGER
* Wait for any buffered Tx data to be sent from the socket.
*
* Parameters:
* psock - Pointer to the socket structure instance
Expand All @@ -322,11 +321,9 @@ int inet_close(FAR struct socket *psock);
*
****************************************************************************/

#ifdef CONFIG_NET_SOLINGER
struct timespec;
int inet_txdrain(FAR struct socket *psock,
FAR const struct timespec *abstime);
#endif

#undef EXTERN
#if defined(__cplusplus)
Expand Down
151 changes: 122 additions & 29 deletions net/inet/inet_close.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
****************************************************************************/

#include <nuttx/config.h>
#ifdef CONFIG_NET

#include <sys/types.h>
#include <sys/socket.h>
Expand Down Expand Up @@ -290,24 +289,26 @@ static inline int tcp_close_disconnect(FAR struct socket *psock)
{
/* Get the current time */

DEBUGVERIFY(clock_gettime(CLOCK_REALTIME, &abstime));

/* NOTE: s_linger's unit is deciseconds so we don't need to update
* abstime.tv_nsec here.
*/
ret = clock_gettime(CLOCK_REALTIME, &abstime);
if (ret >= 0)
{
/* NOTE: s_linger's unit is deciseconds so we don't need to update
* abstime.tv_nsec here.
*/

abstime.tv_sec += psock->s_linger / DSEC_PER_SEC;
abstime.tv_sec += psock->s_linger / DSEC_PER_SEC;

/* Wait until abstime for the buffered TX data to be sent. */
/* Wait until abstime for the buffered TX data to be sent. */

ret = inet_txdrain(psock, &abstime);
if (ret < 0)
{
/* inet_txdrain may fail, but that won't stop us from closing the
* socket.
*/
ret = tcp_txdrain(psock, &abstime);
if (ret < 0)
{
/* tcp_txdrain may fail, but that won't stop us from closing
* the socket.
*/

nerr("ERROR: inet_txdrain() failed: %d\n", ret);
nerr("ERROR: tcp_txdrain() failed: %d\n", ret);
}
}
}
#endif
Expand Down Expand Up @@ -395,6 +396,101 @@ static inline int tcp_close_disconnect(FAR struct socket *psock)
}
#endif /* NET_TCP_HAVE_STACK */

/****************************************************************************
* Name: udp_close
*
* Description:
* Break any current UDP connection
*
* Input Parameters:
* conn - UDP connection structure
*
* Returned Value:
* None
*
* Assumptions:
* Called from normal user-level logic
*
****************************************************************************/

#ifdef NET_UDP_HAVE_STACK
static inline int udp_close(FAR struct socket *psock)
{
FAR struct udp_conn_s *conn;
#ifdef CONFIG_NET_SOLINGER
struct timespec abstime;
bool linger;
#endif
int ret;

/* Interrupts are disabled here to avoid race conditions */

net_lock();

conn = (FAR struct udp_conn_s *)psock->s_conn;
DEBUGASSERT(conn != NULL);

#ifdef CONFIG_NET_SOLINGER
/* SO_LINGER
* Lingers on a close() if data is present. This option controls the
* action taken when unsent messages queue on a socket and close() is
* performed. If SO_LINGER is set, the system shall block the calling
* thread during close() until it can transmit the data or until the
* time expires. If SO_LINGER is not specified, and close() is issued,
* the system handles the call in a way that allows the calling thread
* to continue as quickly as possible. This option takes a linger
* structure, as defined in the <sys/socket.h> header, to specify the
* state of the option and linger interval.
*/

linger = _SO_GETOPT(psock->s_options, SO_LINGER);
if (linger)
{
/* Get the current time */

ret = clock_gettime(CLOCK_REALTIME, &abstime);
if (ret >= 0)
{
/* NOTE: s_linger's unit is deciseconds so we don't need to update
* abstime.tv_nsec here.
*/

abstime.tv_sec += psock->s_linger / DSEC_PER_SEC;

/* Wait until abstime for the buffered TX data to be sent. */

ret = udp_txdrain(psock, &abstime);
if (ret < 0)
{
/* udp_txdrain may fail, but that won't stop us from closing
* the socket.
*/

nerr("ERROR: udp_txdrain() failed: %d\n", ret);
}
}
}
#endif

#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
/* Free any semi-permanent write buffer callback in place. */

if (psock->s_sndcb != NULL)
{
udp_callback_free(conn->dev, conn, psock->s_sndcb);
psock->s_sndcb = NULL;
}
#endif

/* And free the connection structure */

conn->crefs = 0;
udp_free(psock->s_conn);
net_unlock();
return OK;
}
#endif

/****************************************************************************
* Public Functions
****************************************************************************/
Expand Down Expand Up @@ -441,7 +537,7 @@ int inet_close(FAR struct socket *psock)
tcp_unlisten(conn); /* No longer accepting connections */
conn->crefs = 0; /* Discard our reference to the connection */

/* Break any current connections */
/* Break any current connections and close the socket */

ret = tcp_close_disconnect(psock);
if (ret < 0)
Expand Down Expand Up @@ -481,28 +577,26 @@ int inet_close(FAR struct socket *psock)
{
#ifdef NET_UDP_HAVE_STACK
FAR struct udp_conn_s *conn = psock->s_conn;
int ret;

/* Is this the last reference to the connection structure (there
* could be more if the socket was dup'ed).
*/

if (conn->crefs <= 1)
{
/* Yes... */
/* Yes... Clost the socket */

#ifdef CONFIG_NET_UDP_WRITE_BUFFERS
/* Free any semi-permanent write buffer callback in place. */

if (psock->s_sndcb != NULL)
ret = udp_close(psock);
if (ret < 0)
{
udp_callback_free(conn->dev, conn, psock->s_sndcb);
psock->s_sndcb = NULL;
}
#endif
/* And free the connection structure */
/* This would normally occur only if there is a timeout
* from a lingering close.
*/

conn->crefs = 0;
udp_free(psock->s_conn);
nerr("ERROR: udp_close failed: %d\n", ret);
return ret;
}
}
else
{
Expand All @@ -524,4 +618,3 @@ int inet_close(FAR struct socket *psock)

return OK;
}
#endif /* CONFIG_NET */
7 changes: 3 additions & 4 deletions net/inet/inet_txdrain.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@
* Name: inet_txdrain
*
* Description:
* Wait for any buffered Tx data to be sent from the socket. This is part
* of the implementation of SO_LINGER
* Wait for any buffered Tx data to be sent from the socket.
*
* Parameters:
* psock - Pointer to the socket structure instance
Expand All @@ -84,15 +83,15 @@ int inet_txdrain(FAR struct socket *psock,

switch (psock->s_type)
{
#if defined(NET_TCP_HAVE_STACK) && defined(CONFIG_NET_TCP_WRITE_BUFFERS)
#if defined(NET_TCP_HAVE_STACK)
case SOCK_STREAM:
{
ret = tcp_txdrain(psock, abstime);
}
break;
#endif

#if defined(NET_UDP_HAVE_STACK) && defined(CONFIG_NET_UDP_WRITE_BUFFERS)
#if defined(NET_UDP_HAVE_STACK)
case SOCK_DGRAM:
{
ret = udp_txdrain(psock, abstime);
Expand Down

0 comments on commit 077d164

Please sign in to comment.