Fix an error the TCP/IP received sequence number counting

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4416 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2012-02-23 15:53:27 +00:00
parent a9a3097a0e
commit 18379c0657
5 changed files with 66 additions and 27 deletions

View File

@ -2484,3 +2484,12 @@
the accecpt() and connect() logic. Contributed by Max Nekludov.
* net/recvfrom.c and net/uip/uip_tcpcallback.c: Fix a leak in the TCP
read-ahead logic. This is a *critical* bug fix!
* net/uip/uip_tcpinput.c: Correct an error in the TCP stack. It was
incrementing the received sequence number BEFORE determining if the
incoming data could be handled. If the data was dropped (usually because
there is insufficient buffering space), then no ACK will be sent and the
sequence number will be wrong. The end consequence of the bad sequence
number was that the when the dropped packet was re-transmitted, it was
was ignored because its sequence number looked wrong. Fix was, obviously,
to only increment the recevied sequence number if the TCP data was
accepted.

View File

@ -5,8 +5,8 @@
* are used by uIP programs as well as internal uIP structures and function
* declarations.
*
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* This logic was leveraged from uIP which also has a BSD-style license:
*

View File

@ -183,11 +183,15 @@ static inline void recvfrom_newtcpdata(FAR struct uip_driver_s *dev,
nsaved = uip_datahandler(conn, buffer, buflen);
/* There are complicated buffering issues that are not addressed
* properly here. For example, what if up_datahandler() cannot buffer
* the remainder of the packet? In that case, the data will be dropped
* but still ACKed. Therefore it will not be resent. Fixing this could be
* tricky.
/* There are complicated buffering issues that are not addressed fully
* here. For example, what if up_datahandler() cannot buffer the
* remainder of the packet? In that case, the data will be dropped but
* still ACKed. Therefore it would not be resent.
*
* This is probably not an issue here because we only get here if the
* read-ahead buffers are empty and there would have to be something
* serioulsy wrong with the configuration not to be able to buffer a
* partial packet in this context.
*/
#ifdef CONFIG_DEBUG_NET
@ -469,7 +473,9 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
if ((flags & UIP_NEWDATA) != 0)
{
/* Copy the data from the packet */
/* Copy the data from the packet (saving any unused bytes from the
* packet in the read-ahead buffer).
*/
recvfrom_newtcpdata(dev, pstate);
@ -489,10 +495,8 @@ static uint16_t recvfrom_tcpinterrupt(struct uip_driver_s *dev, void *conn,
{
nllvdbg("TCP resume\n");
/* The TCP receive buffer is full. Return now, perhaps truncating
* the received data (need to fix that).
*
* Don't allow any further TCP call backs.
/* The TCP receive buffer is full. Return now and don't allow
* any further TCP call backs.
*/
pstate->rf_cb->flags = 0;

View File

@ -2,8 +2,8 @@
* net/uip/uip_tcpinput.c
* Handling incoming TCP input
*
* Copyright (C) 2007-2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
*
@ -43,6 +43,7 @@
****************************************************************************/
#include <nuttx/config.h>
#if defined(CONFIG_NET) && defined(CONFIG_NET_TCP)
#include <stdint.h>
@ -588,6 +589,10 @@ found:
goto drop;
}
/* Update the sequence number and indicate that the connection has
* been closed.
*/
uip_incr32(conn->rcvseq, dev->d_len + 1);
flags |= UIP_CLOSE;
@ -631,24 +636,20 @@ found:
{
dev->d_urglen = 0;
#else /* CONFIG_NET_TCPURGDATA */
dev->d_appdata =
((uint8_t*)dev->d_appdata) + ((pbuf->urgp[0] << 8) | pbuf->urgp[1]);
dev->d_len -=
(pbuf->urgp[0] << 8) | pbuf->urgp[1];
dev->d_appdata = ((uint8_t*)dev->d_appdata) + ((pbuf->urgp[0] << 8) | pbuf->urgp[1]);
dev->d_len -= (pbuf->urgp[0] << 8) | pbuf->urgp[1];
#endif /* CONFIG_NET_TCPURGDATA */
}
/* If d_len > 0 we have TCP data in the packet, and we flag this
* by setting the UIP_NEWDATA flag and update the sequence number
* we acknowledge. If the application has stopped the dataflow
* using uip_stop(), we must not accept any data packets from the
* remote host.
* by setting the UIP_NEWDATA flag. If the application has stopped
* the dataflow using uip_stop(), we must not accept any data
* packets from the remote host.
*/
if (dev->d_len > 0 && (conn->tcpstateflags & UIP_STOPPED) == 0)
{
flags |= UIP_NEWDATA;
uip_incr32(conn->rcvseq, dev->d_len);
}
/* Check if the available buffer space advertised by the other end
@ -672,7 +673,7 @@ found:
conn->mss = tmp16;
/* If this packet constitutes an ACK for outstanding data (flagged
* by the UIP_ACKDATA flag, we should call the application since it
* by the UIP_ACKDATA flag), we should call the application since it
* might want to send more data. If the incoming packet had data
* from the peer (as flagged by the UIP_NEWDATA flag), the
* application must also be notified.
@ -691,8 +692,33 @@ found:
if ((flags & (UIP_NEWDATA | UIP_ACKDATA)) != 0)
{
/* Clear sndlen and remember the size in d_len. The application
* may modify d_len and we will need this value later when we
* update the sequence number.
*/
dev->d_sndlen = 0;
result = uip_tcpcallback(dev, conn, flags);
len = dev->d_len;
/* Provide the packet to the application */
result = uip_tcpcallback(dev, conn, flags);
/* If the application successfully handled the incoming data,
* then UIP_SNDACK will be set in the result. In this case,
* we need to update the sequence number. The ACK will be
* send by uip_tcpappsend().
*/
if ((result & UIP_SNDACK) != 0)
{
/* Update the sequence number using the saved length */
uip_incr32(conn->rcvseq, len);
}
/* Send the response, ACKing the data or not, as appropriate */
uip_tcpappsend(dev, conn, result);
return;
}

View File

@ -1,8 +1,8 @@
/****************************************************************************
* net/uip/uip_tcpsend.c
*
* Copyright (C) 2007-2010 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
* Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Adapted for NuttX from logic in uIP which also has a BSD-like license:
*