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/tcpsend.c
- 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); + } }