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/ntpserver.c
- Revision:
- 113:904b40231907
- Child:
- 123:44fea08759af
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/udp/ntp/ntpserver.c Tue Jan 22 15:41:12 2019 +0000
@@ -0,0 +1,104 @@
+#include <stdint.h>
+
+#include "clk.h"
+#include "clkgov.h"
+#include "clktime.h"
+#include "clkutc.h"
+#include "clkntp.h"
+#include "clkutc.h"
+#include "ntp.h"
+#include "action.h"
+#include "log.h"
+#include "net.h"
+
+#define LI_PRIOR_NOTICE_SECONDS 10LL * 24 * 60 * 60
+
+bool NtpServerEnable = false;
+
+char* NtpServerName = "";
+
+static int getPrecision()
+{
+ /*
+ The Precision field is set to reflect the maximum reading error of the local clock.
+ For all practical cases it is computed as the negative of the number of significant bits
+ to the right of the decimal point in the NTP timestamp format.
+ While that could be CLK_TIME_ONE_SECOND_SHIFT I think that would be the resolution not the precision
+ I therefore assume I can count on the clock to be good to about a microsecond or 2^-20
+ */
+ return -20;
+}
+static int getLi()
+{
+ if (!ClkTimeIsSet() ) return 3; //Alarm condition; clock is not synchronised
+ if (!ClkUtcGetNextLeapEnable()) return 0; //No warning
+
+ int64_t nowTime = ClkUtcFromTai(ClkNowTime()); //This is TAI time
+ int64_t liPriorNotice = LI_PRIOR_NOTICE_SECONDS << CLK_TIME_ONE_SECOND_SHIFT;
+
+ if (nowTime > ClkUtcGetNextEpoch() - liPriorNotice)
+ {
+ if (ClkUtcGetNextLeapForward()) return 1; //Last minute has 61 seconds
+ else return 2; //Last minute has 59 seconds
+ }
+ else
+ {
+ return 0; //No warning
+ }
+}
+
+static int getStratum()
+{
+ if (ClkTimeIsSet()) return 1;
+ else return 0;
+}
+static char* getIdent()
+{
+ if (!ClkTimeIsSet() ) return "INIT";
+ if (!ClkGovIsSynced()) return "LOCL";
+ return NtpServerName;
+}
+static uint64_t getRefNtp()
+{
+ return ClkTimeToNtpTimeStamp(ClkRefTime());
+}
+int NtpServerRequest(void (*traceback)(void), struct NtpHeader* pHeaderRx, struct NtpHeader* pHeaderTx)
+{
+ if (!NtpServerEnable) return DO_NOTHING;
+
+ if (NtpTrace)
+ {
+ if (NetTraceNewLine) Log("\r\n");
+ LogTimeF("NTP received request\r\n");
+ if (NetTraceStack) traceback();
+ NtpLogHeader(pHeaderRx);
+ }
+
+ uint64_t refNtp = getRefNtp();
+ uint64_t nowNtp = ClkTimeToNtpTimeStamp(ClkTimeGet());
+ int stratum = getStratum();
+ char* ident = getIdent();
+ int li = getLi();
+ int precision = getPrecision();
+
+ pHeaderTx->Mode = NTP_SERVER;
+ pHeaderTx->VN = pHeaderRx->VN;
+ pHeaderTx->LI = li;
+ pHeaderTx->Stratum = stratum;
+ pHeaderTx->Poll = pHeaderRx->Poll;
+ pHeaderTx->Precision = precision;
+ pHeaderTx->RootDelay = 0;
+ pHeaderTx->Dispersion = 0;
+ pHeaderTx->RefIdentifier[0] = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string.
+ pHeaderTx->RefIdentifier[1] = ident[1];
+ pHeaderTx->RefIdentifier[2] = ident[2];
+ pHeaderTx->RefIdentifier[3] = ident[3];
+ pHeaderTx->RefTimeStamp = NetToHost64(refNtp);
+ pHeaderTx->OriTimeStamp = pHeaderRx->TraTimeStamp;
+ pHeaderTx->RecTimeStamp = NetToHost64(nowNtp);
+ pHeaderTx->TraTimeStamp = NetToHost64(nowNtp);
+
+ if (NtpTrace) NtpLogHeader(pHeaderTx);
+ return UNICAST;
+}
+