Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Sat Nov 17 15:49:03 2018 +0000
Revision:
83:08c983006a6e
Parent:
82:20781198d26d
Child:
87:40d46a979cdb
Added "send requests via IPv4" toggles for DNS, NTP and TFTP.

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_KEEP_ALIVE 60
andrewboyson 79:f50e02fb5c94 19 #define TIMEOUT_BROKEN_LINK 600
andrewboyson 74:c3756bfa960e 20
andrewboyson 79:f50e02fb5c94 21 static int addApplicationData(void* pPacket, uint16_t port, uint32_t start, int mss, int todo)
andrewboyson 74:c3756bfa960e 22 {
andrewboyson 74:c3756bfa960e 23 int dataLength = 0;
andrewboyson 74:c3756bfa960e 24 char* pData = (char*)pPacket + TcpHdrSizeGet();
andrewboyson 75:603b10404183 25 switch (port)
andrewboyson 74:c3756bfa960e 26 {
andrewboyson 74:c3756bfa960e 27 case 80:
andrewboyson 75:603b10404183 28 HttpSendReply(&dataLength, pData, start, mss, todo);
andrewboyson 74:c3756bfa960e 29 break;
andrewboyson 74:c3756bfa960e 30 default:
andrewboyson 74:c3756bfa960e 31 break;
andrewboyson 74:c3756bfa960e 32 }
andrewboyson 75:603b10404183 33
andrewboyson 75:603b10404183 34 return dataLength;
andrewboyson 75:603b10404183 35 }
andrewboyson 75:603b10404183 36 static int preparePacket(void* pPacket, struct tcb* pTcb, int dataLength, int* pSize)
andrewboyson 75:603b10404183 37 {
andrewboyson 75:603b10404183 38 //Set the acknowledge flag
andrewboyson 75:603b10404183 39 TcpHdrACK = true;
andrewboyson 74:c3756bfa960e 40
andrewboyson 75:603b10404183 41 //Swap the ports for the reply
andrewboyson 75:603b10404183 42 TcpHdrSrcPort = pTcb->locPort;
andrewboyson 75:603b10404183 43 TcpHdrDstPort = pTcb->remPort;
andrewboyson 75:603b10404183 44
andrewboyson 75:603b10404183 45 //Specify the receive window size to not throttle
andrewboyson 75:603b10404183 46 TcpHdrWindow = 4000;
andrewboyson 75:603b10404183 47
andrewboyson 75:603b10404183 48 //Write the header
andrewboyson 75:603b10404183 49 TcpHdrWriteToPacket(pPacket);
andrewboyson 75:603b10404183 50
andrewboyson 75:603b10404183 51 //Calculate the size of the reply
andrewboyson 75:603b10404183 52 *pSize = TcpHdrSizeGet() + dataLength;
andrewboyson 75:603b10404183 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 79:f50e02fb5c94 98 //Handle the acknowledgement of received bytes
andrewboyson 74:c3756bfa960e 99 bool rcvdSeqHasAdvanced = pTcb->bytesRcvdFromRem > pTcb->bytesAckdToRem;
andrewboyson 74:c3756bfa960e 100 pTcb->bytesAckdToRem = pTcb->bytesRcvdFromRem;
andrewboyson 79:f50e02fb5c94 101 TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send
andrewboyson 74:c3756bfa960e 102
andrewboyson 79:f50e02fb5c94 103 //Specify the start of the data being sent
andrewboyson 79:f50e02fb5c94 104 uint32_t seqToSend = pTcb->bytesSentToRem;
andrewboyson 79:f50e02fb5c94 105 TcpHdrSeqNum = seqToSend + pTcb->locIsn; //Set up the start of the message before adding the bytes sent
andrewboyson 74:c3756bfa960e 106
andrewboyson 74:c3756bfa960e 107 //Record the number of bytes sent
andrewboyson 74:c3756bfa960e 108 uint32_t bytesToSend = 0;
andrewboyson 74:c3756bfa960e 109 if (TcpHdrSYN) bytesToSend += 1; //Add one to acknowledge the SYN
andrewboyson 74:c3756bfa960e 110 bytesToSend += dataLength; //Add the number of bytes received
andrewboyson 74:c3756bfa960e 111 if (TcpHdrFIN) bytesToSend += 1; //Add one to acknowledge the FIN
andrewboyson 74:c3756bfa960e 112
andrewboyson 74:c3756bfa960e 113 pTcb->bytesSentToRem += bytesToSend;
andrewboyson 74:c3756bfa960e 114
andrewboyson 79:f50e02fb5c94 115 //Only send a packet if have bytes or an acknowledgement to send
andrewboyson 75:603b10404183 116 if (!rcvdSeqHasAdvanced && !bytesToSend) return DO_NOTHING;
andrewboyson 79:f50e02fb5c94 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 79:f50e02fb5c94 125 uint32_t 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 79:f50e02fb5c94 134 case TCB_CLOSE_FIN_WAIT:
andrewboyson 75:603b10404183 135 if (pTcb->todo)
andrewboyson 75:603b10404183 136 {
andrewboyson 79:f50e02fb5c94 137 dataLength = addApplicationData(pPacket, pTcb->locPort, seqNum - 1, pTcb->remMss, pTcb->todo);
andrewboyson 75:603b10404183 138 if (dataLength < pTcb->remMss)
andrewboyson 75:603b10404183 139 {
andrewboyson 75:603b10404183 140 TcpHdrFIN = true;
andrewboyson 75:603b10404183 141 pTcb->sentFin = true;
andrewboyson 75:603b10404183 142 }
andrewboyson 75:603b10404183 143 }
andrewboyson 75:603b10404183 144 break;
andrewboyson 74:c3756bfa960e 145 }
andrewboyson 75:603b10404183 146
andrewboyson 75:603b10404183 147 TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send
andrewboyson 75:603b10404183 148 TcpHdrSeqNum = seqNum + pTcb->locIsn; //Set up the start of the message before adding the bytes sent
andrewboyson 79:f50e02fb5c94 149
andrewboyson 75:603b10404183 150 return preparePacket(pPacket, pTcb, dataLength, pSize);
andrewboyson 75:603b10404183 151 }
andrewboyson 75:603b10404183 152 int TcpResendLastAck(int* pSize, void *pPacket, struct tcb* pTcb)
andrewboyson 75:603b10404183 153 {
andrewboyson 75:603b10404183 154 int dataLength = 0;
andrewboyson 75:603b10404183 155 TcpHdrMakeEmpty();
andrewboyson 75:603b10404183 156 TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send
andrewboyson 75:603b10404183 157 TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent
andrewboyson 75:603b10404183 158
andrewboyson 75:603b10404183 159 return preparePacket(pPacket, pTcb, dataLength, pSize);
andrewboyson 75:603b10404183 160 }
andrewboyson 75:603b10404183 161 int TcpSendReset(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 75:603b10404183 168 TcpHdrRST = true;
andrewboyson 75:603b10404183 169
andrewboyson 75:603b10404183 170 return preparePacket(pPacket, pTcb, dataLength, pSize);
andrewboyson 74:c3756bfa960e 171 }
andrewboyson 79:f50e02fb5c94 172 int TcpSendClose(int* pSize, void *pPacket, struct tcb* pTcb)
andrewboyson 79:f50e02fb5c94 173 {
andrewboyson 79:f50e02fb5c94 174 int dataLength = 0;
andrewboyson 79:f50e02fb5c94 175 TcpHdrMakeEmpty();
andrewboyson 79:f50e02fb5c94 176 TcpHdrFIN = true;
andrewboyson 79:f50e02fb5c94 177 pTcb->sentFin = true;
andrewboyson 79:f50e02fb5c94 178 pTcb->bytesSentToRem += 1; //For the FIN
andrewboyson 79:f50e02fb5c94 179 TcpHdrAckNum = pTcb->bytesAckdToRem + pTcb->remIsn; //Set up the acknowledgement field ready to send
andrewboyson 79:f50e02fb5c94 180 TcpHdrSeqNum = pTcb->bytesSentToRem + pTcb->locIsn; //Set up the start of the message before adding the bytes sent
andrewboyson 79:f50e02fb5c94 181
andrewboyson 79:f50e02fb5c94 182 return preparePacket(pPacket, pTcb, dataLength, pSize);
andrewboyson 79:f50e02fb5c94 183 }
andrewboyson 79:f50e02fb5c94 184
andrewboyson 80:4ef1500fca1d 185 int TcpPollForPacketToSend(int* pSize, void* pPacket, int ipType, int* pRemArIndex, int* pLocIpScope)
andrewboyson 74:c3756bfa960e 186 {
andrewboyson 83:08c983006a6e 187 //Loops around the TCBs, moving on if empty but staying if not the right type
andrewboyson 79:f50e02fb5c94 188 static struct tcb* pTcb = NULL; //Passing a pointer containing NULL to TcbGetNext causes it to return the first TCB
andrewboyson 79:f50e02fb5c94 189 static bool stay = false;
andrewboyson 83:08c983006a6e 190 if (!stay) pTcb = TcbGetNext(pTcb);
andrewboyson 79:f50e02fb5c94 191 stay = false;
andrewboyson 78:9d8fc88df405 192 if (!pTcb->state) return DO_NOTHING;
andrewboyson 79:f50e02fb5c94 193 if (pTcb->ipType != ipType)
andrewboyson 79:f50e02fb5c94 194 {
andrewboyson 79:f50e02fb5c94 195 stay = true;
andrewboyson 79:f50e02fb5c94 196 return DO_NOTHING;
andrewboyson 79:f50e02fb5c94 197 }
andrewboyson 79:f50e02fb5c94 198
andrewboyson 79:f50e02fb5c94 199 //Check and make available the remote AR index
andrewboyson 79:f50e02fb5c94 200 if (pTcb->remArIndex < 0)
andrewboyson 79:f50e02fb5c94 201 {
andrewboyson 79:f50e02fb5c94 202 if (TcpTrace) LogTimeF("TCP - Reaping TCB port %hu - missing remote AR index\r\n", pTcb->remPort);
andrewboyson 79:f50e02fb5c94 203 pTcb->state = TCB_EMPTY;
andrewboyson 79:f50e02fb5c94 204 return DO_NOTHING;
andrewboyson 79:f50e02fb5c94 205 }
andrewboyson 79:f50e02fb5c94 206 *pRemArIndex = pTcb->remArIndex;
andrewboyson 80:4ef1500fca1d 207
andrewboyson 80:4ef1500fca1d 208 //Return the local IP scope
andrewboyson 80:4ef1500fca1d 209 if (pLocIpScope) *pLocIpScope = pTcb->locIpScope;
andrewboyson 79:f50e02fb5c94 210
andrewboyson 79:f50e02fb5c94 211 //Close old ones
andrewboyson 82:20781198d26d 212 if (TcbElapsed >= pTcb->timeLastRcvd + TIMEOUT_KEEP_ALIVE)
andrewboyson 79:f50e02fb5c94 213 {
andrewboyson 79:f50e02fb5c94 214 if (TcpTrace) LogTimeF("TCP - Closing TCB port %hu - after keep alive\r\n", pTcb->remPort);
andrewboyson 79:f50e02fb5c94 215 return TcpSendClose(pSize, pPacket, pTcb);
andrewboyson 79:f50e02fb5c94 216 }
andrewboyson 78:9d8fc88df405 217
andrewboyson 79:f50e02fb5c94 218 //Reap old ones
andrewboyson 82:20781198d26d 219 if (TcbElapsed >= pTcb->timeLastRcvd + TIMEOUT_BROKEN_LINK)
andrewboyson 79:f50e02fb5c94 220 {
andrewboyson 79:f50e02fb5c94 221 if (TcpTrace) LogTimeF("TCP - Reaping TCB port %hu - broken link\r\n", pTcb->remPort);
andrewboyson 79:f50e02fb5c94 222 pTcb->state = TCB_EMPTY;
andrewboyson 79:f50e02fb5c94 223 return DO_NOTHING;
andrewboyson 79:f50e02fb5c94 224 }
andrewboyson 78:9d8fc88df405 225
andrewboyson 79:f50e02fb5c94 226 //Reset the RTO if all bytes are acknowledged
andrewboyson 79:f50e02fb5c94 227 if (pTcb->bytesSentToRem == pTcb->bytesAckdByRem)
andrewboyson 79:f50e02fb5c94 228 {
andrewboyson 79:f50e02fb5c94 229 pTcb->timeSendsBeingAcked = TcbElapsed;
andrewboyson 82:20781198d26d 230 pTcb->countSendsNotAcked = 0;
andrewboyson 79:f50e02fb5c94 231 }
andrewboyson 75:603b10404183 232
andrewboyson 79:f50e02fb5c94 233 //Check if have unacknowledged send bytes after the RTO
andrewboyson 82:20781198d26d 234 if (TcbElapsed >= pTcb->timeSendsBeingAcked + TIMEOUT_RETRANSMISSION)
andrewboyson 75:603b10404183 235 {
andrewboyson 82:20781198d26d 236 pTcb->countSendsNotAcked++;
andrewboyson 82:20781198d26d 237 if (pTcb->countSendsNotAcked > MAX_RETRANSMISSIONS)
andrewboyson 82:20781198d26d 238 {
andrewboyson 82:20781198d26d 239 if (TcpTrace)
andrewboyson 82:20781198d26d 240 {
andrewboyson 82:20781198d26d 241 if (NetTraceNewLine) Log("\r\n");
andrewboyson 82:20781198d26d 242 LogTimeF("TCP - Resending seq %lu on port %hu reached maximum retransmissions\r\n", pTcb->bytesAckdByRem, pTcb->remPort);
andrewboyson 82:20781198d26d 243 pTcb->state = TCB_EMPTY;
andrewboyson 82:20781198d26d 244 return TcpSendReset(pSize, pPacket, pTcb);
andrewboyson 82:20781198d26d 245 }
andrewboyson 82:20781198d26d 246 }
andrewboyson 79:f50e02fb5c94 247 if (TcpTrace)
andrewboyson 79:f50e02fb5c94 248 {
andrewboyson 79:f50e02fb5c94 249 if (NetTraceNewLine) Log("\r\n");
andrewboyson 79:f50e02fb5c94 250 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 251 }
andrewboyson 79:f50e02fb5c94 252 pTcb->timeSendsBeingAcked = TcbElapsed;
andrewboyson 75:603b10404183 253 return TcpResendLastUnAcked(pSize, pPacket, pTcb);
andrewboyson 75:603b10404183 254 }
andrewboyson 79:f50e02fb5c94 255
andrewboyson 79:f50e02fb5c94 256 //If haven't had to do anything else then do a normal send
andrewboyson 79:f50e02fb5c94 257 return TcpSend(pSize, pPacket, pTcb);
andrewboyson 74:c3756bfa960e 258 }
andrewboyson 74:c3756bfa960e 259