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: udp/ntp/ntpclient.c
- Revision:
- 112:f8694d0b8858
- Child:
- 113:904b40231907
diff -r 3600389d1add -r f8694d0b8858 udp/ntp/ntpclient.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/ntp/ntpclient.c Mon Jan 21 16:58:28 2019 +0000
@@ -0,0 +1,193 @@
+#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 "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 NtpClientServerName[DNS_MAX_LABEL_LENGTH+1];
+int32_t NtpClientInitialInterval;
+int32_t NtpClientNormalInterval;
+int32_t NtpClientRetryInterval;
+int32_t NtpClientOffsetMs;
+int32_t NtpClientMaxDelayMs;
+
+bool NtpClientSendRequestsViaIp4 = false;
+uint32_t NtpClientServerIp4;
+char NtpClientServerIp6[16];
+bool NtpClientTrace = false;
+
+enum {
+ INTERVAL_INITIAL,
+ INTERVAL_NORMAL,
+ INTERVAL_RETRY
+};
+
+static uint64_t startNtpMs = 0;
+static int intervalTypeNtp = INTERVAL_INITIAL;
+static bool intervalCompleteNtp()
+{
+ uint32_t interval;
+ switch(intervalTypeNtp)
+ {
+ case INTERVAL_INITIAL: interval = NtpClientInitialInterval; break;
+ case INTERVAL_NORMAL: interval = NtpClientNormalInterval; break;
+ case INTERVAL_RETRY: interval = NtpClientRetryInterval; break;
+ }
+ return MsTimerHasElapsed(startNtpMs, interval * 1000);
+}
+static void startIntervalNtp(int type)
+{
+ startNtpMs = MsTimerCount;
+ intervalTypeNtp = type;
+}
+
+void NtpClientSetClockTime(uint64_t ori, uint64_t rec, int li)
+{
+ //Check the received timestamp delay
+ int64_t oriTicks = ClkTimeFromNtpTimeStamp(ori);
+ int64_t ntpTicks = ClkTimeFromNtpTimeStamp(rec);
+ int64_t clkTicks = ClkTimeGet();
+
+ int64_t roundTripTicks = clkTicks - oriTicks;
+ int64_t delayMs = roundTripTicks >> CLK_TIME_ONE_MS_ISH_SHIFT;
+ int64_t limit = NtpClientMaxDelayMs;
+ if (delayMs > limit)
+ {
+ LogTimeF("NtpClient error: delay %lld ms is greater than limit %lld ms\r\n", delayMs, limit);
+ return;
+ }
+
+ if (NtpClientTrace)
+ {
+ int64_t diffMs = ((int64_t)(ntpTicks - clkTicks)) >> CLK_TIME_ONE_MS_ISH_SHIFT;
+ LogTimeF("NtpClient difference (ext-int) is %lld ms\r\n", diffMs);
+ }
+
+ //Handle the LI
+ if (li == 3)
+ {
+ LogTimeF("NtpClient error: NTP server is not synchronised (LI = 3)\r\n");
+ return;
+ }
+ if (li == 1 || li == 2)
+ {
+ struct tm tm;
+ ClkTimeToTmUtc(clkTicks, &tm);
+ int year1970 = tm.tm_year - 70; //1900
+ int month = tm.tm_mon; //0 to 11
+ ClkUtcSetNextEpochMonth1970(year1970 * 12 + month + 1); //+1 as new UTC epoch is at the start of next month
+ ClkUtcSetNextLeapForward(li == 1);
+ ClkUtcSetNextLeapEnable(true);
+ }
+ if (li == 0)
+ {
+ ClkUtcSetNextLeapEnable(false);
+ }
+
+ //Set the clock
+ int64_t offsetTime = NtpClientOffsetMs << CLK_TIME_ONE_MS_ISH_SHIFT;
+ ClkGovSyncTime(ntpTicks + offsetTime);
+
+ //Wait for next time
+ startIntervalNtp(INTERVAL_NORMAL);
+ ClkGovIsReceivingTime = true;
+
+}
+
+void NtpClientInit()
+{
+ startIntervalNtp(INTERVAL_INITIAL);
+ ClkGovIsReceivingTime = false;
+}
+
+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(NtpClientServerName, &NtpClientServerIp4);
+ else if (type == IPV6) return resolve6(NtpClientServerName, NtpClientServerIp6);
+ else return false;
+}
+int NtpClientPollForPacketToSend(int type, void* pPacket, int* pSize)
+{
+ if (NtpClientServerName[0]) //An empty name means ntp client is not enabled
+ {
+ if (intervalCompleteNtp()) //Wait for the time out
+ {
+ bool isMulticast = NtpClientServerName[0] == '*';
+ if (isMulticast || haveIpAndMac(type))
+ {
+ ClkGovIsReceivingTime = false;
+ startIntervalNtp(INTERVAL_RETRY);
+ NtpHdrWriteRequest(pPacket, pSize);
+
+ if (isMulticast) return MULTICAST_NTP;
+ else return UNICAST_NTP;
+ }
+ }
+ }
+ return DO_NOTHING;
+}
\ No newline at end of file