Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

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