A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Wed Apr 10 10:07:06 2019 +0000
Revision:
140:9000ea70b220
Parent:
133:a37eb35a03f1
Child:
144:6bd5c54efc7d
Added ajax functions to AR4, AR6, NR4, NR6 modules

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