Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

Committer:
andrewboyson
Date:
Mon Oct 22 10:24:58 2018 +0000
Revision:
72:19457bba58d0
Parent:
71:736a5747ade1
Child:
73:43e3d7fb3d60
Removed positioninquery and positioninreply variables. Working.

Who changed what in which revision?

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