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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ntpserver.c Source File

ntpserver.c

00001 #include <stdint.h>
00002 #include <stdlib.h>
00003 
00004 #include "clk.h"
00005 #include "clkgov.h"
00006 #include "clktime.h"
00007 #include "clkutc.h"
00008 #include "ntptimestamp.h"
00009 #include "ntp.h"
00010 #include "ntphdr.h"
00011 #include "action.h"
00012 #include "log.h"
00013 #include "net.h"
00014 
00015 #define LI_PRIOR_NOTICE_SECONDS 10LL * 24 * 60 * 60
00016 
00017 bool NtpServerEnable  = false;
00018 
00019 char* NtpServerName = "";
00020 
00021 static int getPrecision()
00022 {
00023     /*
00024     The Precision field is set to reflect the maximum reading error of the local clock.
00025     For all practical cases it is computed as the negative of the number of significant bits
00026     to the right of the decimal point in the NTP timestamp format.
00027     While that could be CLK_TIME_ONE_SECOND_SHIFT I think that would be the resolution not the precision
00028     I therefore assume I can count on the clock to be good to about a microsecond or 2^-20
00029     */
00030     return -20;
00031 }
00032 static int getLi()
00033 {
00034     if (!ClkTimeIsSet()           ) return 3; //Alarm condition; clock is not synchronised
00035     if (!ClkUtcGetNextLeapEnable()) return 0; //No warning
00036     
00037     clktime nowTime = ClkUtcFromTai(ClkNowTai()); //Use the less costly time this scan
00038     clktime liPriorNotice = LI_PRIOR_NOTICE_SECONDS << CLK_TIME_ONE_SECOND_SHIFT;
00039     
00040     if (nowTime > ClkUtcGetNextEpoch() - liPriorNotice)
00041     {
00042         if (ClkUtcGetNextLeapForward()) return 1; //Last minute has 61 seconds
00043         else                            return 2; //Last minute has 59 seconds
00044     }
00045     else
00046     {
00047         return 0;                             //No warning
00048     }
00049 }
00050 
00051 static int getStratum()
00052 {
00053     if (ClkTimeIsSet()) return 1;
00054     else                return 0;
00055 }
00056 static char* getIdent()
00057 {
00058     if (!ClkTimeIsSet()  ) return "INIT";
00059     if (!ClkGovIsSynced()) return "LOCL";
00060     return NtpServerName;
00061 }
00062 static uint64_t getRefNtp()
00063 {
00064     return NtpTimeStampFromClkTime(ClkRefTai());
00065 }
00066 int NtpServerRequest(void (*traceback)(void), char* pPacketRx, char* pPacketTx)
00067 {
00068     if (!NtpServerEnable) return DO_NOTHING;
00069     
00070     if (NtpTrace)
00071     {
00072         if (NetTraceNewLine) Log("\r\n");
00073         LogTimeF("NTP received request\r\n");
00074         if (NetTraceStack) traceback();
00075         NtpLogHeader(pPacketRx);
00076     }
00077 
00078     uint64_t refNtp    = getRefNtp();
00079     uint64_t nowNtp    = NtpTimeStampFromClkTime(ClkTimeGet()); //use the costly time at this instant
00080     int      stratum   = getStratum();
00081     char*    ident     = getIdent();
00082     int      li        = getLi();
00083     int      precision = getPrecision();
00084 
00085     NtpHdrSetMode        (pPacketTx, NTP_SERVER);
00086     NtpHdrSetVersion     (pPacketTx, NtpHdrGetVersion(pPacketRx));
00087     NtpHdrSetLI          (pPacketTx, li);
00088     NtpHdrSetStratum     (pPacketTx, stratum);
00089     NtpHdrSetPoll        (pPacketTx, NtpHdrGetPoll(pPacketRx));
00090     NtpHdrSetPrecision   (pPacketTx, precision);
00091     NtpHdrSetRootDelay   (pPacketTx, 0);
00092     NtpHdrSetDispersion  (pPacketTx, 0);
00093     char* p = NtpHdrPtrRefIdentifier(pPacketTx);
00094     *p++ = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string.
00095     *p++ = ident[1];
00096     *p++ = ident[2];
00097     *p   = ident[3];
00098     NtpHdrSetRefTimeStamp(pPacketTx, refNtp);
00099     NtpHdrSetOriTimeStamp(pPacketTx, NtpHdrGetTraTimeStamp(pPacketRx));
00100     NtpHdrSetRecTimeStamp(pPacketTx, nowNtp);
00101     NtpHdrSetTraTimeStamp(pPacketTx, nowNtp);
00102     
00103     if (NtpTrace) NtpLogHeader(pPacketTx);
00104     return UNICAST;
00105 }
00106