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