Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Files at this revision

API Documentation at this revision

Comitter:
andrewboyson
Date:
Mon Oct 29 09:33:44 2018 +0000
Parent:
73:43e3d7fb3d60
Child:
75:603b10404183
Commit message:
Introduced the polling for and split Tcp into tcpSend and TcpRecv. Testied and working.

Changed in this revision

eth/ar4.c Show annotated file Show diff for this revision Revisions of this file
eth/ar4.h Show annotated file Show diff for this revision Revisions of this file
eth/ar6.c Show annotated file Show diff for this revision Revisions of this file
eth/ar6.h Show annotated file Show diff for this revision Revisions of this file
ip4/ip4.c Show annotated file Show diff for this revision Revisions of this file
ip4/udptcp4.c Show annotated file Show diff for this revision Revisions of this file
ip4/udptcp4.h Show annotated file Show diff for this revision Revisions of this file
ip6/ip6.c Show annotated file Show diff for this revision Revisions of this file
ip6/udptcp6.c Show annotated file Show diff for this revision Revisions of this file
ip6/udptcp6.h Show annotated file Show diff for this revision Revisions of this file
tcp/tcb.c Show annotated file Show diff for this revision Revisions of this file
tcp/tcb.h Show annotated file Show diff for this revision Revisions of this file
tcp/tcp.c Show annotated file Show diff for this revision Revisions of this file
tcp/tcp.h Show annotated file Show diff for this revision Revisions of this file
tcp/tcphdr.c Show annotated file Show diff for this revision Revisions of this file
tcp/tcphdr.h Show annotated file Show diff for this revision Revisions of this file
tcp/tcprecv.c Show annotated file Show diff for this revision Revisions of this file
tcp/tcprecv.h Show annotated file Show diff for this revision Revisions of this file
tcp/tcpsend.c Show annotated file Show diff for this revision Revisions of this file
tcp/tcpsend.h Show annotated file Show diff for this revision Revisions of this file
--- a/eth/ar4.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/eth/ar4.c	Mon Oct 29 09:33:44 2018 +0000
@@ -91,7 +91,7 @@
     records[i].elapsed  = elapsed;
     MacClear(records[i].mac);
 }
-uint32_t* Ar4AddIpRecord(void (*traceback)(void), char* mac, uint32_t ip)
+int Ar4AddIpRecord(void (*traceback)(void), char* mac, uint32_t ip)
 {
     //Don't treat non ips
     if (!ip)
@@ -101,7 +101,7 @@
             LogTime("Ar4AddIpRecord had blank ip\r\n");
             if (NetTraceStack) traceback();
         }
-        return NULL;
+        return -1;
     }
     if (MacIsEmpty(mac))
     {
@@ -110,7 +110,7 @@
             LogTime("Ar4AddIpRecord had blank mac\r\n");
             if (NetTraceStack) traceback();
         }
-        return NULL;
+        return -1;
     }
     int i;
     
@@ -121,7 +121,7 @@
         records[i].elapsed   = elapsed;
         records[i].state = STATE_VALID;
         MacCopy(records[i].mac, mac);
-        return &records[i].ip;
+        return i;
     }
     
     //Otherwise find the first empty slot and add the IP, MAC, and date
@@ -130,7 +130,7 @@
     records[i].elapsed  = elapsed;
     records[i].state = STATE_VALID;
     MacCopy(records[i].mac, mac);
-    return &records[i].ip;
+    return i;
 }
 void Ar4IpToMac(uint32_t ip, char* mac)
 {
@@ -144,6 +144,10 @@
     }
     MacClear(mac);
 }
+uint32_t Ar4IndexToIp(int i)
+{
+    return records[i].ip;
+}
 void Ar4SendHttp()
 {
     for (int i = 0; i < RECORDS_COUNT; i++)
--- a/eth/ar4.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/eth/ar4.h	Mon Oct 29 09:33:44 2018 +0000
@@ -5,10 +5,11 @@
 
 extern void Ar4MakeRequestForMacFromIp(uint32_t ip);
 
-extern uint32_t* Ar4AddIpRecord(void (*traceback)(void), char* pMac, uint32_t ip);
+extern int  Ar4AddIpRecord(void (*traceback)(void), char* pMac, uint32_t ip);
 
-extern void Ar4IpToMac(uint32_t ip, char* pMac);
-extern void Ar4SendHttp(void);
+extern void     Ar4IpToMac(uint32_t ip, char* pMac);
+extern uint32_t Ar4IndexToIp(int index);
+extern void     Ar4SendHttp(void);
 
 extern void Ar4Main(void);
 extern void Ar4Init(void);
--- a/eth/ar6.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/eth/ar6.c	Mon Oct 29 09:33:44 2018 +0000
@@ -92,7 +92,7 @@
     records[i].elapsed  = elapsed;
     MacClear(records[i].mac);
 }
-char* Ar6AddIpRecord(void (*traceback)(void), char* mac, char* ip)
+int Ar6AddIpRecord(void (*traceback)(void), char* mac, char* ip)
 {
     //Don't treat non ips
     if (!ip[0])
@@ -102,7 +102,7 @@
             LogTime("Ar6AddIpRecord had blank ip\r\n");
             if (NetTraceStack) traceback();
         }
-        return NULL;
+        return -1;
     }
     if (MacIsEmpty(mac))
     {
@@ -111,7 +111,7 @@
             LogTime("Ar6AddIpRecord had blank mac\r\n");
             if (NetTraceStack) traceback();
         }
-        return NULL;
+        return -1;
     }
     int i;
     
@@ -122,7 +122,7 @@
         records[i].elapsed = elapsed;
         records[i].state = STATE_VALID;
         MacCopy(records[i].mac, mac);
-        return records[i].ip;
+        return i;
     }
     
     //Otherwise find the first empty slot and add the MAC, IP and date
@@ -131,7 +131,7 @@
     Ip6AddressCopy(records[i].ip, ip);
     records[i].elapsed   = elapsed;
     records[i].state = STATE_VALID;
-    return records[i].ip;
+    return i;
 }
 void Ar6IpToMac(char* ip, char* mac)
 {
@@ -145,6 +145,10 @@
     }
     MacClear(mac);
 }
+void Ar6IndexToIp(int i, char* ip)
+{
+    Ip6AddressCopy(ip, records[i].ip);
+}
 void Ar6SendHttp()
 {
     for (int i = 0; i < RECORDS_COUNT; i++)
--- a/eth/ar6.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/eth/ar6.h	Mon Oct 29 09:33:44 2018 +0000
@@ -4,9 +4,10 @@
 
 extern void Ar6MakeRequestForMacFromIp(char* ip);
 
-extern char* Ar6AddIpRecord(void (*traceback)(void), char* pMac, char* ip);
+extern int  Ar6AddIpRecord(void (*traceback)(void), char* pMac, char* ip);
 
 extern void Ar6IpToMac(char* ip, char* pMac);
+extern void Ar6IndexToIp(int index, char* pIp);
 extern void Ar6SendHttp(void);
 
 extern void Ar6Main(void);
--- a/ip4/ip4.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip4/ip4.c	Mon Oct 29 09:33:44 2018 +0000
@@ -161,7 +161,7 @@
         return DO_NOTHING;
     }
     
-    uint32_t* pCachedRemIp = Ar4AddIpRecord(trace, macRemote, srcIp);
+    int remArIndex = Ar4AddIpRecord(trace, macRemote, srcIp);
     Nr4MakeRequestForNameFromIp(srcIp);
     
     int action = DO_NOTHING;
@@ -170,7 +170,7 @@
         case ICMP:   action = Icmp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
         case IGMP:                                                                                                             break;
         case UDP:    action =  Udp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp); break;
-        case TCP:    action =  Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp, pCachedRemIp); break;
+        case TCP:    action =  Tcp4HandleReceivedPacket(trace, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, &srcIp, &dstIp, remArIndex); break;
         case IP6IN4:                                                                                                           break;
         default:
             LogTimeF("IP4 received packet unknown protocol %d\r\n");
--- a/ip4/udptcp4.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip4/udptcp4.c	Mon Oct 29 09:33:44 2018 +0000
@@ -7,9 +7,12 @@
 #include    "eth.h"
 #include     "ip.h"
 #include "ip4addr.h"
-#include    "tcp.h"
-#include    "udp.h"
-#include "tcphdr.h"
+#include     "tcp.h"
+#include "tcprecv.h"
+#include "tcpsend.h"
+#include  "tcphdr.h"
+#include     "udp.h"
+#include "ar4.h"
 
 static uint16_t calculateChecksum(uint8_t pro, uint32_t srcIp, uint32_t dstIp, int size, void* pPacket)
 {
@@ -39,7 +42,7 @@
     
     switch (pro)
     {
-        case TCP: TcpHdrWrite(size, pPacket); break;
+        case TCP: TcpHdrWriteToPacket(pPacket); break;
         case UDP: UdpMakeHeader(size, pPacket); break;
     }
     
@@ -47,7 +50,7 @@
     
     switch (pro)
     {
-        case TCP: TcpHdrAddChecksum(pPacket, checksum); break;
+        case TCP: TcpHdrAddChecksumToPacket(pPacket, checksum); break;
         case UDP: UdpAddChecksum(pPacket, checksum); break;
     }
     
@@ -74,13 +77,13 @@
         default: LogTimeF("UdpTcp4 - traceback unrecognised protocol %d\r\n", tracePacketProtocol); break;
     }
 }
-int Tcp4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp, uint32_t* pCachedRemIp)
+int Tcp4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp, int remArIndex)
 {   
     pTraceBack = traceback;
     tracePacketProtocol = TCP;
     calculatedChecksum = calculateChecksum(TCP, *pSrcIp, *pDstIp, sizeRx, pPacketRx);
         
-    int action = TcpHandleReceivedPacket(trace, sizeRx, pPacketRx, pSizeTx, pPacketTx, TCP, pCachedRemIp);
+    int action = TcpHandleReceivedPacket(trace, sizeRx, pPacketRx, pSizeTx, pPacketTx, IPV4, remArIndex);
     
     *pDstIp = *pSrcIp;
     
@@ -105,7 +108,9 @@
 }
 int Tcp4PollForPacketToSend(void* pPacket, int* pSize, uint32_t* pSrcIp, uint32_t* pDstIp)
 {        
-    int action = TcpPollForPacketToSend(pSize, pPacket, IPV4, pDstIp);
+    int remArIndex = -1;
+    int action = TcpPollForPacketToSend(pSize, pPacket, IPV4, &remArIndex);
+    if (action && remArIndex >= 0) *pDstIp = Ar4IndexToIp(remArIndex);
     
     finalisePacket(TCP, action, pPacket, *pSize, pSrcIp, pDstIp);
         
--- a/ip4/udptcp4.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip4/udptcp4.h	Mon Oct 29 09:33:44 2018 +0000
@@ -1,4 +1,4 @@
 extern int Udp4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp);
-extern int Tcp4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp, uint32_t* pCachedRemIp);
+extern int Tcp4HandleReceivedPacket(void (*traceback)(void), void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp, int remArIndex);
 extern int Udp4PollForPacketToSend (                                                      void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp);
 extern int Tcp4PollForPacketToSend (                                                      void* pPacketTx, int* pSizeTx, uint32_t* pSrcIp, uint32_t* pDstIp);
--- a/ip6/ip6.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip6/ip6.c	Mon Oct 29 09:33:44 2018 +0000
@@ -156,7 +156,7 @@
     
     NetTraceHostCheckIp6(srcIp);
     
-    char* pCachedRemIp = Ar6AddIpRecord(trace, macRemote, srcIp);
+    int remArIndex = Ar6AddIpRecord(trace, macRemote, srcIp);
     Nr6MakeRequestForNameFromIp(srcIp);
 
     int action = DO_NOTHING;
@@ -165,7 +165,7 @@
         case HOPOPT: action = DO_NOTHING;                                                                                           break;
         case ICMP6:  action = Icmp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
         case UDP:    action =  Udp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp); break;
-        case TCP:    action =  Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp, pCachedRemIp); break;        
+        case TCP:    action =  Tcp6HandleReceivedPacket(trace, scope, pDataRx, dataLengthRx, pDataTx, &dataLengthTx, srcIp, dstIp, remArIndex); break;        
         default:
             LogTimeF("IP6 protocol %d unhandled\r\n", protocol);
             return DO_NOTHING;
--- a/ip6/udptcp6.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip6/udptcp6.c	Mon Oct 29 09:33:44 2018 +0000
@@ -1,18 +1,22 @@
 #include <stdint.h>
 #include <string.h>
 
-#include    "log.h"
-#include    "net.h"
-#include "action.h"
-#include    "eth.h"
-#include   "dhcp.h"
-#include     "ns.h"
-#include     "ip.h"
+#include     "log.h"
+#include     "net.h"
+#include  "action.h"
+#include     "eth.h"
+#include    "dhcp.h"
+#include      "ns.h"
+#include      "ip.h"
 #include "ip6addr.h"
-#include  "slaac.h"
-#include    "tcp.h"
-#include    "udp.h"
-#include "tcphdr.h"
+#include   "slaac.h"
+#include     "tcp.h"
+#include "tcprecv.h"
+#include "tcpsend.h"
+#include  "tcphdr.h"
+#include     "udp.h"
+#include     "led.h"
+#include     "ar6.h"
 
 static uint16_t calculateChecksum(uint8_t pro, char* pSrcIp, char* pDstIp, int size, void* pPacket)
 {
@@ -42,7 +46,7 @@
         
     switch (pro)
     {
-        case TCP: TcpHdrWrite(size, pPacket); break;
+        case TCP: TcpHdrWriteToPacket(pPacket); break;
         case UDP: UdpMakeHeader(size, pPacket); break;
     }
     
@@ -50,7 +54,7 @@
     
     switch (pro)
     {
-        case TCP: TcpHdrAddChecksum(pPacket, checksum); break;
+        case TCP: TcpHdrAddChecksumToPacket(pPacket, checksum); break;
         case UDP: UdpAddChecksum(pPacket, checksum); break;
     }
     
@@ -77,13 +81,13 @@
     }
 }
 
-int Tcp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp, char* pCachedRemIp)
+int Tcp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp, int remArIndex)
 {
     pTraceBack = traceback;
     tracePacketProtocol = TCP;
     calculatedChecksum = calculateChecksum(TCP, pSrcIp, pDstIp, sizeRx, pPacketRx);
     
-    int action = TcpHandleReceivedPacket(trace, sizeRx, pPacketRx, pSizeTx, pPacketTx, IPV6, pCachedRemIp);
+    int action = TcpHandleReceivedPacket(trace, sizeRx, pPacketRx, pSizeTx, pPacketTx, IPV6, remArIndex);
     
     Ip6AddressCopy(pDstIp, pSrcIp);
     
@@ -107,8 +111,10 @@
     return action;
 }
 int Tcp6PollForPacketToSend(void* pPacket, int* pSize, char* pSrcIp, char* pDstIp)
-{        
-    int action = TcpPollForPacketToSend(pSize, pPacket, IPV6, pDstIp);
+{
+    int remArIndex = -1;
+    int action = TcpPollForPacketToSend(pSize, pPacket, IPV6, &remArIndex);
+    if (action && remArIndex >= 0) Ar6IndexToIp(remArIndex, pDstIp);
     
     int scope = SCOPE_LOCAL;
 
--- a/ip6/udptcp6.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/ip6/udptcp6.h	Mon Oct 29 09:33:44 2018 +0000
@@ -1,4 +1,4 @@
 extern int  Udp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp);
-extern int  Tcp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp, char* pCachedRemIp);
+extern int  Tcp6HandleReceivedPacket(void (*traceback)(void), int scope, void* pPacketRx, int sizeRx, void* pPacketTx, int* pSizeTx, char* pSrcIp, char* pDstIp, int remArIndex);
 extern int  Udp6PollForPacketToSend (                                                                 void* pPacket,   int* pSize,   char* pSrcIp, char* pDstIp);
 extern int  Tcp6PollForPacketToSend (                                                                 void* pPacket,   int* pSize,   char* pSrcIp, char* pDstIp);
--- a/tcp/tcb.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcb.c	Mon Oct 29 09:33:44 2018 +0000
@@ -24,7 +24,7 @@
     for (int i = 0; i < TCB_COUNT; i++)
     {
         struct tcb* pTcb = tcbs + i;
-        if (pTcb->state != TCB_EMPTY && pTcb->port == port) return pTcb;
+        if (pTcb->state != TCB_EMPTY && pTcb->remPort == port) return pTcb;
     }
     return NULL;
 }
@@ -37,6 +37,13 @@
     }
     return NULL;
 }
+struct tcb* TcbGetNext()
+{
+    static struct tcb* pTcbNext = tcbs;
+    struct tcb* pTcbThis = pTcbNext++;
+    if (pTcbNext >= tcbs + TCB_COUNT) pTcbNext = tcbs;
+    return pTcbThis;
+}
 
 uint32_t TcbElapsed = 0;
 static void reap()
@@ -48,15 +55,15 @@
     uint32_t limit;
     switch (pTcb->state)
     {
-        case TCB_SYN_RECEIVED: limit = TIMEOUT_SYN_RECEIVED; break;
-        case TCB_ESTABLISHED:  limit = TIMEOUT_ESTABLISHED;  break;
-        case TCB_FIN_WAIT:     limit = TIMEOUT_CLOSING;      break;
-        case TCB_ACK_WAIT:     limit = TIMEOUT_CLOSING;      break;
+        case TCB_SYN_RECEIVED:   limit = TIMEOUT_SYN_RECEIVED; break;
+        case TCB_ESTABLISHED:    limit = TIMEOUT_ESTABLISHED;  break;
+        case TCB_CLOSE_FIN_WAIT: limit = TIMEOUT_CLOSING;      break;
+        case TCB_CLOSE_ACK_WAIT: limit = TIMEOUT_CLOSING;      break;
     }
     
-    if (TcbElapsed - pTcb->elapsed > limit)
+    if (TcbElapsed - pTcb->lastSendTime > limit)
     {
-        if (TcpTrace) LogTimeF("Reaping TCB %d port %d\r\n", pTcb - tcbs, pTcb->port);
+        if (TcpTrace) LogTimeF("Reaping TCB %d port %d\r\n", pTcb - tcbs, pTcb->remPort);
         pTcb->state = TCB_EMPTY;
     }
     
--- a/tcp/tcb.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcb.h	Mon Oct 29 09:33:44 2018 +0000
@@ -1,30 +1,45 @@
+#ifndef TCB_H
+#define TCB_H
+
 #include <stdint.h>
 #include <stdbool.h>
 
-#define TCB_EMPTY        0
-#define TCB_SYN_RECEIVED 1
-#define TCB_ESTABLISHED  2
-#define TCB_FIN_WAIT     3
-#define TCB_ACK_WAIT     4
+#define TCB_EMPTY          0
+#define TCB_SYN_RECEIVED   1
+#define TCB_ESTABLISHED    2
+#define TCB_CLOSE_FIN_WAIT 3
+#define TCB_CLOSE_ACK_WAIT 4
 
 struct tcb
 {
     int      state;
-    bool     hadFin;
-    uint16_t mss;
-    void*    pIp;
-    uint16_t port;
-    uint32_t sendIsn;
-    uint32_t recvIsn;
-    uint32_t sentBytes;
-    uint32_t recdBytes;
-    uint32_t elapsed;
+    uint32_t lastSendTime;
+    int      remArIndex;
+    int      ipType;
+    uint16_t remPort;
+    uint16_t locPort;
+    uint32_t remMss;
+    uint32_t window;
+    
+    uint32_t remIsn;
+    uint32_t bytesRcvdFromRem;
+    uint32_t bytesAckdToRem;
+    bool     rcvdFin;
+    
      int32_t todo;
+    
+    uint32_t locIsn;
+    uint32_t bytesSentToRem;
+    uint32_t bytesAckdByRem;
+    bool     sentFin;
 };
 
 extern uint32_t    TcbElapsed;
 extern uint32_t    TcbGetIsn(void);
 extern struct tcb* TcbGetExisting(uint16_t port);
 extern struct tcb* TcbGetEmpty(void);
+extern struct tcb* TcbGetNext(void);
 extern void        TcbMain(void);
-extern void        TcbInit(void);
\ No newline at end of file
+extern void        TcbInit(void);
+
+#endif
\ No newline at end of file
--- a/tcp/tcp.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcp.c	Mon Oct 29 09:33:44 2018 +0000
@@ -1,260 +1,5 @@
-#include <stdint.h>
 #include <stdbool.h>
 
-#include    "log.h"
-#include    "net.h"
-#include "action.h"
-#include    "tcp.h"
-#include "tcphdr.h"
-#include    "tcb.h"
-#include    "ip4.h"
-#include   "dhcp.h"
-#include   "http.h"
-#include    "led.h"
-
-
-//Payload variables
-static int dataLength;
-static int maxMss = 0;
-
 bool TcpTrace = false;
-static bool doTrace = false;
-
-static struct tcb* pTcb;
-
-static void resetConnectionOut(char* message)
-{
-    if (TcpTrace)
-    {
-        LogTime("TCP ");
-        Log(message);
-        Log("\r\n");
-    }
-    dataLength = 0;
-    TcpHdrClearOptions();
-    TcpHdrACK = false;
-    TcpHdrPSH = false;
-    TcpHdrRST = true;
-    TcpHdrSYN = false;
-    TcpHdrFIN = false;
-    
-    pTcb->state = TCB_EMPTY;
-}
-static void startConnectionIn(void *pPacket, void* pCachedRemIp)
-{
-    TcpHdrReadOptions(pPacket);                 //Get the MSS
-    if (TcpHdrMss > maxMss) TcpHdrMss = maxMss;
-    
-    pTcb->mss     = TcpHdrMss;
-    pTcb->state   = TCB_SYN_RECEIVED;
-    pTcb->elapsed = TcbElapsed;
-    pTcb->pIp     = pCachedRemIp;
-    pTcb->port    = TcpHdrSrcPort;
-    pTcb->hadFin  = false;
-}
-static void startConnectionOut(void* pPacket)
-{
-    TcpHdrMss = maxMss;                 //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20
-    TcpHdrWriteOptions(pPacket);
-    dataLength = 0;
-   
-    TcpHdrACK = true;                    //Send ACK and SYN
-    TcpHdrPSH = false;
-    TcpHdrRST = false;
-    TcpHdrSYN = true;
-    TcpHdrFIN = false;
-}
-static void establishConnectionIn()
-{
-    pTcb->state   = TCB_ESTABLISHED;
-    pTcb->elapsed = TcbElapsed;
-    pTcb->todo    = 0;
-}
-static void handleEstablishedConnectionIn(void* pPacket)
-{
-    char* pData = (char*)pPacket + TcpHdrSize;
-    HttpHandleRequest(dataLength, pData, pTcb->recdBytes - 1, &pTcb->todo);
-}
-static void handleEstablishedConnectionOut(void* pPacket)
-{
-    TcpHdrClearOptions();
-    char* pData = (char*)pPacket + TcpHdrSize;
-    HttpSendReply(&dataLength, pData, pTcb->sentBytes - 1, TcpHdrMss, pTcb->todo);
-    
-    TcpHdrACK = true;                 //Send ACK
-    TcpHdrRST = false;
-    TcpHdrSYN = false;
-    TcpHdrPSH = false;
-    
-    if (dataLength < TcpHdrMss) //If a part packet then there can be no more to send
-    {
-        TcpHdrFIN = true;       //Inform the client that we have no more to send after this
-        if (pTcb->hadFin) pTcb->state = TCB_ACK_WAIT; //Passive close
-        else              pTcb->state = TCB_FIN_WAIT; //Active close
-    }
-    else
-    {
-        TcpHdrFIN = false;
-    }
-
-    pTcb->elapsed = TcbElapsed;
-}
-static void closeConnectionOut()
-{        
-    TcpHdrACK = true;               //Send ACK
-    TcpHdrPSH = false;
-    TcpHdrRST = false;
-    TcpHdrSYN = false;
-    TcpHdrFIN = false;
-    
-    TcpHdrClearOptions();
-    dataLength = 0;
-    
-    pTcb->state  = TCB_EMPTY;
-}
+bool TcpDoTrace = false;
 
-int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int type, void* pCachedRemIp)
-{
-    TcpHdrRead(pPacketRx);
-    
-    dataLength =   sizeRx - TcpHdrSize;
-    maxMss     = *pSizeTx - TcpHdrSize;
-        
-    doTrace = false;
-    
-    //Filter out unwanted links
-    switch (TcpHdrDstPort)
-    {
-        case 80:
-            if (HttpTrace)
-            {
-                if (NetTraceNewLine) Log("\r\n");
-                LogTime("HTTP server request\r\n");
-                doTrace = true;
-            }
-            break;
-            
-        default:
-            if (TcpTrace)
-            {
-                if (NetTraceNewLine) Log("\r\n");
-                LogTimeF("TCP unknown port %d\r\n", TcpHdrDstPort);
-                if (NetTraceStack) traceback();
-            }
-            return DO_NOTHING; //Ignore unknown ports
-    }
-    
-    //Get the 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 (NetTraceNewLine) Log("\r\n");
-            LogTime("TCP received reset - resetting TCB\r\n");
-            if (NetTraceStack) traceback();
-        }
-        pTcb->state  = TCB_EMPTY; //Reset connection
-        return DO_NOTHING;        //Don't reply
-    }
-    
-    //Handle request to synchronise
-    if (TcpHdrSYN)
-    {
-        pTcb->recvIsn   = TcpHdrSeqNum;
-        pTcb->sendIsn   = TcbGetIsn();
-        pTcb->recdBytes = 0;
-        pTcb->sentBytes = 0;
-    }
-    else
-    {
-        pTcb->recdBytes = TcpHdrSeqNum - pTcb->recvIsn;
-        pTcb->sentBytes = TcpHdrAckNum - pTcb->sendIsn;
-    }
-        
-    if (doTrace && NetTraceStack) traceback(); //This will already include the TCP header
-    
-    if (TcpHdrSYN) pTcb->recdBytes += 1;            //Add one to acknowledge the SYN
-                   pTcb->recdBytes += dataLength;   //Add the number of bytes received
-    if (TcpHdrFIN) pTcb->recdBytes += 1;            //Add one to acknowledge the FIN
-
-    switch (pTcb->state)
-    {
-        case TCB_EMPTY:
-            if (!TcpHdrSYN) { resetConnectionOut("received other than a SYN when connection closed"); break; }
-            startConnectionIn(pPacketRx, pCachedRemIp);
-            startConnectionOut(pPacketTx);
-            break;
-            
-        case TCB_SYN_RECEIVED:
-            if (dataLength) { resetConnectionOut("data received before connection established"); break; }
-            if (!TcpHdrACK)       { resetConnectionOut("received other than an ACK before connection established"); break; }
-            establishConnectionIn();
-            return DO_NOTHING;
-            
-        case TCB_ESTABLISHED:
-            if (!TcpHdrACK) { resetConnectionOut("received other than an ACK during established conection"); break; }
-            if (TcpHdrFIN) pTcb->hadFin = true; //When reply is all sent only a passive close is needed
-            handleEstablishedConnectionIn (pPacketRx);
-            handleEstablishedConnectionOut(pPacketTx);
-            break;
-            
-        case TCB_FIN_WAIT: //End of active close
-            if (!TcpHdrFIN) return DO_NOTHING; //Ignore ACK to our FIN. Wait for FIN then close.
-            closeConnectionOut();
-            break;
-            
-        case TCB_ACK_WAIT: //End of passive close
-            if (!TcpHdrACK) { resetConnectionOut("received other than an ACK when closing half open connection"); break; } 
-            pTcb->state = TCB_EMPTY;
-            return DO_NOTHING;
-    }
-    
-    //Specify the start of the data being sent and acknowledge the data received
-    TcpHdrAckNum = pTcb->recdBytes + pTcb->recvIsn;       //Set up the acknowledgement field ready to send
-    TcpHdrSeqNum = pTcb->sentBytes + pTcb->sendIsn;       //Set up the start of the message before adding the bytes sent
-    
-    //Keep a record of where we expect the next packet send to start
-    if (TcpHdrSYN) pTcb->sentBytes += 1;           //Add one to acknowledge the SYN
-                   pTcb->sentBytes += dataLength;  //Record the next sequence number
-    if (TcpHdrFIN) pTcb->sentBytes += 1;           //Add one to acknowledge the FIN
-    
-    //Swap the ports for the reply
-    TcpHdrSrcPort = TcpHdrDstPort;
-    TcpHdrDstPort = pTcb->port;
-    
-    //Specify the receive window size to not throttle
-    TcpHdrWindow = 4000;
-    
-    //Calculate the size of the reply
-    *pSizeTx = TcpHdrSize + dataLength;
-        
-    return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack);
-}
-
-int TcpPollForPacketToSend(int* pSize, void* pPacket, int type, void* pCachedRemIp)
-{    
-    int dataLength =         *pSize - TcpHdrSize;
-    
-    int action = DO_NOTHING;
-    
-    TcpHdrSrcPort = TcpHdrDstPort;
-    TcpHdrDstPort = pTcb->port;
-    
-    *pSize =  TcpHdrSize + dataLength;
-    return action;
-}
-
--- a/tcp/tcp.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcp.h	Mon Oct 29 09:33:44 2018 +0000
@@ -1,7 +1,4 @@
-#include <stdint.h>
 #include <stdbool.h>
 
 extern bool TcpTrace;
-
-extern int  TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int type, void* pCachedRemIp);
-extern int  TcpPollForPacketToSend(int* pSize, void* pPacket, int type, void* pCachedRemIp);
+extern bool TcpDoTrace;
\ No newline at end of file
--- a/tcp/tcphdr.c	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcphdr.c	Mon Oct 29 09:33:44 2018 +0000
@@ -22,7 +22,6 @@
 uint16_t TcpHdrDstPort;
 uint32_t TcpHdrSeqNum;
 uint32_t TcpHdrAckNum;
-int      TcpHdrSize;
 bool     TcpHdrURG; //indicates that the Urgent pointer field is significant
 bool     TcpHdrACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
 bool     TcpHdrPSH; //Push function. Asks to push the buffered data to the receiving application.
@@ -33,29 +32,18 @@
 uint16_t TcpHdrChecksum;
 uint16_t TcpHdrUrgent;
 
-//Option variables
-uint16_t TcpHdrMss;
+//Side effects
+static int      headerSize;
+int TcpHdrSizeGet() { return headerSize; }
 
-void TcpHdrRead(void* pPacket)
+static uint16_t mss = 0;
+void TcpHdrMssSet(uint16_t value)
 {
-    struct header* pHeader = (struct header*)pPacket;
-                        
-    TcpHdrSrcPort = NetToHost16(pHeader->srcPort);
-    TcpHdrDstPort = NetToHost16(pHeader->dstPort);
-    TcpHdrSeqNum  = NetToHost32(pHeader->seqnum);
-    TcpHdrAckNum  = NetToHost32(pHeader->acknum);
-    TcpHdrSize    =            (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
-    uint8_t flags =             pHeader->flags;
-        TcpHdrURG = flags & 0x20; //indicates that the Urgent pointer field is significant
-        TcpHdrACK = flags & 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
-        TcpHdrPSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
-        TcpHdrRST = flags & 0x04; //Reset the connection
-        TcpHdrSYN = flags & 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
-        TcpHdrFIN = flags & 0x01; //No more data from sender
-    TcpHdrWindow   = NetToHost16(pHeader->window);
-    TcpHdrChecksum = NetToHost16(pHeader->checksum);
-    TcpHdrUrgent   = NetToHost16(pHeader->urgent);
+    mss = value;
+    headerSize = sizeof (struct header);
+    if (mss) headerSize += 4;
 }
+uint16_t TcpHdrMssGet() { return mss; }
 
 static void logFlags()
 {
@@ -75,7 +63,7 @@
         Log("  Destination port "); LogF("%hu",     TcpHdrDstPort          ); Log("\r\n");
         Log("  Seq number       "); LogF("%u",      TcpHdrSeqNum           ); Log("\r\n");
         Log("  Ack number       "); LogF("%u",      TcpHdrAckNum           ); Log("\r\n");
-        Log("  Header size      "); LogF("%u",      TcpHdrSize             ); Log("\r\n");
+        Log("  Header size      "); LogF("%u",      headerSize             ); Log("\r\n");
         Log("  Flags           " ); logFlags(                              ); Log("\r\n");
         Log("  Window           "); LogF("%hu",     TcpHdrWindow           ); Log("\r\n");
         Log("  Checksum (hex)   "); LogF("%04hX",   TcpHdrChecksum         ); Log("\r\n");
@@ -90,17 +78,30 @@
         Log("\r\n");
     }
 }
-void TcpHdrAddChecksum(void* pPacket, uint16_t checksum)
+void TcpHdrReadFromPacket(void* pPacket)
 {
     struct header* pHeader = (struct header*)pPacket;
-    pHeader->checksum    = checksum;
-}
-void TcpHdrReadOptions(void* pPacket)
-{
+                        
+    TcpHdrSrcPort = NetToHost16(pHeader->srcPort);
+    TcpHdrDstPort = NetToHost16(pHeader->dstPort);
+    TcpHdrSeqNum  = NetToHost32(pHeader->seqnum);
+    TcpHdrAckNum  = NetToHost32(pHeader->acknum);
+    headerSize    =            (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
+    uint8_t flags =             pHeader->flags;
+        TcpHdrURG = flags & 0x20; //indicates that the Urgent pointer field is significant
+        TcpHdrACK = flags & 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
+        TcpHdrPSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
+        TcpHdrRST = flags & 0x04; //Reset the connection
+        TcpHdrSYN = flags & 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
+        TcpHdrFIN = flags & 0x01; //No more data from sender
+    TcpHdrWindow   = NetToHost16(pHeader->window);
+    TcpHdrChecksum = NetToHost16(pHeader->checksum);
+    TcpHdrUrgent   = NetToHost16(pHeader->urgent);
+    
     char* pOptions     = (char*)pPacket + sizeof(struct header);
-    int   optionLength =     TcpHdrSize - sizeof(struct header);
+    int   optionLength =     headerSize - sizeof(struct header);
 
-    TcpHdrMss = 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
+    mss = 0;
     for (char* p = pOptions; p < pOptions + optionLength; p++)
     {
         switch (*p)
@@ -111,37 +112,35 @@
                 p++;
                 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
                 p++;
-                TcpHdrMss = ((uint16_t)*p) << 8;
+                mss = ((uint16_t)*p) << 8;
                 p++;
-                TcpHdrMss += *p;
+                mss += *p;
                 return;
             default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
         }
     }
 }
-void TcpHdrWriteOptions(void* pPacket)
-{
-    char* pOptions = (char*)pPacket + sizeof(struct header);
-    pOptions[0]  = 2;
-    pOptions[1]  = 4;
-    pOptions[2]  = TcpHdrMss >> 8;
-    pOptions[3]  = TcpHdrMss & 0xFF;
-    TcpHdrSize += sizeof(struct header) + 4;
-}
-void TcpHdrClearOptions()
-{
-    TcpHdrSize = sizeof(struct header);
-}
 
-void TcpHdrWrite(int size, void* pPacket)
+void TcpHdrWriteToPacket(void* pPacket)
 {
     struct header* pHeader = (struct header*)pPacket;
     
+    headerSize = sizeof(struct header);
+    if (TcpHdrMssGet())
+    {
+        char* pOptions = (char*)pPacket + headerSize;
+        pOptions[0]  = 2;
+        pOptions[1]  = 4;
+        pOptions[2]  = mss >> 8;
+        pOptions[3]  = mss & 0xFF;
+        headerSize += 4;
+    }
+    
     pHeader->dstPort    = NetToHost16(TcpHdrDstPort);
     pHeader->srcPort    = NetToHost16(TcpHdrSrcPort);
     pHeader->seqnum     = NetToHost32(TcpHdrSeqNum); //This is the sequence number of the first byte of this message
     pHeader->acknum     = NetToHost32(TcpHdrAckNum); //This is the sequence number we expect in the next message
-    pHeader->dataOffset = TcpHdrSize << 2;           //Same as dividing by 4 to get bytes and left shifting by 4 bits
+    pHeader->dataOffset = headerSize << 2;           //Same as dividing by 4 to get bytes and left shifting by 4 bits
     uint8_t flags = 0;
     if (TcpHdrURG) flags |= 0x20; //indicates that the Urgent pointer field is significant
     if (TcpHdrACK) flags |= 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
@@ -154,4 +153,29 @@
     pHeader->urgent     = NetToHost16(TcpHdrUrgent);
     
     pHeader->checksum   = 0;
+}
+void TcpHdrAddChecksumToPacket(void* pPacket, uint16_t checksum)
+{
+    struct header* pHeader = (struct header*)pPacket;
+    pHeader->checksum    = checksum;
+}
+
+void TcpHdrMakeEmpty()
+{
+    TcpHdrSrcPort  = 0;
+    TcpHdrDstPort  = 0;
+    TcpHdrSeqNum   = 0;
+    TcpHdrAckNum   = 0;
+    headerSize     = sizeof(struct header);
+    TcpHdrURG      = 0;
+    TcpHdrACK      = 0;
+    TcpHdrPSH      = 0;
+    TcpHdrRST      = 0;
+    TcpHdrSYN      = 0;
+    TcpHdrFIN      = 0;
+    TcpHdrWindow   = 0;
+    TcpHdrChecksum = 0;
+    TcpHdrUrgent   = 0;
+    mss            = 0;
+
 }
\ No newline at end of file
--- a/tcp/tcphdr.h	Tue Oct 23 06:46:50 2018 +0000
+++ b/tcp/tcphdr.h	Mon Oct 29 09:33:44 2018 +0000
@@ -1,19 +1,17 @@
 extern void TcpHdrLog(uint16_t calculatedChecksum);
 
-extern void TcpHdrRead (          void* pPacket);
-extern void TcpHdrReadOptions(    void* pPacket);
+extern void TcpHdrReadFromPacket(void* pPacket);
 
-extern void TcpHdrWrite(int size, void* pPacket);
-extern void TcpHdrAddChecksum(void*pPacket, uint16_t checksum);
+extern void TcpHdrWriteToPacket(void* pPacket);
+extern void TcpHdrAddChecksumToPacket(void* pPacket, uint16_t checksum);
 
-extern void TcpHdrWriteOptions(void* pPacket);
-extern void TcpHdrClearOptions(void);
+extern void TcpHdrMakeEmpty(void);
 
 extern uint16_t TcpHdrSrcPort;
 extern uint16_t TcpHdrDstPort;
 extern uint32_t TcpHdrSeqNum;
 extern uint32_t TcpHdrAckNum;
-extern int      TcpHdrSize;
+extern int      TcpHdrSizeGet(void);
 extern bool     TcpHdrURG; //indicates that the Urgent pointer field is significant
 extern bool     TcpHdrACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
 extern bool     TcpHdrPSH; //Push function. Asks to push the buffered data to the receiving application.
@@ -24,4 +22,5 @@
 extern uint16_t TcpHdrChecksum;
 extern uint16_t TcpHdrUrgent;
 
-extern uint16_t TcpHdrMss;
+extern uint16_t TcpHdrMssGet(void);
+extern void     TcpHdrMssSet(uint16_t value);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tcprecv.c	Mon Oct 29 09:33:44 2018 +0000
@@ -0,0 +1,186 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include     "log.h"
+#include     "net.h"
+#include  "action.h"
+#include     "tcp.h"
+#include  "tcphdr.h"
+#include "tcpsend.h"
+#include     "tcb.h"
+#include     "ip4.h"
+#include    "dhcp.h"
+#include    "http.h"
+#include     "led.h"
+
+//Payload variables
+static struct tcb* pTcb;
+
+static void logReset(char* message)
+{
+    if (TcpTrace) { LogTime("TCP sent RST - "); Log(message); Log("\r\n"); }
+}
+
+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
+    int remMss = TcpHdrMssGet();
+    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;
+}
+static void handleReceivedData(void* pPacket, int dataLength)
+{
+    pTcb->window = TcpHdrWindow;
+    char* pData = (char*)pPacket + TcpHdrSizeGet();
+    switch (pTcb->locPort)
+    {
+        case 80:
+            HttpHandleRequest(dataLength, pData, pTcb->bytesRcvdFromRem - 1, &pTcb->todo);
+            break;
+        default:
+            break;
+    }
+}
+
+int TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int ipType, int remArIndex)
+{
+    TcpHdrReadFromPacket(pPacketRx);
+    
+    int dataLength =   sizeRx - TcpHdrSizeGet();
+    int locMss     = *pSizeTx - TcpHdrSizeGet();
+        
+    TcpDoTrace = false;
+    
+    //Filter out unwanted links
+    switch (TcpHdrDstPort)
+    {
+        case 80:
+            if (HttpTrace)
+            {
+                if (NetTraceNewLine) Log("\r\n");
+                LogTime("HTTP server request\r\n");
+                TcpDoTrace = true;
+            }
+            break;
+            
+        default:
+            if (TcpTrace)
+            {
+                if (NetTraceNewLine) Log("\r\n");
+                LogTimeF("TCP unknown port %d\r\n", TcpHdrDstPort);
+                if (NetTraceStack) traceback();
+            }
+            return DO_NOTHING; //Ignore unknown ports
+    }
+    
+    //Get the 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 (NetTraceNewLine) Log("\r\n");
+            LogTime("TCP received reset - resetting TCB\r\n");
+            if (NetTraceStack) traceback();
+        }
+        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;
+    }
+    
+    //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);
+    
+    pTcb->bytesRcvdFromRem = TcpHdrSeqNum - pTcb->remIsn;
+    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
+    
+    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
+
+    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;
+            
+        case TCB_SYN_RECEIVED:
+            if (dataLength)
+            {
+                logReset("data received before connection established");
+                pTcb->state = TCB_EMPTY;
+                return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_RESET);
+            }
+            pTcb->state = TCB_ESTABLISHED;
+            break;
+            
+        case TCB_ESTABLISHED:
+            if (dataLength) handleReceivedData (pPacketRx, dataLength);
+            if (pTcb->sentFin)
+            {
+                pTcb->state = pTcb->rcvdFin ? TCB_CLOSE_ACK_WAIT : TCB_CLOSE_FIN_WAIT;
+            }
+            break;
+            
+        case TCB_CLOSE_FIN_WAIT: //End of active close
+            if (TcpHdrFIN)
+            {
+                pTcb->state = TCB_EMPTY;//Ignore ACK to our FIN. Wait for FIN then close.
+            }
+            break;
+            
+        case TCB_CLOSE_ACK_WAIT: //End of passive close
+            pTcb->state = TCB_EMPTY;
+            break;
+    }
+    
+    return TcpSend(pSizeTx, pPacketTx, pTcb, TCP_SEND_NORMAL);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tcprecv.h	Mon Oct 29 09:33:44 2018 +0000
@@ -0,0 +1,2 @@
+
+extern int  TcpHandleReceivedPacket(void (*traceback)(void), int sizeRx, void* pPacketRx, int* pSizeTx, void* pPacketTx, int type, int remArIndex);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tcpsend.c	Mon Oct 29 09:33:44 2018 +0000
@@ -0,0 +1,130 @@
+#include <stdint.h>
+#include <stdbool.h>
+
+#include    "log.h"
+#include    "net.h"
+#include "action.h"
+#include    "tcp.h"
+#include "tcphdr.h"
+#include    "tcb.h"
+#include    "ip4.h"
+#include   "dhcp.h"
+#include   "http.h"
+#include    "led.h"
+#include "tcpsend.h"
+
+
+
+static int sendData(void* pPacket, struct tcb* pTcb)
+{
+    int dataLength = 0;
+    char* pData = (char*)pPacket + TcpHdrSizeGet();
+    switch (pTcb->locPort)
+    {
+        case 80:
+            HttpSendReply(&dataLength, pData, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo);
+            break;
+        default:
+            break;
+    }    
+    
+    pTcb->lastSendTime = TcbElapsed;
+    
+    return dataLength;
+}
+
+int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb, int sendType)
+{
+    int dataLength = 0;
+    TcpHdrMakeEmpty();
+    int locMss = *pSize - TcpHdrSizeGet();
+    switch (pTcb->state)
+    {
+        case TCB_SYN_RECEIVED:
+            if (pTcb->bytesSentToRem == 0)
+            {
+                TcpHdrMssSet(locMss);
+                TcpHdrSYN = true;
+            }
+            break;
+            
+        case TCB_ESTABLISHED:
+            if (!pTcb->sentFin)
+            {
+                if (pTcb->bytesSentToRem - pTcb->bytesAckdByRem < pTcb->window)
+                {
+                    if (pTcb->todo)
+                    {
+                        dataLength = sendData(pPacket, pTcb);
+                        if (dataLength < pTcb->remMss)
+                        {
+                            TcpHdrFIN     = true;
+                            pTcb->sentFin = true;
+                        }
+                    }
+                    else
+                    {
+                        if (pTcb->rcvdFin)
+                        {
+                            TcpHdrFIN     = true;
+                            pTcb->sentFin = true;
+                        }
+                    }
+                }
+            }
+            break;
+    }
+
+    //See if have need to acknowledge received bytes
+    bool rcvdSeqHasAdvanced = pTcb->bytesRcvdFromRem > pTcb->bytesAckdToRem;
+    
+    //Record the number of bytes acknowledged to the remote
+    pTcb->bytesAckdToRem = pTcb->bytesRcvdFromRem;
+    
+    //Specify the start of the data being sent and acknowledge the data received
+    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
+
+    //Record the number of bytes sent
+    uint32_t bytesToSend = 0;
+    if (TcpHdrSYN) bytesToSend += 1;            //Add one to acknowledge the SYN
+                   bytesToSend += dataLength;   //Add the number of bytes received
+    if (TcpHdrFIN) bytesToSend += 1;            //Add one to acknowledge the FIN
+
+    pTcb->bytesSentToRem += bytesToSend;
+    
+    if (rcvdSeqHasAdvanced || bytesToSend || sendType == TCP_RESEND_ACK || sendType == TCP_SEND_RESET)
+    {
+        //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;
+            
+        return ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack);
+    }
+    else
+    {
+        return DO_NOTHING;
+    }
+}
+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;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tcp/tcpsend.h	Mon Oct 29 09:33:44 2018 +0000
@@ -0,0 +1,8 @@
+#include "tcb.h"
+
+extern int  TcpSend               (int* pSize, void* pPacket, struct tcb* pTcb, int sendType);
+extern int  TcpPollForPacketToSend(int* pSize, void* pPacket, int type, int* pRemArIndex);
+
+#define TCP_SEND_NORMAL 0
+#define TCP_RESEND_ACK  1
+#define TCP_SEND_RESET  2