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@89:9b765a67699b, 2018-11-21 (annotated)
- Committer:
- andrewboyson
- Date:
- Wed Nov 21 17:13:04 2018 +0000
- Revision:
- 89:9b765a67699b
- Parent:
- 88:1ba13e6062a3
- Child:
- 90:955f4c6e18a9
Tidied up the stack traces
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 | 79:f50e02fb5c94 | 16 | #define TIMEOUT_RETRANSMISSION 2 |
andrewboyson | 82:20781198d26d | 17 | #define MAX_RETRANSMISSIONS 10 |
andrewboyson | 79:f50e02fb5c94 | 18 | #define TIMEOUT_BROKEN_LINK 600 |
andrewboyson | 74:c3756bfa960e | 19 | |
andrewboyson | 88:1ba13e6062a3 | 20 | static bool doTrace(uint16_t port) |
andrewboyson | 88:1ba13e6062a3 | 21 | { |
andrewboyson | 88:1ba13e6062a3 | 22 | switch (port) |
andrewboyson | 88:1ba13e6062a3 | 23 | { |
andrewboyson | 88:1ba13e6062a3 | 24 | case 80: |
andrewboyson | 88:1ba13e6062a3 | 25 | if (HttpTrace) return true; |
andrewboyson | 88:1ba13e6062a3 | 26 | default: |
andrewboyson | 88:1ba13e6062a3 | 27 | return false; |
andrewboyson | 88:1ba13e6062a3 | 28 | } |
andrewboyson | 88:1ba13e6062a3 | 29 | } |
andrewboyson | 79:f50e02fb5c94 | 30 | static int addApplicationData(void* pPacket, uint16_t port, uint32_t start, int mss, int todo) |
andrewboyson | 74:c3756bfa960e | 31 | { |
andrewboyson | 74:c3756bfa960e | 32 | int dataLength = 0; |
andrewboyson | 74:c3756bfa960e | 33 | char* pData = (char*)pPacket + TcpHdrSizeGet(); |
andrewboyson | 75:603b10404183 | 34 | switch (port) |
andrewboyson | 74:c3756bfa960e | 35 | { |
andrewboyson | 74:c3756bfa960e | 36 | case 80: |
andrewboyson | 75:603b10404183 | 37 | HttpSendReply(&dataLength, pData, start, mss, todo); |
andrewboyson | 74:c3756bfa960e | 38 | break; |
andrewboyson | 74:c3756bfa960e | 39 | default: |
andrewboyson | 74:c3756bfa960e | 40 | break; |
andrewboyson | 74:c3756bfa960e | 41 | } |
andrewboyson | 75:603b10404183 | 42 | |
andrewboyson | 75:603b10404183 | 43 | return dataLength; |
andrewboyson | 75:603b10404183 | 44 | } |
andrewboyson | 89:9b765a67699b | 45 | static int preparePacket(void* pPacket, struct tcb* pTcb, int dataLength, int* pSize) |
andrewboyson | 75:603b10404183 | 46 | { |
andrewboyson | 75:603b10404183 | 47 | //Set the acknowledge flag |
andrewboyson | 75:603b10404183 | 48 | TcpHdrACK = true; |
andrewboyson | 74:c3756bfa960e | 49 | |
andrewboyson | 75:603b10404183 | 50 | //Swap the ports for the reply |
andrewboyson | 89:9b765a67699b | 51 | TcpHdrSrcPort = pTcb->locPort; |
andrewboyson | 89:9b765a67699b | 52 | TcpHdrDstPort = pTcb->remPort; |
andrewboyson | 75:603b10404183 | 53 | |
andrewboyson | 75:603b10404183 | 54 | //Specify the receive window size to not throttle |
andrewboyson | 75:603b10404183 | 55 | TcpHdrWindow = 4000; |
andrewboyson | 75:603b10404183 | 56 | |
andrewboyson | 75:603b10404183 | 57 | //Write the header |
andrewboyson | 75:603b10404183 | 58 | TcpHdrWriteToPacket(pPacket); |
andrewboyson | 75:603b10404183 | 59 | |
andrewboyson | 75:603b10404183 | 60 | //Calculate the size of the reply |
andrewboyson | 75:603b10404183 | 61 | *pSize = TcpHdrSizeGet() + dataLength; |
andrewboyson | 75:603b10404183 | 62 | |
andrewboyson | 89:9b765a67699b | 63 | return ActionMakeFromDestAndTrace(UNICAST, doTrace(pTcb->locPort) && NetTraceStack); |
andrewboyson | 74:c3756bfa960e | 64 | } |
andrewboyson | 75:603b10404183 | 65 | int TcpSend(int* pSize, void* pPacket, struct tcb* pTcb) |
andrewboyson | 74:c3756bfa960e | 66 | { |
andrewboyson | 74:c3756bfa960e | 67 | int dataLength = 0; |
andrewboyson | 74:c3756bfa960e | 68 | TcpHdrMakeEmpty(); |
andrewboyson | 74:c3756bfa960e | 69 | int locMss = *pSize - TcpHdrSizeGet(); |
andrewboyson | 74:c3756bfa960e | 70 | switch (pTcb->state) |
andrewboyson | 74:c3756bfa960e | 71 | { |
andrewboyson | 74:c3756bfa960e | 72 | case TCB_SYN_RECEIVED: |
andrewboyson | 74:c3756bfa960e | 73 | if (pTcb->bytesSentToRem == 0) |
andrewboyson | 74:c3756bfa960e | 74 | { |
andrewboyson | 74:c3756bfa960e | 75 | TcpHdrMssSet(locMss); |
andrewboyson | 74:c3756bfa960e | 76 | TcpHdrSYN = true; |
andrewboyson | 74:c3756bfa960e | 77 | } |
andrewboyson | 74:c3756bfa960e | 78 | break; |
andrewboyson | 74:c3756bfa960e | 79 | |
andrewboyson | 74:c3756bfa960e | 80 | case TCB_ESTABLISHED: |
andrewboyson | 74:c3756bfa960e | 81 | if (!pTcb->sentFin) |
andrewboyson | 74:c3756bfa960e | 82 | { |
andrewboyson | 74:c3756bfa960e | 83 | if (pTcb->bytesSentToRem - pTcb->bytesAckdByRem < pTcb->window) |
andrewboyson | 74:c3756bfa960e | 84 | { |
andrewboyson | 74:c3756bfa960e | 85 | if (pTcb->todo) |
andrewboyson | 74:c3756bfa960e | 86 | { |
andrewboyson | 75:603b10404183 | 87 | dataLength = addApplicationData(pPacket, pTcb->locPort, pTcb->bytesSentToRem - 1, pTcb->remMss, pTcb->todo); |
andrewboyson | 74:c3756bfa960e | 88 | if (dataLength < pTcb->remMss) |
andrewboyson | 74:c3756bfa960e | 89 | { |
andrewboyson | 74:c3756bfa960e | 90 | TcpHdrFIN = true; |
andrewboyson | 74:c3756bfa960e | 91 | pTcb->sentFin = true; |
andrewboyson | 74:c3756bfa960e | 92 | } |
andrewboyson | 74:c3756bfa960e | 93 | } |
andrewboyson | 74:c3756bfa960e | 94 | else |
andrewboyson | 74:c3756bfa960e | 95 | { |
andrewboyson | 74:c3756bfa960e | 96 | if (pTcb->rcvdFin) |
andrewboyson | 74:c3756bfa960e | 97 | { |
andrewboyson | 74:c3756bfa960e | 98 | TcpHdrFIN = true; |
andrewboyson | 74:c3756bfa960e | 99 | pTcb->sentFin = true; |
andrewboyson | 74:c3756bfa960e | 100 | } |
andrewboyson | 74:c3756bfa960e | 101 | } |
andrewboyson | 74:c3756bfa960e | 102 | } |
andrewboyson | 74:c3756bfa960e | 103 | } |
andrewboyson | 74:c3756bfa960e | 104 | break; |
andrewboyson | 74:c3756bfa960e | 105 | } |
andrewboyson | 74:c3756bfa960e | 106 | |
andrewboyson | 79:f50e02fb5c94 | 107 | //Handle the acknowledgement of received bytes |
andrewboyson | 74:c3756bfa960e | 108 | bool rcvdSeqHasAdvanced = pTcb->bytesRcvdFromRem > pTcb->bytesAckdToRem; |
andrewboyson | 74:c3756bfa960e | 109 | pTcb->bytesAckdToRem = pTcb->bytesRcvdFromRem; |
andrewboyson | 79:f50e02fb5c94 | 110 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 74:c3756bfa960e | 111 | |
andrewboyson | 79:f50e02fb5c94 | 112 | //Specify the start of the data being sent |
andrewboyson | 79:f50e02fb5c94 | 113 | uint32_t seqToSend = pTcb->bytesSentToRem; |
andrewboyson | 79:f50e02fb5c94 | 114 | TcpHdrSeqNum = seqToSend + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 74:c3756bfa960e | 115 | |
andrewboyson | 74:c3756bfa960e | 116 | //Record the number of bytes sent |
andrewboyson | 74:c3756bfa960e | 117 | uint32_t bytesToSend = 0; |
andrewboyson | 74:c3756bfa960e | 118 | if (TcpHdrSYN) bytesToSend += 1; //Add one to acknowledge the SYN |
andrewboyson | 74:c3756bfa960e | 119 | bytesToSend += dataLength; //Add the number of bytes received |
andrewboyson | 74:c3756bfa960e | 120 | if (TcpHdrFIN) bytesToSend += 1; //Add one to acknowledge the FIN |
andrewboyson | 74:c3756bfa960e | 121 | |
andrewboyson | 74:c3756bfa960e | 122 | pTcb->bytesSentToRem += bytesToSend; |
andrewboyson | 74:c3756bfa960e | 123 | |
andrewboyson | 79:f50e02fb5c94 | 124 | //Only send a packet if have bytes or an acknowledgement to send |
andrewboyson | 75:603b10404183 | 125 | if (!rcvdSeqHasAdvanced && !bytesToSend) return DO_NOTHING; |
andrewboyson | 79:f50e02fb5c94 | 126 | |
andrewboyson | 89:9b765a67699b | 127 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 128 | } |
andrewboyson | 75:603b10404183 | 129 | int TcpResendLastUnAcked(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 130 | { |
andrewboyson | 75:603b10404183 | 131 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 132 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 133 | int locMss = *pSize - TcpHdrSizeGet(); |
andrewboyson | 79:f50e02fb5c94 | 134 | uint32_t seqNum = pTcb->bytesAckdByRem; |
andrewboyson | 75:603b10404183 | 135 | switch (pTcb->state) |
andrewboyson | 74:c3756bfa960e | 136 | { |
andrewboyson | 75:603b10404183 | 137 | case TCB_SYN_RECEIVED: |
andrewboyson | 75:603b10404183 | 138 | TcpHdrMssSet(locMss); |
andrewboyson | 75:603b10404183 | 139 | TcpHdrSYN = true; |
andrewboyson | 75:603b10404183 | 140 | break; |
andrewboyson | 74:c3756bfa960e | 141 | |
andrewboyson | 75:603b10404183 | 142 | case TCB_ESTABLISHED: |
andrewboyson | 79:f50e02fb5c94 | 143 | case TCB_CLOSE_FIN_WAIT: |
andrewboyson | 75:603b10404183 | 144 | if (pTcb->todo) |
andrewboyson | 75:603b10404183 | 145 | { |
andrewboyson | 79:f50e02fb5c94 | 146 | dataLength = addApplicationData(pPacket, pTcb->locPort, seqNum - 1, pTcb->remMss, pTcb->todo); |
andrewboyson | 75:603b10404183 | 147 | if (dataLength < pTcb->remMss) |
andrewboyson | 75:603b10404183 | 148 | { |
andrewboyson | 75:603b10404183 | 149 | TcpHdrFIN = true; |
andrewboyson | 75:603b10404183 | 150 | pTcb->sentFin = true; |
andrewboyson | 75:603b10404183 | 151 | } |
andrewboyson | 75:603b10404183 | 152 | } |
andrewboyson | 75:603b10404183 | 153 | break; |
andrewboyson | 74:c3756bfa960e | 154 | } |
andrewboyson | 75:603b10404183 | 155 | |
andrewboyson | 75:603b10404183 | 156 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 157 | TcpHdrSeqNum = seqNum + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 79:f50e02fb5c94 | 158 | |
andrewboyson | 89:9b765a67699b | 159 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 160 | } |
andrewboyson | 75:603b10404183 | 161 | int TcpResendLastAck(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 162 | { |
andrewboyson | 75:603b10404183 | 163 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 164 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 165 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 166 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 75:603b10404183 | 167 | |
andrewboyson | 89:9b765a67699b | 168 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 75:603b10404183 | 169 | } |
andrewboyson | 75:603b10404183 | 170 | int TcpSendReset(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 75:603b10404183 | 171 | { |
andrewboyson | 75:603b10404183 | 172 | int dataLength = 0; |
andrewboyson | 75:603b10404183 | 173 | TcpHdrMakeEmpty(); |
andrewboyson | 75:603b10404183 | 174 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 75:603b10404183 | 175 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 75:603b10404183 | 176 | |
andrewboyson | 75:603b10404183 | 177 | TcpHdrRST = true; |
andrewboyson | 75:603b10404183 | 178 | |
andrewboyson | 89:9b765a67699b | 179 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 74:c3756bfa960e | 180 | } |
andrewboyson | 79:f50e02fb5c94 | 181 | int TcpSendClose(int* pSize, void *pPacket, struct tcb* pTcb) |
andrewboyson | 79:f50e02fb5c94 | 182 | { |
andrewboyson | 79:f50e02fb5c94 | 183 | int dataLength = 0; |
andrewboyson | 79:f50e02fb5c94 | 184 | TcpHdrMakeEmpty(); |
andrewboyson | 79:f50e02fb5c94 | 185 | TcpHdrFIN = true; |
andrewboyson | 79:f50e02fb5c94 | 186 | pTcb->sentFin = true; |
andrewboyson | 79:f50e02fb5c94 | 187 | pTcb->bytesSentToRem += 1; //For the FIN |
andrewboyson | 79:f50e02fb5c94 | 188 | TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send |
andrewboyson | 79:f50e02fb5c94 | 189 | TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent |
andrewboyson | 79:f50e02fb5c94 | 190 | |
andrewboyson | 89:9b765a67699b | 191 | return preparePacket(pPacket, pTcb, dataLength, pSize); |
andrewboyson | 79:f50e02fb5c94 | 192 | } |
andrewboyson | 79:f50e02fb5c94 | 193 | |
andrewboyson | 80:4ef1500fca1d | 194 | int TcpPollForPacketToSend(int* pSize, void* pPacket, int ipType, int* pRemArIndex, int* pLocIpScope) |
andrewboyson | 74:c3756bfa960e | 195 | { |
andrewboyson | 83:08c983006a6e | 196 | //Loops around the TCBs, moving on if empty but staying if not the right type |
andrewboyson | 79:f50e02fb5c94 | 197 | static struct tcb* pTcb = NULL; //Passing a pointer containing NULL to TcbGetNext causes it to return the first TCB |
andrewboyson | 79:f50e02fb5c94 | 198 | static bool stay = false; |
andrewboyson | 83:08c983006a6e | 199 | if (!stay) pTcb = TcbGetNext(pTcb); |
andrewboyson | 79:f50e02fb5c94 | 200 | stay = false; |
andrewboyson | 78:9d8fc88df405 | 201 | if (!pTcb->state) return DO_NOTHING; |
andrewboyson | 79:f50e02fb5c94 | 202 | if (pTcb->ipType != ipType) |
andrewboyson | 79:f50e02fb5c94 | 203 | { |
andrewboyson | 79:f50e02fb5c94 | 204 | stay = true; |
andrewboyson | 79:f50e02fb5c94 | 205 | return DO_NOTHING; |
andrewboyson | 79:f50e02fb5c94 | 206 | } |
andrewboyson | 79:f50e02fb5c94 | 207 | |
andrewboyson | 79:f50e02fb5c94 | 208 | //Check and make available the remote AR index |
andrewboyson | 79:f50e02fb5c94 | 209 | if (pTcb->remArIndex < 0) |
andrewboyson | 79:f50e02fb5c94 | 210 | { |
andrewboyson | 79:f50e02fb5c94 | 211 | if (TcpTrace) LogTimeF("TCP - Reaping TCB port %hu - missing remote AR index\r\n", pTcb->remPort); |
andrewboyson | 79:f50e02fb5c94 | 212 | pTcb->state = TCB_EMPTY; |
andrewboyson | 79:f50e02fb5c94 | 213 | return DO_NOTHING; |
andrewboyson | 79:f50e02fb5c94 | 214 | } |
andrewboyson | 79:f50e02fb5c94 | 215 | *pRemArIndex = pTcb->remArIndex; |
andrewboyson | 80:4ef1500fca1d | 216 | |
andrewboyson | 80:4ef1500fca1d | 217 | //Return the local IP scope |
andrewboyson | 80:4ef1500fca1d | 218 | if (pLocIpScope) *pLocIpScope = pTcb->locIpScope; |
andrewboyson | 87:40d46a979cdb | 219 | |
andrewboyson | 79:f50e02fb5c94 | 220 | //Reap old ones |
andrewboyson | 82:20781198d26d | 221 | if (TcbElapsed >= pTcb->timeLastRcvd + TIMEOUT_BROKEN_LINK) |
andrewboyson | 79:f50e02fb5c94 | 222 | { |
andrewboyson | 79:f50e02fb5c94 | 223 | if (TcpTrace) LogTimeF("TCP - Reaping TCB port %hu - broken link\r\n", pTcb->remPort); |
andrewboyson | 79:f50e02fb5c94 | 224 | pTcb->state = TCB_EMPTY; |
andrewboyson | 79:f50e02fb5c94 | 225 | return DO_NOTHING; |
andrewboyson | 79:f50e02fb5c94 | 226 | } |
andrewboyson | 78:9d8fc88df405 | 227 | |
andrewboyson | 79:f50e02fb5c94 | 228 | //Reset the RTO if all bytes are acknowledged |
andrewboyson | 79:f50e02fb5c94 | 229 | if (pTcb->bytesSentToRem == pTcb->bytesAckdByRem) |
andrewboyson | 79:f50e02fb5c94 | 230 | { |
andrewboyson | 79:f50e02fb5c94 | 231 | pTcb->timeSendsBeingAcked = TcbElapsed; |
andrewboyson | 82:20781198d26d | 232 | pTcb->countSendsNotAcked = 0; |
andrewboyson | 79:f50e02fb5c94 | 233 | } |
andrewboyson | 75:603b10404183 | 234 | |
andrewboyson | 79:f50e02fb5c94 | 235 | //Check if have unacknowledged send bytes after the RTO |
andrewboyson | 82:20781198d26d | 236 | if (TcbElapsed >= pTcb->timeSendsBeingAcked + TIMEOUT_RETRANSMISSION) |
andrewboyson | 75:603b10404183 | 237 | { |
andrewboyson | 82:20781198d26d | 238 | pTcb->countSendsNotAcked++; |
andrewboyson | 82:20781198d26d | 239 | if (pTcb->countSendsNotAcked > MAX_RETRANSMISSIONS) |
andrewboyson | 82:20781198d26d | 240 | { |
andrewboyson | 82:20781198d26d | 241 | if (TcpTrace) |
andrewboyson | 82:20781198d26d | 242 | { |
andrewboyson | 82:20781198d26d | 243 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 82:20781198d26d | 244 | LogTimeF("TCP - Resending seq %lu on port %hu reached maximum retransmissions\r\n", pTcb->bytesAckdByRem, pTcb->remPort); |
andrewboyson | 82:20781198d26d | 245 | pTcb->state = TCB_EMPTY; |
andrewboyson | 82:20781198d26d | 246 | return TcpSendReset(pSize, pPacket, pTcb); |
andrewboyson | 82:20781198d26d | 247 | } |
andrewboyson | 82:20781198d26d | 248 | } |
andrewboyson | 79:f50e02fb5c94 | 249 | if (TcpTrace) |
andrewboyson | 79:f50e02fb5c94 | 250 | { |
andrewboyson | 79:f50e02fb5c94 | 251 | if (NetTraceNewLine) Log("\r\n"); |
andrewboyson | 79:f50e02fb5c94 | 252 | LogTimeF("TCP - Resending seq %lu on port %hu waiting for ack of %lu bytes\r\n", pTcb->bytesAckdByRem, pTcb->remPort, pTcb->bytesSentToRem); |
andrewboyson | 79:f50e02fb5c94 | 253 | } |
andrewboyson | 79:f50e02fb5c94 | 254 | pTcb->timeSendsBeingAcked = TcbElapsed; |
andrewboyson | 75:603b10404183 | 255 | return TcpResendLastUnAcked(pSize, pPacket, pTcb); |
andrewboyson | 75:603b10404183 | 256 | } |
andrewboyson | 79:f50e02fb5c94 | 257 | |
andrewboyson | 79:f50e02fb5c94 | 258 | //If haven't had to do anything else then do a normal send |
andrewboyson | 79:f50e02fb5c94 | 259 | return TcpSend(pSize, pPacket, pTcb); |
andrewboyson | 74:c3756bfa960e | 260 | } |
andrewboyson | 74:c3756bfa960e | 261 |