A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Revision:
75:603b10404183
Parent:
74:c3756bfa960e
Child:
76:17534bde28d3
--- a/tcp/tcprecv.c	Mon Oct 29 09:33:44 2018 +0000
+++ b/tcp/tcprecv.c	Tue Oct 30 22:11:22 2018 +0000
@@ -1,5 +1,6 @@
 #include <stdint.h>
 #include <stdbool.h>
+#include <stdarg.h>
 
 #include     "log.h"
 #include     "net.h"
@@ -21,6 +22,20 @@
     if (TcpTrace) { LogTime("TCP sent RST - "); Log(message); Log("\r\n"); }
 }
 
+static void logTraceBack(void (*traceback)(void), char* fmt, ...)
+{
+    if (TcpTrace)
+    {
+        if (NetTraceNewLine) Log("\r\n");
+        va_list argptr;
+        va_start(argptr, fmt);
+        LogV(fmt, argptr);
+        va_end(argptr);
+        Log("\r\n");
+        if (NetTraceStack) traceback();
+    }
+}
+
 static void startConnection(void *pPacket, int ipType, int remArIndex, int locMss)
 {
     //Get the MSS to use for sends - it is the lower of the MSS advertised by the remote host and our local MSS
@@ -28,24 +43,30 @@
     pTcb->remMss = remMss ? remMss : 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
     if (pTcb->remMss > locMss) pTcb->remMss = locMss;
     
-    pTcb->lastSendTime = TcbElapsed;
-    pTcb->remArIndex   = remArIndex;
-    pTcb->ipType       = ipType;
-    pTcb->remPort      = TcpHdrSrcPort;
-    pTcb->locPort      = TcpHdrDstPort;
-    pTcb->rcvdFin      = false;
-    pTcb->sentFin      = false;
-    pTcb->window       = TcpHdrWindow;
-    pTcb->todo         = 0;
+    pTcb->lastSendTime     = TcbElapsed;
+    pTcb->remArIndex       = remArIndex;
+    pTcb->ipType           = ipType;
+    pTcb->remPort          = TcpHdrSrcPort;
+    pTcb->locPort          = TcpHdrDstPort;
+    pTcb->rcvdFin          = false;
+    pTcb->sentFin          = false;
+    pTcb->window           = TcpHdrWindow;
+    pTcb->todo             = 0;
+    pTcb->remIsn           = TcpHdrSeqNum;
+    pTcb->locIsn           = TcbGetIsn();
+    pTcb->bytesRcvdFromRem = 0;
+    pTcb->bytesAckdByRem   = 0;
+    pTcb->bytesAckdToRem   = 0;
+    pTcb->bytesSentToRem   = 0;
 }
-static void handleReceivedData(void* pPacket, int dataLength)
+static void handleReceivedData(void* pPacket, int dataLength, uint32_t position)
 {
     pTcb->window = TcpHdrWindow;
     char* pData = (char*)pPacket + TcpHdrSizeGet();
     switch (pTcb->locPort)
     {
         case 80:
-            HttpHandleRequest(dataLength, pData, pTcb->bytesRcvdFromRem - 1, &pTcb->todo);
+            HttpHandleRequest(dataLength, pData, position, &pTcb->todo);
             break;
         default:
             break;
@@ -74,67 +95,56 @@
             break;
             
         default:
-            if (TcpTrace)
-            {
-                if (NetTraceNewLine) Log("\r\n");
-                LogTimeF("TCP unknown port %d\r\n", TcpHdrDstPort);
-                if (NetTraceStack) traceback();
-            }
+            logTraceBack(traceback, "TCP - unknown port %d\r\n", TcpHdrDstPort);
             return DO_NOTHING; //Ignore unknown ports
     }
     
-    //Get the Transmission Control Block
+    //Get the existing Transmission Control Block
     pTcb = TcbGetExisting(TcpHdrSrcPort);
-    if (!pTcb)  pTcb = TcbGetEmpty();
-    if (!pTcb)
-    {
-        if (TcpTrace)
-        {
-            if (NetTraceNewLine) Log("\r\n");
-            LogTime("TCP no more tcbs are available\r\n");
-            if (NetTraceStack) traceback();
-        }
-        return DO_NOTHING; //Bomb out if no more tcbs are available
-    }
-
+    
     //Handle request to reset
     if (TcpHdrRST)
     {
-        if (TcpTrace)
+        if (pTcb)
         {
-            if (NetTraceNewLine) Log("\r\n");
-            LogTime("TCP received reset - resetting TCB\r\n");
-            if (NetTraceStack) traceback();
+            logTraceBack(traceback, "TCP - received reset - resetting TCB\r\n");
+            pTcb->state = TCB_EMPTY;
         }
-        pTcb->state = TCB_EMPTY;
         return DO_NOTHING;        //Don't reply
     }
     
     //Handle request to synchronise
     if (TcpHdrSYN)
     {
-        pTcb->remIsn   = TcpHdrSeqNum;
-        pTcb->locIsn   = TcbGetIsn();
-        pTcb->bytesRcvdFromRem = 0;
-        pTcb->bytesAckdByRem   = 0;
-        pTcb->bytesAckdToRem   = 0;
-        pTcb->bytesSentToRem   = 0;
+        if (pTcb)
+        {
+            logReset("received a SYN when connection open");
+            pTcb->state = TCB_EMPTY;
+            return TcpSendReset(pSizeTx, pPacketTx, pTcb);
+        }
+        pTcb = TcbGetEmpty();
+        if (!pTcb) //Bomb out if no more tcbs are available
+        {
+            logTraceBack(traceback, "TCP - no more tcbs are available\r\n");
+            return DO_NOTHING;
+        }
+        startConnection(pPacketRx, ipType, remArIndex, locMss);
     }
     
     //Check window and just resend the last ACK if not good
     uint32_t seqRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn;
     bool resendAck = seqRcvdFromRem != pTcb->bytesAckdToRem;
-    if (resendAck) return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_RESEND_ACK);
+    if (resendAck) return TcpResendLastAck(pSizeTx, pPacketTx, pTcb);
     
-    pTcb->bytesRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn;
-    pTcb->bytesAckdByRem   = TcpHdrAckNum - pTcb->locIsn;
-
+    //Record the number of bytes acked by the remote host
+    pTcb->bytesAckdByRem = TcpHdrAckNum - pTcb->locIsn;
     
     //Handle FIN
     if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed
         
     if (TcpDoTrace && NetTraceStack) traceback(); //This will already include the TCP header
     
+    //Record the number of bytes received from the remote host
     if (TcpHdrSYN) pTcb->bytesRcvdFromRem += 1;          //Add one to acknowledge the SYN
                    pTcb->bytesRcvdFromRem += dataLength; //Add the number of bytes received
     if (TcpHdrFIN) pTcb->bytesRcvdFromRem += 1;          //Add one to acknowledge the FIN
@@ -142,13 +152,6 @@
     switch (pTcb->state)
     {
         case TCB_EMPTY:
-            if (!TcpHdrSYN)
-            {
-                logReset("received other than a SYN when connection closed");
-                pTcb->state = TCB_EMPTY;
-                return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_RESET);
-            }
-            startConnection(pPacketRx, ipType, remArIndex, locMss);
             pTcb->state = TCB_SYN_RECEIVED;
             break;
             
@@ -157,13 +160,13 @@
             {
                 logReset("data received before connection established");
                 pTcb->state = TCB_EMPTY;
-                return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_RESET);
+                return TcpSendReset(pSizeTx, pPacketTx, pTcb);
             }
             pTcb->state = TCB_ESTABLISHED;
             break;
             
         case TCB_ESTABLISHED:
-            if (dataLength) handleReceivedData (pPacketRx, dataLength);
+            if (dataLength) handleReceivedData (pPacketRx, dataLength, seqRcvdFromRem - 1);
             if (pTcb->sentFin)
             {
                 pTcb->state = pTcb->rcvdFin ? TCB_CLOSE_ACK_WAIT : TCB_CLOSE_FIN_WAIT;
@@ -182,5 +185,5 @@
             break;
     }
     
-    return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_NORMAL);
+    return TcpSend(pSizeTx, pPacketTx, pTcb);
 }