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

Revision:
113:904b40231907
Child:
116:60521b29e4c9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/ntp/ntpclientquery.c	Tue Jan 22 15:41:12 2019 +0000
@@ -0,0 +1,150 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include      "log.h"
+#include      "clk.h"
+#include  "mstimer.h"
+#include  "clktime.h"
+#include   "clkntp.h"
+#include   "clkutc.h"
+#include   "clkgov.h"
+#include    "clktm.h"
+#include      "net.h"
+#include      "ntp.h"
+#include "ntpclient.h"
+#include      "dns.h"
+#include      "ip4.h"
+#include    "ar4.h"
+#include    "ar6.h"
+#include    "arp.h"
+#include    "eth.h"
+#include    "nr4.h"
+#include    "nr6.h"
+#include "ip6addr.h"
+#include    "mac.h"
+#include "action.h"
+
+#define ONE_BILLION 1000000000ULL
+#define ONE_MILLION     1000000LL
+
+char    NtpClientQueryServerName[DNS_MAX_LABEL_LENGTH+1]; 
+int32_t NtpClientQueryInitialInterval;                    
+int32_t NtpClientQueryNormalInterval;                     
+int32_t NtpClientQueryRetryInterval;                      
+
+bool       NtpClientQuerySendRequestsViaIp4 = false;
+uint32_t   NtpClientQueryServerIp4;
+char       NtpClientQueryServerIp6[16];
+
+static uint64_t startNtpMs = 0;
+static int  intervalTypeNtp = NTP_QUERY_INTERVAL_INITIAL;
+static bool intervalCompleteNtp()
+{
+    uint32_t interval;
+    switch(intervalTypeNtp)
+    {
+        case NTP_QUERY_INTERVAL_INITIAL: interval = NtpClientQueryInitialInterval; break;
+        case NTP_QUERY_INTERVAL_NORMAL:  interval = NtpClientQueryNormalInterval;  break;
+        case NTP_QUERY_INTERVAL_RETRY:   interval = NtpClientQueryRetryInterval;   break;
+    }
+    return MsTimerHasElapsed(startNtpMs, interval * 1000);
+}
+void NtpClientQueryStartInterval(int type)
+{
+    startNtpMs = MsTimerCount;
+    intervalTypeNtp = type;
+}
+
+static bool resolve4(char* server, uint32_t* pIp)
+{
+    //Check if have IP, if not, then request it and stop
+    Nr4NameToIp(server, pIp);
+    if (!*pIp)
+    {
+        Nr4MakeRequestForIpFromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
+        return false;
+    }
+
+    //Check if have MAC and, if not, request it and stop
+    char mac[6];
+    Ar4IpToMac(*pIp, mac);
+    if (MacIsEmpty(mac))
+    {
+        Ar4MakeRequestForMacFromIp(*pIp); //The request is only repeated if made after a freeze time - call as often as you want.
+        return false;
+    }
+    
+    return true;
+}
+static bool resolve6(char* server, char* ip)
+{
+    //Check if have IP, if not, then request it and stop
+    Nr6NameToIp(server, ip);
+    if (Ip6AddressIsEmpty(ip))
+    {
+        Nr6MakeRequestForIpFromName(server); //The request is only repeated if made after a freeze time - call as often as you want.
+        return false;
+    }
+
+    //Check if have MAC and, if not, request it and stop
+    char mac[6];
+    Ar6IpToMac(ip, mac);
+    if (MacIsEmpty(mac))
+    {
+        Ar6MakeRequestForMacFromIp(ip); //The request is only repeated if made after a freeze time - call as often as you want.
+        return false;
+    }
+    
+    return true;
+}
+static bool haveIpAndMac(int type)
+{
+    if      (type == IPV4) return resolve4(NtpClientQueryServerName, &NtpClientQueryServerIp4);
+    else if (type == IPV6) return resolve6(NtpClientQueryServerName,  NtpClientQueryServerIp6);
+    else                   return false;
+}
+void writeRequest(void* pPacket, int* pSize)
+{
+    struct NtpHeader* pHeader = (struct NtpHeader*)pPacket;
+    
+    pHeader->Mode             = NTP_CLIENT;
+    pHeader->VN               = 3;
+    pHeader->LI               = 0;
+    pHeader->Stratum          = 0;
+    pHeader->Poll             = 0;
+    pHeader->Precision        = 0;
+    pHeader->RootDelay        = 0;
+    pHeader->Dispersion       = 0;
+    pHeader->RefIdentifier[0] = 0;
+    pHeader->RefIdentifier[1] = 0;
+    pHeader->RefIdentifier[2] = 0;
+    pHeader->RefIdentifier[3] = 0;
+    pHeader->RefTimeStamp     = 0;
+    pHeader->OriTimeStamp     = 0;
+    pHeader->RecTimeStamp     = 0;
+    pHeader->TraTimeStamp     = NetToHost64(ClkTimeToNtpTimeStamp(ClkTimeGet()));
+
+    *pSize = sizeof(struct NtpHeader);
+}
+
+int NtpClientQueryPoll(int type, void* pPacket, int* pSize)
+{
+    if (NtpClientQueryServerName[0]) //An empty name means ntp client is not enabled
+    {
+        if (intervalCompleteNtp()) //Wait for the time out
+        {
+            bool isMulticast = NtpClientQueryServerName[0] == '*';
+            if (isMulticast || haveIpAndMac(type))
+            {
+                ClkGovIsReceivingTime = false;
+                NtpClientQueryStartInterval(NTP_QUERY_INTERVAL_RETRY);
+                writeRequest(pPacket, pSize);
+                
+                if (isMulticast) return MULTICAST_NTP;
+                else             return   UNICAST_NTP;
+            }
+        }
+    }
+    return DO_NOTHING;
+}
\ No newline at end of file