Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

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?

UserRevisionLine numberNew 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