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:
90:955f4c6e18a9
Parent:
89:9b765a67699b
Child:
91:879545b19260
--- a/tcp/tcprecv.c	Wed Nov 21 17:13:04 2018 +0000
+++ b/tcp/tcprecv.c	Thu Nov 22 17:35:59 2018 +0000
@@ -62,8 +62,19 @@
             break;
     }
 }
-static int sendResetFromPacket(int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope)
+static int sendResetFromPacket(int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope, int seqLengthRcvd)
 {
+    /*RFC793 p36 If the connection does not exist (CLOSED) then a reset is sent
+    in response to any incoming segment except another reset.
+    If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment,
+    otherwise                                 the reset has sequence number zero
+    and
+    the ACK field is set to the sum of the sequence number and segment length of the incoming segment.
+    The connection remains in the CLOSED state.
+    In TcpSendReset TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn;  //Set up the acknowledgement field ready to send
+                    TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn;  //Set up the start of the message before adding the bytes sent
+    */
+    
     struct tcb tcb;
     struct tcb* pTcb = &tcb;
     pTcb->timeLastRcvd     = TcbElapsed;
@@ -75,12 +86,24 @@
     pTcb->window           = TcpHdrWindow;
     pTcb->state            = TCB_EMPTY;
 
+    pTcb->timeSendsBeingAcked = TcbElapsed;
+    pTcb->countSendsNotAcked  = 0;
+    pTcb->rcvdFin             = false;
+    pTcb->sentFin             = false;
+    pTcb->todo                = 0;
+    pTcb->remIsn              = TcpHdrSeqNum + seqLengthRcvd; //Ack number
+    pTcb->locIsn              = TcpHdrACK ? TcpHdrAckNum : 0; //Seq number
+    pTcb->bytesRcvdFromRem    = 0;
+    pTcb->bytesAckdByRem      = 0;
+    pTcb->bytesAckdToRem      = 0;
+    pTcb->bytesSentToRem      = 0;
+
     return TcpSendReset(pSizeTx, pPacketTx, pTcb);
 }
 
 int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int ipType, int remArIndex, int locIpScope)
 {
-    int dest = DO_NOTHING;
+    int action = DO_NOTHING;
     bool traceRequested = false;
     
     Led1Set(true);
@@ -97,6 +120,12 @@
     int dataLength =   sizeRx - TcpHdrSizeGet();
     int locMss     = *pSizeTx - TcpHdrSizeGet();
     
+    //Calculate the sequence length of the received packet
+    int seqLengthRcvd = 0;
+    if (TcpHdrSYN) seqLengthRcvd += 1;          //Add one to acknowledge the SYN
+                   seqLengthRcvd += dataLength; //Add the number of bytes received
+    if (TcpHdrFIN) seqLengthRcvd += 1;          //Add one to acknowledge the FIN
+    
     //Filter out unwanted links
     switch (TcpHdrDstPort)
     {
@@ -111,9 +140,9 @@
             
         default: //Send reset if unknown port
             log(traceback, "unhandled local port %hu -> sent reset", TcpHdrDstPort);
-            dest = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope);
+            action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd);
             Led1Set(false);
-            return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+            return action;
     }
     
     //Get the Transmission Control Block
@@ -122,9 +151,9 @@
     if (!pTcb) //send reset if no more tcbs are available
     {
         log(traceback, "no more tcbs available -> sent reset");
-        dest = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope);
+        action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd);
         Led1Set(false);
-        return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+        return action;
     }
     pTcb->timeLastRcvd     = TcbElapsed;
     pTcb->remArIndex       = remArIndex;
@@ -153,9 +182,9 @@
         {
             log(traceback, "received a SYN on an open connection -> sent reset");
             pTcb->state = TCB_EMPTY;
-            dest = TcpSendReset(pSizeTx, pPacketTx, pTcb);
+            action = TcpSendReset(pSizeTx, pPacketTx, pTcb);
             Led1Set(false);
-            ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+            return action;
         }
         else
         {
@@ -163,36 +192,15 @@
         }
     }
     
-    //Calculate the sequence length of the received packet
-    int seqLengthRcvd = 0;
-    if (TcpHdrSYN) seqLengthRcvd += 1;          //Add one to acknowledge the SYN
-                   seqLengthRcvd += dataLength; //Add the number of bytes received
-    if (TcpHdrFIN) seqLengthRcvd += 1;          //Add one to acknowledge the FIN
-    
-    /*RFC793 p36 If the connection does not exist (CLOSED) then a reset is sent
-    in response to any incoming segment except another reset.
-    If the incoming segment has an ACK field, the reset takes its sequence number from the ACK field of the segment,
-    otherwise                                 the reset has sequence number zero
-    and
-    the ACK field is set to the sum of the sequence number and segment length of the incoming segment.
-    The connection remains in the CLOSED state.
-    In TcpSendReset TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn;  //Set up the acknowledgement field ready to send
-                    TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn;  //Set up the start of the message before adding the bytes sent
-    */
+    //Handle non SYN packet on an empty connection
     if (!TcpHdrSYN && !pTcb->state)
     {
-        pTcb->remIsn           = 0;
-        pTcb->locIsn           = 0;
-        pTcb->bytesRcvdFromRem = 0;
-        pTcb->bytesAckdByRem   = 0;
-        
-        pTcb->bytesSentToRem   = TcpHdrACK ? TcpHdrAckNum : 0; //Seq number
-        pTcb->bytesAckdToRem   = TcpHdrSeqNum + seqLengthRcvd; //Ack number
+
         log(traceback, "non SYN packet received on a closed connection -> sent reset");
         pTcb->state = TCB_EMPTY;
-        dest = TcpSendReset(pSizeTx, pPacketTx, pTcb);
+        action = sendResetFromPacket(pSizeTx, pPacketTx, ipType, remArIndex, locIpScope, seqLengthRcvd);
         Led1Set(false);
-        return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+        return action;
     }
     
     //Check if the acks of bytes sent has progressed and reset the timer
@@ -220,15 +228,27 @@
         {
             log(traceback, "seq rcvd is %d and last seq ackd was %d -> resent last ACK", seqRcvdFromRem, pTcb->bytesAckdToRem);
         }
-        dest = TcpResendLastAck(pSizeTx, pPacketTx, pTcb);
+        action = TcpResendLastAck(pSizeTx, pPacketTx, pTcb);
         Led1Set(false);
-        return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+        return action;
     }
+    //Ignore data before established
+    if (pTcb->state != TCB_ESTABLISHED && dataLength)
+    {
+        log(traceback, "data received before connection established -> sent reset");
+        pTcb->state = TCB_EMPTY;
+        action = TcpSendReset(pSizeTx, pPacketTx, pTcb);
+        Led1Set(false);
+        return action;
+    }
+    
     Led2Set(true);
+    
     //Handle FIN
     if (TcpHdrFIN) pTcb->rcvdFin = true; //When reply is all sent only a passive close is needed
-        
-    if (traceRequested && NetTraceStack) traceback(); //This will already include the TCP header
+    
+    //From now on there are no errors so display traceback if requested
+    if (traceRequested && NetTraceStack) traceback();
     
     //Record the number of bytes received from the remote host
     pTcb->bytesRcvdFromRem += seqLengthRcvd;
@@ -240,15 +260,6 @@
             break;
             
         case TCB_SYN_RECEIVED:
-            if (dataLength)
-            {
-                log(traceback, "data received before connection established -> sent reset");
-                pTcb->state = TCB_EMPTY;
-                dest = TcpSendReset(pSizeTx, pPacketTx, pTcb);
-                Led1Set(false);
-                Led2Set(false);
-                return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
-            }
             pTcb->state = TCB_ESTABLISHED;
             break;
             
@@ -269,9 +280,9 @@
             
     }
     
-    dest = TcpSend(pSizeTx, pPacketTx, pTcb);
+    action = TcpSend(pSizeTx, pPacketTx, pTcb);
     Led1Set(false);
     Led2Set(false);
 
-    return ActionMakeFromDestAndTrace(dest, traceRequested && NetTraceStack);
+    return action;
 }