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
tcp/tcpsend.c
- Committer:
- andrewboyson
- Date:
- 2018-11-05
- Revision:
- 78:9d8fc88df405
- Parent:
- 75:603b10404183
- Child:
- 79:f50e02fb5c94
File content as of revision 78:9d8fc88df405:
#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" #define RTO_TIME 2 static int addApplicationData(void* pPacket, uint16_t port, int start, int mss, int todo) { int dataLength = 0; char* pData = (char*)pPacket + TcpHdrSizeGet(); switch (port) { case 80: 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 ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack); } int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb) { 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 = addApplicationData(pPacket, pTcb->locPort, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo); 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) 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) { case TCB_SYN_RECEIVED: TcpHdrMssSet(locMss); TcpHdrSYN = true; break; 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; } 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) { //This loops around the TCBs //struct tcb* pTcb = TcbGetOld(); static struct tcb* pTcb = NULL; //Passing a pointer containing NULL to TcbGetNext causes it to return the first TCB TcbGetNext(&pTcb); //Ignore empty TCBs if (!pTcb->state) return DO_NOTHING; //Ignore TCBs of a different IP type if (pTcb->ipType != ipType) return DO_NOTHING; //Return the remote AR index *pRemArIndex = pTcb->remArIndex; //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); } }