From e684270a1ae6eccb65fbc4ab44f455e8d46de29f Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 23 Feb 2012 15:53:27 +0000 Subject: 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 --- apps/interpreters/ficl/README.txt | 84 +++++++++++++++++++-------------------- nuttx/ChangeLog | 9 +++++ nuttx/include/net/uip/uip.h | 4 +- nuttx/net/recvfrom.c | 24 ++++++----- nuttx/net/uip/uip_tcpinput.c | 52 ++++++++++++++++++------ nuttx/net/uip/uip_tcpsend.c | 4 +- 6 files changed, 108 insertions(+), 69 deletions(-) diff --git a/apps/interpreters/ficl/README.txt b/apps/interpreters/ficl/README.txt index d775db1e8..bac9f3148 100755 --- a/apps/interpreters/ficl/README.txt +++ b/apps/interpreters/ficl/README.txt @@ -1,42 +1,42 @@ -apps/interpreter/README.txt -=========================== - -Ficl is a programming language interpreter designed to be embedded into -other systems as a command, macro, and development prototyping language. -Ficl is an acronym for "Forth Inspired Command Language". See -http://ficl.sourceforge.net/ - -Build Instructions ------------------- - -Disclaimer: This installation steps have only been exercised using Ficl -4.1.0. With new versions you will likely have to make some adjustments -to this instructtions or to the files within this directory. This of this -information as "recommendations" -- not necessarily proven instructions. - -1. CD to apps/interpreters/ficl - -2. Download Ficl: http://sourceforge.net/projects/ficl/files/ - -3. Uznip the Ficl compressed file. - - For example, 'unzip ficl-4.1.0.zip' will leave the file - apps/interpreters/ficl/ficl-4.1.0 - -4. Configure to build Ficl in the apps/interpreters/ficl directory using - the configure.sh script. - - For example, './configure.sh ficl-4.1.0' will leave the Makefile - fragment 'Make.srcs' in the ficl build directory. - -5. Create your NuttX configuration. The appconfig file should include - (1) the path to your application code, and (2) the path to the Ficl - build directory. That latter would appear as the following line in - your appconfig file: - - CONFIGURED_APPS += interpreters/ficl - - 6. Configure and build NuttX. On successful completion, the Ficl objects - will be available in apps/libapps.a and that NuttX binary will be - linked against that file. Of course, Ficl will do nothing unless - you have written some application code that uses it! +apps/interpreter/README.txt +=========================== + +Ficl is a programming language interpreter designed to be embedded into +other systems as a command, macro, and development prototyping language. +Ficl is an acronym for "Forth Inspired Command Language". See +http://ficl.sourceforge.net/ + +Build Instructions +------------------ + +Disclaimer: This installation steps have only been exercised using Ficl +4.1.0. With new versions you will likely have to make some adjustments +to this instructtions or to the files within this directory. Think of this +information as "recommendations" -- not necessarily proven instructions. + +1. CD to apps/interpreters/ficl + +2. Download Ficl: http://sourceforge.net/projects/ficl/files/ + +3. Uznip the Ficl compressed file. + + For example, 'unzip ficl-4.1.0.zip' will leave the file + apps/interpreters/ficl/ficl-4.1.0 + +4. Configure to build Ficl in the apps/interpreters/ficl directory using + the configure.sh script. + + For example, './configure.sh ficl-4.1.0' will leave the Makefile + fragment 'Make.srcs' in the ficl build directory. + +5. Create your NuttX configuration. The appconfig file should include + (1) the path to your application code, and (2) the path to the Ficl + build directory. That latter would appear as the following line in + your appconfig file: + + CONFIGURED_APPS += interpreters/ficl + + 6. Configure and build NuttX. On successful completion, the Ficl objects + will be available in apps/libapps.a and that NuttX binary will be + linked against that file. Of course, Ficl will do nothing unless + you have written some application code that uses it! diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 27bd1cb7f..df9646b47 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -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. diff --git a/nuttx/include/net/uip/uip.h b/nuttx/include/net/uip/uip.h index ea11dede8..c36efa355 100644 --- a/nuttx/include/net/uip/uip.h +++ b/nuttx/include/net/uip/uip.h @@ -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 + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * This logic was leveraged from uIP which also has a BSD-style license: * diff --git a/nuttx/net/recvfrom.c b/nuttx/net/recvfrom.c index ee8f100bf..d7b7c561e 100644 --- a/nuttx/net/recvfrom.c +++ b/nuttx/net/recvfrom.c @@ -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; diff --git a/nuttx/net/uip/uip_tcpinput.c b/nuttx/net/uip/uip_tcpinput.c index f7811cdf7..bdeccf4b7 100644 --- a/nuttx/net/uip/uip_tcpinput.c +++ b/nuttx/net/uip/uip_tcpinput.c @@ -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 + * Copyright (C) 2007-2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Adapted for NuttX from logic in uIP which also has a BSD-like license: * @@ -43,6 +43,7 @@ ****************************************************************************/ #include + #if defined(CONFIG_NET) && defined(CONFIG_NET_TCP) #include @@ -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; } diff --git a/nuttx/net/uip/uip_tcpsend.c b/nuttx/net/uip/uip_tcpsend.c index ba28fd9c6..9ca81a606 100644 --- a/nuttx/net/uip/uip_tcpsend.c +++ b/nuttx/net/uip/uip_tcpsend.c @@ -1,8 +1,8 @@ /**************************************************************************** * net/uip/uip_tcpsend.c * - * Copyright (C) 2007-2010 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt + * Copyright (C) 2007-2010, 2012 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt * * Adapted for NuttX from logic in uIP which also has a BSD-like license: * -- cgit v1.2.3