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:
Mon Nov 13 21:46:31 2017 +0000
Revision:
55:e64b8b47a2b6
Parent:
54:84ef2b29cf7e
Child:
56:35117a8b5c65
Rearranged the TCP code

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 55:e64b8b47a2b6 52 static int positionInRequestStream;
andrewboyson 55:e64b8b47a2b6 53 static int positionInReplyStream;
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 55:e64b8b47a2b6 70 void TcpLogHeader(uint16_t calculatedChecksum, bool isSend)
andrewboyson 43:bc028d5a6424 71 {
andrewboyson 43:bc028d5a6424 72 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 73 {
andrewboyson 43:bc028d5a6424 74 Log("TCP header\r\n");
andrewboyson 43:bc028d5a6424 75 LogF(" Source port %hu\r\n", srcPort);
andrewboyson 43:bc028d5a6424 76 LogF(" Destination port %hu\r\n", dstPort);
andrewboyson 54:84ef2b29cf7e 77 if (isSend)
andrewboyson 54:84ef2b29cf7e 78 {
andrewboyson 55:e64b8b47a2b6 79 LogF(" Loc Seq number %u (%u)\r\n", seqnum - pTcb->locIsn, seqnum);
andrewboyson 55:e64b8b47a2b6 80 LogF(" Rem Ack number %u (%u)\r\n", acknum - pTcb->remIsn, acknum);
andrewboyson 54:84ef2b29cf7e 81 }
andrewboyson 54:84ef2b29cf7e 82 else
andrewboyson 54:84ef2b29cf7e 83 {
andrewboyson 55:e64b8b47a2b6 84 LogF(" Rem Seq number %u (%u)\r\n", seqnum - pTcb->remIsn, seqnum);
andrewboyson 55:e64b8b47a2b6 85 LogF(" Loc Ack number %u (%u)\r\n", acknum - pTcb->locIsn, acknum);
andrewboyson 54:84ef2b29cf7e 86 }
andrewboyson 43:bc028d5a6424 87 LogF(" Header size %u\r\n", headersize);
andrewboyson 52:fbc5a46b5e16 88 Log (" Flags "); logFlags(); Log("\r\n");
andrewboyson 43:bc028d5a6424 89 LogF(" Window %hu\r\n", window);
andrewboyson 43:bc028d5a6424 90 LogF(" Checksum (hex) %04hX\r\n", checksum);
andrewboyson 43:bc028d5a6424 91 LogF(" Calculated (hex) %04hX\r\n", calculatedChecksum);
andrewboyson 43:bc028d5a6424 92 LogF(" Urgent pointer %hu\r\n", urgent);
andrewboyson 43:bc028d5a6424 93 LogF(" Option length %d\r\n", optionLength);
andrewboyson 43:bc028d5a6424 94 LogF(" Data length %d\r\n", dataLength);
andrewboyson 54:84ef2b29cf7e 95 LogF(" locIsn %u\r\n", pTcb->locIsn);
andrewboyson 54:84ef2b29cf7e 96 LogF(" remIsn %u\r\n", pTcb->remIsn);
andrewboyson 54:84ef2b29cf7e 97 LogF(" locSeq %u\r\n", pTcb->locSeq);
andrewboyson 54:84ef2b29cf7e 98 LogF(" remSeq %u\r\n", pTcb->remSeq);
andrewboyson 54:84ef2b29cf7e 99
andrewboyson 43:bc028d5a6424 100 }
andrewboyson 43:bc028d5a6424 101 else
andrewboyson 43:bc028d5a6424 102 {
andrewboyson 44:83ce5ace337b 103 LogF("TCP header %hu >>> %hu", srcPort, dstPort);
andrewboyson 52:fbc5a46b5e16 104 logFlags();
andrewboyson 55:e64b8b47a2b6 105 if (isSend) LogF(", loc seq %u, rem ack %u", seqnum - pTcb->locIsn, acknum - pTcb->remIsn);
andrewboyson 55:e64b8b47a2b6 106 else LogF(", rem seq %u, loc ack %u", seqnum - pTcb->remIsn, acknum - pTcb->locIsn);
andrewboyson 52:fbc5a46b5e16 107 Log("\r\n");
andrewboyson 43:bc028d5a6424 108 }
andrewboyson 10:f0854784e960 109 }
andrewboyson 10:f0854784e960 110 void TcpAddChecksum(void* pPacket, uint16_t checksum)
andrewboyson 10:f0854784e960 111 {
andrewboyson 10:f0854784e960 112 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 113 pHeader->checksum = checksum;
andrewboyson 10:f0854784e960 114 }
andrewboyson 10:f0854784e960 115 static void readOptions()
andrewboyson 10:f0854784e960 116 {
andrewboyson 10:f0854784e960 117 mss = 536; //default MSS for IPv4 [576 - 20(TCP) - 20(IP)];
andrewboyson 10:f0854784e960 118 for (char* p = pOptions; p < pOptions + optionLength; p++)
andrewboyson 10:f0854784e960 119 {
andrewboyson 10:f0854784e960 120 switch (*p)
andrewboyson 10:f0854784e960 121 {
andrewboyson 10:f0854784e960 122 case 0: break; //End of options - used to pad to 32 bit boundary
andrewboyson 10:f0854784e960 123 case 1: break; //NOP, padding - optional
andrewboyson 10:f0854784e960 124 case 2:
andrewboyson 10:f0854784e960 125 p++;
andrewboyson 10:f0854784e960 126 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 10:f0854784e960 127 p++;
andrewboyson 10:f0854784e960 128 mss = ((uint16_t)*p) << 8;
andrewboyson 10:f0854784e960 129 p++;
andrewboyson 10:f0854784e960 130 mss += *p;
andrewboyson 10:f0854784e960 131 return;
andrewboyson 10:f0854784e960 132 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 10:f0854784e960 133 }
andrewboyson 10:f0854784e960 134 }
andrewboyson 10:f0854784e960 135 if (mss > MAX_MSS) mss = MAX_MSS;
andrewboyson 10:f0854784e960 136 }
andrewboyson 10:f0854784e960 137 static void writeOptions()
andrewboyson 10:f0854784e960 138 {
andrewboyson 10:f0854784e960 139 pOptions[0] = 2;
andrewboyson 10:f0854784e960 140 pOptions[1] = 4;
andrewboyson 10:f0854784e960 141 pOptions[2] = mss >> 8;
andrewboyson 10:f0854784e960 142 pOptions[3] = mss & 0xFF;
andrewboyson 10:f0854784e960 143 optionLength = 4;
andrewboyson 10:f0854784e960 144 }
andrewboyson 10:f0854784e960 145
andrewboyson 10:f0854784e960 146 void TcpReadHeader(void* pPacket, uint16_t size)
andrewboyson 10:f0854784e960 147 {
andrewboyson 10:f0854784e960 148 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 149
andrewboyson 10:f0854784e960 150 srcPort = NetToHost16(pHeader->srcPort);
andrewboyson 10:f0854784e960 151 dstPort = NetToHost16(pHeader->dstPort);
andrewboyson 10:f0854784e960 152 seqnum = NetToHost32(pHeader->seqnum);
andrewboyson 10:f0854784e960 153 acknum = NetToHost32(pHeader->acknum);
andrewboyson 10:f0854784e960 154 headersize = (pHeader->dataOffset >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 10:f0854784e960 155 flags = pHeader->flags;
andrewboyson 10:f0854784e960 156 URG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 10:f0854784e960 157 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 10:f0854784e960 158 PSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 10:f0854784e960 159 RST = flags & 0x04; //Reset the connection
andrewboyson 10:f0854784e960 160 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 10:f0854784e960 161 FIN = flags & 0x01; //No more data from sender
andrewboyson 10:f0854784e960 162
andrewboyson 10:f0854784e960 163 window = NetToHost16(pHeader->window);
andrewboyson 10:f0854784e960 164 checksum = NetToHost16(pHeader->checksum);
andrewboyson 10:f0854784e960 165 urgent = NetToHost16(pHeader->urgent);
andrewboyson 10:f0854784e960 166 pOptions = (char*)pPacket + 20;
andrewboyson 10:f0854784e960 167 optionLength = headersize - 20;
andrewboyson 10:f0854784e960 168
andrewboyson 10:f0854784e960 169 pData = (char*)pPacket + headersize;
andrewboyson 10:f0854784e960 170 dataLength = size - headersize;
andrewboyson 10:f0854784e960 171 }
andrewboyson 10:f0854784e960 172
andrewboyson 10:f0854784e960 173 void TcpMakeHeader(int size, void* pPacket)
andrewboyson 10:f0854784e960 174 {
andrewboyson 10:f0854784e960 175 struct header* pHeader = (header*)pPacket;
andrewboyson 10:f0854784e960 176
andrewboyson 10:f0854784e960 177 pHeader->dstPort = NetToHost16(dstPort);
andrewboyson 10:f0854784e960 178 pHeader->srcPort = NetToHost16(srcPort);
andrewboyson 10:f0854784e960 179 pHeader->seqnum = NetToHost32(seqnum); //This is the sequence number of the first byte of this message
andrewboyson 10:f0854784e960 180 pHeader->acknum = NetToHost32(acknum); //This is the sequence number we expect in the next message
andrewboyson 10:f0854784e960 181 pHeader->dataOffset = headersize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 10:f0854784e960 182 flags = 0;
andrewboyson 10:f0854784e960 183 if(URG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 10:f0854784e960 184 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 10:f0854784e960 185 if(PSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 10:f0854784e960 186 if(RST) flags |= 0x04; //Reset the connection
andrewboyson 10:f0854784e960 187 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 10:f0854784e960 188 if(FIN) flags |= 0x01; //No more data from sender
andrewboyson 10:f0854784e960 189 pHeader->flags = flags;
andrewboyson 10:f0854784e960 190 pHeader->window = NetToHost16(window);
andrewboyson 10:f0854784e960 191 pHeader->urgent = NetToHost16(urgent);
andrewboyson 10:f0854784e960 192
andrewboyson 10:f0854784e960 193 pHeader->checksum = 0;
andrewboyson 10:f0854784e960 194 }
andrewboyson 55:e64b8b47a2b6 195 static void makeRST()
andrewboyson 55:e64b8b47a2b6 196 {
andrewboyson 55:e64b8b47a2b6 197 dataLength = 0;
andrewboyson 55:e64b8b47a2b6 198 headersize = 20;
andrewboyson 55:e64b8b47a2b6 199 seqnum = acknum;
andrewboyson 55:e64b8b47a2b6 200 acknum = 0;
andrewboyson 55:e64b8b47a2b6 201 ACK = false;
andrewboyson 55:e64b8b47a2b6 202 PSH = false;
andrewboyson 55:e64b8b47a2b6 203 RST = true;
andrewboyson 55:e64b8b47a2b6 204 SYN = false;
andrewboyson 55:e64b8b47a2b6 205 FIN = false;
andrewboyson 55:e64b8b47a2b6 206 }
andrewboyson 54:84ef2b29cf7e 207 static int stateClosed()
andrewboyson 10:f0854784e960 208 {
andrewboyson 10:f0854784e960 209 if (!SYN) //Reset if anything other than a request to establish conection from client
andrewboyson 10:f0854784e960 210 {
andrewboyson 55:e64b8b47a2b6 211 if (TcpTrace) LogTimeF("TCP did not received other than a SYN when closed - sent reset.\r\n");
andrewboyson 55:e64b8b47a2b6 212 makeRST();
andrewboyson 10:f0854784e960 213 return 1;
andrewboyson 10:f0854784e960 214 }
andrewboyson 10:f0854784e960 215
andrewboyson 10:f0854784e960 216 readOptions(); //Get the MSS
andrewboyson 52:fbc5a46b5e16 217 pTcb->mss = mss;
andrewboyson 52:fbc5a46b5e16 218 pTcb->state = TCB_SYN_RECEIVED;
andrewboyson 52:fbc5a46b5e16 219 pTcb->elapsed = TcbElapsed;
andrewboyson 52:fbc5a46b5e16 220 pTcb->port = srcPort;
andrewboyson 55:e64b8b47a2b6 221
andrewboyson 10:f0854784e960 222 dataLength = 0;
andrewboyson 10:f0854784e960 223
andrewboyson 10:f0854784e960 224 mss = MAX_MSS; //Ethernet 1500 - 20 - 20; or, in our case 768 - 20 - 20
andrewboyson 10:f0854784e960 225 writeOptions();
andrewboyson 10:f0854784e960 226 headersize = 24; //20 header plus 4 option
andrewboyson 10:f0854784e960 227
andrewboyson 10:f0854784e960 228 ACK = true; //Send ACK and SYN
andrewboyson 10:f0854784e960 229 PSH = false;
andrewboyson 10:f0854784e960 230 RST = false;
andrewboyson 10:f0854784e960 231 SYN = true;
andrewboyson 10:f0854784e960 232 FIN = false;
andrewboyson 10:f0854784e960 233
andrewboyson 10:f0854784e960 234 return 1;
andrewboyson 10:f0854784e960 235 }
andrewboyson 54:84ef2b29cf7e 236 static int stateSynReceived()
andrewboyson 10:f0854784e960 237 {
andrewboyson 55:e64b8b47a2b6 238 if (dataLength) LogTimeF("%d bytes data received before TCB established - ignoring\r\n", dataLength);
andrewboyson 10:f0854784e960 239 if (ACK)
andrewboyson 10:f0854784e960 240 {
andrewboyson 52:fbc5a46b5e16 241 pTcb->state = TCB_ESTABLISHED;
andrewboyson 52:fbc5a46b5e16 242 pTcb->elapsed = TcbElapsed;
andrewboyson 54:84ef2b29cf7e 243 pTcb->todo = 0;
andrewboyson 10:f0854784e960 244 }
andrewboyson 10:f0854784e960 245 return 0;
andrewboyson 10:f0854784e960 246 }
andrewboyson 54:84ef2b29cf7e 247 static int stateEstablished()
andrewboyson 10:f0854784e960 248 {
andrewboyson 10:f0854784e960 249 if (!ACK) return 0; //Ignore any packets which don't contain an ACK
andrewboyson 10:f0854784e960 250
andrewboyson 10:f0854784e960 251 //Handle reception of data
andrewboyson 54:84ef2b29cf7e 252 char* pRequestStream = pData;
andrewboyson 54:84ef2b29cf7e 253 char* pReplyStream = pOptions;
andrewboyson 54:84ef2b29cf7e 254
andrewboyson 55:e64b8b47a2b6 255 HttpHandleRequest(&dataLength, pRequestStream, positionInRequestStream - 1, pReplyStream, positionInReplyStream - 1, mss, &pTcb->todo);
andrewboyson 10:f0854784e960 256
andrewboyson 10:f0854784e960 257 //Rearrange the buffers
andrewboyson 10:f0854784e960 258 headersize = 20;
andrewboyson 54:84ef2b29cf7e 259 pData = pReplyStream;
andrewboyson 55:e64b8b47a2b6 260
andrewboyson 10:f0854784e960 261 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 262 RST = false;
andrewboyson 10:f0854784e960 263 SYN = false;
andrewboyson 22:914b970356f0 264 PSH = false;
andrewboyson 10:f0854784e960 265
andrewboyson 22:914b970356f0 266 if (dataLength < mss) //If a part packet then there can be no more to send
andrewboyson 10:f0854784e960 267 {
andrewboyson 22:914b970356f0 268 FIN = true; //Inform the client that we have no more to send after this
andrewboyson 10:f0854784e960 269 pTcb->state = TCB_CLOSING; //Start closing
andrewboyson 10:f0854784e960 270 }
andrewboyson 22:914b970356f0 271
andrewboyson 52:fbc5a46b5e16 272 pTcb->elapsed = TcbElapsed;
andrewboyson 10:f0854784e960 273 return 1;
andrewboyson 10:f0854784e960 274 }
andrewboyson 54:84ef2b29cf7e 275 static int stateClosing()
andrewboyson 10:f0854784e960 276 {
andrewboyson 10:f0854784e960 277 if (!FIN) return 0; //Ignore any packets which don't contain a FIN
andrewboyson 55:e64b8b47a2b6 278
andrewboyson 10:f0854784e960 279 ACK = true; //Send ACK
andrewboyson 10:f0854784e960 280 PSH = false;
andrewboyson 10:f0854784e960 281 RST = false;
andrewboyson 10:f0854784e960 282 SYN = false;
andrewboyson 10:f0854784e960 283 FIN = false;
andrewboyson 10:f0854784e960 284
andrewboyson 10:f0854784e960 285 headersize = 20;
andrewboyson 10:f0854784e960 286 dataLength = 0;
andrewboyson 10:f0854784e960 287
andrewboyson 10:f0854784e960 288 pTcb->state = TCB_CLOSED;
andrewboyson 10:f0854784e960 289
andrewboyson 10:f0854784e960 290 return 1;
andrewboyson 10:f0854784e960 291 }
andrewboyson 10:f0854784e960 292
andrewboyson 37:793b39683406 293 int TcpHandleReceivedPacket(void (*traceback)(void), int* pSize, void* pPacket)
andrewboyson 10:f0854784e960 294 {
andrewboyson 54:84ef2b29cf7e 295 pTraceback = traceback;
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 52:fbc5a46b5e16 304 LogTime("TCP no more tcbs are available\r\n");
andrewboyson 55:e64b8b47a2b6 305 pTraceback(); //This will already include the TCP header
andrewboyson 52:fbc5a46b5e16 306 }
andrewboyson 52:fbc5a46b5e16 307 return DO_NOTHING; //Bomb out if no more tcbs are available
andrewboyson 52:fbc5a46b5e16 308 }
andrewboyson 10:f0854784e960 309
andrewboyson 55:e64b8b47a2b6 310 //Handle request to reset
andrewboyson 10:f0854784e960 311 if (RST)
andrewboyson 10:f0854784e960 312 {
andrewboyson 10:f0854784e960 313 pTcb->state = TCB_CLOSED; //Reset connection
andrewboyson 10:f0854784e960 314 return DO_NOTHING; //Bomb out
andrewboyson 10:f0854784e960 315 }
andrewboyson 55:e64b8b47a2b6 316
andrewboyson 55:e64b8b47a2b6 317 //Handle request to synchronise
andrewboyson 55:e64b8b47a2b6 318 if (SYN)
andrewboyson 55:e64b8b47a2b6 319 {
andrewboyson 55:e64b8b47a2b6 320 pTcb->remIsn = seqnum;
andrewboyson 55:e64b8b47a2b6 321 pTcb->remSeq = pTcb->remIsn;
andrewboyson 55:e64b8b47a2b6 322 pTcb->locIsn = TcbGetIsn();
andrewboyson 55:e64b8b47a2b6 323 pTcb->locSeq = pTcb->locIsn;
andrewboyson 55:e64b8b47a2b6 324 acknum = pTcb->locIsn;
andrewboyson 55:e64b8b47a2b6 325 }
andrewboyson 55:e64b8b47a2b6 326
andrewboyson 55:e64b8b47a2b6 327 //Check the sequence is not lost or out of order
andrewboyson 55:e64b8b47a2b6 328 if (seqnum != pTcb->remSeq)
andrewboyson 55:e64b8b47a2b6 329 {
andrewboyson 55:e64b8b47a2b6 330 LogTimeF("TCP had sequence %u but expected %u\r\n", seqnum, pTcb->remSeq);
andrewboyson 55:e64b8b47a2b6 331 }
andrewboyson 55:e64b8b47a2b6 332
andrewboyson 55:e64b8b47a2b6 333 //Check the remote host has received all bytes
andrewboyson 55:e64b8b47a2b6 334 if (acknum != pTcb->locSeq)
andrewboyson 55:e64b8b47a2b6 335 {
andrewboyson 55:e64b8b47a2b6 336 LogTimeF("TCP acknowledged %u but expected %u\r\n", acknum, pTcb->locSeq);
andrewboyson 55:e64b8b47a2b6 337 }
andrewboyson 55:e64b8b47a2b6 338
andrewboyson 55:e64b8b47a2b6 339 positionInRequestStream = seqnum - pTcb->remIsn;
andrewboyson 55:e64b8b47a2b6 340 positionInReplyStream = acknum - pTcb->locIsn;
andrewboyson 10:f0854784e960 341
andrewboyson 52:fbc5a46b5e16 342 //Filter out unwanted links
andrewboyson 10:f0854784e960 343 switch (dstPort)
andrewboyson 10:f0854784e960 344 {
andrewboyson 55:e64b8b47a2b6 345 case 80:
andrewboyson 55:e64b8b47a2b6 346 doTrace = HttpTrace;
andrewboyson 55:e64b8b47a2b6 347 if (doTrace)
andrewboyson 52:fbc5a46b5e16 348 {
andrewboyson 55:e64b8b47a2b6 349 if (NetTraceNewLine) Log("\r\n");
andrewboyson 55:e64b8b47a2b6 350 LogTime("HTTP server request\r\n");
andrewboyson 52:fbc5a46b5e16 351 }
andrewboyson 55:e64b8b47a2b6 352 break;
andrewboyson 55:e64b8b47a2b6 353
andrewboyson 55:e64b8b47a2b6 354 default:
andrewboyson 55:e64b8b47a2b6 355 doTrace = TcpTrace;
andrewboyson 55:e64b8b47a2b6 356 if (doTrace)
andrewboyson 55:e64b8b47a2b6 357 {
andrewboyson 55:e64b8b47a2b6 358 if (NetTraceNewLine) Log("\r\n");
andrewboyson 55:e64b8b47a2b6 359 LogTimeF("TCP unknown port %d\r\n", dstPort);
andrewboyson 55:e64b8b47a2b6 360 }
andrewboyson 55:e64b8b47a2b6 361 return DO_NOTHING; //Ignore unknown ports
andrewboyson 52:fbc5a46b5e16 362 }
andrewboyson 55:e64b8b47a2b6 363 if (doTrace && NetTraceStack) pTraceback(); //This will already include the TCP header
andrewboyson 55:e64b8b47a2b6 364
andrewboyson 55:e64b8b47a2b6 365 if (SYN) pTcb->remSeq += 1; //Add one to acknowledge the SYN
andrewboyson 55:e64b8b47a2b6 366 pTcb->remSeq += dataLength; //Add the number of bytes received
andrewboyson 55:e64b8b47a2b6 367 if (FIN) pTcb->remSeq += 1; //Add one to acknowledge the FIN
andrewboyson 55:e64b8b47a2b6 368 acknum = pTcb->remSeq; //Set up the acknowledgement field ready to send
andrewboyson 10:f0854784e960 369
andrewboyson 10:f0854784e960 370 switch (pTcb->state)
andrewboyson 10:f0854784e960 371 {
andrewboyson 54:84ef2b29cf7e 372 case TCB_CLOSED: if (stateClosed ()) break; return DO_NOTHING;
andrewboyson 54:84ef2b29cf7e 373 case TCB_SYN_RECEIVED: if (stateSynReceived()) break; return DO_NOTHING;
andrewboyson 54:84ef2b29cf7e 374 case TCB_ESTABLISHED: if (stateEstablished()) break; return DO_NOTHING;
andrewboyson 54:84ef2b29cf7e 375 case TCB_CLOSING: if (stateClosing ()) break; return DO_NOTHING;
andrewboyson 10:f0854784e960 376 }
andrewboyson 10:f0854784e960 377
andrewboyson 55:e64b8b47a2b6 378 seqnum = pTcb->locSeq; //Set the sequence number to the first byte of this message
andrewboyson 55:e64b8b47a2b6 379 if (SYN) pTcb->locSeq += 1; //Add one to acknowledge the SYN
andrewboyson 55:e64b8b47a2b6 380 pTcb->locSeq += dataLength; //Record the next sequence number
andrewboyson 55:e64b8b47a2b6 381 if (FIN) pTcb->locSeq += 1; //Add one to acknowledge the FIN
andrewboyson 55:e64b8b47a2b6 382
andrewboyson 55:e64b8b47a2b6 383
andrewboyson 10:f0854784e960 384 srcPort = dstPort;
andrewboyson 10:f0854784e960 385 dstPort = pTcb->port;
andrewboyson 10:f0854784e960 386
andrewboyson 10:f0854784e960 387 *pSize = dataLength + headersize;
andrewboyson 54:84ef2b29cf7e 388
andrewboyson 55:e64b8b47a2b6 389 return ActionMakeFromDestAndTrace(UNICAST, doTrace && NetTraceStack);
andrewboyson 10:f0854784e960 390
andrewboyson 10:f0854784e960 391 }