Andrew Boyson / net

Dependents:   oldheating gps motorhome heating

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;
+}
+