summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-20 17:21:42 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-20 17:21:42 +0000
commit28695c8508c93758792dd4ecfb884e108b87c48b (patch)
tree3ee55926a70a6240e51b4ca670a46911916df56d
parent5128effaf839159a5d0897c0d6a3cc4790b55514 (diff)
downloadnuttx-28695c8508c93758792dd4ecfb884e108b87c48b.tar.gz
nuttx-28695c8508c93758792dd4ecfb884e108b87c48b.tar.bz2
nuttx-28695c8508c93758792dd4ecfb884e108b87c48b.zip
Centralize TCP loss-of-connection bit twiddling
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5542 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--apps/netutils/telnetd/telnetd_driver.c9
-rw-r--r--nuttx/net/net_internal.h62
-rw-r--r--nuttx/net/net_monitor.c93
-rw-r--r--nuttx/net/recvfrom.c37
-rw-r--r--nuttx/net/send.c11
5 files changed, 120 insertions, 92 deletions
diff --git a/apps/netutils/telnetd/telnetd_driver.c b/apps/netutils/telnetd/telnetd_driver.c
index 274fde370..1b04bfbe5 100644
--- a/apps/netutils/telnetd/telnetd_driver.c
+++ b/apps/netutils/telnetd/telnetd_driver.c
@@ -1,7 +1,7 @@
/****************************************************************************
* apps/netutils/telnetd_driver.c
*
- * Copyright (C) 2007, 2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007, 2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This is a leverage of similar logic from uIP which has a compatible BSD
@@ -593,6 +593,13 @@ static ssize_t telnetd_read(FAR struct file *filep, FAR char *buffer, size_t len
}
while (ret == 0);
+ /* Return:
+ *
+ * ret > 0: The number of characters copied into the user buffer by
+ * telnetd_receive().
+ * ret <= 0: Loss of connection or error events reported by recv().
+ */
+
return ret;
}
diff --git a/nuttx/net/net_internal.h b/nuttx/net/net_internal.h
index ed2f12aa7..0726c7a80 100644
--- a/nuttx/net/net_internal.h
+++ b/nuttx/net/net_internal.h
@@ -1,7 +1,7 @@
/****************************************************************************
* net/net_internal.h
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -139,94 +139,96 @@
* Public Variables
****************************************************************************/
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
/* List of registered ethernet device drivers */
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-extern struct uip_driver_s *g_netdevices;
+EXTERN struct uip_driver_s *g_netdevices;
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
-#undef EXTERN
-#if defined(__cplusplus)
-#define EXTERN extern "C"
-extern "C" {
-#else
-#define EXTERN extern
-#endif
-
/* net_sockets.c *************************************************************/
-EXTERN int sockfd_allocate(int minsd);
-EXTERN void sock_release(FAR struct socket *psock);
-EXTERN void sockfd_release(int sockfd);
-EXTERN FAR struct socket *sockfd_socket(int sockfd);
+int sockfd_allocate(int minsd);
+void sock_release(FAR struct socket *psock);
+void sockfd_release(int sockfd);
+FAR struct socket *sockfd_socket(int sockfd);
/* net_connect.c *************************************************************/
#ifdef CONFIG_NET_TCP
-EXTERN int net_startmonitor(FAR struct socket *psock);
-EXTERN void net_stopmonitor(FAR struct uip_conn *conn);
+int net_startmonitor(FAR struct socket *psock);
+void net_stopmonitor(FAR struct uip_conn *conn);
+void net_lostconnection(FAR struct socket *psock, uint16_t flags);
#endif
/* net_close.c ***************************************************************/
-EXTERN int psock_close(FAR struct socket *psock);
+int psock_close(FAR struct socket *psock);
/* sockopt support ***********************************************************/
#if defined(CONFIG_NET_SOCKOPTS) && !defined(CONFIG_DISABLE_CLOCK)
-EXTERN int net_timeo(uint32_t start_time, socktimeo_t timeo);
-EXTERN socktimeo_t net_timeval2dsec(struct timeval *tv);
-EXTERN void net_dsec2timeval(uint16_t dsec, struct timeval *tv);
+int net_timeo(uint32_t start_time, socktimeo_t timeo);
+socktimeo_t net_timeval2dsec(FAR struct timeval *tv);
+void net_dsec2timeval(uint16_t dsec, FAR struct timeval *tv);
#endif
/* net_register.c ************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN void netdev_seminit(void);
-EXTERN void netdev_semtake(void);
-EXTERN void netdev_semgive(void);
+void netdev_seminit(void);
+void netdev_semtake(void);
+void netdev_semgive(void);
#endif
/* net_findbyname.c **********************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN FAR struct uip_driver_s *netdev_findbyname(const char *ifname);
+FAR struct uip_driver_s *netdev_findbyname(FAR const char *ifname);
#endif
/* net_findbyaddr.c **********************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN FAR struct uip_driver_s *netdev_findbyaddr(const uip_ipaddr_t *raddr);
+FAR struct uip_driver_s *netdev_findbyaddr(FAR const uip_ipaddr_t *raddr);
#endif
/* net_txnotify.c ************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN void netdev_txnotify(const uip_ipaddr_t *raddr);
+void netdev_txnotify(const uip_ipaddr_t *raddr);
#endif
/* net_count.c ***************************************************************/
#if CONFIG_NSOCKET_DESCRIPTORS > 0
-EXTERN int netdev_count(void);
+int netdev_count(void);
#endif
/* net_arptimer.c ************************************************************/
#ifdef CONFIG_NET_ARP
-EXTERN void arptimer_init(void);
+void arptimer_init(void);
#else
# define arptimer_init()
#endif
/* send.c ********************************************************************/
-EXTERN ssize_t psock_send(FAR struct socket *psock, const void *buf,
- size_t len, int flags);
+ssize_t psock_send(FAR struct socket *psock, FAR const void *buf, size_t len,
+ int flags);
#undef EXTERN
#if defined(__cplusplus)
diff --git a/nuttx/net/net_monitor.c b/nuttx/net/net_monitor.c
index 4bdae4ccf..1eeb4bd27 100644
--- a/nuttx/net/net_monitor.c
+++ b/nuttx/net/net_monitor.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/net_monitor.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
@@ -67,7 +67,6 @@ static void connection_event(struct uip_conn *conn, uint16_t flags);
* Some connection related event has occurred
*
* Parameters:
- * dev The sructure of the network driver that caused the interrupt
* conn The connection structure associated with the socket
* flags Set of events describing why the callback was invoked
*
@@ -79,7 +78,7 @@ static void connection_event(struct uip_conn *conn, uint16_t flags);
*
****************************************************************************/
-static void connection_event(struct uip_conn *conn, uint16_t flags)
+static void connection_event(FAR struct uip_conn *conn, uint16_t flags)
{
FAR struct socket *psock = (FAR struct socket *)conn->connection_private;
@@ -87,37 +86,11 @@ static void connection_event(struct uip_conn *conn, uint16_t flags)
{
nllvdbg("flags: %04x s_flags: %02x\n", flags, psock->s_flags);
- /* These loss-of-connection events may be reported:
- *
- * UIP_CLOSE: The remote host has closed the connection
- * UIP_ABORT: The remote host has aborted the connection
- * UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
- *
- * And we need to set these two socket status bits appropriately:
- *
- * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
- * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
- * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
- */
+ /* UIP_CLOSE, UIP_ABORT, or UIP_TIMEDOUT: Loss-of-connection events */
- if ((flags & UIP_CLOSE) != 0)
- {
- /* The peer gracefully closed the connection. Marking the
- * connection as disconnected will suppress some subsequent
- * ENOTCONN errors from receive. A graceful disconnection is
- * not handle as an error but as an "end-of-file"
- */
-
- psock->s_flags &= ~_SF_CONNECTED;
- psock->s_flags |= _SF_CLOSED;
- }
- else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
+ if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
- /* The loss of connection was less than graceful. This will (eventually)
- * be reported as an ENOTCONN error.
- */
-
- psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
+ net_lostconnection(psock, flags);
}
/* UIP_CONNECTED: The socket is successfully connected */
@@ -184,4 +157,60 @@ void net_stopmonitor(FAR struct uip_conn *conn)
conn->connection_event = NULL;
}
+/****************************************************************************
+ * Name: net_lostconnection
+ *
+ * Description:
+ * Called when a loss-of-connection event has occurred.
+ *
+ * Parameters:
+ * psock The TCP socket structure associated.
+ * flags Set of connection events events
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ * Running at the interrupt level
+ *
+ ****************************************************************************/
+
+void net_lostconnection(FAR struct socket *psock, uint16_t flags)
+{
+ DEBUGASSERT(psock)
+
+ /* These loss-of-connection events may be reported:
+ *
+ * UIP_CLOSE: The remote host has closed the connection
+ * UIP_ABORT: The remote host has aborted the connection
+ * UIP_TIMEDOUT: Connection aborted due to too many retransmissions.
+ *
+ * And we need to set these two socket status bits appropriately:
+ *
+ * _SF_CONNECTED==1 && _SF_CLOSED==0 - the socket is connected
+ * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was gracefully disconnected
+ * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was rudely disconnected
+ */
+
+ if ((flags & UIP_CLOSE) != 0)
+ {
+ /* The peer gracefully closed the connection. Marking the
+ * connection as disconnected will suppress some subsequent
+ * ENOTCONN errors from receive. A graceful disconnection is
+ * not handle as an error but as an "end-of-file"
+ */
+
+ psock->s_flags &= ~_SF_CONNECTED;
+ psock->s_flags |= _SF_CLOSED;
+ }
+ else if ((flags & (UIP_ABORT|UIP_TIMEDOUT)) != 0)
+ {
+ /* The loss of connection was less than graceful. This will (eventually)
+ * be reported as an ENOTCONN error.
+ */
+
+ psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
+ }
+}
+
#endif /* CONFIG_NET && CONFIG_NET_TCP */
diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c
index a1a6742c5..6864dace3 100644
--- a/nuttx/net/recvfrom.c
+++ b/nuttx/net/recvfrom.c
@@ -1,7 +1,7 @@
/****************************************************************************
* net/recvfrom.c
*
- * Copyright (C) 2007-2009, 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2007-2009, 2011-2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -464,10 +464,11 @@ static inline void recvfrom_tcpsender(struct uip_driver_s *dev, struct recvfrom_
****************************************************************************/
#ifdef CONFIG_NET_TCP
-static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
- void *pvpriv, uint16_t flags)
+static uint16_t recvfrom_tcpinterrupt(FAR struct uip_driver_s *dev,
+ FAR void *conn, FAR void *pvpriv,
+ uint16_t flags)
{
- struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv;
+ FAR struct recvfrom_s *pstate = (struct recvfrom_s *)pvpriv;
nllvdbg("flags: %04x\n", flags);
@@ -553,9 +554,7 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
else if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 0)
{
- FAR struct socket *psock = 0;
-
- nllvdbg("error\n");
+ nllvdbg("Lost connection\n");
/* Stop further callbacks */
@@ -563,24 +562,14 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
pstate->rf_cb->priv = NULL;
pstate->rf_cb->event = NULL;
- /* Check if the peer gracefully closed the connection. We need
- * these flags in case we return zero (below) to remember the
- * state of the connection.
- *
- * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was
- * gracefully disconnected
- * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was
- * rudely disconnected
- */
+ /* Handle loss-of-connection event */
- psock = pstate->rf_sock;
- if ((flags & UIP_CLOSE) != 0)
- {
- /* Report that the connection was gracefully closed */
+ net_lostconnection(pstate->rf_sock, flags);
- psock->s_flags &= ~_SF_CONNECTED;
- psock->s_flags |= _SF_CLOSED;
+ /* Check if the peer gracefully closed the connection. */
+ if ((flags & UIP_CLOSE) != 0)
+ {
/* This case should always return success (zero)! The value of
* rf_recvlen, if zero, will indicate that the connection was
* gracefully closed.
@@ -590,10 +579,6 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
}
else
{
- /* Report that the connection was rudely lost */
-
- psock->s_flags &= ~(_SF_CONNECTED |_SF_CLOSED);
-
/* If no data has been received, then return ENOTCONN.
* Otherwise, let this return success. The failure will
* be reported the next time that recv[from]() is called.
diff --git a/nuttx/net/send.c b/nuttx/net/send.c
index 8c07b391c..79dfef4ec 100644
--- a/nuttx/net/send.c
+++ b/nuttx/net/send.c
@@ -227,6 +227,8 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
/* Report not connected */
nllvdbg("Lost connection\n");
+
+ net_lostconnection(pstate->snd_sock, flags);
pstate->snd_sent = -ENOTCONN;
goto end_wait;
}
@@ -275,10 +277,13 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn,
* 3. Not enough data for two packets.
*
* Then we will split the remaining, single packet into two partial
- * packets. This will stimulate the RFC 1122 not into ACKing sooner.
+ * packets. This will stimulate the RFC 1122 peer to ACK sooner.
*
- * Check if there is more data to be sent (more than or equal to
- * CONFIG_NET_TCP_SPLIT_SIZE):
+ * Don't try to split very small packets (less than CONFIG_NET_TCP_SPLIT_SIZE).
+ * Only the first even packet and the last odd packets could have
+ * sndlen less than CONFIG_NET_TCP_SPLIT_SIZE. The value of sndlen on
+ * the last even packet is guaranteed to be at least MSS/2 by the
+ * logic below.
*/
if (sndlen >= CONFIG_NET_TCP_SPLIT_SIZE)