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
ar6.c
00001 #include <stdint.h> 00002 #include <stdbool.h> 00003 00004 #include "log.h" 00005 #include "mstimer.h" 00006 #include "net.h" 00007 #include "mac.h" 00008 #include "ip6addr.h" 00009 #include "ns.h" 00010 #include "http.h" 00011 00012 bool Ar6Trace = false; 00013 00014 #define CACHE_TIMEOUT_MS 3600 * 1000 00015 #define FREEZE_TIMEOUT_MS 1800 * 1000 00016 #define REPLY_TIMEOUT_MS 1 * 1000 00017 #define SEND_ATTEMPTS 3 00018 #define RECORDS_COUNT 20 00019 00020 #define STATE_EMPTY 0 00021 #define STATE_WANT 1 00022 #define STATE_SENT 2 00023 #define STATE_VALID 3 00024 00025 struct record 00026 { 00027 uint32_t elapsed; 00028 char ip[16]; 00029 uint8_t state; 00030 uint8_t tries; 00031 char mac[6]; 00032 }; 00033 static struct record records[RECORDS_COUNT]; 00034 static int getExistingIp(char* ip) 00035 { 00036 for (int i = 0; i < RECORDS_COUNT; i++) 00037 { 00038 if (records[i].state && Ip6AddrIsSame(records[i].ip, ip)) return i; 00039 } 00040 return -1; 00041 } 00042 static int getOldest() 00043 { 00044 int iOldest = 0; 00045 uint32_t ageOldest = 0; 00046 for (int i = 0; i < RECORDS_COUNT; i++) 00047 { 00048 if (!records[i].state) return i; //Found an empty slot so just return it 00049 uint32_t age = MsTimerCount - records[i].elapsed; 00050 if (age >= ageOldest) 00051 { 00052 ageOldest = age; 00053 iOldest = i; 00054 } 00055 } 00056 return iOldest; //Otherwise return the oldest 00057 } 00058 void Ar6MakeRequestForMacFromIp(char* ip) 00059 { 00060 //Don't treat non ips 00061 if (!ip[0]) return; 00062 int i; 00063 00064 //If a record already exists then request an update 00065 i = getExistingIp(ip); 00066 if (i > -1) 00067 { 00068 if (!MsTimerRelative(records[i].elapsed, FREEZE_TIMEOUT_MS)) return; 00069 if (Ar6Trace) 00070 { 00071 LogTime("AR6 Updated request for MAC of "); 00072 Ip6AddrLog(ip); 00073 Log("\r\n"); 00074 } 00075 records[i].state = STATE_WANT; 00076 records[i].tries = 0; 00077 records[i].elapsed = MsTimerCount; 00078 return; 00079 } 00080 00081 //If a record does not exist then find the first empty slot and add the IP and date 00082 if (Ar6Trace) 00083 { 00084 LogTime("AR6 Made request for MAC of "); 00085 Ip6AddrLog(ip); 00086 Log("\r\n"); 00087 } 00088 i = getOldest(); 00089 Ip6AddrCopy(records[i].ip, ip); 00090 records[i].state = STATE_WANT; 00091 records[i].tries = 0; 00092 records[i].elapsed = MsTimerCount; 00093 MacClear(records[i].mac); 00094 } 00095 int Ar6AddIpRecord(void (*traceback)(void), char* mac, char* ip) 00096 { 00097 //Don't treat non ips 00098 if (!ip[0]) 00099 { 00100 if (Ar6Trace) 00101 { 00102 LogTime("Ar6AddIpRecord had blank ip\r\n"); 00103 if (NetTraceStack) traceback(); 00104 } 00105 return -1; 00106 } 00107 if (MacIsEmpty(mac)) 00108 { 00109 if (Ar6Trace) 00110 { 00111 LogTime("Ar6AddIpRecord had blank mac\r\n"); 00112 if (NetTraceStack) traceback(); 00113 } 00114 return -1; 00115 } 00116 int i; 00117 00118 //See if any record corresponds to the IP and, if so, update the MAC and time 00119 i = getExistingIp(ip); 00120 if (i > -1) 00121 { 00122 records[i].elapsed = MsTimerCount; 00123 records[i].state = STATE_VALID; 00124 MacCopy(records[i].mac, mac); 00125 return i; 00126 } 00127 00128 //Otherwise find the first empty slot and add the MAC, IP and date 00129 i = getOldest(); 00130 MacCopy(records[i].mac, mac); 00131 Ip6AddrCopy(records[i].ip, ip); 00132 records[i].elapsed = MsTimerCount; 00133 records[i].state = STATE_VALID; 00134 return i; 00135 } 00136 void Ar6IpToMac(char* ip, char* mac) 00137 { 00138 for (int i = 0; i < RECORDS_COUNT; i++) 00139 { 00140 if (records[i].state == STATE_VALID && Ip6AddrIsSame(records[i].ip, ip)) 00141 { 00142 MacCopy(mac, records[i].mac); 00143 return; 00144 } 00145 } 00146 MacClear(mac); 00147 } 00148 bool Ar6HaveMacForIp(char* ip) 00149 { 00150 for (int i = 0; i < RECORDS_COUNT; i++) 00151 { 00152 if (records[i].state == STATE_VALID && Ip6AddrIsSame(records[i].ip, ip)) return true; 00153 } 00154 return false; 00155 } 00156 bool Ar6CheckHaveMacAndFetchIfNot(char* ip) 00157 { 00158 if (!Ar6HaveMacForIp(ip)) 00159 { 00160 Ar6MakeRequestForMacFromIp(ip); //The request is only repeated if made after a freeze time - call as often as you want. 00161 return false; 00162 } 00163 return true; 00164 } 00165 void Ar6IndexToIp(int i, char* ip) 00166 { 00167 Ip6AddrCopy(ip, records[i].ip); 00168 } 00169 void Ar6SendHttp() 00170 { 00171 for (int i = 0; i < RECORDS_COUNT; i++) 00172 { 00173 if (records[i].state) 00174 { 00175 HttpAddF("%4u ", (MsTimerCount - records[i].elapsed) / 1000 / 60); 00176 00177 int ipLen = Ip6AddrHttp(records[i].ip); 00178 HttpAddFillChar(' ', 40 - ipLen); 00179 00180 MacHttp(records[i].mac); 00181 00182 HttpAddChar('\r'); 00183 HttpAddChar('\n'); 00184 } 00185 } 00186 } 00187 void Ar6SendAjax() 00188 { 00189 for (int i = 0; i < RECORDS_COUNT; i++) 00190 { 00191 if (records[i].state) 00192 { 00193 HttpAddByteAsHex(i); 00194 HttpAddChar('\t'); 00195 HttpAddInt32AsHex(MsTimerCount - records[i].elapsed); 00196 HttpAddChar('\t'); 00197 for (int b = 0; b < 16; b++) HttpAddByteAsHex(records[i].ip[b]); 00198 HttpAddChar('\t'); 00199 for (int b = 0; b < 6; b++) HttpAddByteAsHex(records[i].mac[b]); 00200 HttpAddChar('\n'); 00201 } 00202 } 00203 } 00204 static void clear(struct record* pr) 00205 { 00206 pr->state = STATE_EMPTY; 00207 } 00208 static void clearCache(struct record* pr) 00209 { 00210 if (MsTimerRelative(pr->elapsed, CACHE_TIMEOUT_MS)) clear(pr); 00211 } 00212 static void retry(struct record* pr) 00213 { 00214 if (pr->state == STATE_SENT && MsTimerRelative(pr->elapsed, REPLY_TIMEOUT_MS)) 00215 { 00216 if (pr->tries < SEND_ATTEMPTS) 00217 { 00218 pr->state = STATE_WANT; 00219 pr->elapsed = MsTimerCount; 00220 pr->tries++; 00221 } 00222 else 00223 { 00224 clear(pr); 00225 } 00226 } 00227 } 00228 static void sendRequest(struct record* pr) 00229 { 00230 if (!NsResolveRequestFlag) 00231 { 00232 if (pr->state == STATE_WANT) 00233 { 00234 if (Ar6Trace) 00235 { 00236 LogTime("AR6 Send request for MAC from IP6 "); 00237 Ip6AddrLog(pr->ip); 00238 Log("\r\n"); 00239 } 00240 Ip6AddrCopy(NsAddressToResolve, pr->ip); 00241 NsResolveRequestFlag = true; 00242 pr->state = STATE_SENT; 00243 pr->elapsed = MsTimerCount; 00244 return; 00245 } 00246 } 00247 } 00248 void Ar6Main() 00249 { 00250 static int i = -1; 00251 i++; 00252 if (i >= RECORDS_COUNT) i = 0; 00253 00254 struct record* pr = &records[i]; 00255 00256 clearCache (pr); 00257 retry (pr); 00258 sendRequest(pr); 00259 } 00260 void Ar6Init() 00261 { 00262 for (int i = 0; i < RECORDS_COUNT; i++) 00263 { 00264 00265 struct record* pr = &records[i]; 00266 clear(pr); 00267 } 00268 }
Generated on Tue Jul 12 2022 18:53:40 by 1.7.2