Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Tue Nov 28 17:05:46 2017 +0000
Revision:
57:e0fb648acf48
Parent:
56:35117a8b5c65
Child:
59:e0e556c8bd46
Added TFTP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 37:793b39683406 1 #include "mbed.h"
andrewboyson 37:793b39683406 2 #include "log.h"
andrewboyson 37:793b39683406 3 #include "net.h"
andrewboyson 37:793b39683406 4 #include "action.h"
andrewboyson 37:793b39683406 5 #include "tcp.h"
andrewboyson 37:793b39683406 6 #include "tcb.h"
andrewboyson 37:793b39683406 7 #include "ip4.h"
andrewboyson 37:793b39683406 8 #include "dhcp.h"
andrewboyson 49:1a6336f2b3f9 9 #include "http.h"
andrewboyson 10:f0854784e960 10
andrewboyson 10:f0854784e960 11 #define MAX_MSS 536 //This is 576 - 20 - 20
andrewboyson 10:f0854784e960 12
andrewboyson 52:fbc5a46b5e16 13 bool TcpTrace = false;
andrewboyson 55:e64b8b47a2b6 14 static bool doTrace = false;
andrewboyson 52:fbc5a46b5e16 15
andrewboyson 10:f0854784e960 16 __packed struct header
andrewboyson 10:f0854784e960 17 {
andrewboyson 10:f0854784e960 18 uint16_t srcPort;
andrewboyson 10:f0854784e960 19 uint16_t dstPort;
andrewboyson 10:f0854784e960 20 uint32_t seqnum;
andrewboyson 10:f0854784e960 21 uint32_t acknum;
andrewboyson 10:f0854784e960 22 uint8_t dataOffset;
andrewboyson 10:f0854784e960 23 uint8_t flags;
andrewboyson 10:f0854784e960 24 uint16_t window;
andrewboyson 10:f0854784e960 25 uint16_t checksum;
andrewboyson 10:f0854784e960 26 uint16_t urgent;
andrewboyson 10:f0854784e960 27 };
andrewboyson 10:f0854784e960 28
andrewboyson 10:f0854784e960 29 //Header variables
andrewboyson 10:f0854784e960 30
andrewboyson 54:84ef2b29cf7e 31 static uint16_t srcPort;
andrewboyson 54:84ef2b29cf7e 32 static uint16_t dstPort;
andrewboyson 54:84ef2b29cf7e 33 static uint32_t seqnum;
andrewboyson 54:84ef2b29cf7e 34 static uint32_t acknum;
andrewboyson 54:84ef2b29cf7e 35 static int headersize;
andrewboyson 54:84ef2b29cf7e 36 static uint8_t flags;
andrewboyson 54:84ef2b29cf7e 37 static bool URG; //indicates that the Urgent pointer field is significant
andrewboyson 54:84ef2b29cf7e 38 static bool ACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 54:84ef2b29cf7e 39 static bool PSH; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 54:84ef2b29cf7e 40 static bool RST; //Reset the connection
andrewboyson 54:84ef2b29cf7e 41 static bool SYN; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 54:84ef2b29cf7e 42 static bool FIN; //No more data from sender
andrewboyson 10:f0854784e960 43
andrewboyson 54:84ef2b29cf7e 44 static uint16_t window;
andrewboyson 54:84ef2b29cf7e 45 static uint16_t checksum;
andrewboyson 54:84ef2b29cf7e 46 static uint16_t urgent;
andrewboyson 54:84ef2b29cf7e 47 static int optionLength;
andrewboyson 10:f0854784e960 48
andrewboyson 54:84ef2b29cf7e 49 static char* pOptions;
andrewboyson 54:84ef2b29cf7e 50 static char* pData;
andrewboyson 54:84ef2b29cf7e 51 static int dataLength;
andrewboyson 56:35117a8b5c65 52 static int positionInQuery;
andrewboyson 56:35117a8b5c65 53 static int positionInReply;
andrewboyson 54:84ef2b29cf7e 54
andrewboyson 55:e64b8b47a2b6 55 static uint16_t mss;
andrewboyson 54:84ef2b29cf7e 56
andrewboyson 54:84ef2b29cf7e 57 static void (*pTraceback)(void);
andrewboyson 54:84ef2b29cf7e 58
andrewboyson 54:84ef2b29cf7e 59 static struct tcb* pTcb;
andrewboyson 54:84ef2b29cf7e 60
andrewboyson 52:fbc5a46b5e16 61 static void logFlags()
andrewboyson 52:fbc5a46b5e16 62 {
andrewboyson 52:fbc5a46b5e16 63 if (URG) Log(" URG");
andrewboyson 52:fbc5a46b5e16 64 if (ACK) Log(" ACK");
andrewboyson 52:fbc5a46b5e16 65 if (PSH) Log(" PSH");
andrewboyson 52:fbc5a46b5e16 66 if (RST) Log(" RST");
andrewboyson 52:fbc5a46b5e16 67 if (SYN) Log(" SYN");
andrewboyson 52:fbc5a46b5e16 68 if (FIN) Log(" FIN");
andrewboyson 52:fbc5a46b5e16 69 }
andrewboyson 56:35117a8b5c65 70 void TcpLogHeader(uint16_t calculatedChecksum)
andrewboyson 43:bc028d5a6424 71 {
andrewboyson 43:bc028d5a6424 72 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 73 {
andrewboyson 43:bc028d5a6424 74 Log("TCP header\r\n");
andrewboyson 57:e0fb648acf48 75 Log(" Source port "); LogF("%hu", srcPort ); Log("\r\n");
andrewboyson 57:e0fb648acf48 76 Log(" Destination port "); LogF("%hu", dstPort ); Log("\r\n");
andrewboyson 57:e0fb648acf48 77 Log(" Seq number "); LogF("%u (%u)", positionInQuery, seqnum); Log("\r\n");
andrewboyson 57:e0fb648acf48 78 Log(" Ack number "); LogF("%u (%u)", positionInReply, acknum); Log("\r\n");
andrewboyson 57:e0fb648acf48 79 Log(" Header size "); LogF("%u", headersize ); Log("\r\n");
andrewboyson 57:e0fb648acf48 80 Log(" Flags " ); logFlags( ); Log("\r\n");
andrewboyson 57:e0fb648acf48 81 Log(" Window "); LogF("%hu", window ); Log("\r\n");
andrewboyson 57:e0fb648acf48 82 Log(" Checksum (hex) "); LogF("%04hX", checksum ); Log("\r\n");
andrewboyson 57:e0fb648acf48 83 Log(" Calculated (hex) "); LogF("%04hX", calculatedChecksum ); Log("\r\n");
andrewboyson 57:e0fb648acf48 84 Log(" Urgent pointer "); LogF("%hu", urgent ); Log("\r\n");
andrewboyson 57:e0fb648acf48 85 Log(" Option length "); LogF("%d", optionLength ); Log("\r\n");
andrewboyson 57:e0fb648acf48 86 Log(" Data length "); LogF("%u", dataLength ); Log("\r\n");
andrewboyson 57:e0fb648acf48 87 Log(" sendIsn "); LogF("%u", pTcb->sendIsn ); Log("\r\n");
andrewboyson 57:e0fb648acf48 88 Log(" recvIsn "); LogF("%u", pTcb->recvIsn ); Log("\r\n");
andrewboyson 57:e0fb648acf48 89 Log(" sentBytes "); LogF("%u", pTcb->sentBytes ); Log("\r\n");
andrewboyson 57:e0fb648acf48 90 Log(" recdBytes "); LogF("%u", pTcb->recdBytes ); Log("\r\n");
andrewboyson 54:84ef2b29cf7e 91
andrewboyson 43:bc028d5a6424 92 }
andrewboyson 43:bc028d5a6424 93 else
andrewboyson 43:bc028d5a6424 94 {
andrewboyson 44:83ce5ace337b 95 LogF("TCP header %hu >>> %hu", srcPort, dstPort);
andrewboyson 52:fbc5a46b5e16 96 logFlags();
andrewboyson 57:e0fb648acf48 97 LogF(", query %u, reply %u", positionInQuery, positionInReply);
andrewboyson 52:fbc5a46b5e16 98 Log("\r\n");
andrewboyson 43:bc028d5a6424 99 }
andrewboyson 10:f0854784e960 100 }
andrewboyson 10:f0854784e960 101 void TcpAddChecksum(void* pPacket, uint16_t checksum)
andrewboyson 10:f0854784e960 102 {
andrewboyson 10:f0854784e960 103 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 104 pHeader->checksum = checksum;
andrewboyson 10:f0854784e960 105 }
andrewboyson 10:f0854784e960 106 static void readOptions()
andrewboyson 10:f0854784e960 107 {
andrewboyson 10:f0854784e960 108 mss = 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
andrewboyson 10:f0854784e960 109 for (char* p = pOptions; p < pOptions + optionLength; p++)
andrewboyson 10:f0854784e960 110 {
andrewboyson 10:f0854784e960 111 switch (*p)
andrewboyson 10:f0854784e960 112 {
andrewboyson 10:f0854784e960 113 case 0: break; //End of options - used to pad to 32 bit boundary
andrewboyson 10:f0854784e960 114 case 1: break; //NOP, padding - optional
andrewboyson 10:f0854784e960 115 case 2:
andrewboyson 10:f0854784e960 116 p++;
andrewboyson 10:f0854784e960 117 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 10:f0854784e960 118 p++;
andrewboyson 10:f0854784e960 119 mss = ((uint16_t)*p) << 8;
andrewboyson 10:f0854784e960 120 p++;
andrewboyson 10:f0854784e960 121 mss += *p;
andrewboyson 10:f0854784e960 122 return;
andrewboyson 10:f0854784e960 123 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 10:f0854784e960 124 }
andrewboyson 10:f0854784e960 125 }
andrewboyson 10:f0854784e960 126 if (mss > MAX_MSS) mss = MAX_MSS;
andrewboyson 10:f0854784e960 127 }
andrewboyson 10:f0854784e960 128 static void writeOptions()
andrewboyson 10:f0854784e960 129 {
andrewboyson 10:f0854784e960 130 pOptions[0] = 2;
andrewboyson 10:f0854784e960 131 pOptions[1] = 4;
andrewboyson 10:f0854784e960 132 pOptions[2] = mss >> 8;
andrewboyson 10:f0854784e960 133 pOptions[3] = mss & 0xFF;
andrewboyson 10:f0854784e960 134 optionLength = 4;
andrewboyson 10:f0854784e960 135 }
andrewboyson 10:f0854784e960 136
andrewboyson 10:f0854784e960 137 void TcpReadHeader(void* pPacket, uint16_t size)
andrewboyson 10:f0854784e960 138 {
andrewboyson 10:f0854784e960 139 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 140
andrewboyson 56:35117a8b5c65 141 srcPort = NetToHost16(pHeader->srcPort);
andrewboyson 56:35117a8b5c65 142 dstPort = NetToHost16(pHeader->dstPort);
andrewboyson 56:35117a8b5c65 143 seqnum = NetToHost32(pHeader->seqnum);
andrewboyson 56:35117a8b5c65 144 acknum = NetToHost32(pHeader->acknum);
andrewboyson 56:35117a8b5c65 145 headersize = (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 56:35117a8b5c65 146 flags = pHeader->flags;
andrewboyson 56:35117a8b5c65 147 URG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 56:35117a8b5c65 148 ACK = flags & 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 56:35117a8b5c65 149 PSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 56:35117a8b5c65 150 RST = flags & 0x04; //Reset the connection
andrewboyson 56:35117a8b5c65 151 SYN = flags & 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 56:35117a8b5c65 152 FIN = flags & 0x01; //No more data from sender
andrewboyson 10:f0854784e960 153
andrewboyson 56:35117a8b5c65 154 window = NetToHost16(pHeader->window);
andrewboyson 56:35117a8b5c65 155 checksum = NetToHost16(pHeader->checksum);
andrewboyson 56:35117a8b5c65 156 urgent = NetToHost16(pHeader->urgent);
andrewboyson 56:35117a8b5c65 157 pOptions = (char*)pPacket + 20;
andrewboyson 57:e0fb648acf48 158 optionLength = headersize - 20;
andrewboyson 56:35117a8b5c65 159 pData = (char*)pPacket + headersize;
andrewboyson 56:35117a8b5c65 160 dataLength = size - headersize;
andrewboyson 10:f0854784e960 161 }
andrewboyson 10:f0854784e960 162
andrewboyson 10:f0854784e960 163 void TcpMakeHeader(int size, void* pPacket)
andrewboyson 10:f0854784e960 164 {
andrewboyson 10:f0854784e960 165 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 166
andrewboyson 10:f0854784e960 167 pHeader->dstPort = NetToHost16(dstPort);
andrewboyson 10:f0854784e960 168 pHeader->srcPort = NetToHost16(srcPort);
andrewboyson 10:f0854784e960 169 pHeader->seqnum = NetToHost32(seqnum); //This is the sequence number of the first byte of this message
andrewboyson 10:f0854784e960 170 pHeader->acknum = NetToHost32(acknum); //This is the sequence number we expect in the next message
andrewboyson 10:f0854784e960 171 pHeader->dataOffset = headersize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 10:f0854784e960 172 flags = 0;
andrewboyson 56:35117a8b5c65 173 if (URG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 56:35117a8b5c65 174 if (ACK) flags |= 0x10; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 56:35117a8b5c65 175 if (PSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 56:35117a8b5c65 176 if (RST) flags |= 0x04; //Reset the connection
andrewboyson 56:35117a8b5c65 177 if (SYN) flags |= 0x02; //Synchronize sequence numbers. Only the first packet sent from each end should have this flag set. Some other flags and fields change meaning based on this flag, and some are only valid for when it is set, and others when it is clear.
andrewboyson 56:35117a8b5c65 178 if (FIN) flags |= 0x01; //No more data from sender
andrewboyson 10:f0854784e960 179 pHeader->flags = flags;
andrewboyson 10:f0854784e960 180 pHeader->window = NetToHost16(window);
andrewboyson 10:f0854784e960 181 pHeader->urgent = NetToHost16(urgent);
andrewboyson 10:f0854784e960 182
andrewboyson 10:f0854784e960 183 pHeader->checksum = 0;
andrewboyson 10:f0854784e960 184 }
andrewboyson 56:35117a8b5c65 185 static void resetConnection(char* message)
andrewboyson 55:e64b8b47a2b6 186 {
andrewboyson 56:35117a8b5c65 187 if (TcpTrace)
andrewboyson 56:35117a8b5c65 188 {
andrewboyson 56:35117a8b5c65 189 LogTime("TCP ");
andrewboyson 56:35117a8b5c65 190 Log(message);
andrewboyson 56:35117a8b5c65 191 Log("\r\n");
andrewboyson 56:35117a8b5c65 192 }
andrewboyson 55:e64b8b47a2b6 193 dataLength = 0;
andrewboyson 55:e64b8b47a2b6 194 headersize = 20;
andrewboyson 55:e64b8b47a2b6 195 ACK = false;
andrewboyson 55:e64b8b47a2b6 196 PSH = false;
andrewboyson 55:e64b8b47a2b6 197 RST = true;
andrewboyson 55:e64b8b47a2b6 198 SYN = false;
andrewboyson 55:e64b8b47a2b6 199 FIN = false;
andrewboyson 55:e64b8b47a2b6 200 }
andrewboyson 56:35117a8b5c65 201 static void startConnection()
andrewboyson 10:f0854784e960 202 {
andrewboyson 10:f0854784e960 203 readOptions(); //Get the MSS
andrewboyson 52:fbc5a46b5e16 204 pTcb->mss = mss;
andrewboyson 52:fbc5a46b5e16 205 pTcb->state = TCB_SYN_RECEIVED;
andrewboyson 52:fbc5a46b5e16 206 pTcb->elapsed = TcbElapsed;
andrewboyson 52:fbc5a46b5e16 207 pTcb->port = srcPort;
andrewboyson 57:e0fb648acf48 208 pTcb->hadFin = false;
andrewboyson 55:e64b8b47a2b6 209
andrewboyson 10:f0854784e960 210 dataLength = 0;
andrewboyson 10:f0854784e960 211
andrewboyson 10:f0854784e960 212 mss = MAX_MSS; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20
andrewboyson 10:f0854784e960 213 writeOptions();
andrewboyson 10:f0854784e960 214 headersize = 24; //20 header plus 4 option
andrewboyson 10:f0854784e960 215
andrewboyson 10:f0854784e960 216 ACK = true; //Send ACK and SYN
andrewboyson 10:f0854784e960 217 PSH = false;
andrewboyson 10:f0854784e960 218 RST = false;
andrewboyson 10:f0854784e960 219 SYN = true;
andrewboyson 10:f0854784e960 220 FIN = false;
andrewboyson 10:f0854784e960 221 }
andrewboyson 56:35117a8b5c65 222 static void establishConnection()
andrewboyson 10:f0854784e960 223 {
andrewboyson 56:35117a8b5c65 224 pTcb->state = TCB_ESTABLISHED;
andrewboyson 56:35117a8b5c65 225 pTcb->elapsed = TcbElapsed;
andrewboyson 57:e0fb648acf48 226 pTcb->todo = 0;
andrewboyson 10:f0854784e960 227 }
andrewboyson 56:35117a8b5c65 228 static void handleEstablishedConnection()
andrewboyson 56:35117a8b5c65 229 {
andrewboyson 54:84ef2b29cf7e 230 char* pRequestStream = pData;
andrewboyson 54:84ef2b29cf7e 231 char* pReplyStream = pOptions;
andrewboyson 54:84ef2b29cf7e 232
andrewboyson 56:35117a8b5c65 233 HttpHandleRequest(&dataLength, pRequestStream, positionInQuery - 1, pReplyStream, positionInReply - 1, mss, &pTcb->todo);
andrewboyson 10:f0854784e960 234
andrewboyson 10:f0854784e960 235 headersize = 20;
andrewboyson 54:84ef2b29cf7e 236 pData = pReplyStream;
andrewboyson 55:e64b8b47a2b6 237
andrewboyson 10:f0854784e960 238 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 239 RST = false;
andrewboyson 10:f0854784e960 240 SYN = false;
andrewboyson 22:914b970356f0 241 PSH = false;
andrewboyson 10:f0854784e960 242
andrewboyson 22:914b970356f0 243 if (dataLength < mss) //If a part packet then there can be no more to send
andrewboyson 10:f0854784e960 244 {
andrewboyson 57:e0fb648acf48 245 FIN = true; //Inform the client that we have no more to send after this
andrewboyson 57:e0fb648acf48 246 if (pTcb->hadFin) pTcb->state = TCB_ACK_WAIT; //Passive close
andrewboyson 57:e0fb648acf48 247 else pTcb->state = TCB_FIN_WAIT; //Active close
andrewboyson 10:f0854784e960 248 }
andrewboyson 56:35117a8b5c65 249 else
andrewboyson 56:35117a8b5c65 250 {
andrewboyson 56:35117a8b5c65 251 FIN = false;
andrewboyson 56:35117a8b5c65 252 }
andrewboyson 22:914b970356f0 253
andrewboyson 52:fbc5a46b5e16 254 pTcb->elapsed = TcbElapsed;
andrewboyson 10:f0854784e960 255 }
andrewboyson 56:35117a8b5c65 256 static void closeConnection()
andrewboyson 56:35117a8b5c65 257 {
andrewboyson 10:f0854784e960 258 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 259 PSH = false;
andrewboyson 10:f0854784e960 260 RST = false;
andrewboyson 10:f0854784e960 261 SYN = false;
andrewboyson 10:f0854784e960 262 FIN = false;
andrewboyson 10:f0854784e960 263
andrewboyson 10:f0854784e960 264 headersize = 20;
andrewboyson 10:f0854784e960 265 dataLength = 0;
andrewboyson 10:f0854784e960 266
andrewboyson 57:e0fb648acf48 267 pTcb->state = TCB_EMPTY;
andrewboyson 10:f0854784e960 268 }
andrewboyson 10:f0854784e960 269
andrewboyson 37:793b39683406 270 int TcpHandleReceivedPacket(void (*traceback)(void), int* pSize, void* pPacket)
andrewboyson 10:f0854784e960 271 {
andrewboyson 54:84ef2b29cf7e 272 pTraceback = traceback;
andrewboyson 57:e0fb648acf48 273 doTrace = false;
andrewboyson 57:e0fb648acf48 274
andrewboyson 57:e0fb648acf48 275 //Filter out unwanted links
andrewboyson 57:e0fb648acf48 276 switch (dstPort)
andrewboyson 57:e0fb648acf48 277 {
andrewboyson 57:e0fb648acf48 278 case 80:
andrewboyson 57:e0fb648acf48 279 if (HttpTrace)
andrewboyson 57:e0fb648acf48 280 {
andrewboyson 57:e0fb648acf48 281 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 282 LogTime("HTTP server request\r\n");
andrewboyson 57:e0fb648acf48 283 doTrace = true;
andrewboyson 57:e0fb648acf48 284 }
andrewboyson 57:e0fb648acf48 285 break;
andrewboyson 57:e0fb648acf48 286
andrewboyson 57:e0fb648acf48 287 default:
andrewboyson 57:e0fb648acf48 288 if (TcpTrace)
andrewboyson 57:e0fb648acf48 289 {
andrewboyson 57:e0fb648acf48 290 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 291 LogTimeF("TCP unknown port %d\r\n", dstPort);
andrewboyson 57:e0fb648acf48 292 if (NetTraceStack) pTraceback();
andrewboyson 57:e0fb648acf48 293 }
andrewboyson 57:e0fb648acf48 294 return DO_NOTHING; //Ignore unknown ports
andrewboyson 57:e0fb648acf48 295 }
andrewboyson 55:e64b8b47a2b6 296
andrewboyson 55:e64b8b47a2b6 297 //Get the Transmission Control Block
andrewboyson 54:84ef2b29cf7e 298 pTcb = TcbGetExisting(srcPort);
andrewboyson 10:f0854784e960 299 if (!pTcb) pTcb = TcbGetEmpty();
andrewboyson 52:fbc5a46b5e16 300 if (!pTcb)
andrewboyson 52:fbc5a46b5e16 301 {
andrewboyson 52:fbc5a46b5e16 302 if (TcpTrace)
andrewboyson 52:fbc5a46b5e16 303 {
andrewboyson 57:e0fb648acf48 304 if (NetTraceNewLine) Log("\r\n");
andrewboyson 52:fbc5a46b5e16 305 LogTime("TCP no more tcbs are available\r\n");
andrewboyson 57:e0fb648acf48 306 if (NetTraceStack) pTraceback();
andrewboyson 52:fbc5a46b5e16 307 }
andrewboyson 52:fbc5a46b5e16 308 return DO_NOTHING; //Bomb out if no more tcbs are available
andrewboyson 52:fbc5a46b5e16 309 }
andrewboyson 10:f0854784e960 310
andrewboyson 55:e64b8b47a2b6 311 //Handle request to reset
andrewboyson 10:f0854784e960 312 if (RST)
andrewboyson 10:f0854784e960 313 {
andrewboyson 57:e0fb648acf48 314 if (TcpTrace)
andrewboyson 57:e0fb648acf48 315 {
andrewboyson 57:e0fb648acf48 316 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 317 LogTime("TCP received reset - resetting TCB\r\n");
andrewboyson 57:e0fb648acf48 318 if (NetTraceStack) pTraceback();
andrewboyson 57:e0fb648acf48 319 }
andrewboyson 57:e0fb648acf48 320 pTcb->state = TCB_EMPTY; //Reset connection
andrewboyson 57:e0fb648acf48 321 return DO_NOTHING; //Don't reply
andrewboyson 10:f0854784e960 322 }
andrewboyson 55:e64b8b47a2b6 323
andrewboyson 55:e64b8b47a2b6 324 //Handle request to synchronise
andrewboyson 55:e64b8b47a2b6 325 if (SYN)
andrewboyson 55:e64b8b47a2b6 326 {
andrewboyson 57:e0fb648acf48 327 pTcb->recvIsn = seqnum;
andrewboyson 57:e0fb648acf48 328 pTcb->recdBytes = 0;
andrewboyson 57:e0fb648acf48 329 pTcb->sendIsn = TcbGetIsn();
andrewboyson 57:e0fb648acf48 330 pTcb->sentBytes = 0;
andrewboyson 57:e0fb648acf48 331 acknum = pTcb->sendIsn;
andrewboyson 55:e64b8b47a2b6 332 }
andrewboyson 55:e64b8b47a2b6 333
andrewboyson 57:e0fb648acf48 334 //Calculate positions
andrewboyson 57:e0fb648acf48 335 positionInQuery = seqnum - pTcb->recvIsn;
andrewboyson 57:e0fb648acf48 336 positionInReply = acknum - pTcb->sendIsn;
andrewboyson 57:e0fb648acf48 337
andrewboyson 57:e0fb648acf48 338 //Check packet sequences
andrewboyson 57:e0fb648acf48 339 if (positionInQuery != pTcb->recdBytes || positionInReply != pTcb->sentBytes)
andrewboyson 10:f0854784e960 340 {
andrewboyson 57:e0fb648acf48 341 if (TcpTrace)
andrewboyson 57:e0fb648acf48 342 {
andrewboyson 57:e0fb648acf48 343 if (NetTraceNewLine) Log("\r\n");
andrewboyson 57:e0fb648acf48 344 LogTime("TCP received packet");
andrewboyson 57:e0fb648acf48 345 if (positionInQuery != pTcb->recdBytes) LogF(": starting at byte %u rather than %u so data reread" , positionInQuery, pTcb->recdBytes);
andrewboyson 57:e0fb648acf48 346 if (positionInReply != pTcb->sentBytes) LogF(": acknowledging byte %u rather than %u so data resent", positionInReply, pTcb->sentBytes);
andrewboyson 57:e0fb648acf48 347 Log("\r\n");
andrewboyson 55:e64b8b47a2b6 348
andrewboyson 57:e0fb648acf48 349 if (NetTraceStack) pTraceback();
andrewboyson 57:e0fb648acf48 350 doTrace = true;
andrewboyson 57:e0fb648acf48 351 }
andrewboyson 57:e0fb648acf48 352 pTcb->recdBytes = positionInQuery;
andrewboyson 57:e0fb648acf48 353 pTcb->sentBytes = positionInReply;
andrewboyson 52:fbc5a46b5e16 354 }
andrewboyson 55:e64b8b47a2b6 355 if (doTrace && NetTraceStack) pTraceback(); //This will already include the TCP header
andrewboyson 55:e64b8b47a2b6 356
andrewboyson 57:e0fb648acf48 357 if (SYN) pTcb->recdBytes += 1; //Add one to acknowledge the SYN
andrewboyson 57:e0fb648acf48 358 pTcb->recdBytes += dataLength; //Add the number of bytes received
andrewboyson 57:e0fb648acf48 359 if (FIN) pTcb->recdBytes += 1; //Add one to acknowledge the FIN
andrewboyson 10:f0854784e960 360
andrewboyson 10:f0854784e960 361 switch (pTcb->state)
andrewboyson 10:f0854784e960 362 {
andrewboyson 57:e0fb648acf48 363 case TCB_EMPTY:
andrewboyson 56:35117a8b5c65 364 if (!SYN) { resetConnection("received other than a SYN when connection closed"); break; }
andrewboyson 56:35117a8b5c65 365 startConnection();
andrewboyson 56:35117a8b5c65 366 break;
andrewboyson 56:35117a8b5c65 367
andrewboyson 56:35117a8b5c65 368 case TCB_SYN_RECEIVED:
andrewboyson 56:35117a8b5c65 369 if (dataLength) { resetConnection("data received before connection established"); break; }
andrewboyson 56:35117a8b5c65 370 if (!ACK) { resetConnection("received other than an ACK before connection established"); break; }
andrewboyson 56:35117a8b5c65 371 establishConnection();
andrewboyson 56:35117a8b5c65 372 return DO_NOTHING;
andrewboyson 56:35117a8b5c65 373
andrewboyson 56:35117a8b5c65 374 case TCB_ESTABLISHED:
andrewboyson 57:e0fb648acf48 375 if (!ACK) { resetConnection("received other than an ACK during established conection"); break; }
andrewboyson 57:e0fb648acf48 376 if (FIN) pTcb->hadFin = true; //When reply is all sent only a passive close is needed
andrewboyson 56:35117a8b5c65 377 handleEstablishedConnection();
andrewboyson 56:35117a8b5c65 378 break;
andrewboyson 56:35117a8b5c65 379
andrewboyson 57:e0fb648acf48 380 case TCB_FIN_WAIT: //End of active close
andrewboyson 56:35117a8b5c65 381 if (!FIN) return DO_NOTHING; //Ignore ACK to our FIN. Wait for FIN then close.
andrewboyson 56:35117a8b5c65 382 closeConnection();
andrewboyson 56:35117a8b5c65 383 break;
andrewboyson 57:e0fb648acf48 384
andrewboyson 57:e0fb648acf48 385 case TCB_ACK_WAIT: //End of passive close
andrewboyson 57:e0fb648acf48 386 if (!ACK) { resetConnection("received other than an ACK when closing half open connection"); break; }
andrewboyson 57:e0fb648acf48 387 pTcb->state = TCB_EMPTY;
andrewboyson 57:e0fb648acf48 388 return DO_NOTHING;
andrewboyson 10:f0854784e960 389 }
andrewboyson 10:f0854784e960 390
andrewboyson 57:e0fb648acf48 391 positionInReply = pTcb->recdBytes; //Set up the acknowledgement field ready to send
andrewboyson 57:e0fb648acf48 392 positionInQuery = pTcb->sentBytes; //Record the start of the query before adding the bytes sent
andrewboyson 57:e0fb648acf48 393
andrewboyson 57:e0fb648acf48 394 //Keep a record of where we expect the next packet send to start
andrewboyson 57:e0fb648acf48 395 if (SYN) pTcb->sentBytes += 1; //Add one to acknowledge the SYN
andrewboyson 57:e0fb648acf48 396 pTcb->sentBytes += dataLength; //Record the next sequence number
andrewboyson 57:e0fb648acf48 397 if (FIN) pTcb->sentBytes += 1; //Add one to acknowledge the FIN
andrewboyson 55:e64b8b47a2b6 398
andrewboyson 57:e0fb648acf48 399 //Specify the start of the data being sent and acknowledge the data received
andrewboyson 57:e0fb648acf48 400 seqnum = positionInQuery + pTcb->sendIsn;
andrewboyson 57:e0fb648acf48 401 acknum = positionInReply + pTcb->recvIsn;
andrewboyson 55:e64b8b47a2b6 402
andrewboyson 57:e0fb648acf48 403 //Swap the ports for the reply
andrewboyson 10:f0854784e960 404 srcPort = dstPort;
andrewboyson 10:f0854784e960 405 dstPort = pTcb->port;
andrewboyson 10:f0854784e960 406
andrewboyson 57:e0fb648acf48 407 //Calculate the size of the reply
andrewboyson 10:f0854784e960 408 *pSize = dataLength + headersize;
andrewboyson 54:84ef2b29cf7e 409
andrewboyson 55:e64b8b47a2b6 410 return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack);
andrewboyson 10:f0854784e960 411
andrewboyson 10:f0854784e960 412 }