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