forked from Archive/PX4-Autopilot
Centralize TCP loss-of-connection bit twiddling
git-svn-id: http://svn.code.sf.net/p/nuttx/code/trunk@5542 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
28a0cf4aa0
commit
70cab4d797
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
if ((flags & (UIP_CLOSE|UIP_ABORT|UIP_TIMEDOUT)) != 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);
|
||||
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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
net_lostconnection(pstate->rf_sock, flags);
|
||||
|
||||
/* Check if the peer gracefully closed the connection. */
|
||||
|
||||
psock = pstate->rf_sock;
|
||||
if ((flags & UIP_CLOSE) != 0)
|
||||
{
|
||||
/* Report that the connection was gracefully closed */
|
||||
|
||||
psock->s_flags &= ~_SF_CONNECTED;
|
||||
psock->s_flags |= _SF_CLOSED;
|
||||
|
||||
/* 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.
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue