mirror of
https://github.com/apache/nuttx.git
synced 2026-05-26 10:46:28 +08:00
Squashed commit of the following:
net/tcp: Add logic to send probes when SO_KEEPALIVE is enabled.
net/tcp: TCP socket should not have to be connected to configure KeepAlive.
net/: Add a separate configuration to enable/disable KEEPALIVE socket options.
net/tcp: Arguments to TCP keep-alive timing functions probably should be struct timeval as are the times for other time-related socket options.
net/tcp: Fix a backward conditional
net/tcp: Add some more checks and debug output to TCP-protocol socket options.
net/tcp: Cosmetic changes to some alignment.
net/: Adds socket options needed to manage TCP-keepalive and TCP state machine logic to detect if that the remote peer is alive. Still missing the timer poll logic to send the keep-alive probes and the state machine logic to respond to probes.
This commit is contained in:
+19
-7
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/netinet/tcp.h
|
||||
*
|
||||
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -46,15 +46,27 @@
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* "The netinet/tcp.h header shall define the following macro for use as a
|
||||
* socket option at the IPPROTO_TCP level:" -- OpenGroup.org
|
||||
/* Per OpenGroup.org:
|
||||
*
|
||||
* "The netinet/tcp.h header shall define the following macro for use as a
|
||||
* socket option at the IPPROTO_TCP level:" -- OpenGroup.org
|
||||
*/
|
||||
|
||||
#define TCP_NODELAY __SO_PROTOCOL /* Avoid coalescing of small segments. */
|
||||
#define TCP_NODELAY (__SO_PROTOCOL + 0) /* Avoid coalescing of small segments. */
|
||||
|
||||
/* "The macro shall be defined in the header. The implementation need not
|
||||
* allow the value of the option to be set via setsockopt() or retrieved via
|
||||
* getsockopt()." -- OpenGroup.org
|
||||
/* "The macro shall be defined in the header. The implementation need not
|
||||
* allow the value of the option to be set via setsockopt() or retrieved via
|
||||
* getsockopt()."
|
||||
*/
|
||||
|
||||
/* Additional TCP protocol socket operations not specified at OpenGroup.org */
|
||||
/* TCP protocol socket operations needed to support TCP Keep-Alive: */
|
||||
|
||||
#define TCP_KEEPIDLE (__SO_PROTOCOL + 1) /* Start keeplives after this IDLE period
|
||||
* Argument: struct timeval */
|
||||
#define TCP_KEEPINTVL (__SO_PROTOCOL + 2) /* Interval between keepalives
|
||||
* Argument: struct timeval */
|
||||
#define TCP_KEEPCNT (__SO_PROTOCOL + 3) /* Number of keepalives before death
|
||||
* Argument: max retry count */
|
||||
|
||||
#endif /* __INCLUDE_NETINET_TCP_H */
|
||||
|
||||
+21
-3
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/clock.h
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2011-2012, 2014, 2016-2017 Gregory Nutt.
|
||||
* Copyright (C) 2007-2009, 2011-2012, 2014, 2016-2018 Gregory Nutt.
|
||||
All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
@@ -120,6 +120,21 @@
|
||||
|
||||
#define NSEC_PER_USEC 1000L /* Microseconds */
|
||||
|
||||
#define SEC_PER_MIN 60L
|
||||
#define NSEC_PER_MIN (NSEC_PER_SEC * SEC_PER_MIN)
|
||||
#define USEC_PER_MIN (USEC_PER_SEC * SEC_PER_MIN)
|
||||
#define MSEC_PER_MIN (MSEC_PER_SEC * SEC_PER_MIN)
|
||||
#define DSEC_PER_MIN (HSEC_PER_SEC * SEC_PER_MIN)
|
||||
#define HSEC_PER_MIN (HSEC_PER_SEC * SEC_PER_MIN)
|
||||
|
||||
#define MIN_PER_HOUR 60L
|
||||
#define NSEC_PER_HOUR (NSEC_PER_MIN * MIN_PER_HOUR)
|
||||
#define USEC_PER_HOUR (USEC_PER_MIN * MIN_PER_HOUR)
|
||||
#define MSEC_PER_HOUR (MSEC_PER_MIN * MIN_PER_HOUR)
|
||||
#define DSEC_PER_HOUR (HSEC_PER_SEC * MIN_PER_HOUR)
|
||||
#define HSEC_PER_HOUR (DSEC_PER_MIN * MIN_PER_HOUR)
|
||||
#define SEC_PER_HOUR (SEC_PER_MIN * MIN_PER_HOUR)
|
||||
|
||||
/* If CONFIG_SCHED_TICKLESS is not defined, then the interrupt interval of
|
||||
* the system timer is given by USEC_PER_TICK. This is the expected number
|
||||
* of microseconds between calls from the processor-specific logic to
|
||||
@@ -145,10 +160,13 @@
|
||||
* preferred for that reason (at the risk of overflow)
|
||||
*/
|
||||
|
||||
#define TICK_PER_DSEC (USEC_PER_DSEC / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_HSEC (USEC_PER_HSEC / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_HOUR (USEC_PER_HOUR / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_MIN (USEC_PER_MIN / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_SEC (USEC_PER_SEC / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_MSEC (USEC_PER_MSEC / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_DSEC (USEC_PER_DSEC / USEC_PER_TICK) /* Truncates! */
|
||||
#define TICK_PER_HSEC (USEC_PER_HSEC / USEC_PER_TICK) /* Truncates! */
|
||||
|
||||
#define MSEC_PER_TICK (USEC_PER_TICK / USEC_PER_MSEC) /* Truncates! */
|
||||
#define NSEC_PER_TICK (USEC_PER_TICK * NSEC_PER_USEC) /* Exact */
|
||||
|
||||
|
||||
+13
-5
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* include/sys/socket.h
|
||||
*
|
||||
* Copyright (C) 2007, 2009, 2011, 2015-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007, 2009, 2011, 2015-2016, 2018 Gregory Nutt. All
|
||||
* rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -128,7 +129,7 @@
|
||||
* an integer value */
|
||||
#define SO_KEEPALIVE 5 /* Keeps connections active by enabling the periodic transmission
|
||||
* of messages (get/set).
|
||||
* arg: pointer to integer containing a boolean value */
|
||||
* arg: pointer to integer containing a boolean int value */
|
||||
#define SO_LINGER 6 /* Lingers on a close() if data is present (get/set)
|
||||
* arg: struct linger */
|
||||
#define SO_OOBINLINE 7 /* Leaves received out-of-band data (data marked urgent) inline
|
||||
@@ -149,15 +150,22 @@
|
||||
* being sent(get/set). arg: struct timeval */
|
||||
#define SO_TYPE 15 /* Reports the socket type (get only). return: int */
|
||||
|
||||
/* Protocol-level socket operations */
|
||||
|
||||
#define SOL_IP 1 /* See options in include/netinet/ip.h */
|
||||
#define SOL_IPV6 2 /* See options in include/netinet/ip6.h */
|
||||
#define SOL_TCP 3 /* See options in include/netinet/tcp.h */
|
||||
#define SOL_UDP 4 /* See options in include/netinit/udp.h */
|
||||
|
||||
/* Protocol-level socket options may begin with this value */
|
||||
|
||||
#define __SO_PROTOCOL 16
|
||||
|
||||
/* Values for the 'how' argument of shutdown() */
|
||||
|
||||
#define SHUT_RD 1 /* Bit 0: Disables further receive operations */
|
||||
#define SHUT_WR 2 /* Bit 1: Disables further send operations */
|
||||
#define SHUT_RDWR 3 /* Bits 0+1: Disables further send and receive operations */
|
||||
#define SHUT_RD 1 /* Bit 0: Disables further receive operations */
|
||||
#define SHUT_WR 2 /* Bit 1: Disables further send operations */
|
||||
#define SHUT_RDWR 3 /* Bits 0+1: Disables further send and receive operations */
|
||||
|
||||
/****************************************************************************
|
||||
* Type Definitions
|
||||
|
||||
@@ -24,6 +24,12 @@ config NET_SOCKOPTS
|
||||
---help---
|
||||
Enable or disable support for socket options
|
||||
|
||||
config NET_TCPPROTO_OPTIONS
|
||||
bool
|
||||
default n
|
||||
---help---
|
||||
Enable or disable support for TCP protocol level socket options.
|
||||
|
||||
if NET_SOCKOPTS
|
||||
|
||||
config NET_SOLINGER
|
||||
|
||||
+148
-44
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* net/socket/getsockopt.c
|
||||
*
|
||||
* Copyright (C) 2007-2009, 2012, 2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2009, 2012, 2014, 2017-2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -48,19 +49,20 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "tcp/tcp.h"
|
||||
#include "usrsock/usrsock.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_getsockopt
|
||||
* Name: psock_socketlevel_option
|
||||
*
|
||||
* Description:
|
||||
* getsockopt() retrieve thse value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* getsockopt() retrieve the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
@@ -68,9 +70,12 @@
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To
|
||||
* retrieve options at the socket level, specify the level argument as
|
||||
* SOL_SOCKET.
|
||||
* SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
|
||||
* argument is SOL_CP.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the 'option' argument.
|
||||
* See <sys/socket.h> a complete list of values for the socket-level
|
||||
* 'option' argument. Protocol-specific options are are protocol specific
|
||||
* header files (such as netinet/tcp.h for the case of the TCP protocol).
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
@@ -80,24 +85,14 @@
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error.
|
||||
*
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shutdown.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'psock' argument does not refer to a socket.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_getsockopt() for
|
||||
* the complete list of appropriate return error codes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
/* Verify that the socket option if valid (but might not be supported ) */
|
||||
|
||||
@@ -126,7 +121,7 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
|
||||
default: /* Other options are passed to usrsock daemon. */
|
||||
{
|
||||
return usrsock_getsockopt(conn, level, option, value, value_len);
|
||||
return usrsock_getsockopt(conn, SOL_SOCKET, option, value, value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,8 +139,10 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
case SO_DEBUG: /* Enables recording of debugging information */
|
||||
case SO_BROADCAST: /* Permits sending of broadcast messages */
|
||||
case SO_REUSEADDR: /* Allow reuse of local addresses */
|
||||
case SO_KEEPALIVE: /* Keeps connections active by enabling the
|
||||
* periodic transmission */
|
||||
#ifndef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
#endif
|
||||
case SO_OOBINLINE: /* Leaves received out-of-band data inline */
|
||||
case SO_DONTROUTE: /* Requests outgoing messages bypass standard routing */
|
||||
{
|
||||
@@ -172,6 +169,23 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
/* Any connection-oriented protocol could potentially support
|
||||
* SO_KEEPALIVE. However, this option is currently only available for
|
||||
* TCP/IP.
|
||||
*
|
||||
* NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
|
||||
* protocol-level option. A given TCP connection may service multiple
|
||||
* sockets (via dup'ing of the socket). There is, however, still only
|
||||
* one connection to be monitored and that is a global attribute across
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
return tcp_getsockopt(psock, option, value, value_len);
|
||||
#endif
|
||||
|
||||
case SO_TYPE: /* Reports the socket type */
|
||||
{
|
||||
/* Verify that option is the size of an 'int'. Should also check
|
||||
@@ -257,24 +271,114 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* getsockopt() retrieve the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To
|
||||
* retrieve options at the socket level, specify the level argument as
|
||||
* SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
|
||||
* argument is SOL_CP.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the socket-level
|
||||
* 'option' argument. Protocol-specific options are are protocol specific
|
||||
* header files (such as netinet/tcp.h for the case of the TCP protocol).
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to get
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error.
|
||||
*
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shutdown.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'psock' argument does not refer to a socket.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Handle retrieval of the socket option according to the level at which
|
||||
* option should be applied.
|
||||
*/
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case SOL_SOCKET: /* Socket-level options (see include/sys/socket.h) */
|
||||
ret = psock_socketlevel_option(psock, option, value, value_len);
|
||||
break;
|
||||
|
||||
case SOL_TCP: /* TCP protocol socket options (see include/netinet/tcp.h) */
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
ret = tcp_getsockopt(psock, option, value, value_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* These levels are defined in sys/socket.h, but are not yet
|
||||
* implemented.
|
||||
*/
|
||||
|
||||
case SOL_IP: /* TCP protocol socket options (see include/netinet/ip.h) */
|
||||
case SOL_IPV6: /* TCP protocol socket options (see include/netinet/ip6.h) */
|
||||
case SOL_UDP: /* TCP protocol socket options (see include/netinit/udp.h) */
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
|
||||
default: /* The provided level is invalid */
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: getsockopt
|
||||
*
|
||||
* Description:
|
||||
* getsockopt() retrieve thse value for the option specified by the
|
||||
* getsockopt() retrieve the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'sockfd' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the'value'.
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To
|
||||
* retrieve options at the socket level, specify the level argument as
|
||||
* SOL_SOCKET.
|
||||
* SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
|
||||
* argument is SOL_CP.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the 'option' argument.
|
||||
* See <sys/socket.h> a complete list of values for the socket-level
|
||||
* 'option' argument. Protocol-specific options are are protocol specific
|
||||
* header files (such as netinet/tcp.h for the case of the TCP protocol).
|
||||
*
|
||||
* Parameters:
|
||||
* Input Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to get
|
||||
@@ -282,21 +386,21 @@ int psock_getsockopt(FAR struct socket *psock, int level, int option,
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, -1 (ERROR) is returned and th
|
||||
* errno variable is set appropriately:
|
||||
* Returns zero (OK) on success. On failure, -1 (ERROR) is returned and th
|
||||
* errno variable is set appropriately:
|
||||
*
|
||||
* EBADF
|
||||
* The 'sockfd' argument is not a valid socket descriptor.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shutdown.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
* EBADF
|
||||
* The 'sockfd' argument is not a valid socket descriptor.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shutdown.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
+160
-67
@@ -1,8 +1,8 @@
|
||||
/****************************************************************************
|
||||
* net/socket/setsockopt.c
|
||||
*
|
||||
* Copyright (C) 2007, 2008, 2011-2012, 2014-2015, 2017 Gregory Nutt. All
|
||||
* rights reserved.
|
||||
* Copyright (C) 2007, 2008, 2011-2012, 2014-2015, 2017-2018 Gregory Nutt.
|
||||
* All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -52,6 +52,7 @@
|
||||
#include <nuttx/net/net.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "tcp/tcp.h"
|
||||
#include "usrsock/usrsock.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
@@ -60,54 +61,31 @@
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_setsockopt
|
||||
* Name: psock_socketlevel_option
|
||||
*
|
||||
* Description:
|
||||
* psock_setsockopt() sets the option specified by the 'option' argument,
|
||||
* at the protocol level specified by the 'level' argument, to the value
|
||||
* pointed to by the 'value' argument for the socket on the 'psock' argument.
|
||||
* psock_socketlevel_option() sets the socket-level option specified by the
|
||||
* 'option' argument to the value pointed to by the 'value' argument for
|
||||
* the socket specified by the 'psock' argument.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To set
|
||||
* options at the socket level, specify the level argument as SOL_SOCKET.
|
||||
* See <sys/socket.h> a complete list of values for the socket level
|
||||
* 'option' argument.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the 'option' argument.
|
||||
*
|
||||
* Parameters:
|
||||
* Input Parameters:
|
||||
* psock Socket structure of socket to operate on
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to set
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error:
|
||||
*
|
||||
* EDOM
|
||||
* The send and receive timeout values are too big to fit into the
|
||||
* timeout fields in the socket structure.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shut down.
|
||||
* EISCONN
|
||||
* The socket is already connected, and a specified option cannot be set
|
||||
* while the socket is connected.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOMEM
|
||||
* There was insufficient memory available for the operation to complete.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
* Assumptions:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_setcockopt() for
|
||||
* the list of possible error values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
static int psock_socketlevel_option(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
/* Verify that the socket option if valid (but might not be supported ) */
|
||||
|
||||
@@ -135,7 +113,8 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
|
||||
default: /* Other options are passed to usrsock daemon. */
|
||||
{
|
||||
return usrsock_setsockopt(conn, level, option, value, value_len);
|
||||
return usrsock_setsockopt(conn, SOL_SOCKET, option, value,
|
||||
value_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -153,8 +132,10 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
case SO_DEBUG: /* Enables recording of debugging information */
|
||||
case SO_BROADCAST: /* Permits sending of broadcast messages */
|
||||
case SO_REUSEADDR: /* Allow reuse of local addresses */
|
||||
case SO_KEEPALIVE: /* Keeps connections active by enabling the
|
||||
* periodic transmission */
|
||||
#ifndef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
#endif
|
||||
case SO_OOBINLINE: /* Leaves received out-of-band data inline */
|
||||
case SO_DONTROUTE: /* Requests outgoing messages bypass standard routing */
|
||||
{
|
||||
@@ -194,6 +175,23 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
/* Any connection-oriented protocol could potentially support
|
||||
* SO_KEEPALIVE. However, this option is currently only available for
|
||||
* TCP/IP.
|
||||
*
|
||||
* NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
|
||||
* protocol-level option. A given TCP connection may service multiple
|
||||
* sockets (via dup'ing of the socket). There is, however, still only
|
||||
* one connection to be monitored and that is a global attribute across
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
return tcp_setsockopt(psock, option, value, value_len);
|
||||
#endif
|
||||
|
||||
case SO_RCVTIMEO:
|
||||
case SO_SNDTIMEO:
|
||||
{
|
||||
@@ -208,7 +206,7 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
}
|
||||
|
||||
/* Get the timeout value. Any microsecond remainder will be
|
||||
* force to the next larger, whole decisecond value.
|
||||
* forced to the next larger, whole decisecond value.
|
||||
*/
|
||||
|
||||
timeo = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
|
||||
@@ -296,6 +294,99 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_setsockopt
|
||||
*
|
||||
* Description:
|
||||
* psock_setsockopt() sets the option specified by the 'option' argument,
|
||||
* at the protocol level specified by the 'level' argument, to the value
|
||||
* pointed to by the 'value' argument for the socket specified by the
|
||||
* 'psock' argument.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To set
|
||||
* options at the socket level, specify the level argument as SOL_SOCKET.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the socket level
|
||||
* 'option' argument.
|
||||
*
|
||||
* Protocol level options, such as SOL_TCP, are defined in protocol-specific
|
||||
* header files, for example include/netinet/tcp.h
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock Socket structure of socket to operate on
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to set
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error:
|
||||
*
|
||||
* EDOM
|
||||
* The send and receive timeout values are too big to fit into the
|
||||
* timeout fields in the socket structure.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shut down.
|
||||
* EISCONN
|
||||
* The socket is already connected, and a specified option cannot be set
|
||||
* while the socket is connected.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOMEM
|
||||
* There was insufficient memory available for the operation to complete.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Handle setting of the socket option according to the level at which
|
||||
* option should be applied.
|
||||
*/
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case SOL_SOCKET: /* Socket-level options (see include/sys/socket.h) */
|
||||
ret = psock_socketlevel_option(psock, option, value, value_len);
|
||||
break;
|
||||
|
||||
case SOL_TCP: /* TCP protocol socket options (see include/netinet/tcp.h) */
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
ret = tcp_setsockopt(psock, option, value, value_len);
|
||||
break;
|
||||
#endif
|
||||
|
||||
/* These levels are defined in sys/socket.h, but are not yet
|
||||
* implemented.
|
||||
*/
|
||||
|
||||
case SOL_IP: /* TCP protocol socket options (see include/netinet/ip.h) */
|
||||
case SOL_IPV6: /* TCP protocol socket options (see include/netinet/ip6.h) */
|
||||
case SOL_UDP: /* TCP protocol socket options (see include/netinit/udp.h) */
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
|
||||
default: /* The provided level is invalid */
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: setsockopt
|
||||
*
|
||||
@@ -305,12 +396,16 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
* pointed to by the 'value' argument for the socket associated with the
|
||||
* file descriptor specified by the 'sockfd' argument.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To set
|
||||
* The 'level' argument specifies the protocol level of the option. To set
|
||||
* options at the socket level, specify the level argument as SOL_SOCKET.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the 'option' argument.
|
||||
* See <sys/socket.h> a complete list of values for the socket level
|
||||
* 'option' argument.
|
||||
*
|
||||
* Parameters:
|
||||
* Protocol level options, such as SOL_TCP, are defined in protocol-specific
|
||||
* header files, for example include/netinet/tcp.h
|
||||
*
|
||||
* Input Parameters:
|
||||
* sockfd Socket descriptor of socket
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to set
|
||||
@@ -318,30 +413,28 @@ int psock_setsockopt(FAR struct socket *psock, int level, int option,
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* 0 on success; -1 on failure
|
||||
* 0 on success; -1 on failure
|
||||
*
|
||||
* EBADF
|
||||
* The 'sockfd' argument is not a valid socket descriptor.
|
||||
* EDOM
|
||||
* The send and receive timeout values are too big to fit into the
|
||||
* timeout fields in the socket structure.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shut down.
|
||||
* EISCONN
|
||||
* The socket is already connected, and a specified option cannot be set
|
||||
* while the socket is connected.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOMEM
|
||||
* There was insufficient memory available for the operation to complete.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
* Assumptions:
|
||||
* EBADF
|
||||
* The 'sockfd' argument is not a valid socket descriptor.
|
||||
* EDOM
|
||||
* The send and receive timeout values are too big to fit into the
|
||||
* timeout fields in the socket structure.
|
||||
* EINVAL
|
||||
* The specified option is invalid at the specified socket 'level' or the
|
||||
* socket has been shut down.
|
||||
* EISCONN
|
||||
* The socket is already connected, and a specified option cannot be set
|
||||
* while the socket is connected.
|
||||
* ENOPROTOOPT
|
||||
* The 'option' is not supported by the protocol.
|
||||
* ENOTSOCK
|
||||
* The 'sockfd' argument does not refer to a socket.
|
||||
* ENOMEM
|
||||
* There was insufficient memory available for the operation to complete.
|
||||
* ENOBUFS
|
||||
* Insufficient resources are available in the system to complete the
|
||||
* call.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
@@ -20,6 +20,14 @@ config NET_TCP_NO_STACK
|
||||
|
||||
if NET_TCP && !NET_TCP_NO_STACK
|
||||
|
||||
config NET_TCP_KEEPALIVE
|
||||
bool "TCP/IP Keep-alive support"
|
||||
default n
|
||||
select NET_TCPPROTO_OPTIONS
|
||||
depends on EXPERIMENTAL
|
||||
---help---
|
||||
Enable support for the SO_KEEPALIVE socket option
|
||||
|
||||
config NET_TCPURGDATA
|
||||
bool "Urgent data"
|
||||
default n
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
############################################################################
|
||||
# net/tcp/Make.defs
|
||||
#
|
||||
# Copyright (C) 2014, 2017 Gregory Nutt. All rights reserved.
|
||||
# Copyright (C) 2014, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
# Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
@@ -58,6 +58,10 @@ NET_CSRCS += tcp_netpoll.c
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NET_TCPPROTO_OPTIONS),y)
|
||||
SOCK_CSRCS += tcp_setsockopt.c tcp_getsockopt.c
|
||||
endif
|
||||
|
||||
# Transport layer
|
||||
|
||||
NET_CSRCS += tcp_conn.c tcp_seqno.c tcp_devpoll.c tcp_finddev.c tcp_timer.c
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <queue.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/mm/iob.h>
|
||||
#include <nuttx/net/ip.h>
|
||||
|
||||
@@ -199,6 +200,21 @@ struct tcp_conn_s
|
||||
FAR struct tcp_backlog_s *backlog;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* There fields manage TCP/IP keep-alive. All times are in units of the
|
||||
* system clock tick.
|
||||
*/
|
||||
|
||||
systime_t keeptime; /* Last time that the TCP socket was known to be
|
||||
* alive (ACK or data received) OR time that the
|
||||
* last probe was sent. */
|
||||
uint16_t keepidle; /* Elapsed idle time before first probe sent (dsec) */
|
||||
uint16_t keepintvl; /* Interval between probes (dsec) */
|
||||
bool keepalive; /* True: KeepAlive enabled; false: disabled */
|
||||
uint8_t keepcnt; /* Number of retries before the socket is closed */
|
||||
uint8_t keepretries; /* Number of retries attempted */
|
||||
#endif
|
||||
|
||||
/* Application callbacks:
|
||||
*
|
||||
* Data transfer events are retained in 'list'. Event handlers in 'list'
|
||||
@@ -1271,6 +1287,74 @@ struct socket;
|
||||
ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf,
|
||||
size_t len);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_setsockopt
|
||||
*
|
||||
* Description:
|
||||
* tcp_setsockopt() sets the TCP-protocol option specified by the
|
||||
* 'option' argument to the value pointed to by the 'value' argument for
|
||||
* the socket specified by the 'psock' argument.
|
||||
*
|
||||
* See <netinet/tcp.h> for the a complete list of values of TCP protocol
|
||||
* options.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock Socket structure of socket to operate on
|
||||
* option identifies the option to set
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_setcockopt() for
|
||||
* the list of possible error values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* tcp_getsockopt() retrieves the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To
|
||||
* retrieve options at the socket level, specify the level argument as
|
||||
* SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
|
||||
* argument is SOL_CP.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the socket-level
|
||||
* 'option' argument. Protocol-specific options are are protocol specific
|
||||
* header files (such as netinet/tcp.h for the case of the TCP protocol).
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to get
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_getsockopt() for
|
||||
* the complete list of appropriate return error codes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len);
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: psock_tcp_cansend
|
||||
*
|
||||
|
||||
+9
-1
@@ -1,7 +1,8 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_conn.c
|
||||
*
|
||||
* Copyright (C) 2007-2011, 2013-2015 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2011, 2013-2015, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Large parts of this file were leveraged from uIP logic:
|
||||
@@ -53,6 +54,7 @@
|
||||
|
||||
#include <arch/irq.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/net/netconfig.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
@@ -714,6 +716,12 @@ FAR struct tcp_conn_s *tcp_alloc(uint8_t domain)
|
||||
conn->tcpstateflags = TCP_ALLOCATED;
|
||||
#if defined(CONFIG_NET_IPv4) && defined(CONFIG_NET_IPv6)
|
||||
conn->domain = domain;
|
||||
#endif
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
conn->keeptime = clock_systimer();
|
||||
conn->keepidle = 2 * DSEC_PER_HOUR;
|
||||
conn->keepintvl = 2 * DSEC_PER_SEC;
|
||||
conn->keepcnt = 3;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_setsockopt.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/tcp.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "tcp/tcp.h"
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_getsockopt
|
||||
*
|
||||
* Description:
|
||||
* tcp_getsockopt() retrieves the value for the option specified by the
|
||||
* 'option' argument for the socket specified by the 'psock' argument. If
|
||||
* the size of the option value is greater than 'value_len', the value
|
||||
* stored in the object pointed to by the 'value' argument will be silently
|
||||
* truncated. Otherwise, the length pointed to by the 'value_len' argument
|
||||
* will be modified to indicate the actual length of the 'value'.
|
||||
*
|
||||
* The 'level' argument specifies the protocol level of the option. To
|
||||
* retrieve options at the socket level, specify the level argument as
|
||||
* SOL_SOCKET; to retrieve options at the TCP-protocol level, the level
|
||||
* argument is SOL_CP.
|
||||
*
|
||||
* See <sys/socket.h> a complete list of values for the socket-level
|
||||
* 'option' argument. Protocol-specific options are are protocol specific
|
||||
* header files (such as netinet/tcp.h for the case of the TCP protocol).
|
||||
*
|
||||
* Parameters:
|
||||
* psock Socket structure of the socket to query
|
||||
* level Protocol level to set the option
|
||||
* option identifies the option to get
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_getsockopt() for
|
||||
* the complete list of appropriate return error codes.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int tcp_getsockopt(FAR struct socket *psock, int option,
|
||||
FAR void *value, FAR socklen_t *value_len)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* Keep alive options are the only TCP protocol socket option currently
|
||||
* supported.
|
||||
*/
|
||||
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(psock != NULL && value != NULL && value_len != NULL &&
|
||||
psock->s_conn != NULL);
|
||||
conn = (FAR struct tcp_conn_s *)psock->s_conn;
|
||||
|
||||
/* All of the TCP protocol options apply only TCP sockets. The sockets
|
||||
* do not have to be connected.. that might occur later with the KeepAlive
|
||||
* already configured.
|
||||
*/
|
||||
|
||||
if (psock->s_type != SOCK_STREAM)
|
||||
{
|
||||
nerr("ERROR: Not a TCP socket\n");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* Handle the Keep-Alive option */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
/* Handle the SO_KEEPALIVE socket-level option.
|
||||
*
|
||||
* NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
|
||||
* protocol-level option. A given TCP connection may service multiple
|
||||
* sockets (via dup'ing of the socket). There is, however, still only
|
||||
* one connection to be monitored and that is a global attribute across
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
if (*value_len < sizeof(int))
|
||||
{
|
||||
/* REVISIT: POSIX says that we should truncate the value if it
|
||||
* is larger than value_len. That just doesn't make sense
|
||||
* to me in this case.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR int *keepalive = (FAR int *)value;
|
||||
*keepalive = (int)conn->keepalive;
|
||||
*value_len = sizeof(int);
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_NODELAY: /* Avoid coalescing of small segments. */
|
||||
nerr("ERROR: TCP_NODELAY not supported\n");
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
|
||||
case TCP_KEEPIDLE: /* Start keepalives after this IDLE period */
|
||||
if (*value_len < sizeof(struct timeval))
|
||||
{
|
||||
/* REVISIT: POSIX says that we should truncate the value if it
|
||||
* is larger than value_len. That just doesn't make sense
|
||||
* to me in this case.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert the KeepIdle time from deciseconds to struct
|
||||
* timeval.
|
||||
*/
|
||||
|
||||
net_dsec2timeval(conn->keepidle, tv);
|
||||
*value_len = sizeof(struct timeval);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_KEEPINTVL: /* Interval between keepalives */
|
||||
if (*value_len < sizeof(struct timeval))
|
||||
{
|
||||
/* REVISIT: POSIX says that we should truncate the value if it
|
||||
* is larger than value_len. That just doesn't make sense
|
||||
* to me in this case.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Convert the KeepIdle time from deciseconds to struct
|
||||
* timeval.
|
||||
*/
|
||||
|
||||
net_dsec2timeval(conn->keepintvl, tv);
|
||||
*value_len = sizeof(struct timeval);
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_KEEPCNT: /* Number of keepalives before death */
|
||||
if (*value_len < sizeof(int))
|
||||
{
|
||||
/* REVISIT: POSIX says that we should truncate the value if it
|
||||
* is larger than value_len. That just doesn't make sense
|
||||
* to me in this case.
|
||||
*/
|
||||
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR int *keepcnt = (FAR int *)value;
|
||||
*keepcnt = (int)conn->keepcnt;
|
||||
*value_len = sizeof(int);
|
||||
ret = OK;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized TCP option: %d\n", option);
|
||||
ret = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_TCPPROTO_OPTIONS */
|
||||
+27
-7
@@ -2,7 +2,7 @@
|
||||
* net/tcp/tcp_input.c
|
||||
* Handling incoming TCP input
|
||||
*
|
||||
* Copyright (C) 2007-2014, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2014, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/net/netconfig.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/netstats.h>
|
||||
@@ -385,7 +386,7 @@ found:
|
||||
dev->d_len -= (len + iplen);
|
||||
|
||||
/* First, check if the sequence number of the incoming packet is
|
||||
* what we're expecting next. If not, we send out an ACK with the
|
||||
* what we're expecting next. If not, we send out an ACK with the
|
||||
* correct numbers in, unless we are in the SYN_RCVD state and
|
||||
* receive a SYN, in which case we should retransmit our SYNACK
|
||||
* (which is done further down).
|
||||
@@ -685,14 +686,14 @@ found:
|
||||
|
||||
case TCP_ESTABLISHED:
|
||||
/* In the ESTABLISHED state, we call upon the application to feed
|
||||
* data into the d_buf. If the TCP_ACKDATA flag is set, the
|
||||
* data into the d_buf. If the TCP_ACKDATA flag is set, the
|
||||
* application should put new data into the buffer, otherwise we are
|
||||
* retransmitting an old segment, and the application should put that
|
||||
* data into the buffer.
|
||||
*
|
||||
* If the incoming packet is a FIN, we should close the connection on
|
||||
* this side as well, and we send out a FIN and enter the LAST_ACK
|
||||
* state. We require that there is no outstanding data; otherwise the
|
||||
* state. We require that there is no outstanding data; otherwise the
|
||||
* sequence numbers will be screwed up.
|
||||
*/
|
||||
|
||||
@@ -763,6 +764,25 @@ found:
|
||||
#endif /* CONFIG_NET_TCPURGDATA */
|
||||
}
|
||||
|
||||
#ifdef NET_TCP_KEEPALIVE
|
||||
/* If the established socket receives an ACK or any kind of data
|
||||
* from the remote peer (whether we accept it or not), then reset
|
||||
* the keep alive timer.
|
||||
*/
|
||||
|
||||
if (conn->keepalive && (dev->d_len > 0 || (tcp->flags & TCP_ACK) != 0))
|
||||
{
|
||||
/* Reset the last known "alive" time.
|
||||
*
|
||||
* REVISIT: At this level, we don't actually know if keep-
|
||||
* alive is enabled for this connection.
|
||||
*/
|
||||
|
||||
conn->keeptime = clock_systimer();
|
||||
conn->keepretries = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If d_len > 0 we have TCP data in the packet, and we flag this
|
||||
* by setting the TCP_NEWDATA flag. If the application has stopped
|
||||
* the data flow using TCP_STOPPED, we must not accept any data
|
||||
@@ -776,19 +796,19 @@ found:
|
||||
|
||||
/* If this packet constitutes an ACK for outstanding data (flagged
|
||||
* by the TCP_ACKDATA flag), we should call the application since it
|
||||
* might want to send more data. If the incoming packet had data
|
||||
* might want to send more data. If the incoming packet had data
|
||||
* from the peer (as flagged by the TCP_NEWDATA flag), the
|
||||
* application must also be notified.
|
||||
*
|
||||
* When the application is called, the d_len field
|
||||
* contains the length of the incoming data. The application can
|
||||
* contains the length of the incoming data. The application can
|
||||
* access the incoming data through the global pointer
|
||||
* d_appdata, which usually points hdrlen bytes into the d_buf
|
||||
* array.
|
||||
*
|
||||
* If the application wishes to send any data, this data should be
|
||||
* put into the d_appdata and the length of the data should be
|
||||
* put into d_len. If the application don't have any data to
|
||||
* put into d_len. If the application don't have any data to
|
||||
* send, d_len must be set to 0.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_monitor.c
|
||||
*
|
||||
* Copyright (C) 2007-2013, 2017 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2013, 2017-2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -206,7 +206,7 @@ static uint16_t tcp_disconnect_event(FAR struct net_driver_s *dev,
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void tcp_shutdown_monitor(FAR struct tcp_conn_s *conn, uint16_t flags)
|
||||
static void tcp_shutdown_monitor(FAR struct tcp_conn_s *conn, uint16_t flags)
|
||||
{
|
||||
DEBUGASSERT(conn);
|
||||
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/****************************************************************************
|
||||
* net/tcp/tcp_setsockopt.c
|
||||
*
|
||||
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* 3. Neither the name NuttX nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/tcp.h>
|
||||
|
||||
#include "socket/socket.h"
|
||||
#include "utils/utils.h"
|
||||
#include "tcp/tcp.h"
|
||||
|
||||
#ifdef CONFIG_NET_TCPPROTO_OPTIONS
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: tcp_setsockopt
|
||||
*
|
||||
* Description:
|
||||
* tcp_setsockopt() sets the TCP-protocol option specified by the
|
||||
* 'option' argument to the value pointed to by the 'value' argument for
|
||||
* the socket specified by the 'psock' argument.
|
||||
*
|
||||
* See <netinet/tcp.h> for the a complete list of values of TCP protocol
|
||||
* options.
|
||||
*
|
||||
* Input Parameters:
|
||||
* psock Socket structure of socket to operate on
|
||||
* option identifies the option to set
|
||||
* value Points to the argument value
|
||||
* value_len The length of the argument value
|
||||
*
|
||||
* Returned Value:
|
||||
* Returns zero (OK) on success. On failure, it returns a negated errno
|
||||
* value to indicate the nature of the error. See psock_setcockopt() for
|
||||
* the list of possible error values.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int tcp_setsockopt(FAR struct socket *psock, int option,
|
||||
FAR const void *value, socklen_t value_len)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* Keep alive options are the only TCP protocol socket option currently
|
||||
* supported.
|
||||
*/
|
||||
|
||||
FAR struct tcp_conn_s *conn;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(psock != NULL && value != NULL && psock->s_conn != NULL);
|
||||
conn = (FAR struct tcp_conn_s *)psock->s_conn;
|
||||
|
||||
/* All of the TCP protocol options apply only TCP sockets. The sockets
|
||||
* do not have to be connected.. that might occur later with the KeepAlive
|
||||
* already configured.
|
||||
*/
|
||||
|
||||
if (psock->s_type != SOCK_STREAM)
|
||||
{
|
||||
nerr("ERROR: Not a TCP socket\n");
|
||||
return -ENOTCONN;
|
||||
}
|
||||
|
||||
/* Handle the Keep-Alive option */
|
||||
|
||||
switch (option)
|
||||
{
|
||||
/* Handle the SO_KEEPALIVE socket-level option.
|
||||
*
|
||||
* NOTE: SO_KEEPALIVE is not really a socket-level option; it is a
|
||||
* protocol-level option. A given TCP connection may service multiple
|
||||
* sockets (via dup'ing of the socket). There is, however, still only
|
||||
* one connection to be monitored and that is a global attribute across
|
||||
* all of the clones that may use the underlying connection.
|
||||
*/
|
||||
|
||||
case SO_KEEPALIVE: /* Verifies TCP connections active by enabling the
|
||||
* periodic transmission of probes */
|
||||
if (value_len != sizeof(int))
|
||||
{
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
int keepalive = *(FAR int *)value;
|
||||
|
||||
if (keepalive != 0 && keepalive != 1)
|
||||
{
|
||||
nerr("ERROR: SO_KEEPALIVE value out of range: %d\n",
|
||||
keepalive);
|
||||
return -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->keepalive = (bool)keepalive;
|
||||
conn->keeptime = clock_systimer(); /* Reset start time */
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_NODELAY: /* Avoid coalescing of small segments. */
|
||||
nerr("ERROR: TCP_NODELAY not supported\n");
|
||||
ret = -ENOSYS;
|
||||
break;
|
||||
|
||||
case TCP_KEEPIDLE: /* Start keepalives after this IDLE period */
|
||||
if (value_len != sizeof(struct timeval))
|
||||
{
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int dsecs;
|
||||
|
||||
/* Get the IDLE time value. Any microsecond remainder will
|
||||
* be forced to the next larger, whole decisecond value.
|
||||
*/
|
||||
|
||||
dsecs = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
|
||||
if (dsecs > UINT16_MAX)
|
||||
{
|
||||
nwarn("WARNING: TCP_KEEPIDLE value out of range: %u\n",
|
||||
dsecs);
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->keepidle = (uint16_t)dsecs;
|
||||
conn->keeptime = clock_systimer(); /* Reset start time */
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_KEEPINTVL: /* Interval between keepalives */
|
||||
if (value_len != sizeof(struct timeval))
|
||||
{
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
FAR struct timeval *tv = (FAR struct timeval *)value;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int dsecs;
|
||||
|
||||
/* Get the IDLE time value. Any microsecond remainder will
|
||||
* be forced to the next larger, whole decisecond value.
|
||||
*/
|
||||
|
||||
dsecs = (socktimeo_t)net_timeval2dsec(tv, TV2DS_CEIL);
|
||||
if (dsecs > UINT16_MAX)
|
||||
{
|
||||
nwarn("WARNING: TCP_KEEPINTVL value out of range: %u\n",
|
||||
dsecs);
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->keepintvl = (uint16_t)dsecs;
|
||||
conn->keeptime = clock_systimer(); /* Reset start time */
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case TCP_KEEPCNT: /* Number of keepalives before death */
|
||||
if (value_len != sizeof(int))
|
||||
{
|
||||
ret = -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
int keepcnt = *(FAR int *)value;
|
||||
|
||||
if (keepcnt < 0 || keepcnt > UINT8_MAX)
|
||||
{
|
||||
nerr("ERROR: TCP_KEEPCNT value out of range: %d\n", keepcnt);
|
||||
return -EDOM;
|
||||
}
|
||||
else
|
||||
{
|
||||
conn->keepcnt = (uint8_t)keepcnt;
|
||||
conn->keeptime = clock_systimer(); /* Reset start time */
|
||||
ret = OK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
nerr("ERROR: Unrecognized TCP option: %d\n", option);
|
||||
ret = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
#else
|
||||
return -ENOPROTOOPT;
|
||||
#endif /* CONFIG_NET_TCP_KEEPALIVE */
|
||||
}
|
||||
|
||||
#endif /* CONFIG_NET_TCPPROTO_OPTIONS */
|
||||
+87
-5
@@ -2,7 +2,8 @@
|
||||
* net/tcp/tcp_timer.c
|
||||
* Poll for the availability of TCP TX data
|
||||
*
|
||||
* Copyright (C) 2007-2010, 2015-2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2010, 2015-2016, 2018 Gregory Nutt. All rights
|
||||
* reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
|
||||
@@ -50,11 +51,13 @@
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/net/netconfig.h>
|
||||
#include <nuttx/net/net.h>
|
||||
#include <nuttx/net/netdev.h>
|
||||
#include <nuttx/net/netstats.h>
|
||||
#include <nuttx/net/tcp.h>
|
||||
|
||||
#include "devif/devif.h"
|
||||
#include "socket/socket.h"
|
||||
#include "tcp/tcp.h"
|
||||
|
||||
/****************************************************************************
|
||||
@@ -347,10 +350,6 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
|
||||
else if ((conn->tcpstateflags & TCP_STATE_MASK) == TCP_ESTABLISHED)
|
||||
{
|
||||
/* If there was no need for a retransmission, we poll the
|
||||
* application for new data.
|
||||
*/
|
||||
|
||||
/* The TCP connection is established and, hence, should be bound
|
||||
* to a device. Make sure that the polling device is the one that
|
||||
* we are bound to.
|
||||
@@ -359,6 +358,89 @@ void tcp_timer(FAR struct net_driver_s *dev, FAR struct tcp_conn_s *conn,
|
||||
DEBUGASSERT(conn->dev != NULL);
|
||||
if (dev == conn->dev)
|
||||
{
|
||||
#ifdef CONFIG_NET_TCP_KEEPALIVE
|
||||
/* Is this an established connected with KeepAlive enabled? */
|
||||
|
||||
if (conn->keepalive)
|
||||
{
|
||||
socktimeo_t timeo;
|
||||
|
||||
/* If this is the first probe, then the keepstart time is
|
||||
* the time that the last ACK or data was received from the
|
||||
* remote.
|
||||
*
|
||||
* On subsequent retries, keepstart is the time that the
|
||||
* last probe was sent.
|
||||
*/
|
||||
|
||||
if (conn->keepretries > 0)
|
||||
{
|
||||
timeo = (socktimeo_t)conn->keepintvl;
|
||||
}
|
||||
else
|
||||
{
|
||||
timeo = (socktimeo_t)conn->keepidle;
|
||||
}
|
||||
/* Yes... has the idle period elapsed with no data or ACK
|
||||
* received from the remote peer?
|
||||
*/
|
||||
|
||||
if (net_timeo(conn->keeptime, timeo))
|
||||
{
|
||||
/* Yes.. Has the retry count expired? */
|
||||
|
||||
if (conn->keepretries >= conn->keepcnt)
|
||||
{
|
||||
/* Yes... stop the network monitor, closing the connection and all sockets
|
||||
* associated with the connection.
|
||||
*/
|
||||
|
||||
tcp_stop_monitor(conn, TCP_ABORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int tcpiplen;
|
||||
|
||||
/* No.. we need to send another probe.
|
||||
*
|
||||
* Get the size of the IP header and the TCP header.
|
||||
*/
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
if (conn->domain == PF_INET)
|
||||
#endif
|
||||
{
|
||||
tcpiplen = IPv4_HDRLEN + TCP_HDRLEN;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_NET_IPv6
|
||||
#ifdef CONFIG_NET_IPv4
|
||||
else
|
||||
#endif
|
||||
{
|
||||
tcpiplen = IPv6_HDRLEN + TCP_HDRLEN;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* And send the probe */
|
||||
|
||||
tcp_send(dev, conn, TCP_ACK, tcpiplen);
|
||||
|
||||
/* Update for the next probe */
|
||||
|
||||
conn->keeptime = clock_systimer();
|
||||
conn->keepretries++;
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* There was no need for a retransmission and there was no
|
||||
* need to probe the remote peer. We poll the application for
|
||||
* new outgoing data.
|
||||
*/
|
||||
|
||||
result = tcp_callback(dev, conn, TCP_POLL);
|
||||
tcp_appsend(dev, conn, result);
|
||||
goto done;
|
||||
|
||||
Reference in New Issue
Block a user