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:
parent
a9a3097a0e
commit
18379c0657
@ -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.
|
||||
|
@ -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:
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user