Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Thu Nov 22 17:35:59 2018 +0000
Revision:
90:955f4c6e18a9
Parent:
89:9b765a67699b
Child:
93:580fc113d9e9
Tidied up a lot of TCP

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