Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
Diff: tcp/tcp.cpp
- Revision:
- 57:e0fb648acf48
- Parent:
- 56:35117a8b5c65
- Child:
- 59:e0e556c8bd46
--- a/tcp/tcp.cpp Tue Nov 14 17:43:08 2017 +0000 +++ b/tcp/tcp.cpp Tue Nov 28 17:05:46 2017 +0000 @@ -72,29 +72,29 @@ if (NetTraceVerbose) { Log("TCP header\r\n"); - LogF(" Source port %hu\r\n", srcPort); - LogF(" Destination port %hu\r\n", dstPort); - LogF(" Seq number %u (%u)\r\n", positionInQuery, seqnum); - LogF(" Ack number %u (%u)\r\n", positionInReply, acknum); - LogF(" Header size %u\r\n", headersize); - Log (" Flags "); logFlags(); Log("\r\n"); - LogF(" Window %hu\r\n", window); - LogF(" Checksum (hex) %04hX\r\n", checksum); - LogF(" Calculated (hex) %04hX\r\n", calculatedChecksum); - LogF(" Urgent pointer %hu\r\n", urgent); - LogF(" Option length %d\r\n", optionLength); - LogF(" Data length %d\r\n", dataLength); - LogF(" locIsn %u\r\n", pTcb->locIsn); - LogF(" remIsn %u\r\n", pTcb->remIsn); - LogF(" locSeq %u\r\n", pTcb->locSeq); - LogF(" remSeq %u\r\n", pTcb->remSeq); + Log(" Source port "); LogF("%hu", srcPort ); Log("\r\n"); + Log(" Destination port "); LogF("%hu", dstPort ); Log("\r\n"); + Log(" Seq number "); LogF("%u (%u)", positionInQuery, seqnum); Log("\r\n"); + Log(" Ack number "); LogF("%u (%u)", positionInReply, acknum); Log("\r\n"); + Log(" Header size "); LogF("%u", headersize ); Log("\r\n"); + Log(" Flags " ); logFlags( ); Log("\r\n"); + Log(" Window "); LogF("%hu", window ); Log("\r\n"); + Log(" Checksum (hex) "); LogF("%04hX", checksum ); Log("\r\n"); + Log(" Calculated (hex) "); LogF("%04hX", calculatedChecksum ); Log("\r\n"); + Log(" Urgent pointer "); LogF("%hu", urgent ); Log("\r\n"); + Log(" Option length "); LogF("%d", optionLength ); Log("\r\n"); + Log(" Data length "); LogF("%u", dataLength ); Log("\r\n"); + Log(" sendIsn "); LogF("%u", pTcb->sendIsn ); Log("\r\n"); + Log(" recvIsn "); LogF("%u", pTcb->recvIsn ); Log("\r\n"); + Log(" sentBytes "); LogF("%u", pTcb->sentBytes ); Log("\r\n"); + Log(" recdBytes "); LogF("%u", pTcb->recdBytes ); Log("\r\n"); } else { LogF("TCP header %hu >>> %hu", srcPort, dstPort); logFlags(); - LogF(", seq %u, ack %u", positionInQuery, positionInReply); + LogF(", query %u, reply %u", positionInQuery, positionInReply); Log("\r\n"); } } @@ -155,7 +155,7 @@ checksum = NetToHost16(pHeader->checksum); urgent = NetToHost16(pHeader->urgent); pOptions = (char*)pPacket + 20; - optionLength = headersize - 20; + optionLength = headersize - 20; pData = (char*)pPacket + headersize; dataLength = size - headersize; } @@ -205,6 +205,7 @@ pTcb->state = TCB_SYN_RECEIVED; pTcb->elapsed = TcbElapsed; pTcb->port = srcPort; + pTcb->hadFin = false; dataLength = 0; @@ -222,7 +223,7 @@ { pTcb->state = TCB_ESTABLISHED; pTcb->elapsed = TcbElapsed; - pTcb->todo = 0; + pTcb->todo = 0; } static void handleEstablishedConnection() { @@ -241,8 +242,9 @@ 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->state = TCB_CLOSING; //Start closing + FIN = 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 { @@ -262,12 +264,35 @@ headersize = 20; dataLength = 0; - pTcb->state = TCB_CLOSED; + pTcb->state = TCB_EMPTY; } int TcpHandleReceivedPacket(void (*traceback)(void), int* pSize, void* pPacket) { pTraceback = traceback; + doTrace = false; + + //Filter out unwanted links + switch (dstPort) + { + 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", dstPort); + if (NetTraceStack) pTraceback(); + } + return DO_NOTHING; //Ignore unknown ports + } //Get the Transmission Control Block pTcb = TcbGetExisting(srcPort); @@ -276,8 +301,9 @@ { if (TcpTrace) { + if (NetTraceNewLine) Log("\r\n"); LogTime("TCP no more tcbs are available\r\n"); - pTraceback(); //This will already include the TCP header + if (NetTraceStack) pTraceback(); } return DO_NOTHING; //Bomb out if no more tcbs are available } @@ -285,66 +311,56 @@ //Handle request to reset if (RST) { - pTcb->state = TCB_CLOSED; //Reset connection - return DO_NOTHING; //Don't reply + if (TcpTrace) + { + if (NetTraceNewLine) Log("\r\n"); + LogTime("TCP received reset - resetting TCB\r\n"); + if (NetTraceStack) pTraceback(); + } + pTcb->state = TCB_EMPTY; //Reset connection + return DO_NOTHING; //Don't reply } //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); + pTcb->recvIsn = seqnum; + pTcb->recdBytes = 0; + pTcb->sendIsn = TcbGetIsn(); + pTcb->sentBytes = 0; + acknum = pTcb->sendIsn; } - //Check the remote host has received all bytes - if (acknum != pTcb->locSeq) - { - LogTimeF("TCP acknowledged %u but expected %u\r\n", acknum, pTcb->locSeq); - } - - positionInQuery = seqnum - pTcb->remIsn; - positionInReply = acknum - pTcb->locIsn; - - //Filter out unwanted links - switch (dstPort) + //Calculate positions + positionInQuery = seqnum - pTcb->recvIsn; + positionInReply = acknum - pTcb->sendIsn; + + //Check packet sequences + if (positionInQuery != pTcb->recdBytes || positionInReply != pTcb->sentBytes) { - case 80: - doTrace = HttpTrace; - if (doTrace) - { - if (NetTraceNewLine) Log("\r\n"); - LogTime("HTTP server request\r\n"); - } - break; + if (TcpTrace) + { + if (NetTraceNewLine) Log("\r\n"); + LogTime("TCP received packet"); + if (positionInQuery != pTcb->recdBytes) LogF(": starting at byte %u rather than %u so data reread" , positionInQuery, pTcb->recdBytes); + if (positionInReply != pTcb->sentBytes) LogF(": acknowledging byte %u rather than %u so data resent", positionInReply, pTcb->sentBytes); + Log("\r\n"); - default: - doTrace = TcpTrace; - if (doTrace) - { - if (NetTraceNewLine) Log("\r\n"); - LogTimeF("TCP unknown port %d\r\n", dstPort); - } - return DO_NOTHING; //Ignore unknown ports + if (NetTraceStack) pTraceback(); + doTrace = true; + } + pTcb->recdBytes = positionInQuery; + pTcb->sentBytes = positionInReply; } 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 + if (SYN) pTcb->recdBytes += 1; //Add one to acknowledge the SYN + pTcb->recdBytes += dataLength; //Add the number of bytes received + if (FIN) pTcb->recdBytes += 1; //Add one to acknowledge the FIN switch (pTcb->state) { - case TCB_CLOSED: + case TCB_EMPTY: if (!SYN) { resetConnection("received other than a SYN when connection closed"); break; } startConnection(); break; @@ -356,27 +372,39 @@ return DO_NOTHING; case TCB_ESTABLISHED: - if (!ACK) { resetConnection("received other than an ACK during established conection"); break; } + if (!ACK) { resetConnection("received other than an ACK during established conection"); break; } + if (FIN) pTcb->hadFin = true; //When reply is all sent only a passive close is needed handleEstablishedConnection(); break; - case TCB_CLOSING: + case TCB_FIN_WAIT: //End of active close if (!FIN) return DO_NOTHING; //Ignore ACK to our FIN. Wait for FIN then close. closeConnection(); break; + + case TCB_ACK_WAIT: //End of passive close + if (!ACK) { resetConnection("received other than an ACK when closing half open connection"); break; } + pTcb->state = TCB_EMPTY; + 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 + positionInReply = pTcb->recdBytes; //Set up the acknowledgement field ready to send + positionInQuery = pTcb->sentBytes; //Record the start of the query before adding the bytes sent + + //Keep a record of where we expect the next packet send to start + if (SYN) pTcb->sentBytes += 1; //Add one to acknowledge the SYN + pTcb->sentBytes += dataLength; //Record the next sequence number + if (FIN) pTcb->sentBytes += 1; //Add one to acknowledge the FIN - positionInQuery = seqnum - pTcb->locIsn; - positionInReply = acknum - pTcb->remIsn; + //Specify the start of the data being sent and acknowledge the data received + seqnum = positionInQuery + pTcb->sendIsn; + acknum = positionInReply + pTcb->recvIsn; + //Swap the ports for the reply srcPort = dstPort; dstPort = pTcb->port; + //Calculate the size of the reply *pSize = dataLength + headersize; return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack);