From 28695c8508c93758792dd4ecfb884e108b87c48b Mon Sep 17 00:00:00 2001 From: patacongo Date: Sun, 20 Jan 2013 17:21:42 +0000 Subject: 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 --- apps/netutils/telnetd/telnetd_driver.c | 9 +++- nuttx/net/net_internal.h | 62 ++++++++++++----------- nuttx/net/net_monitor.c | 93 ++++++++++++++++++++++------------ nuttx/net/recvfrom.c | 37 ++++---------- nuttx/net/send.c | 11 ++-- 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 * * 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 * * 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 * * 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 * * 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) -- cgit v1.2.3