From 0d20be167a79f6d8bf80af8d724279ff21a5f529 Mon Sep 17 00:00:00 2001 From: patacongo Date: Sat, 19 Jan 2013 19:18:44 +0000 Subject: Fix a bug where recv[from]() would hang when remote host gracefully closed connection git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5539 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/ChangeLog | 4 ++++ nuttx/net/recvfrom.c | 24 +++++++++++++++++++++++- nuttx/net/send.c | 2 +- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 122187410..80944db66 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -3989,3 +3989,7 @@ Marcelo, adapted to use kconfig-frontends. * net/send(): Add logic to work around delayed ACKs by splitting packets (contributed by Yan T.). + * net/recvfrom(): Fix a bug. When the host closes a connection + (gracefully). recv[from]() returned success and the closure + was never detected. Hmmm.. I don't know why the network monitor + did not catch this event. This is an important bug fix. diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c index 6bfbd31ad..679b5e8ce 100644 --- a/nuttx/net/recvfrom.c +++ b/nuttx/net/recvfrom.c @@ -83,7 +83,7 @@ struct recvfrom_s FAR struct sockaddr_in *rf_from; /* Address of sender */ #endif size_t rf_recvlen; /* The received length */ - int rf_result; /* OK:success, failure:negated errno */ + int rf_result; /* Success:OK, failure:negated errno */ }; #endif /* CONFIG_NET_UDP || CONFIG_NET_TCP */ @@ -553,6 +553,8 @@ 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"); /* Stop further callbacks */ @@ -563,9 +565,29 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn, /* If the peer gracefully closed the connection, then return zero * (end-of-file). Otherwise, report a not-connected error + * _SF_CONNECTED==0 && _SF_CLOSED==1 - the socket was + * gracefully disconnected + * _SF_CONNECTED==0 && _SF_CLOSED==0 - the socket was + * rudely disconnected */ + psock = pstate->rf_sock; if ((flags & UIP_CLOSE) != 0) + { + psock->s_flags &= ~_SF_CONNECTED; + psock->s_flags |= _SF_CLOSED; + } + else + { + 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. + */ + + if (pstate->rf_recvlen > 0) { pstate->rf_result = 0; } diff --git a/nuttx/net/send.c b/nuttx/net/send.c index b75a864e3..8c07b391c 100644 --- a/nuttx/net/send.c +++ b/nuttx/net/send.c @@ -324,7 +324,7 @@ static uint16_t send_interrupt(struct uip_driver_s *dev, void *pvconn, if (next_sndlen > 0 && (next_sndlen - uip_mss(conn)) < 0) { - /* Here, we know that sndlen must be MSS <= sndlen <= 2*MSS + /* Here, we know that sndlen must be MSS < sndlen <= 2*MSS * and so (sndlen / 2) is <= MSS. */ -- cgit v1.2.3