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@75:603b10404183, 2018-10-30 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Oct 30 22:11:22 2018 +0000
- Revision:
- 75:603b10404183
- Parent:
- 74:c3756bfa960e
- Child:
- 78:9d8fc88df405
A lot of tidying up and prevented requests other than the first packet from doing anything.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 74:c3756bfa960e | 1 | #include <stdint.h> |
andrewboyson | 74:c3756bfa960e | 2 | #include <stdbool.h> |
andrewboyson | 74:c3756bfa960e | 3 | |
andrewboyson | 74:c3756bfa960e | 4 | #include "log.h" |
andrewboyson | 74:c3756bfa960e | 5 | #include "net.h" |
andrewboyson | 74:c3756bfa960e | 6 | #include "action.h" |
andrewboyson | 74:c3756bfa960e | 7 | #include "tcp.h" |
andrewboyson | 74:c3756bfa960e | 8 | #include "tcphdr.h" |
andrewboyson | 74:c3756bfa960e | 9 | #include "tcb.h" |
andrewboyson | 74:c3756bfa960e | 10 | #include "ip4.h" |
andrewboyson | 74:c3756bfa960e | 11 | #include "dhcp.h" |
andrewboyson | 74:c3756bfa960e | 12 | #include "http.h" |
andrewboyson | 74:c3756bfa960e | 13 | #include "led.h" |
andrewboyson | 74:c3756bfa960e | 14 | #include "tcpsend.h" |
andrewboyson | 74:c3756bfa960e | 15 | |
andrewboyson | 75:603b10404183 | 16 | #define RTO_TIME 2 |
andrewboyson | 74:c3756bfa960e | 17 | |
andrewboyson | 75:603b10404183 | 18 | static int addApplicationData(void* pPacket, uint16_t port, int start, int mss, int todo) |
andrewboyson | 74:c3756bfa960e | 19 | { |
andrewboyson | 74:c3756bfa960e | 20 | int dataLength = 0; |
andrewboyson | 74:c3756bfa960e | 21 | char* pData = (char*)pPacket + TcpHdrSizeGet(); |
andrewboyson | 75:603b10404183 | 22 | switch (port) |
andrewboyson | 74:c3756bfa960e | 23 | { |
andrewboyson | 74:c3756bfa960e | 24 | case 80: |
andrewboyson | 75:603b10404183 | 25 | HttpSendReply(&dataLength, pData, start, mss, todo); |
andrewboyson | 74:c3756bfa960e | 26 | break; |
andrewboyson | 74:c3756bfa960e | 27 | default: |
andrewboyson | 74:c3756bfa960e | 28 | break; |
andrewboyson | 74:c3756bfa960e | 29 | } |
andrewboyson | 75:603b10404183 | 30 | |
andrewboyson | 75:603b10404183 | 31 | return dataLength; |
andrewboyson | 75:603b10404183 | 32 | } |
andrewboyson | 75:603b10404183 | 33 | static int preparePacket(void* pPacket, struct tcb* pTcb, int dataLength, int* pSize) |
andrewboyson | 75:603b10404183 | 34 | { |
andrewboyson | 75:603b10404183 | 35 | //Set the acknowledge flag |
andrewboyson | 75:603b10404183 | 36 | TcpHdrACK = true; |
andrewboyson | 74:c3756bfa960e | 37 | |
andrewboyson | 75:603b10404183 | 38 | //Swap the ports for the reply |
andrewboyson | 75:603b10404183 | 39 | TcpHdrSrcPort = pTcb->locPort; |
andrewboyson | 75:603b10404183 | 40 | TcpHdrDstPort = pTcb->remPort; |
andrewboyson | 75:603b10404183 | 41 | |
andrewboyson | 75:603b10404183 | 42 | //Specify the receive window size to not throttle |
andrewboyson | 75:603b10404183 | 43 | TcpHdrWindow = 4000; |
andrewboyson | 75:603b10404183 | 44 | |
andrewboyson | 75:603b10404183 | 45 | //Write the header |
andrewboyson | 75:603b10404183 | 46 | TcpHdrWriteToPacket(pPacket); |
andrewboyson | 75:603b10404183 | 47 | |
andrewboyson | 75:603b10404183 | 48 | //Calculate the size of the reply |
andrewboyson | 75:603b10404183 | 49 | *pSize = TcpHdrSizeGet() + dataLength; |
andrewboyson | 75:603b10404183 | 50 | |
andrewboyson | 75:603b10404183 | 51 | //Update the last send time |
andrewboyson | 74:c3756bfa960e | 52 | pTcb->lastSendTime = TcbElapsed; |
andrewboyson | 74:c3756bfa960e | 53 | |
andrewboyson | 75:603b10404183 | 54 | return ActionMakeFromDestAndTrace(UNICAST, TcpDoTrace && NetTraceStack); |
andrewboyson | 74:c3756bfa960e | 55 | } |
andrewboyson | 75:603b10404183 | 56 | int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb) |
andrewboyson | 74:c3756bfa960e | 57 | { |
andrewboyson | 74:c3756bfa960e | 58 | int dataLength = 0; |
andrewboyson | 74:c3756bfa960e | 59 | TcpHdrMakeEmpty(); |
andrewboyson | 74:c3756bfa960e | 60 | int locMss = *pSize - TcpHdrSizeGet(); |
andrewboyson | 74:c3756bfa960e | 61 | switch (pTcb->state) |
andrewboyson | 74:c3756bfa960e | 62 | { |
andrewboyson | 74:c3756bfa960e | 63 | case TCB_SYN_RECEIVED: |
andrewboyson | 74:c3756bfa960e | 64 | if (pTcb->bytesSentToRem == 0) |
andrewboyson | 74:c3756bfa960e | 65 | { |
andrewboyson | 74:c3756bfa960e | 66 | TcpHdrMssSet(locMss); |
andrewboyson | 74:c3756bfa960e | 67 | TcpHdrSYN = true; |
andrewboyson | 74:c3756bfa960e | 68 | } |
andrewboyson | 74:c3756bfa960e | 69 | break; |
andrewboyson | 74:c3756bfa960e | 70 | |
andrewboyson | 74:c3756bfa960e | 71 | case TCB_ESTABLISHED: |
andrewboyson | 74:c3756bfa960e | 72 | if (!pTcb->sentFin) |
andrewboyson | 74:c3756bfa960e | 73 | { |
andrewboyson | 74:c3756bfa960e | 74 | if (pTcb->bytesSentToRem - pTcb->bytesAckdByRem < pTcb->window) |
andrewboyson | 74:c3756bfa960e | 75 | { |
andrewboyson | 74:c3756bfa960e | 76 | if (pTcb->todo) |
andrewboyson | 74:c3756bfa960e | 77 | { |
andrewboyson | 75:603b10404183 | 78 | dataLength = addApplicationData(pPacket, pTcb->locPort, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo); |
andrewboyson | 74:c3756bfa960e | 79 | if (dataLength < pTcb->remMss) |
andrewboyson | 74:c3756bfa960e | 80 | { |
andrewboyson | 74:c3756bfa960e | 81 | TcpHdrFIN = true; |
andrewboyson | 74:c3756bfa960e | 82 | pTcb->sentFin = true; |
andrewboyson | 74:c3756bfa960e | 83 | } |
andrewboyson | 74:c3756bfa960e | 84 | } |
andrewboyson | 74:c3756bfa960e | 85 | else |
andrewboyson | 74:c3756bfa960e | 86 | { |
andrewboyson | 74:c3756bfa960e | 87 | if (pTcb->rcvdFin) |
andrewboyson | 74:c3756bfa960e | 88 | { |
andrewboyson | 74:c3756bfa960e | 89 | TcpHdrFIN = true; |
andrewboyson | 74:c3756bfa960e | 90 | pTcb->sentFin = true; |
andrewboyson | 74:c3756bfa960e | 91 | } |
andrewboyson | 74:c3756bfa960e | 92 | } |
andrewboyson | 74:c3756bfa960e | 93 | } |
andrewboyson | 74:c3756bfa960e | 94 | } |
andrewboyson | 74:c3756bfa960e | 95 | break; |
andrewboyson | 74:c3756bfa960e | 96 | } |
andrewboyson | 74:c3756bfa960e | 97 | |
andrewboyson | 74:c3756bfa960e | 98 | //See if have need to acknowledge received bytes |
andrewboyson | 74:c3756bfa960e | 99 | bool rcvdSeqHasAdvanced = pTcb->bytesRcvdFromRem > pTcb->bytesAckdToRem; |
andrewboyson | 74:c3756bfa960e | 100 | |
andrewboyson | 74:c3756bfa960e | 101 | //Record the number of bytes acknowledged to the remote |
andrewboyson | 74:c3756bfa960e | 102 | pTcb->bytesAckdToRem = pTcb->bytesRcvdFromRem; |
andrewboyson | 74:c3756bfa960e | 103 | |
andrewboyson | 74:c3756bfa960e | 104 | //Specify the start of the data being sent and acknowledge the data received |
andrewboyson | 74:c3756bfa960e | 105 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 74:c3756bfa960e | 106 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 74:c3756bfa960e | 107 | |
andrewboyson | 74:c3756bfa960e | 108 | //Record the number of bytes sent |
andrewboyson | 74:c3756bfa960e | 109 | uint32_t bytesToSend = 0; |
andrewboyson | 74:c3756bfa960e | 110 | if (TcpHdrSYN) bytesToSend += 1; //Add one to acknowledge the SYN |
andrewboyson | 74:c3756bfa960e | 111 | bytesToSend += dataLength; //Add the number of bytes received |
andrewboyson | 74:c3756bfa960e | 112 | if (TcpHdrFIN) bytesToSend += 1; //Add one to acknowledge the FIN |
andrewboyson | 74:c3756bfa960e | 113 | |
andrewboyson | 74:c3756bfa960e | 114 | pTcb->bytesSentToRem += bytesToSend; |
andrewboyson | 74:c3756bfa960e | 115 | |
andrewboyson | 75:603b10404183 | 116 | if (!rcvdSeqHasAdvanced && !bytesToSend) return DO_NOTHING; |
andrewboyson | 75:603b10404183 | 117 | |
andrewboyson | 75:603b10404183 | 118 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 119 | } |
andrewboyson | 75:603b10404183 | 120 | int TcpResendLastUnAcked(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 121 | { |
andrewboyson | 75:603b10404183 | 122 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 123 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 124 | int locMss = *pSize - TcpHdrSizeGet(); |
andrewboyson | 75:603b10404183 | 125 | int seqNum = pTcb->bytesAckdByRem; |
andrewboyson | 75:603b10404183 | 126 | switch (pTcb->state) |
andrewboyson | 74:c3756bfa960e | 127 | { |
andrewboyson | 75:603b10404183 | 128 | case TCB_SYN_RECEIVED: |
andrewboyson | 75:603b10404183 | 129 | TcpHdrMssSet(locMss); |
andrewboyson | 75:603b10404183 | 130 | TcpHdrSYN = true; |
andrewboyson | 75:603b10404183 | 131 | break; |
andrewboyson | 74:c3756bfa960e | 132 | |
andrewboyson | 75:603b10404183 | 133 | case TCB_ESTABLISHED: |
andrewboyson | 75:603b10404183 | 134 | if (pTcb->todo) |
andrewboyson | 75:603b10404183 | 135 | { |
andrewboyson | 75:603b10404183 | 136 | dataLength = addApplicationData(pPacket, pTcb->locPort, seqNum, pTcb->remMss, pTcb->todo); |
andrewboyson | 75:603b10404183 | 137 | if (dataLength < pTcb->remMss) |
andrewboyson | 75:603b10404183 | 138 | { |
andrewboyson | 75:603b10404183 | 139 | TcpHdrFIN = true; |
andrewboyson | 75:603b10404183 | 140 | pTcb->sentFin = true; |
andrewboyson | 75:603b10404183 | 141 | } |
andrewboyson | 75:603b10404183 | 142 | } |
andrewboyson | 75:603b10404183 | 143 | break; |
andrewboyson | 74:c3756bfa960e | 144 | } |
andrewboyson | 75:603b10404183 | 145 | |
andrewboyson | 75:603b10404183 | 146 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 147 | TcpHdrSeqNum = seqNum + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 75:603b10404183 | 148 | |
andrewboyson | 75:603b10404183 | 149 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 150 | } |
andrewboyson | 75:603b10404183 | 151 | int TcpResendLastAck(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 152 | { |
andrewboyson | 75:603b10404183 | 153 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 154 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 155 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 156 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 75:603b10404183 | 157 | |
andrewboyson | 75:603b10404183 | 158 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 159 | } |
andrewboyson | 75:603b10404183 | 160 | int TcpSendReset(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 161 | { |
andrewboyson | 75:603b10404183 | 162 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 163 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 164 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 165 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 75:603b10404183 | 166 | |
andrewboyson | 75:603b10404183 | 167 | TcpHdrRST = true; |
andrewboyson | 75:603b10404183 | 168 | |
andrewboyson | 75:603b10404183 | 169 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 74:c3756bfa960e | 170 | } |
andrewboyson | 74:c3756bfa960e | 171 | int TcpPollForPacketToSend(int* pSize, void* pPacket, int ipType, int* pRemArIndex) |
andrewboyson | 74:c3756bfa960e | 172 | { |
andrewboyson | 74:c3756bfa960e | 173 | struct tcb* pTcb = TcbGetNext(); //This loops around the TCBs |
andrewboyson | 74:c3756bfa960e | 174 | if (pTcb->ipType != ipType) return DO_NOTHING; |
andrewboyson | 74:c3756bfa960e | 175 | *pRemArIndex = pTcb->remArIndex; |
andrewboyson | 75:603b10404183 | 176 | |
andrewboyson | 75:603b10404183 | 177 | //Check if have unacknowledged bytes longer than a time out |
andrewboyson | 75:603b10404183 | 178 | if (TcbElapsed - pTcb->lastSendTime > RTO_TIME && pTcb->bytesSentToRem > pTcb->bytesAckdByRem) |
andrewboyson | 75:603b10404183 | 179 | { |
andrewboyson | 75:603b10404183 | 180 | return TcpResendLastUnAcked(pSize, pPacket, pTcb); |
andrewboyson | 75:603b10404183 | 181 | } |
andrewboyson | 75:603b10404183 | 182 | //Otherwise do a normal send |
andrewboyson | 75:603b10404183 | 183 | else |
andrewboyson | 75:603b10404183 | 184 | { |
andrewboyson | 75:603b10404183 | 185 | return TcpSend(pSize, pPacket, pTcb); |
andrewboyson | 75:603b10404183 | 186 | } |
andrewboyson | 74:c3756bfa960e | 187 | } |
andrewboyson | 74:c3756bfa960e | 188 |