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:
Tue Nov 14 17:43:08 2017 +0000
Revision:
56:35117a8b5c65
Parent:
55:e64b8b47a2b6
Child:
57:e0fb648acf48
Corrected closing FIN requirement

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 56:35117a8b5c65 75 LogF(" Source port %hu\r\n", srcPort);
andrewboyson 56:35117a8b5c65 76 LogF(" Destination port %hu\r\n", dstPort);
andrewboyson 56:35117a8b5c65 77 LogF(" Seq number %u (%u)\r\n", positionInQuery, seqnum);
andrewboyson 56:35117a8b5c65 78 LogF(" Ack number %u (%u)\r\n", positionInReply, acknum);
andrewboyson 56:35117a8b5c65 79 LogF(" Header size %u\r\n", headersize);
andrewboyson 52:fbc5a46b5e16 80 Log (" Flags "); logFlags(); Log("\r\n");
andrewboyson 56:35117a8b5c65 81 LogF(" Window %hu\r\n", window);
andrewboyson 56:35117a8b5c65 82 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 56:35117a8b5c65 83 LogF(" Calculated (hex) %04hX\r\n", calculatedChecksum);
andrewboyson 56:35117a8b5c65 84 LogF(" Urgent pointer %hu\r\n", urgent);
andrewboyson 56:35117a8b5c65 85 LogF(" Option length %d\r\n", optionLength);
andrewboyson 56:35117a8b5c65 86 LogF(" Data length %d\r\n", dataLength);
andrewboyson 56:35117a8b5c65 87 LogF(" locIsn %u\r\n", pTcb->locIsn);
andrewboyson 56:35117a8b5c65 88 LogF(" remIsn %u\r\n", pTcb->remIsn);
andrewboyson 56:35117a8b5c65 89 LogF(" locSeq %u\r\n", pTcb->locSeq);
andrewboyson 56:35117a8b5c65 90 LogF(" remSeq %u\r\n", pTcb->remSeq);
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 56:35117a8b5c65 97 LogF(", seq %u, ack %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 56:35117a8b5c65 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 55:e64b8b47a2b6 208
andrewboyson 10:f0854784e960 209 dataLength = 0;
andrewboyson 10:f0854784e960 210
andrewboyson 10:f0854784e960 211 mss = MAX_MSS; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20
andrewboyson 10:f0854784e960 212 writeOptions();
andrewboyson 10:f0854784e960 213 headersize = 24; //20 header plus 4 option
andrewboyson 10:f0854784e960 214
andrewboyson 10:f0854784e960 215 ACK = true; //Send ACK and SYN
andrewboyson 10:f0854784e960 216 PSH = false;
andrewboyson 10:f0854784e960 217 RST = false;
andrewboyson 10:f0854784e960 218 SYN = true;
andrewboyson 10:f0854784e960 219 FIN = false;
andrewboyson 10:f0854784e960 220 }
andrewboyson 56:35117a8b5c65 221 static void establishConnection()
andrewboyson 10:f0854784e960 222 {
andrewboyson 56:35117a8b5c65 223 pTcb->state = TCB_ESTABLISHED;
andrewboyson 56:35117a8b5c65 224 pTcb->elapsed = TcbElapsed;
andrewboyson 56:35117a8b5c65 225 pTcb->todo = 0;
andrewboyson 10:f0854784e960 226 }
andrewboyson 56:35117a8b5c65 227 static void handleEstablishedConnection()
andrewboyson 56:35117a8b5c65 228 {
andrewboyson 54:84ef2b29cf7e 229 char* pRequestStream = pData;
andrewboyson 54:84ef2b29cf7e 230 char* pReplyStream = pOptions;
andrewboyson 54:84ef2b29cf7e 231
andrewboyson 56:35117a8b5c65 232 HttpHandleRequest(&dataLength, pRequestStream, positionInQuery - 1, pReplyStream, positionInReply - 1, mss, &pTcb->todo);
andrewboyson 10:f0854784e960 233
andrewboyson 10:f0854784e960 234 headersize = 20;
andrewboyson 54:84ef2b29cf7e 235 pData = pReplyStream;
andrewboyson 55:e64b8b47a2b6 236
andrewboyson 10:f0854784e960 237 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 238 RST = false;
andrewboyson 10:f0854784e960 239 SYN = false;
andrewboyson 22:914b970356f0 240 PSH = false;
andrewboyson 10:f0854784e960 241
andrewboyson 22:914b970356f0 242 if (dataLength < mss) //If a part packet then there can be no more to send
andrewboyson 10:f0854784e960 243 {
andrewboyson 22:914b970356f0 244 FIN = true; //Inform the client that we have no more to send after this
andrewboyson 10:f0854784e960 245 pTcb->state = TCB_CLOSING; //Start closing
andrewboyson 10:f0854784e960 246 }
andrewboyson 56:35117a8b5c65 247 else
andrewboyson 56:35117a8b5c65 248 {
andrewboyson 56:35117a8b5c65 249 FIN = false;
andrewboyson 56:35117a8b5c65 250 }
andrewboyson 22:914b970356f0 251
andrewboyson 52:fbc5a46b5e16 252 pTcb->elapsed = TcbElapsed;
andrewboyson 10:f0854784e960 253 }
andrewboyson 56:35117a8b5c65 254 static void closeConnection()
andrewboyson 56:35117a8b5c65 255 {
andrewboyson 10:f0854784e960 256 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 257 PSH = false;
andrewboyson 10:f0854784e960 258 RST = false;
andrewboyson 10:f0854784e960 259 SYN = false;
andrewboyson 10:f0854784e960 260 FIN = false;
andrewboyson 10:f0854784e960 261
andrewboyson 10:f0854784e960 262 headersize = 20;
andrewboyson 10:f0854784e960 263 dataLength = 0;
andrewboyson 10:f0854784e960 264
andrewboyson 10:f0854784e960 265 pTcb->state = TCB_CLOSED;
andrewboyson 10:f0854784e960 266 }
andrewboyson 10:f0854784e960 267
andrewboyson 37:793b39683406 268 int TcpHandleReceivedPacket(void (*traceback)(void), int* pSize, void* pPacket)
andrewboyson 10:f0854784e960 269 {
andrewboyson 54:84ef2b29cf7e 270 pTraceback = traceback;
andrewboyson 55:e64b8b47a2b6 271
andrewboyson 55:e64b8b47a2b6 272 //Get the Transmission Control Block
andrewboyson 54:84ef2b29cf7e 273 pTcb = TcbGetExisting(srcPort);
andrewboyson 10:f0854784e960 274 if (!pTcb) pTcb = TcbGetEmpty();
andrewboyson 52:fbc5a46b5e16 275 if (!pTcb)
andrewboyson 52:fbc5a46b5e16 276 {
andrewboyson 52:fbc5a46b5e16 277 if (TcpTrace)
andrewboyson 52:fbc5a46b5e16 278 {
andrewboyson 52:fbc5a46b5e16 279 LogTime("TCP no more tcbs are available\r\n");
andrewboyson 55:e64b8b47a2b6 280 pTraceback(); //This will already include the TCP header
andrewboyson 52:fbc5a46b5e16 281 }
andrewboyson 52:fbc5a46b5e16 282 return DO_NOTHING; //Bomb out if no more tcbs are available
andrewboyson 52:fbc5a46b5e16 283 }
andrewboyson 10:f0854784e960 284
andrewboyson 55:e64b8b47a2b6 285 //Handle request to reset
andrewboyson 10:f0854784e960 286 if (RST)
andrewboyson 10:f0854784e960 287 {
andrewboyson 10:f0854784e960 288 pTcb->state = TCB_CLOSED; //Reset connection
andrewboyson 56:35117a8b5c65 289 return DO_NOTHING; //Don't reply
andrewboyson 10:f0854784e960 290 }
andrewboyson 55:e64b8b47a2b6 291
andrewboyson 55:e64b8b47a2b6 292 //Handle request to synchronise
andrewboyson 55:e64b8b47a2b6 293 if (SYN)
andrewboyson 55:e64b8b47a2b6 294 {
andrewboyson 55:e64b8b47a2b6 295 pTcb->remIsn = seqnum;
andrewboyson 55:e64b8b47a2b6 296 pTcb->remSeq = pTcb->remIsn;
andrewboyson 55:e64b8b47a2b6 297 pTcb->locIsn = TcbGetIsn();
andrewboyson 55:e64b8b47a2b6 298 pTcb->locSeq = pTcb->locIsn;
andrewboyson 55:e64b8b47a2b6 299 acknum = pTcb->locIsn;
andrewboyson 55:e64b8b47a2b6 300 }
andrewboyson 55:e64b8b47a2b6 301
andrewboyson 55:e64b8b47a2b6 302 //Check the sequence is not lost or out of order
andrewboyson 55:e64b8b47a2b6 303 if (seqnum != pTcb->remSeq)
andrewboyson 55:e64b8b47a2b6 304 {
andrewboyson 55:e64b8b47a2b6 305 LogTimeF("TCP had sequence %u but expected %u\r\n", seqnum, pTcb->remSeq);
andrewboyson 55:e64b8b47a2b6 306 }
andrewboyson 55:e64b8b47a2b6 307
andrewboyson 55:e64b8b47a2b6 308 //Check the remote host has received all bytes
andrewboyson 55:e64b8b47a2b6 309 if (acknum != pTcb->locSeq)
andrewboyson 55:e64b8b47a2b6 310 {
andrewboyson 55:e64b8b47a2b6 311 LogTimeF("TCP acknowledged %u but expected %u\r\n", acknum, pTcb->locSeq);
andrewboyson 55:e64b8b47a2b6 312 }
andrewboyson 55:e64b8b47a2b6 313
andrewboyson 56:35117a8b5c65 314 positionInQuery = seqnum - pTcb->remIsn;
andrewboyson 56:35117a8b5c65 315 positionInReply = acknum - pTcb->locIsn;
andrewboyson 10:f0854784e960 316
andrewboyson 52:fbc5a46b5e16 317 //Filter out unwanted links
andrewboyson 10:f0854784e960 318 switch (dstPort)
andrewboyson 10:f0854784e960 319 {
andrewboyson 55:e64b8b47a2b6 320 case 80:
andrewboyson 55:e64b8b47a2b6 321 doTrace = HttpTrace;
andrewboyson 55:e64b8b47a2b6 322 if (doTrace)
andrewboyson 52:fbc5a46b5e16 323 {
andrewboyson 55:e64b8b47a2b6 324 if (NetTraceNewLine) Log("\r\n");
andrewboyson 55:e64b8b47a2b6 325 LogTime("HTTP server request\r\n");
andrewboyson 52:fbc5a46b5e16 326 }
andrewboyson 55:e64b8b47a2b6 327 break;
andrewboyson 55:e64b8b47a2b6 328
andrewboyson 55:e64b8b47a2b6 329 default:
andrewboyson 55:e64b8b47a2b6 330 doTrace = TcpTrace;
andrewboyson 55:e64b8b47a2b6 331 if (doTrace)
andrewboyson 55:e64b8b47a2b6 332 {
andrewboyson 55:e64b8b47a2b6 333 if (NetTraceNewLine) Log("\r\n");
andrewboyson 55:e64b8b47a2b6 334 LogTimeF("TCP unknown port %d\r\n", dstPort);
andrewboyson 55:e64b8b47a2b6 335 }
andrewboyson 55:e64b8b47a2b6 336 return DO_NOTHING; //Ignore unknown ports
andrewboyson 52:fbc5a46b5e16 337 }
andrewboyson 55:e64b8b47a2b6 338 if (doTrace && NetTraceStack) pTraceback(); //This will already include the TCP header
andrewboyson 55:e64b8b47a2b6 339
andrewboyson 55:e64b8b47a2b6 340 if (SYN) pTcb->remSeq += 1; //Add one to acknowledge the SYN
andrewboyson 55:e64b8b47a2b6 341 pTcb->remSeq += dataLength; //Add the number of bytes received
andrewboyson 55:e64b8b47a2b6 342 if (FIN) pTcb->remSeq += 1; //Add one to acknowledge the FIN
andrewboyson 55:e64b8b47a2b6 343 acknum = pTcb->remSeq; //Set up the acknowledgement field ready to send
andrewboyson 10:f0854784e960 344
andrewboyson 10:f0854784e960 345 switch (pTcb->state)
andrewboyson 10:f0854784e960 346 {
andrewboyson 56:35117a8b5c65 347 case TCB_CLOSED:
andrewboyson 56:35117a8b5c65 348 if (!SYN) { resetConnection("received other than a SYN when connection closed"); break; }
andrewboyson 56:35117a8b5c65 349 startConnection();
andrewboyson 56:35117a8b5c65 350 break;
andrewboyson 56:35117a8b5c65 351
andrewboyson 56:35117a8b5c65 352 case TCB_SYN_RECEIVED:
andrewboyson 56:35117a8b5c65 353 if (dataLength) { resetConnection("data received before connection established"); break; }
andrewboyson 56:35117a8b5c65 354 if (!ACK) { resetConnection("received other than an ACK before connection established"); break; }
andrewboyson 56:35117a8b5c65 355 establishConnection();
andrewboyson 56:35117a8b5c65 356 return DO_NOTHING;
andrewboyson 56:35117a8b5c65 357
andrewboyson 56:35117a8b5c65 358 case TCB_ESTABLISHED:
andrewboyson 56:35117a8b5c65 359 if (!ACK) { resetConnection("received other than an ACK during established conection"); break; }
andrewboyson 56:35117a8b5c65 360 handleEstablishedConnection();
andrewboyson 56:35117a8b5c65 361 break;
andrewboyson 56:35117a8b5c65 362
andrewboyson 56:35117a8b5c65 363 case TCB_CLOSING:
andrewboyson 56:35117a8b5c65 364 if (!FIN) return DO_NOTHING; //Ignore ACK to our FIN. Wait for FIN then close.
andrewboyson 56:35117a8b5c65 365 closeConnection();
andrewboyson 56:35117a8b5c65 366 break;
andrewboyson 10:f0854784e960 367 }
andrewboyson 10:f0854784e960 368
andrewboyson 55:e64b8b47a2b6 369 seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message
andrewboyson 55:e64b8b47a2b6 370 if (SYN) pTcb->locSeq += 1; //Add one to acknowledge the SYN
andrewboyson 55:e64b8b47a2b6 371 pTcb->locSeq += dataLength; //Record the next sequence number
andrewboyson 55:e64b8b47a2b6 372 if (FIN) pTcb->locSeq += 1; //Add one to acknowledge the FIN
andrewboyson 55:e64b8b47a2b6 373
andrewboyson 56:35117a8b5c65 374 positionInQuery = seqnum - pTcb->locIsn;
andrewboyson 56:35117a8b5c65 375 positionInReply = acknum - pTcb->remIsn;
andrewboyson 55:e64b8b47a2b6 376
andrewboyson 10:f0854784e960 377 srcPort = dstPort;
andrewboyson 10:f0854784e960 378 dstPort = pTcb->port;
andrewboyson 10:f0854784e960 379
andrewboyson 10:f0854784e960 380 *pSize = dataLength + headersize;
andrewboyson 54:84ef2b29cf7e 381
andrewboyson 55:e64b8b47a2b6 382 return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack);
andrewboyson 10:f0854784e960 383
andrewboyson 10:f0854784e960 384 }