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:
Thu Apr 02 19:08:25 2020 +0000
Revision:
167:3ba4e3c49631
Parent:
156:be12b8fd5b21
Modified resolution cache ajaxs to include the index

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 73:43e3d7fb3d60 1 #include <stdint.h>
andrewboyson 73:43e3d7fb3d60 2 #include <stdbool.h>
andrewboyson 73:43e3d7fb3d60 3
andrewboyson 98:b977424ec7f7 4 #include "log.h"
andrewboyson 98:b977424ec7f7 5 #include "net.h"
andrewboyson 142:a8c0890a58d1 6 #include "restart.h"
andrewboyson 73:43e3d7fb3d60 7
andrewboyson 137:cf6e7db0e985 8 static char* hdrPtrSrcPort (char* pPacket) { return pPacket + 0; } //2
andrewboyson 137:cf6e7db0e985 9 static char* hdrPtrDstPort (char* pPacket) { return pPacket + 2; } //2
andrewboyson 137:cf6e7db0e985 10 static char* hdrPtrSeqnum (char* pPacket) { return pPacket + 4; } //4
andrewboyson 137:cf6e7db0e985 11 static char* hdrPtrAcknum (char* pPacket) { return pPacket + 8; } //4
andrewboyson 137:cf6e7db0e985 12 static char* hdrPtrDataOffset(char* pPacket) { return pPacket + 12; } //1
andrewboyson 137:cf6e7db0e985 13 static char* hdrPtrFlags (char* pPacket) { return pPacket + 13; } //1
andrewboyson 137:cf6e7db0e985 14 static char* hdrPtrWindow (char* pPacket) { return pPacket + 14; } //2
andrewboyson 137:cf6e7db0e985 15 static char* hdrPtrChecksum (char* pPacket) { return pPacket + 16; } //2
andrewboyson 137:cf6e7db0e985 16 static char* hdrPtrUrgent (char* pPacket) { return pPacket + 18; } //2
andrewboyson 137:cf6e7db0e985 17 static const int HEADER_LENGTH = 20;
andrewboyson 137:cf6e7db0e985 18
andrewboyson 137:cf6e7db0e985 19 void TcpHdrSetChecksum (char* pPacket, uint16_t value) { NetDirect16(hdrPtrChecksum (pPacket), &value); } //The checksum is calculated inverted so don't re-invert here
andrewboyson 73:43e3d7fb3d60 20
andrewboyson 73:43e3d7fb3d60 21 //Header variables
andrewboyson 73:43e3d7fb3d60 22 uint16_t TcpHdrSrcPort;
andrewboyson 73:43e3d7fb3d60 23 uint16_t TcpHdrDstPort;
andrewboyson 73:43e3d7fb3d60 24 uint32_t TcpHdrSeqNum;
andrewboyson 73:43e3d7fb3d60 25 uint32_t TcpHdrAckNum;
andrewboyson 73:43e3d7fb3d60 26 bool TcpHdrURG; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 27 bool TcpHdrACK; //indicates that the Acknowledgment field is significant. All packets after the initial SYN packet sent by the client should have this flag set.
andrewboyson 73:43e3d7fb3d60 28 bool TcpHdrPSH; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 29 bool TcpHdrRST; //Reset the connection
andrewboyson 73:43e3d7fb3d60 30 bool TcpHdrSYN; //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 73:43e3d7fb3d60 31 bool TcpHdrFIN; //No more data from sender
andrewboyson 73:43e3d7fb3d60 32 uint16_t TcpHdrWindow;
andrewboyson 73:43e3d7fb3d60 33 uint16_t TcpHdrChecksum;
andrewboyson 73:43e3d7fb3d60 34 uint16_t TcpHdrUrgent;
andrewboyson 73:43e3d7fb3d60 35
andrewboyson 74:c3756bfa960e 36 //Side effects
andrewboyson 74:c3756bfa960e 37 static int headerSize;
andrewboyson 74:c3756bfa960e 38 int TcpHdrSizeGet() { return headerSize; }
andrewboyson 73:43e3d7fb3d60 39
andrewboyson 74:c3756bfa960e 40 static uint16_t mss = 0;
andrewboyson 74:c3756bfa960e 41 void TcpHdrMssSet(uint16_t value)
andrewboyson 73:43e3d7fb3d60 42 {
andrewboyson 74:c3756bfa960e 43 mss = value;
andrewboyson 137:cf6e7db0e985 44 headerSize = HEADER_LENGTH;
andrewboyson 74:c3756bfa960e 45 if (mss) headerSize += 4;
andrewboyson 73:43e3d7fb3d60 46 }
andrewboyson 74:c3756bfa960e 47 uint16_t TcpHdrMssGet() { return mss; }
andrewboyson 73:43e3d7fb3d60 48
andrewboyson 73:43e3d7fb3d60 49 static void logFlags()
andrewboyson 73:43e3d7fb3d60 50 {
andrewboyson 73:43e3d7fb3d60 51 if (TcpHdrURG) Log(" URG");
andrewboyson 73:43e3d7fb3d60 52 if (TcpHdrACK) Log(" ACK");
andrewboyson 73:43e3d7fb3d60 53 if (TcpHdrPSH) Log(" PSH");
andrewboyson 73:43e3d7fb3d60 54 if (TcpHdrRST) Log(" RST");
andrewboyson 73:43e3d7fb3d60 55 if (TcpHdrSYN) Log(" SYN");
andrewboyson 73:43e3d7fb3d60 56 if (TcpHdrFIN) Log(" FIN");
andrewboyson 73:43e3d7fb3d60 57 }
andrewboyson 73:43e3d7fb3d60 58 void TcpHdrLog(uint16_t calculatedChecksum)
andrewboyson 73:43e3d7fb3d60 59 {
andrewboyson 73:43e3d7fb3d60 60 if (NetTraceVerbose)
andrewboyson 73:43e3d7fb3d60 61 {
andrewboyson 73:43e3d7fb3d60 62 Log("TCP header\r\n");
andrewboyson 73:43e3d7fb3d60 63 Log(" Source port "); LogF("%hu", TcpHdrSrcPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 64 Log(" Destination port "); LogF("%hu", TcpHdrDstPort ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 65 Log(" Seq number "); LogF("%u", TcpHdrSeqNum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 66 Log(" Ack number "); LogF("%u", TcpHdrAckNum ); Log("\r\n");
andrewboyson 74:c3756bfa960e 67 Log(" Header size "); LogF("%u", headerSize ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 68 Log(" Flags " ); logFlags( ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 69 Log(" Window "); LogF("%hu", TcpHdrWindow ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 70 Log(" Checksum (hex) "); LogF("%04hX", TcpHdrChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 71 Log(" Calculated (hex) "); LogF("%04hX", calculatedChecksum ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 72 Log(" Urgent pointer "); LogF("%hu", TcpHdrUrgent ); Log("\r\n");
andrewboyson 73:43e3d7fb3d60 73
andrewboyson 73:43e3d7fb3d60 74 }
andrewboyson 73:43e3d7fb3d60 75 else
andrewboyson 73:43e3d7fb3d60 76 {
andrewboyson 73:43e3d7fb3d60 77 LogF("TCP header %hu >>> %hu", TcpHdrSrcPort, TcpHdrDstPort);
andrewboyson 73:43e3d7fb3d60 78 logFlags();
andrewboyson 73:43e3d7fb3d60 79 Log("\r\n");
andrewboyson 73:43e3d7fb3d60 80 }
andrewboyson 73:43e3d7fb3d60 81 }
andrewboyson 137:cf6e7db0e985 82 void TcpHdrReadFromPacket(char* pPacket)
andrewboyson 73:43e3d7fb3d60 83 {
andrewboyson 142:a8c0890a58d1 84 int lastRestartPoint = RestartPoint;
andrewboyson 142:a8c0890a58d1 85 RestartPoint = FAULT_POINT_TcpHdrReadFromPacket;
andrewboyson 74:c3756bfa960e 86
andrewboyson 137:cf6e7db0e985 87 NetInvert16(&TcpHdrSrcPort, hdrPtrSrcPort (pPacket));
andrewboyson 137:cf6e7db0e985 88 NetInvert16(&TcpHdrDstPort, hdrPtrDstPort (pPacket));
andrewboyson 137:cf6e7db0e985 89 NetInvert32(&TcpHdrSeqNum, hdrPtrSeqnum (pPacket));
andrewboyson 137:cf6e7db0e985 90 NetInvert32(&TcpHdrAckNum, hdrPtrAcknum (pPacket));
andrewboyson 137:cf6e7db0e985 91 headerSize = (*hdrPtrDataOffset(pPacket) >> 2) & 0xFC; //Same as right shifting by 4 bits and multiplying by 4
andrewboyson 137:cf6e7db0e985 92 uint8_t flags = *hdrPtrFlags (pPacket);
andrewboyson 74:c3756bfa960e 93 TcpHdrURG = flags & 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 74:c3756bfa960e 94 TcpHdrACK = 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 74:c3756bfa960e 95 TcpHdrPSH = flags & 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 74:c3756bfa960e 96 TcpHdrRST = flags & 0x04; //Reset the connection
andrewboyson 74:c3756bfa960e 97 TcpHdrSYN = 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 74:c3756bfa960e 98 TcpHdrFIN = flags & 0x01; //No more data from sender
andrewboyson 137:cf6e7db0e985 99 NetInvert16(&TcpHdrWindow, hdrPtrWindow (pPacket));
andrewboyson 137:cf6e7db0e985 100 NetInvert16(&TcpHdrChecksum, hdrPtrChecksum (pPacket));
andrewboyson 137:cf6e7db0e985 101 NetInvert16(&TcpHdrUrgent, hdrPtrUrgent (pPacket));
andrewboyson 74:c3756bfa960e 102
andrewboyson 138:5ff0c7069300 103 char* pOptions = pPacket + HEADER_LENGTH;
andrewboyson 138:5ff0c7069300 104 int optionLength = headerSize - HEADER_LENGTH;
andrewboyson 73:43e3d7fb3d60 105
andrewboyson 74:c3756bfa960e 106 mss = 0;
andrewboyson 88:1ba13e6062a3 107 for (char* p = pOptions; p < pOptions + optionLength; p++) //If the header size is zero then optionLength will be negative and the for loop will do nothing.
andrewboyson 73:43e3d7fb3d60 108 {
andrewboyson 73:43e3d7fb3d60 109 switch (*p)
andrewboyson 73:43e3d7fb3d60 110 {
andrewboyson 142:a8c0890a58d1 111 case 0: RestartPoint = lastRestartPoint; return; //End of options so stop
andrewboyson 88:1ba13e6062a3 112 case 1: break; //NOP, padding - optional used to pad to 32 bit boundary
andrewboyson 73:43e3d7fb3d60 113 case 2:
andrewboyson 73:43e3d7fb3d60 114 p++;
andrewboyson 73:43e3d7fb3d60 115 if (*p != 4) LogTimeF("MSS option width %d when expected 4\r\n", *p);
andrewboyson 73:43e3d7fb3d60 116 p++;
andrewboyson 74:c3756bfa960e 117 mss = ((uint16_t)*p) << 8;
andrewboyson 73:43e3d7fb3d60 118 p++;
andrewboyson 74:c3756bfa960e 119 mss += *p;
andrewboyson 142:a8c0890a58d1 120 RestartPoint = lastRestartPoint;
andrewboyson 88:1ba13e6062a3 121 return; //Got what we want so stop
andrewboyson 73:43e3d7fb3d60 122 default: LogTimeF("Unrecognised TCP option %d\r\n", *p);
andrewboyson 73:43e3d7fb3d60 123 }
andrewboyson 73:43e3d7fb3d60 124 }
andrewboyson 142:a8c0890a58d1 125 RestartPoint = lastRestartPoint;
andrewboyson 73:43e3d7fb3d60 126 }
andrewboyson 73:43e3d7fb3d60 127
andrewboyson 137:cf6e7db0e985 128 void TcpHdrWriteToPacket(char* pPacket)
andrewboyson 73:43e3d7fb3d60 129 {
andrewboyson 137:cf6e7db0e985 130 headerSize = HEADER_LENGTH;
andrewboyson 156:be12b8fd5b21 131 if (mss)
andrewboyson 74:c3756bfa960e 132 {
andrewboyson 137:cf6e7db0e985 133 char* pOptions = pPacket + headerSize;
andrewboyson 74:c3756bfa960e 134 pOptions[0] = 2;
andrewboyson 74:c3756bfa960e 135 pOptions[1] = 4;
andrewboyson 74:c3756bfa960e 136 pOptions[2] = mss >> 8;
andrewboyson 74:c3756bfa960e 137 pOptions[3] = mss & 0xFF;
andrewboyson 74:c3756bfa960e 138 headerSize += 4;
andrewboyson 74:c3756bfa960e 139 }
andrewboyson 74:c3756bfa960e 140
andrewboyson 137:cf6e7db0e985 141 NetInvert16(hdrPtrDstPort (pPacket), &TcpHdrDstPort);
andrewboyson 137:cf6e7db0e985 142 NetInvert16(hdrPtrSrcPort (pPacket), &TcpHdrSrcPort);
andrewboyson 137:cf6e7db0e985 143 NetInvert32(hdrPtrSeqnum (pPacket), &TcpHdrSeqNum ); //This is the sequence number of the first byte of this message
andrewboyson 137:cf6e7db0e985 144 NetInvert32(hdrPtrAcknum (pPacket), &TcpHdrAckNum ); //This is the sequence number we expect in the next message
andrewboyson 137:cf6e7db0e985 145 *hdrPtrDataOffset(pPacket) = headerSize << 2; //Same as dividing by 4 to get bytes and left shifting by 4 bits
andrewboyson 73:43e3d7fb3d60 146 uint8_t flags = 0;
andrewboyson 73:43e3d7fb3d60 147 if (TcpHdrURG) flags |= 0x20; //indicates that the Urgent pointer field is significant
andrewboyson 73:43e3d7fb3d60 148 if (TcpHdrACK) 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 73:43e3d7fb3d60 149 if (TcpHdrPSH) flags |= 0x08; //Push function. Asks to push the buffered data to the receiving application.
andrewboyson 73:43e3d7fb3d60 150 if (TcpHdrRST) flags |= 0x04; //Reset the connection
andrewboyson 73:43e3d7fb3d60 151 if (TcpHdrSYN) 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 73:43e3d7fb3d60 152 if (TcpHdrFIN) flags |= 0x01; //No more data from sender
andrewboyson 137:cf6e7db0e985 153 *hdrPtrFlags (pPacket) = flags;
andrewboyson 137:cf6e7db0e985 154 NetInvert16(hdrPtrWindow (pPacket), &TcpHdrWindow);
andrewboyson 137:cf6e7db0e985 155 NetInvert16(hdrPtrUrgent (pPacket), &TcpHdrUrgent);
andrewboyson 137:cf6e7db0e985 156 TcpHdrSetChecksum( pPacket, 0);
andrewboyson 74:c3756bfa960e 157 }
andrewboyson 74:c3756bfa960e 158
andrewboyson 74:c3756bfa960e 159 void TcpHdrMakeEmpty()
andrewboyson 74:c3756bfa960e 160 {
andrewboyson 74:c3756bfa960e 161 TcpHdrSrcPort = 0;
andrewboyson 74:c3756bfa960e 162 TcpHdrDstPort = 0;
andrewboyson 74:c3756bfa960e 163 TcpHdrSeqNum = 0;
andrewboyson 74:c3756bfa960e 164 TcpHdrAckNum = 0;
andrewboyson 137:cf6e7db0e985 165 headerSize = HEADER_LENGTH;
andrewboyson 74:c3756bfa960e 166 TcpHdrURG = 0;
andrewboyson 74:c3756bfa960e 167 TcpHdrACK = 0;
andrewboyson 74:c3756bfa960e 168 TcpHdrPSH = 0;
andrewboyson 74:c3756bfa960e 169 TcpHdrRST = 0;
andrewboyson 74:c3756bfa960e 170 TcpHdrSYN = 0;
andrewboyson 74:c3756bfa960e 171 TcpHdrFIN = 0;
andrewboyson 74:c3756bfa960e 172 TcpHdrWindow = 0;
andrewboyson 74:c3756bfa960e 173 TcpHdrChecksum = 0;
andrewboyson 74:c3756bfa960e 174 TcpHdrUrgent = 0;
andrewboyson 74:c3756bfa960e 175 mss = 0;
andrewboyson 74:c3756bfa960e 176
andrewboyson 73:43e3d7fb3d60 177 }