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
Diff: tcp/tcp.cpp
- Revision:
- 55:e64b8b47a2b6
- Parent:
- 54:84ef2b29cf7e
- Child:
- 56:35117a8b5c65
--- a/tcp/tcp.cpp Mon Nov 13 08:06:55 2017 +0000 +++ b/tcp/tcp.cpp Mon Nov 13 21:46:31 2017 +0000 @@ -11,6 +11,7 @@ #define MAX_MSS 536 //This is 576 - 20 - 20 bool TcpTrace = false; +static bool doTrace = false; __packed struct header { @@ -48,9 +49,10 @@ static char* pOptions; static char* pData; static int dataLength; -static uint16_t mss; +static int positionInRequestStream; +static int positionInReplyStream; -static bool isSend = false; +static uint16_t mss; static void (*pTraceback)(void); @@ -65,7 +67,7 @@ if (SYN) Log(" SYN"); if (FIN) Log(" FIN"); } -void TcpLogHeader(uint16_t calculatedChecksum) +void TcpLogHeader(uint16_t calculatedChecksum, bool isSend) { if (NetTraceVerbose) { @@ -74,13 +76,13 @@ LogF(" Destination port %hu\r\n", dstPort); if (isSend) { - LogF(" Sequence number %u (%u)\r\n", seqnum - pTcb->locIsn, seqnum); - LogF(" Ack number %u (%u)\r\n", acknum - pTcb->remIsn, acknum); + LogF(" Loc Seq number %u (%u)\r\n", seqnum - pTcb->locIsn, seqnum); + LogF(" Rem Ack number %u (%u)\r\n", acknum - pTcb->remIsn, acknum); } else { - LogF(" Sequence number %u (%u)\r\n", seqnum - pTcb->remIsn, seqnum); - LogF(" Ack number %u (%u)\r\n", acknum - pTcb->locIsn, acknum); + LogF(" Rem Seq number %u (%u)\r\n", seqnum - pTcb->remIsn, seqnum); + LogF(" Loc Ack number %u (%u)\r\n", acknum - pTcb->locIsn, acknum); } LogF(" Header size %u\r\n", headersize); Log (" Flags "); logFlags(); Log("\r\n"); @@ -100,8 +102,8 @@ { LogF("TCP header %hu >>> %hu", srcPort, dstPort); logFlags(); - if (isSend) LogF(", seq %u, ack %u", seqnum - pTcb->locIsn, acknum - pTcb->remIsn); - else LogF(", seq %u, ack %u", seqnum - pTcb->remIsn, acknum - pTcb->locIsn); + if (isSend) LogF(", loc seq %u, rem ack %u", seqnum - pTcb->locIsn, acknum - pTcb->remIsn); + else LogF(", rem seq %u, loc ack %u", seqnum - pTcb->remIsn, acknum - pTcb->locIsn); Log("\r\n"); } } @@ -190,19 +192,24 @@ pHeader->checksum = 0; } +static void makeRST() +{ + dataLength = 0; + headersize = 20; + seqnum = acknum; + acknum = 0; + ACK = false; + PSH = false; + RST = true; + SYN = false; + FIN = false; +} static int stateClosed() { if (!SYN) //Reset if anything other than a request to establish conection from client { - dataLength = 0; - headersize = 20; - seqnum = acknum; - acknum = 0; - ACK = false; //Send RST - PSH = false; - RST = true; - SYN = false; - FIN = false; + if (TcpTrace) LogTimeF("TCP did not received other than a SYN when closed - sent reset.\r\n"); + makeRST(); return 1; } @@ -211,17 +218,7 @@ pTcb->state = TCB_SYN_RECEIVED; pTcb->elapsed = TcbElapsed; pTcb->port = srcPort; - pTcb->locIsn = TcbGetIsn(); - pTcb->locSeq = pTcb->locIsn; - pTcb->remIsn = seqnum; - pTcb->remSeq = pTcb->remIsn; - - pTcb->remSeq += 1; //Add one to acknowledge the SYN - acknum = pTcb->remSeq; - - seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message - pTcb->locSeq += 1; //Add one to the next sequence number as we are sending a SYN - + dataLength = 0; mss = MAX_MSS; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20 @@ -238,7 +235,7 @@ } static int stateSynReceived() { - if (dataLength) LogTimeF("%d bytes data received before TCB established\r\n", dataLength); + if (dataLength) LogTimeF("%d bytes data received before TCB established - ignoring\r\n", dataLength); if (ACK) { pTcb->state = TCB_ESTABLISHED; @@ -252,32 +249,23 @@ if (!ACK) return 0; //Ignore any packets which don't contain an ACK //Handle reception of data - pTcb->remSeq = seqnum + dataLength; - acknum = pTcb->remSeq; //Set the ack num to the next byte expected from the client - int positionInRequestStream = seqnum - pTcb->remIsn - 1; - int positionInReplyStream = pTcb->locSeq - pTcb->locIsn - 1; char* pRequestStream = pData; char* pReplyStream = pOptions; - HttpHandleRequest(pTraceback, &dataLength, pRequestStream, positionInRequestStream, pReplyStream, positionInReplyStream, mss, &pTcb->todo); + HttpHandleRequest(&dataLength, pRequestStream, positionInRequestStream - 1, pReplyStream, positionInReplyStream - 1, mss, &pTcb->todo); //Rearrange the buffers headersize = 20; pData = pReplyStream; - - seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message - + ACK = true; //Send ACK RST = false; SYN = false; PSH = false; - pTcb->locSeq += dataLength; //Record the next sequence number - if (dataLength < mss) //If a part packet then there can be no more to send { FIN = true; //Inform the client that we have no more to send after this - pTcb->locSeq += 1; //Record the FIN in the sequence pTcb->state = TCB_CLOSING; //Start closing } @@ -287,13 +275,7 @@ static int stateClosing() { if (!FIN) return 0; //Ignore any packets which don't contain a FIN - - pTcb->remSeq += 1; //Add one to acknowledge the FIN - acknum = pTcb->remSeq; - - seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message - //but don't change it for the next - + ACK = true; //Send ACK PSH = false; RST = false; @@ -311,7 +293,8 @@ int TcpHandleReceivedPacket(void (*traceback)(void), int* pSize, void* pPacket) { pTraceback = traceback; - isSend = false; + + //Get the Transmission Control Block pTcb = TcbGetExisting(srcPort); if (!pTcb) pTcb = TcbGetEmpty(); if (!pTcb) @@ -319,59 +302,71 @@ if (TcpTrace) { LogTime("TCP no more tcbs are available\r\n"); - traceback(); //This will already include the TCP header + pTraceback(); //This will already include the TCP header } return DO_NOTHING; //Bomb out if no more tcbs are available } + //Handle request to reset if (RST) { pTcb->state = TCB_CLOSED; //Reset connection return DO_NOTHING; //Bomb out } + + //Handle request to synchronise + if (SYN) + { + pTcb->remIsn = seqnum; + pTcb->remSeq = pTcb->remIsn; + pTcb->locIsn = TcbGetIsn(); + pTcb->locSeq = pTcb->locIsn; + acknum = pTcb->locIsn; + } + + //Check the sequence is not lost or out of order + if (seqnum != pTcb->remSeq) + { + LogTimeF("TCP had sequence %u but expected %u\r\n", seqnum, pTcb->remSeq); + } + + //Check the remote host has received all bytes + if (acknum != pTcb->locSeq) + { + LogTimeF("TCP acknowledged %u but expected %u\r\n", acknum, pTcb->locSeq); + } + + positionInRequestStream = seqnum - pTcb->remIsn; + positionInReplyStream = acknum - pTcb->locIsn; //Filter out unwanted links switch (dstPort) { - case 80: break; - default: - if (TcpTrace) + case 80: + doTrace = HttpTrace; + if (doTrace) { - LogTimeF("TCP unknown port %d\r\n", dstPort); - traceback(); //This will already include the TCP header + if (NetTraceNewLine) Log("\r\n"); + LogTime("HTTP server request\r\n"); } - return DO_NOTHING; //This needs to become a reset - } - - if (TcpTrace) - { - if (!SYN && (int32_t)(seqnum - pTcb->remSeq)) - { - LogTime("TCP"); - logFlags(); - LogF(" off=%d seq num=%u expected=%u packet length %d from port %u\r\n", (int32_t)(seqnum - pTcb->remSeq), seqnum, pTcb->remSeq, *pSize, srcPort); - } + break; + + default: + doTrace = TcpTrace; + if (doTrace) + { + if (NetTraceNewLine) Log("\r\n"); + LogTimeF("TCP unknown port %d\r\n", dstPort); + } + return DO_NOTHING; //Ignore unknown ports } - //Drop duplicate packets - /* - if (!TCB_CLOSED && (int32_t)(seqnum - pTcb->remSeq) < 0) - { - if (TcpTrace) - { - LogTimeF("TCP Dropped duplicate seq num=%d expected=%d packet length %d from port %u\r\n", seqnum, pTcb->remSeq, *pSize, srcPort); - traceback(); - } - return DO_NOTHING; - } - */ - if (TcpTrace) - { - if (NetTraceNewLine) Log("\r\n"); - LogF("TCP server request\r\n"); - traceback(); - } + if (doTrace && NetTraceStack) pTraceback(); //This will already include the TCP header + + if (SYN) pTcb->remSeq += 1; //Add one to acknowledge the SYN + pTcb->remSeq += dataLength; //Add the number of bytes received + if (FIN) pTcb->remSeq += 1; //Add one to acknowledge the FIN + acknum = pTcb->remSeq; //Set up the acknowledgement field ready to send - isSend = true; switch (pTcb->state) { case TCB_CLOSED: if (stateClosed ()) break; return DO_NOTHING; @@ -380,11 +375,17 @@ case TCB_CLOSING: if (stateClosing ()) break; return DO_NOTHING; } + seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message + if (SYN) pTcb->locSeq += 1; //Add one to acknowledge the SYN + pTcb->locSeq += dataLength; //Record the next sequence number + if (FIN) pTcb->locSeq += 1; //Add one to acknowledge the FIN + + srcPort = dstPort; dstPort = pTcb->port; *pSize = dataLength + headersize; - return ActionMakeFromDestAndTrace(UNICAST, TcpTrace && NetTraceStack); + return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack); }