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 May 20 14:32:52 2021 +0000
Revision:
200:5acbc41bf469
Parent:
193:47a953ab571b
Increased number of arp entries from 20 to 30 to accommodate the number of WIZ devices plus a few incoming port 80 calls from the internet.

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 60:1d8c7a1e7483 4 #include "log.h"
andrewboyson 93:580fc113d9e9 5 #include "mstimer.h"
andrewboyson 60:1d8c7a1e7483 6 #include "net.h"
andrewboyson 60:1d8c7a1e7483 7 #include "mac.h"
andrewboyson 60:1d8c7a1e7483 8 #include "ip6addr.h"
andrewboyson 60:1d8c7a1e7483 9 #include "ns.h"
andrewboyson 60:1d8c7a1e7483 10 #include "http.h"
andrewboyson 60:1d8c7a1e7483 11
andrewboyson 60:1d8c7a1e7483 12 bool Ar6Trace = false;
andrewboyson 60:1d8c7a1e7483 13
andrewboyson 93:580fc113d9e9 14 #define CACHE_TIMEOUT_MS 3600 * 1000
andrewboyson 93:580fc113d9e9 15 #define FREEZE_TIMEOUT_MS 1800 * 1000
andrewboyson 116:60521b29e4c9 16 #define REPLY_TIMEOUT_MS 1 * 1000
andrewboyson 60:1d8c7a1e7483 17 #define SEND_ATTEMPTS 3
andrewboyson 60:1d8c7a1e7483 18 #define RECORDS_COUNT 20
andrewboyson 60:1d8c7a1e7483 19
andrewboyson 60:1d8c7a1e7483 20 #define STATE_EMPTY 0
andrewboyson 60:1d8c7a1e7483 21 #define STATE_WANT 1
andrewboyson 60:1d8c7a1e7483 22 #define STATE_SENT 2
andrewboyson 60:1d8c7a1e7483 23 #define STATE_VALID 3
andrewboyson 60:1d8c7a1e7483 24
andrewboyson 60:1d8c7a1e7483 25 struct record
andrewboyson 60:1d8c7a1e7483 26 {
andrewboyson 60:1d8c7a1e7483 27 uint32_t elapsed;
andrewboyson 60:1d8c7a1e7483 28 char ip[16];
andrewboyson 60:1d8c7a1e7483 29 uint8_t state;
andrewboyson 60:1d8c7a1e7483 30 uint8_t tries;
andrewboyson 60:1d8c7a1e7483 31 char mac[6];
andrewboyson 60:1d8c7a1e7483 32 };
andrewboyson 60:1d8c7a1e7483 33 static struct record records[RECORDS_COUNT];
andrewboyson 60:1d8c7a1e7483 34 static int getExistingIp(char* ip)
andrewboyson 60:1d8c7a1e7483 35 {
andrewboyson 60:1d8c7a1e7483 36 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 37 {
andrewboyson 172:9bc3c7b2cca1 38 if (records[i].state && Ip6AddrIsSame(records[i].ip, ip)) return i;
andrewboyson 60:1d8c7a1e7483 39 }
andrewboyson 60:1d8c7a1e7483 40 return -1;
andrewboyson 60:1d8c7a1e7483 41 }
andrewboyson 60:1d8c7a1e7483 42 static int getOldest()
andrewboyson 60:1d8c7a1e7483 43 {
andrewboyson 93:580fc113d9e9 44 int iOldest = 0;
andrewboyson 93:580fc113d9e9 45 uint32_t ageOldest = 0;
andrewboyson 60:1d8c7a1e7483 46 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 47 {
andrewboyson 60:1d8c7a1e7483 48 if (!records[i].state) return i; //Found an empty slot so just return it
andrewboyson 93:580fc113d9e9 49 uint32_t age = MsTimerCount - records[i].elapsed;
andrewboyson 93:580fc113d9e9 50 if (age >= ageOldest)
andrewboyson 60:1d8c7a1e7483 51 {
andrewboyson 93:580fc113d9e9 52 ageOldest = age;
andrewboyson 93:580fc113d9e9 53 iOldest = i;
andrewboyson 60:1d8c7a1e7483 54 }
andrewboyson 60:1d8c7a1e7483 55 }
andrewboyson 93:580fc113d9e9 56 return iOldest; //Otherwise return the oldest
andrewboyson 60:1d8c7a1e7483 57 }
andrewboyson 60:1d8c7a1e7483 58 void Ar6MakeRequestForMacFromIp(char* ip)
andrewboyson 60:1d8c7a1e7483 59 {
andrewboyson 60:1d8c7a1e7483 60 //Don't treat non ips
andrewboyson 60:1d8c7a1e7483 61 if (!ip[0]) return;
andrewboyson 60:1d8c7a1e7483 62 int i;
andrewboyson 60:1d8c7a1e7483 63
andrewboyson 60:1d8c7a1e7483 64 //If a record already exists then request an update
andrewboyson 60:1d8c7a1e7483 65 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 66 if (i > -1)
andrewboyson 60:1d8c7a1e7483 67 {
andrewboyson 133:a37eb35a03f1 68 if (!MsTimerRelative(records[i].elapsed, FREEZE_TIMEOUT_MS)) return;
andrewboyson 60:1d8c7a1e7483 69 if (Ar6Trace)
andrewboyson 60:1d8c7a1e7483 70 {
andrewboyson 60:1d8c7a1e7483 71 LogTime("AR6 Updated request for MAC of ");
andrewboyson 172:9bc3c7b2cca1 72 Ip6AddrLog(ip);
andrewboyson 60:1d8c7a1e7483 73 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 74 }
andrewboyson 60:1d8c7a1e7483 75 records[i].state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 76 records[i].tries = 0;
andrewboyson 93:580fc113d9e9 77 records[i].elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 78 return;
andrewboyson 60:1d8c7a1e7483 79 }
andrewboyson 60:1d8c7a1e7483 80
andrewboyson 60:1d8c7a1e7483 81 //If a record does not exist then find the first empty slot and add the IP and date
andrewboyson 60:1d8c7a1e7483 82 if (Ar6Trace)
andrewboyson 60:1d8c7a1e7483 83 {
andrewboyson 60:1d8c7a1e7483 84 LogTime("AR6 Made request for MAC of ");
andrewboyson 172:9bc3c7b2cca1 85 Ip6AddrLog(ip);
andrewboyson 60:1d8c7a1e7483 86 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 87 }
andrewboyson 60:1d8c7a1e7483 88 i = getOldest();
andrewboyson 172:9bc3c7b2cca1 89 Ip6AddrCopy(records[i].ip, ip);
andrewboyson 60:1d8c7a1e7483 90 records[i].state = STATE_WANT;
andrewboyson 60:1d8c7a1e7483 91 records[i].tries = 0;
andrewboyson 93:580fc113d9e9 92 records[i].elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 93 MacClear(records[i].mac);
andrewboyson 60:1d8c7a1e7483 94 }
andrewboyson 74:c3756bfa960e 95 int Ar6AddIpRecord(void (*traceback)(void), char* mac, char* ip)
andrewboyson 60:1d8c7a1e7483 96 {
andrewboyson 60:1d8c7a1e7483 97 //Don't treat non ips
andrewboyson 60:1d8c7a1e7483 98 if (!ip[0])
andrewboyson 60:1d8c7a1e7483 99 {
andrewboyson 60:1d8c7a1e7483 100 if (Ar6Trace)
andrewboyson 60:1d8c7a1e7483 101 {
andrewboyson 60:1d8c7a1e7483 102 LogTime("Ar6AddIpRecord had blank ip\r\n");
andrewboyson 60:1d8c7a1e7483 103 if (NetTraceStack) traceback();
andrewboyson 60:1d8c7a1e7483 104 }
andrewboyson 74:c3756bfa960e 105 return -1;
andrewboyson 60:1d8c7a1e7483 106 }
andrewboyson 60:1d8c7a1e7483 107 if (MacIsEmpty(mac))
andrewboyson 60:1d8c7a1e7483 108 {
andrewboyson 60:1d8c7a1e7483 109 if (Ar6Trace)
andrewboyson 60:1d8c7a1e7483 110 {
andrewboyson 60:1d8c7a1e7483 111 LogTime("Ar6AddIpRecord had blank mac\r\n");
andrewboyson 60:1d8c7a1e7483 112 if (NetTraceStack) traceback();
andrewboyson 60:1d8c7a1e7483 113 }
andrewboyson 74:c3756bfa960e 114 return -1;
andrewboyson 60:1d8c7a1e7483 115 }
andrewboyson 60:1d8c7a1e7483 116 int i;
andrewboyson 60:1d8c7a1e7483 117
andrewboyson 60:1d8c7a1e7483 118 //See if any record corresponds to the IP and, if so, update the MAC and time
andrewboyson 60:1d8c7a1e7483 119 i = getExistingIp(ip);
andrewboyson 60:1d8c7a1e7483 120 if (i > -1)
andrewboyson 60:1d8c7a1e7483 121 {
andrewboyson 93:580fc113d9e9 122 records[i].elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 123 records[i].state = STATE_VALID;
andrewboyson 60:1d8c7a1e7483 124 MacCopy(records[i].mac, mac);
andrewboyson 74:c3756bfa960e 125 return i;
andrewboyson 60:1d8c7a1e7483 126 }
andrewboyson 60:1d8c7a1e7483 127
andrewboyson 60:1d8c7a1e7483 128 //Otherwise find the first empty slot and add the MAC, IP and date
andrewboyson 60:1d8c7a1e7483 129 i = getOldest();
andrewboyson 60:1d8c7a1e7483 130 MacCopy(records[i].mac, mac);
andrewboyson 172:9bc3c7b2cca1 131 Ip6AddrCopy(records[i].ip, ip);
andrewboyson 93:580fc113d9e9 132 records[i].elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 133 records[i].state = STATE_VALID;
andrewboyson 74:c3756bfa960e 134 return i;
andrewboyson 60:1d8c7a1e7483 135 }
andrewboyson 60:1d8c7a1e7483 136 void Ar6IpToMac(char* ip, char* mac)
andrewboyson 60:1d8c7a1e7483 137 {
andrewboyson 60:1d8c7a1e7483 138 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 139 {
andrewboyson 172:9bc3c7b2cca1 140 if (records[i].state == STATE_VALID && Ip6AddrIsSame(records[i].ip, ip))
andrewboyson 60:1d8c7a1e7483 141 {
andrewboyson 60:1d8c7a1e7483 142 MacCopy(mac, records[i].mac);
andrewboyson 60:1d8c7a1e7483 143 return;
andrewboyson 60:1d8c7a1e7483 144 }
andrewboyson 60:1d8c7a1e7483 145 }
andrewboyson 60:1d8c7a1e7483 146 MacClear(mac);
andrewboyson 60:1d8c7a1e7483 147 }
andrewboyson 193:47a953ab571b 148 bool Ar6HaveMacForIp(char* ip)
andrewboyson 116:60521b29e4c9 149 {
andrewboyson 116:60521b29e4c9 150 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 116:60521b29e4c9 151 {
andrewboyson 172:9bc3c7b2cca1 152 if (records[i].state == STATE_VALID && Ip6AddrIsSame(records[i].ip, ip)) return true;
andrewboyson 116:60521b29e4c9 153 }
andrewboyson 116:60521b29e4c9 154 return false;
andrewboyson 116:60521b29e4c9 155 }
andrewboyson 193:47a953ab571b 156 bool Ar6CheckHaveMacAndFetchIfNot(char* ip)
andrewboyson 193:47a953ab571b 157 {
andrewboyson 193:47a953ab571b 158 if (!Ar6HaveMacForIp(ip))
andrewboyson 193:47a953ab571b 159 {
andrewboyson 193:47a953ab571b 160 Ar6MakeRequestForMacFromIp(ip); //The request is only repeated if made after a freeze time - call as often as you want.
andrewboyson 193:47a953ab571b 161 return false;
andrewboyson 193:47a953ab571b 162 }
andrewboyson 193:47a953ab571b 163 return true;
andrewboyson 193:47a953ab571b 164 }
andrewboyson 74:c3756bfa960e 165 void Ar6IndexToIp(int i, char* ip)
andrewboyson 74:c3756bfa960e 166 {
andrewboyson 172:9bc3c7b2cca1 167 Ip6AddrCopy(ip, records[i].ip);
andrewboyson 74:c3756bfa960e 168 }
andrewboyson 60:1d8c7a1e7483 169 void Ar6SendHttp()
andrewboyson 60:1d8c7a1e7483 170 {
andrewboyson 60:1d8c7a1e7483 171 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 172 {
andrewboyson 60:1d8c7a1e7483 173 if (records[i].state)
andrewboyson 60:1d8c7a1e7483 174 {
andrewboyson 93:580fc113d9e9 175 HttpAddF("%4u ", (MsTimerCount - records[i].elapsed) / 1000 / 60);
andrewboyson 60:1d8c7a1e7483 176
andrewboyson 172:9bc3c7b2cca1 177 int ipLen = Ip6AddrHttp(records[i].ip);
andrewboyson 159:3ebef2d02f7f 178 HttpAddFillChar(' ', 40 - ipLen);
andrewboyson 60:1d8c7a1e7483 179
andrewboyson 60:1d8c7a1e7483 180 MacHttp(records[i].mac);
andrewboyson 60:1d8c7a1e7483 181
andrewboyson 60:1d8c7a1e7483 182 HttpAddChar('\r');
andrewboyson 60:1d8c7a1e7483 183 HttpAddChar('\n');
andrewboyson 60:1d8c7a1e7483 184 }
andrewboyson 60:1d8c7a1e7483 185 }
andrewboyson 60:1d8c7a1e7483 186 }
andrewboyson 140:9000ea70b220 187 void Ar6SendAjax()
andrewboyson 140:9000ea70b220 188 {
andrewboyson 140:9000ea70b220 189 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 140:9000ea70b220 190 {
andrewboyson 140:9000ea70b220 191 if (records[i].state)
andrewboyson 140:9000ea70b220 192 {
andrewboyson 167:3ba4e3c49631 193 HttpAddByteAsHex(i);
andrewboyson 167:3ba4e3c49631 194 HttpAddChar('\t');
andrewboyson 140:9000ea70b220 195 HttpAddInt32AsHex(MsTimerCount - records[i].elapsed);
andrewboyson 167:3ba4e3c49631 196 HttpAddChar('\t');
andrewboyson 140:9000ea70b220 197 for (int b = 0; b < 16; b++) HttpAddByteAsHex(records[i].ip[b]);
andrewboyson 167:3ba4e3c49631 198 HttpAddChar('\t');
andrewboyson 140:9000ea70b220 199 for (int b = 0; b < 6; b++) HttpAddByteAsHex(records[i].mac[b]);
andrewboyson 140:9000ea70b220 200 HttpAddChar('\n');
andrewboyson 140:9000ea70b220 201 }
andrewboyson 140:9000ea70b220 202 }
andrewboyson 140:9000ea70b220 203 }
andrewboyson 60:1d8c7a1e7483 204 static void clear(struct record* pr)
andrewboyson 60:1d8c7a1e7483 205 {
andrewboyson 60:1d8c7a1e7483 206 pr->state = STATE_EMPTY;
andrewboyson 60:1d8c7a1e7483 207 }
andrewboyson 60:1d8c7a1e7483 208 static void clearCache(struct record* pr)
andrewboyson 60:1d8c7a1e7483 209 {
andrewboyson 133:a37eb35a03f1 210 if (MsTimerRelative(pr->elapsed, CACHE_TIMEOUT_MS)) clear(pr);
andrewboyson 60:1d8c7a1e7483 211 }
andrewboyson 60:1d8c7a1e7483 212 static void retry(struct record* pr)
andrewboyson 60:1d8c7a1e7483 213 {
andrewboyson 133:a37eb35a03f1 214 if (pr->state == STATE_SENT && MsTimerRelative(pr->elapsed, REPLY_TIMEOUT_MS))
andrewboyson 60:1d8c7a1e7483 215 {
andrewboyson 60:1d8c7a1e7483 216 if (pr->tries < SEND_ATTEMPTS)
andrewboyson 60:1d8c7a1e7483 217 {
andrewboyson 60:1d8c7a1e7483 218 pr->state = STATE_WANT;
andrewboyson 93:580fc113d9e9 219 pr->elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 220 pr->tries++;
andrewboyson 60:1d8c7a1e7483 221 }
andrewboyson 60:1d8c7a1e7483 222 else
andrewboyson 60:1d8c7a1e7483 223 {
andrewboyson 60:1d8c7a1e7483 224 clear(pr);
andrewboyson 60:1d8c7a1e7483 225 }
andrewboyson 60:1d8c7a1e7483 226 }
andrewboyson 60:1d8c7a1e7483 227 }
andrewboyson 60:1d8c7a1e7483 228 static void sendRequest(struct record* pr)
andrewboyson 60:1d8c7a1e7483 229 {
andrewboyson 60:1d8c7a1e7483 230 if (!NsResolveRequestFlag)
andrewboyson 60:1d8c7a1e7483 231 {
andrewboyson 60:1d8c7a1e7483 232 if (pr->state == STATE_WANT)
andrewboyson 60:1d8c7a1e7483 233 {
andrewboyson 60:1d8c7a1e7483 234 if (Ar6Trace)
andrewboyson 60:1d8c7a1e7483 235 {
andrewboyson 60:1d8c7a1e7483 236 LogTime("AR6 Send request for MAC from IP6 ");
andrewboyson 172:9bc3c7b2cca1 237 Ip6AddrLog(pr->ip);
andrewboyson 60:1d8c7a1e7483 238 Log("\r\n");
andrewboyson 60:1d8c7a1e7483 239 }
andrewboyson 172:9bc3c7b2cca1 240 Ip6AddrCopy(NsAddressToResolve, pr->ip);
andrewboyson 60:1d8c7a1e7483 241 NsResolveRequestFlag = true;
andrewboyson 60:1d8c7a1e7483 242 pr->state = STATE_SENT;
andrewboyson 93:580fc113d9e9 243 pr->elapsed = MsTimerCount;
andrewboyson 60:1d8c7a1e7483 244 return;
andrewboyson 60:1d8c7a1e7483 245 }
andrewboyson 60:1d8c7a1e7483 246 }
andrewboyson 60:1d8c7a1e7483 247 }
andrewboyson 60:1d8c7a1e7483 248 void Ar6Main()
andrewboyson 60:1d8c7a1e7483 249 {
andrewboyson 60:1d8c7a1e7483 250 static int i = -1;
andrewboyson 60:1d8c7a1e7483 251 i++;
andrewboyson 60:1d8c7a1e7483 252 if (i >= RECORDS_COUNT) i = 0;
andrewboyson 60:1d8c7a1e7483 253
andrewboyson 60:1d8c7a1e7483 254 struct record* pr = &records[i];
andrewboyson 60:1d8c7a1e7483 255
andrewboyson 60:1d8c7a1e7483 256 clearCache (pr);
andrewboyson 60:1d8c7a1e7483 257 retry (pr);
andrewboyson 60:1d8c7a1e7483 258 sendRequest(pr);
andrewboyson 60:1d8c7a1e7483 259 }
andrewboyson 60:1d8c7a1e7483 260 void Ar6Init()
andrewboyson 60:1d8c7a1e7483 261 {
andrewboyson 60:1d8c7a1e7483 262 for (int i = 0; i < RECORDS_COUNT; i++)
andrewboyson 60:1d8c7a1e7483 263 {
andrewboyson 60:1d8c7a1e7483 264
andrewboyson 60:1d8c7a1e7483 265 struct record* pr = &records[i];
andrewboyson 60:1d8c7a1e7483 266 clear(pr);
andrewboyson 60:1d8c7a1e7483 267 }
andrewboyson 60:1d8c7a1e7483 268 }