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
This commit is contained in:
patacongo 2013-01-19 19:18:44 +00:00
parent 82a2cd6155
commit 4e7340ab13
3 changed files with 28 additions and 2 deletions

View File

@ -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.

View File

@ -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;
}

View File

@ -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.
*/