summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-19 19:18:44 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-01-19 19:18:44 +0000
commit0d20be167a79f6d8bf80af8d724279ff21a5f529 (patch)
tree7bd1ddce49503ee6c07ef50fa6e76ce44388f6a4
parent0aad9ccecb8d4fbb8712cbf050fe7654168e0c13 (diff)
downloadnuttx-0d20be167a79f6d8bf80af8d724279ff21a5f529.tar.gz
nuttx-0d20be167a79f6d8bf80af8d724279ff21a5f529.tar.bz2
nuttx-0d20be167a79f6d8bf80af8d724279ff21a5f529.zip
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
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/net/recvfrom.c24
-rw-r--r--nuttx/net/send.c2
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,10 +565,30 @@ 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;
}
else
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.
*/