Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
Diff: resolve/nr6.c
- Revision:
- 171:f708d6776752
- Parent:
- 170:96c637dc3f52
diff -r 96c637dc3f52 -r f708d6776752 resolve/nr6.c
--- a/resolve/nr6.c Wed Dec 09 18:11:05 2020 +0000
+++ b/resolve/nr6.c Sat Dec 12 20:10:02 2020 +0000
@@ -18,8 +18,8 @@
#define NAME_MAX_LENGTH 20
#define CACHE_TIMEOUT_MS 3600 * 1000
#define STALE_TIMEOUT_MS 1800 * 1000
-#define EMPTY_TIMEOUT_MS 5 * 1000
-#define REPLY_TIMEOUT_MS 1 * 1000
+#define EMPTY_TIMEOUT_MS 300 * 1000
+#define REPLY_TIMEOUT_MS 100
#define RECORDS_COUNT 20
@@ -28,17 +28,20 @@
#define STATE_SENT 2
#define STATE_VALID 3
-#define TODO_NONE 0
-#define TODO_NAME_FROM_IP 1
-#define TODO_IP_FROM_NAME 2
+#define TODO_NONE 0
+#define TODO_NAME_FROM_IP 1
+#define TODO_IP4_FROM_NAME 2
+#define TODO_IP6_FROM_NAME 3
struct record
{
- uint32_t elapsed;
+ uint32_t replyMs;
+ uint32_t ageMs;
char ip[16];
uint8_t todo;
uint8_t state;
- uint8_t protocol;
+ uint8_t dnsProtocol;
+ uint8_t ipProtocol;
char name[NAME_MAX_LENGTH];
};
static struct record records[RECORDS_COUNT];
@@ -88,7 +91,7 @@
for (int i = 0; i < RECORDS_COUNT; i++)
{
if (records[i].state == STATE_EMPTY) return i; //Found an empty slot so just return it
- uint32_t age = MsTimerCount - records[i].elapsed;
+ uint32_t age = MsTimerCount - records[i].ageMs;
if (age >= ageOldest)
{
ageOldest = age;
@@ -97,7 +100,7 @@
}
return iOldest; //Otherwise return the oldest
}
-void Nr6MakeRequestForNameFromIp(char* ip)
+static void makeRequestForNameFromIp(char* ip)
{
//Don't treat non ips
if (!ip[0]) return;
@@ -107,13 +110,14 @@
i = getExistingIp(ip);
if (i > -1)
{
+ if (records[i].state == STATE_WANT || records[i].state == STATE_SENT) return;
if (records[i].name[0] == 0)
{
- if (!MsTimerRelative(records[i].elapsed, EMPTY_TIMEOUT_MS)) return;
+ if (!MsTimerRelative(records[i].ageMs, EMPTY_TIMEOUT_MS)) return;
}
else
{
- if (!MsTimerRelative(records[i].elapsed, STALE_TIMEOUT_MS)) return;
+ if (!MsTimerRelative(records[i].ageMs, STALE_TIMEOUT_MS)) return;
}
if (Nr6Trace)
{
@@ -121,29 +125,29 @@
Ip6AddressLog(ip);
Log("\r\n");
}
- records[i].todo = TODO_NAME_FROM_IP;
- records[i].state = STATE_WANT;
- records[i].protocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
- records[i].elapsed = MsTimerCount;
- return;
+ //Leave the ip as is
+ //Leave the name as is
+ //Leave age as is
}
-
- //If a record does not exist then find the first empty slot and add the IP and date
- if (Nr6Trace)
+ else
{
- LogTimeF("NR - request name of ");
- Ip6AddressLog(ip);
- Log("\r\n");
+ //If a record does not exist then find the first empty slot and add the IP and date
+ if (Nr6Trace)
+ {
+ LogTimeF("NR - request name of ");
+ Ip6AddressLog(ip);
+ Log("\r\n");
+ }
+ i = getOldest();
+ Ip6AddressCopy(records[i].ip, ip); //Set the ip
+ records[i].name[0] = 0; //Clear the name
+ records[i].ageMs = MsTimerCount; //Start age
}
- i = getOldest();
- Ip6AddressCopy(records[i].ip, ip);
- records[i].todo = TODO_NAME_FROM_IP;
- records[i].state = STATE_WANT;
- records[i].protocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
- records[i].elapsed = MsTimerCount;
- records[i].name[0] = 0;
+ records[i].todo = TODO_NAME_FROM_IP;
+ records[i].state = STATE_WANT;
+ records[i].dnsProtocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
}
-void Nr6MakeRequestForIpFromName(char* name)
+static void makeRequestForIpFromName(char* name, int todo)
{
//Don't treat non names
if (!name[0]) return;
@@ -153,57 +157,71 @@
i = getExistingName(name);
if (i > -1)
{
+ if (records[i].state == STATE_WANT || records[i].state == STATE_SENT) return;
if (Ip6AddressIsEmpty(records[i].ip))
{
- if (!MsTimerRelative(records[i].elapsed, EMPTY_TIMEOUT_MS)) return;
+ if (!MsTimerRelative(records[i].ageMs, EMPTY_TIMEOUT_MS)) return;
}
else
{
- if (!MsTimerRelative(records[i].elapsed, STALE_TIMEOUT_MS)) return;
+ if (!MsTimerRelative(records[i].ageMs, STALE_TIMEOUT_MS)) return;
}
if (Nr6Trace)
{
LogTimeF("NR - renew IPv6 of %s\r\n", name);
}
- records[i].todo = TODO_IP_FROM_NAME;
- records[i].state = STATE_WANT;
- records[i].protocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
- records[i].elapsed = MsTimerCount;
- return;
+ //Leave name as is
+ //Leave the ip as is
+ //Leave age as is
}
-
- //If a record does not exist then find the first empty slot and add the name and date
- if (Nr6Trace)
- {
- LogTimeF("NR - request IPv6 of %s\r\n", name);
+ else
+ {
+ //If a record does not exist then find the first empty slot and add the name and date
+ if (Nr6Trace)
+ {
+ LogTimeF("NR - request IPv6 of %s\r\n", name);
+ }
+ i = getOldest();
+ strncpy(records[i].name, name, NAME_MAX_LENGTH); //Set the name
+ records[i].name[NAME_MAX_LENGTH - 1] = 0;
+ Ip6AddressClear(records[i].ip); //Clear the ip
+ records[i].ageMs = MsTimerCount; //Start age
}
- i = getOldest();
- records[i].ip[0] = 0;
- records[i].todo = TODO_IP_FROM_NAME;
- records[i].state = STATE_WANT;
- records[i].protocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
- records[i].elapsed = MsTimerCount;
+ records[i].todo = todo;
+ records[i].state = STATE_WANT;
+ records[i].dnsProtocol = DnsGetNextProtocol(DNS_PROTOCOL_NONE);
+}
+static void updateIpRecord(int i, char* ip, char* name, int dnsProtocol)
+{
+ records[i].todo = TODO_NONE;
+ records[i].ageMs = MsTimerCount;
+ Ip6AddressCopy(records[i].ip, ip);
+ records[i].dnsProtocol = dnsProtocol;
+ records[i].state = STATE_VALID;
strncpy(records[i].name, name, NAME_MAX_LENGTH);
records[i].name[NAME_MAX_LENGTH - 1] = 0;
}
-static void addIpRecord(int i, char* ip, char* name, int protocol)
+void addIpRecord(char* ip, char* name, int dnsProtocol)
{
- records[i].todo = TODO_NONE;
- records[i].elapsed = MsTimerCount;
- Ip6AddressCopy(records[i].ip, ip);
- records[i].protocol = protocol;
- records[i].state = STATE_VALID;
- strncpy(records[i].name, name, NAME_MAX_LENGTH);
- records[i].name[NAME_MAX_LENGTH - 1] = 0;
-}
-void Nr6AddIpRecord(char* ip, char* name, int protocol)
-{
+ /*
+ A number of situations may need to be handled:
+ - An existing ip with the same name ; the usual situation : just reset the elapsed time and return
+ - An existing ip with no or a different name; usual if we are resolving an ip : add or update the ip of this record
+ - Same name with an empty ip ; usual if we are resolving a name : add the ip to this record
+ - Same name with another ip ; normal situation : do nothing
+ - No existing ip or name ; usual if another device has done a reolution : add a new record and return
+
+ Quite often we will simultaneously attempt to resolve both the name and the ip of the same device.
+ When this happens there will be two entriesone with the ame and an empty ip; the othert with the ip but and an empty name.
+ In this case we first add the name to the existing ip but also check for the name with an empty ip and delete it.
+ */
+
int i;
//Print what is being handled
if (Nr6Trace)
{
- LogTimeF("NR - received response ");
+ LogTimeF("NR - received ");
Ip6AddressLog(ip);
Log(" == '");
Log(name);
@@ -213,7 +231,7 @@
//Ignore records which do not have both ip and name
if (Ip6AddressIsEmpty(ip) || name == 0 || name[0] == 0)
{
- if (Nr6Trace) LogTimeF("NR - ignoring unresolved response\r\n");
+ if (Nr6Trace) LogTimeF("NR - ignoring invalid entry\r\n");
return;
}
@@ -225,24 +243,14 @@
{
if (DnsLabelIsSame(name, records[i].name))
{
- LogTimeF("NR record %d - confirm existing name for ", i);
- Ip6AddressLog(ip);
- Log(" is '");
- Log(name);
- Log("'\r\n");
+ LogTimeF("NR record %d - refresh existing entry\r\n", i);
}
else
{
- LogTimeF("NR record %d - update name for ip ", i);
- Ip6AddressLog(ip);
- Log(" from '");
- Log(records[i].name);
- Log("' to '");
- Log(name);
- Log("'\r\n");
+ LogTimeF("NR record %d - update entry name from '%s' to '%s'\r\n", i, records[i].name, name);
}
}
- addIpRecord(i, ip, name, protocol);
+ updateIpRecord(i, ip, name, dnsProtocol);
i = getNameOnly(name);
if (i >= 0)
@@ -259,15 +267,11 @@
{
if (Nr6Trace)
{
- LogTimeF("NR record %d - update ip for name", i);
- Log(name);
- Log(" from ");
+ LogTimeF("NR record %d - add ip ", i);
Ip6AddressLog(ip);
- Log(" to ");
- Ip6AddressLog(records[i].ip);
Log("\r\n");
}
- addIpRecord(i, ip, name, protocol);
+ updateIpRecord(i, ip, name, dnsProtocol);
return;
}
@@ -275,15 +279,11 @@
i = getOldest();
if (Nr6Trace)
{
- LogTimeF("NR record %d - add entry for ", i);
- Ip6AddressLog(ip);
- Log(" == '");
- Log(name);
- Log("'\r\n");
+ LogTimeF("NR record %d - add entry\r\n", i);
}
- addIpRecord(i, ip, name, protocol);
+ updateIpRecord(i, ip, name, dnsProtocol);
}
-void Nr6IpToName(char* ip, char* name)
+static void ipToName(char* ip, char* name)
{
for (int i = 0; i < RECORDS_COUNT; i++)
{
@@ -296,7 +296,7 @@
}
name[0] = 0;
}
-void Nr6NameToIp(char* name, char* ip)
+static void nameToIp(char* name, char* ip)
{
uint32_t newest = 0xFFFFFFFF;
Ip6AddressClear(ip);
@@ -305,7 +305,7 @@
if (records[i].state == STATE_EMPTY) continue;
if(Ip6AddressIsEmpty(records[i].ip)) continue;
if (!DnsLabelIsSame(records[i].name, name)) continue;
- uint32_t age = MsTimerCount - records[i].elapsed;
+ uint32_t age = MsTimerCount - records[i].ageMs;
if (age <= newest)
{
newest = age;
@@ -313,17 +313,55 @@
}
}
}
-bool Nr6HaveIpForName(char* name)
+void Nr6MakeRequestForNameFromIp(char* ip)
+{
+ makeRequestForNameFromIp(ip);
+}
+void Nr4MakeRequestForNameFromIp(uint32_t ip4)
+{
+ char ip6[16];
+ Ip6AddressFromIp4(ip6, ip4);
+ makeRequestForNameFromIp(ip6);
+}
+void Nr6MakeRequestForIpFromName(char* name)
+{
+ makeRequestForIpFromName(name, TODO_IP6_FROM_NAME);
+}
+void Nr4MakeRequestForIpFromName(char* name)
+{
+ makeRequestForIpFromName(name, TODO_IP4_FROM_NAME);
+}
+void Nr6AddIpRecord(char* ip, char* name, int dnsProtocol)
+{
+ addIpRecord(ip, name, dnsProtocol);
+}
+void Nr4AddIpRecord(uint32_t ip4, char* name, int dnsProtocol)
{
- for (int i = 0; i < RECORDS_COUNT; i++)
- {
- if (records[i].state == STATE_EMPTY) continue;
- if(Ip6AddressIsEmpty(records[i].ip)) continue;
- if (!DnsLabelIsSame(records[i].name, name)) return true;
- }
- return false;
+ char ip6[16];
+ Ip6AddressFromIp4(ip6, ip4);
+ addIpRecord(ip6, name, dnsProtocol);
+}
+void Nr6NameToIp(char* name, char* ip)
+{
+ nameToIp(name, ip);
}
-static char letterFromStateAndProtocol(uint8_t dnsState, uint8_t protocol)
+void Nr4NameToIp(char* name, uint32_t* pIp)
+{
+ char ip6[16];
+ nameToIp(name, ip6);
+ *pIp = Ip6AddressToIp4(ip6);
+}
+void Nr6IpToName(char* ip, char* name)
+{
+ ipToName(ip, name);
+}
+void Nr4IpToName(uint32_t ip4, char* name)
+{
+ char ip6[16];
+ Ip6AddressFromIp4(ip6, ip4);
+ ipToName(ip6, name);
+}
+static char letterFromStateAndProtocol(uint8_t dnsState, uint8_t dnsProtocol)
{
switch (dnsState)
{
@@ -331,7 +369,7 @@
case STATE_SENT: return '>';
case STATE_VALID:
- switch (protocol)
+ switch (dnsProtocol)
{
case DNS_PROTOCOL_UDNS: return 'd';
case DNS_PROTOCOL_MDNS: return 'm';
@@ -349,12 +387,13 @@
if (records[i].state == STATE_EMPTY) continue;
if (!Ip6AddressIsEmpty(records[i].ip) || records[i].name[0])
{
- HttpAddF("%4u ", (MsTimerCount - records[i].elapsed) / 1000 / 60);
+ HttpAddF("%4u ", (MsTimerCount - records[i].ageMs) / 1000 / 60);
- int ipLen = Ip6AddressHttp(records[i].ip);
+ int ipLen;
+ ipLen = Ip6AddressHttp(records[i].ip);
HttpAddFillChar(' ', 40 - ipLen);
- HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].protocol));
+ HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].dnsProtocol));
HttpAddChar(' ');
@@ -374,11 +413,11 @@
{
HttpAddByteAsHex(i);
HttpAddChar('\t');
- HttpAddInt32AsHex(MsTimerCount - records[i].elapsed);
+ HttpAddInt32AsHex(MsTimerCount - records[i].ageMs);
HttpAddChar('\t');
for (int b = 0; b < 16; b++) HttpAddByteAsHex(records[i].ip[b]);
HttpAddChar('\t');
- HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].protocol));
+ HttpAddChar(letterFromStateAndProtocol(records[i].state, records[i].dnsProtocol));
HttpAddChar('\t');
HttpAddText(records[i].name);
HttpAddChar('\n');
@@ -387,24 +426,26 @@
}
static void clearCache(struct record* pr)
{
- if (MsTimerRelative(pr->elapsed, CACHE_TIMEOUT_MS)) pr->state = STATE_EMPTY;
+ if (MsTimerRelative(pr->ageMs, CACHE_TIMEOUT_MS)) pr->state = STATE_EMPTY;
}
static void nextProtocol(struct record* pr)
{
- if (pr->state == STATE_SENT && MsTimerRelative(pr->elapsed, REPLY_TIMEOUT_MS) && pr->protocol)
+ if (pr->state == STATE_SENT && MsTimerRelative(pr->replyMs, REPLY_TIMEOUT_MS) && pr->dnsProtocol)
{
- pr->protocol = DnsGetNextProtocol(pr->protocol);
- if (pr->protocol)
+ pr->dnsProtocol = DnsGetNextProtocol(pr->dnsProtocol);
+ if (pr->dnsProtocol)
{
pr->state = STATE_WANT;
}
- else
+ else //We have tried everything and resolution has failed
{
if (pr->todo == TODO_NAME_FROM_IP) pr->name[0] = 0;
- if (pr->todo == TODO_IP_FROM_NAME) Ip6AddressClear(pr->ip);
+ if (pr->todo == TODO_IP4_FROM_NAME || pr->todo == TODO_IP6_FROM_NAME) Ip6AddressClear(pr->ip);
+ pr->todo = TODO_NONE;
pr->state = STATE_VALID;
+ pr->ageMs = MsTimerCount;
}
- pr->elapsed = MsTimerCount;
+ pr->replyMs = MsTimerCount;
}
}
static void queryNameFromIp(struct record* pr)
@@ -412,36 +453,48 @@
if (Nr6Trace)
{
LogTime("NR - send ");
- DnsProtocolLog(pr->protocol);
- Log(" request for name from IP6 ");
+ DnsProtocolLog(pr->dnsProtocol);
+ if (Ip6AddrIsIp4(pr->ip)) Log(" request for name from IP4 ");
+ else Log(" request for name from IP6 ");
Ip6AddressLog(pr->ip);
Log("\r\n");
}
- DnsQueryNameFromIp6(pr->ip, pr->protocol);
+ if (Ip6AddrIsIp4(pr->ip))
+ {
+ uint32_t ip4 = Ip6AddressToIp4(pr->ip);
+ DnsQueryNameFromIp4(ip4, pr->dnsProtocol, pr->ipProtocol);
+ }
+ else
+ {
+ DnsQueryNameFromIp6(pr->ip, pr->dnsProtocol, pr->ipProtocol);
+ }
}
-static void queryIpFromName(struct record* pr)
+static void queryIpFromName(struct record* pr, int todo)
{
if (Nr6Trace)
{
LogTime("NR - send ");
- DnsProtocolLog(pr->protocol);
- Log(" request for IP6 from name '");
+ DnsProtocolLog(pr->dnsProtocol);
+ if (todo == TODO_IP4_FROM_NAME) Log(" request for IP4 from name '");
+ else Log(" request for IP6 from name '");
Log(pr->name);
Log("'\r\n");
}
- DnsQueryIp6FromName(pr->name, pr->protocol);
+ if (todo == TODO_IP4_FROM_NAME) DnsQueryIp4FromName(pr->name, pr->dnsProtocol, pr->ipProtocol);
+ else DnsQueryIp6FromName(pr->name, pr->dnsProtocol, pr->ipProtocol);
}
static void sendRequest(struct record* pr)
{
- if ( DnsQueryIsBusy ) return;
- if ( pr->state != STATE_WANT) return;
- if (!pr->protocol ) return;
+ if ( DnsQueryIsBusy ) return;
+ if ( pr->state != STATE_WANT ) return;
+ if (!pr->dnsProtocol ) return;
- if (pr->todo == TODO_NAME_FROM_IP) queryNameFromIp(pr);
- if (pr->todo == TODO_IP_FROM_NAME) queryIpFromName(pr);
+ if (pr->todo == TODO_NAME_FROM_IP ) queryNameFromIp(pr);
+ if (pr->todo == TODO_IP4_FROM_NAME) queryIpFromName(pr, TODO_IP4_FROM_NAME);
+ if (pr->todo == TODO_IP6_FROM_NAME) queryIpFromName(pr, TODO_IP6_FROM_NAME);
pr->state = STATE_SENT;
- pr->elapsed = MsTimerCount;
+ pr->replyMs = MsTimerCount;
}
void Nr6Main()
{