Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Revision:
75:603b10404183
Parent:
74:c3756bfa960e
Child:
78:9d8fc88df405
--- a/tcp/tcpsend.c	Mon Oct 29 09:33:44 2018 +0000
+++ b/tcp/tcpsend.c	Tue Oct 30 22:11:22 2018 +0000
@@ -13,27 +13,47 @@
 #include    "led.h"
 #include "tcpsend.h"
 
-
+#define RTO_TIME 2
 
-static int sendData(void* pPacket, struct tcb* pTcb)
+static int addApplicationData(void* pPacket, uint16_t port, int start, int mss, int todo)
 {
     int dataLength = 0;
     char* pData = (char*)pPacket + TcpHdrSizeGet();
-    switch (pTcb->locPort)
+    switch (port)
     {
         case 80:
-            HttpSendReply(&dataLength, pData, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo);
+            HttpSendReply(&dataLength, pData, start, mss, todo);
             break;
         default:
             break;
     }    
+        
+    return dataLength;
+}
+static int preparePacket(void* pPacket, struct tcb* pTcb, int dataLength, int* pSize)
+{
+    //Set the acknowledge flag
+    TcpHdrACK = true;
     
+    //Swap the ports for the reply
+    TcpHdrSrcPort = pTcb->locPort;
+    TcpHdrDstPort = pTcb->remPort;
+    
+    //Specify the receive window size to not throttle
+    TcpHdrWindow = 4000;
+    
+    //Write the header
+    TcpHdrWriteToPacket(pPacket);
+    
+    //Calculate the size of the reply
+    *pSize = TcpHdrSizeGet() + dataLength;
+    
+    //Update the last send time
     pTcb->lastSendTime = TcbElapsed;
     
-    return dataLength;
+    return ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack);
 }
-
-int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb, int sendType)
+int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb)
 {
     int dataLength = 0;
     TcpHdrMakeEmpty();
@@ -55,7 +75,7 @@
                 {
                     if (pTcb->todo)
                     {
-                        dataLength = sendData(pPacket, pTcb);
+                        dataLength = addApplicationData(pPacket, pTcb->locPort, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo);
                         if (dataLength < pTcb->remMss)
                         {
                             TcpHdrFIN     = true;
@@ -93,38 +113,76 @@
 
     pTcb->bytesSentToRem += bytesToSend;
     
-    if (rcvdSeqHasAdvanced || bytesToSend || sendType == TCP_RESEND_ACK || sendType == TCP_SEND_RESET)
+    if (!rcvdSeqHasAdvanced && !bytesToSend) return DO_NOTHING;
+    
+    return preparePacket(pPacket, pTcb, dataLength, pSize);
+}
+int TcpResendLastUnAcked(int* pSize, void *pPacket, struct tcb* pTcb)
+{
+    int dataLength = 0;
+    TcpHdrMakeEmpty();
+    int locMss = *pSize - TcpHdrSizeGet();
+    int seqNum = pTcb->bytesAckdByRem;
+    switch (pTcb->state)
     {
-        //Set the acknowledge flag
-        TcpHdrACK = true;
-        TcpHdrRST = sendType == TCP_SEND_RESET;
-        
-        //Swap the ports for the reply
-        TcpHdrSrcPort = pTcb->locPort;
-        TcpHdrDstPort = pTcb->remPort;
-                
-        //Specify the receive window size to not throttle
-        TcpHdrWindow = 4000;
-        
-        //Write the header
-        TcpHdrWriteToPacket(pPacket);
-        
-        //Calculate the size of the reply
-        *pSize = TcpHdrSizeGet() + dataLength;
+        case TCB_SYN_RECEIVED:
+            TcpHdrMssSet(locMss);
+            TcpHdrSYN = true;
+            break;
             
-        return ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack);
+        case TCB_ESTABLISHED:
+            if (pTcb->todo)
+            {
+                dataLength = addApplicationData(pPacket, pTcb->locPort, seqNum, pTcb->remMss, pTcb->todo);
+                if (dataLength < pTcb->remMss)
+                {
+                    TcpHdrFIN     = true;
+                    pTcb->sentFin = true;
+                }
+            }
+            break;
     }
-    else
-    {
-        return DO_NOTHING;
-    }
+
+    TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn;  //Set up the acknowledgement field ready to send
+    TcpHdrSeqNum = seqNum               + pTcb->locIsn;  //Set up the start of the message before adding the bytes sent
+
+    return preparePacket(pPacket, pTcb, dataLength, pSize);
+}
+int TcpResendLastAck(int* pSize, void *pPacket, struct tcb* pTcb)
+{
+    int dataLength = 0;
+    TcpHdrMakeEmpty();
+    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
+    
+    return preparePacket(pPacket, pTcb, dataLength, pSize);
+}
+int TcpSendReset(int* pSize, void *pPacket, struct tcb* pTcb)
+{
+    int dataLength = 0;
+    TcpHdrMakeEmpty();
+    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
+    
+    TcpHdrRST = true;
+    
+    return preparePacket(pPacket, pTcb, dataLength, pSize);
 }
 int TcpPollForPacketToSend(int* pSize, void* pPacket, int ipType, int* pRemArIndex)
 {
     struct tcb* pTcb = TcbGetNext(); //This loops around the TCBs
     if (pTcb->ipType != ipType) return DO_NOTHING;
     *pRemArIndex = pTcb->remArIndex;
-    int action = TcpSend(pSize, pPacket, pTcb, TCP_SEND_NORMAL);
-    return action;
+    
+    //Check if have unacknowledged bytes longer than a time out
+    if (TcbElapsed - pTcb->lastSendTime > RTO_TIME && pTcb->bytesSentToRem > pTcb->bytesAckdByRem)
+    {
+        return TcpResendLastUnAcked(pSize, pPacket, pTcb);
+    }
+    //Otherwise do a normal send
+    else
+    {
+        return TcpSend(pSize, pPacket, pTcb);
+    }
 }