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
udp/ntp/ntpserver.c@123:44fea08759af, 2019-02-21 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Feb 21 12:53:06 2019 +0000
- Revision:
- 123:44fea08759af
- Parent:
- 113:904b40231907
- Child:
- 124:6e558721ec1c
Updated clock library
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 113:904b40231907 | 1 | #include <stdint.h> |
| andrewboyson | 113:904b40231907 | 2 | |
| andrewboyson | 113:904b40231907 | 3 | #include "clk.h" |
| andrewboyson | 113:904b40231907 | 4 | #include "clkgov.h" |
| andrewboyson | 113:904b40231907 | 5 | #include "clktime.h" |
| andrewboyson | 113:904b40231907 | 6 | #include "clkutc.h" |
| andrewboyson | 113:904b40231907 | 7 | #include "clkntp.h" |
| andrewboyson | 113:904b40231907 | 8 | #include "clkutc.h" |
| andrewboyson | 113:904b40231907 | 9 | #include "ntp.h" |
| andrewboyson | 113:904b40231907 | 10 | #include "action.h" |
| andrewboyson | 113:904b40231907 | 11 | #include "log.h" |
| andrewboyson | 113:904b40231907 | 12 | #include "net.h" |
| andrewboyson | 113:904b40231907 | 13 | |
| andrewboyson | 113:904b40231907 | 14 | #define LI_PRIOR_NOTICE_SECONDS 10LL * 24 * 60 * 60 |
| andrewboyson | 113:904b40231907 | 15 | |
| andrewboyson | 113:904b40231907 | 16 | bool NtpServerEnable = false; |
| andrewboyson | 113:904b40231907 | 17 | |
| andrewboyson | 113:904b40231907 | 18 | char* NtpServerName = ""; |
| andrewboyson | 113:904b40231907 | 19 | |
| andrewboyson | 113:904b40231907 | 20 | static int getPrecision() |
| andrewboyson | 113:904b40231907 | 21 | { |
| andrewboyson | 113:904b40231907 | 22 | /* |
| andrewboyson | 113:904b40231907 | 23 | The Precision field is set to reflect the maximum reading error of the local clock. |
| andrewboyson | 113:904b40231907 | 24 | For all practical cases it is computed as the negative of the number of significant bits |
| andrewboyson | 113:904b40231907 | 25 | to the right of the decimal point in the NTP timestamp format. |
| andrewboyson | 113:904b40231907 | 26 | While that could be CLK_TIME_ONE_SECOND_SHIFT I think that would be the resolution not the precision |
| andrewboyson | 113:904b40231907 | 27 | I therefore assume I can count on the clock to be good to about a microsecond or 2^-20 |
| andrewboyson | 113:904b40231907 | 28 | */ |
| andrewboyson | 113:904b40231907 | 29 | return -20; |
| andrewboyson | 113:904b40231907 | 30 | } |
| andrewboyson | 113:904b40231907 | 31 | static int getLi() |
| andrewboyson | 113:904b40231907 | 32 | { |
| andrewboyson | 113:904b40231907 | 33 | if (!ClkTimeIsSet() ) return 3; //Alarm condition; clock is not synchronised |
| andrewboyson | 113:904b40231907 | 34 | if (!ClkUtcGetNextLeapEnable()) return 0; //No warning |
| andrewboyson | 113:904b40231907 | 35 | |
| andrewboyson | 123:44fea08759af | 36 | int64_t nowTime = ClkUtcFromTai(ClkNowTai()); |
| andrewboyson | 113:904b40231907 | 37 | int64_t liPriorNotice = LI_PRIOR_NOTICE_SECONDS << CLK_TIME_ONE_SECOND_SHIFT; |
| andrewboyson | 113:904b40231907 | 38 | |
| andrewboyson | 113:904b40231907 | 39 | if (nowTime > ClkUtcGetNextEpoch() - liPriorNotice) |
| andrewboyson | 113:904b40231907 | 40 | { |
| andrewboyson | 113:904b40231907 | 41 | if (ClkUtcGetNextLeapForward()) return 1; //Last minute has 61 seconds |
| andrewboyson | 113:904b40231907 | 42 | else return 2; //Last minute has 59 seconds |
| andrewboyson | 113:904b40231907 | 43 | } |
| andrewboyson | 113:904b40231907 | 44 | else |
| andrewboyson | 113:904b40231907 | 45 | { |
| andrewboyson | 113:904b40231907 | 46 | return 0; //No warning |
| andrewboyson | 113:904b40231907 | 47 | } |
| andrewboyson | 113:904b40231907 | 48 | } |
| andrewboyson | 113:904b40231907 | 49 | |
| andrewboyson | 113:904b40231907 | 50 | static int getStratum() |
| andrewboyson | 113:904b40231907 | 51 | { |
| andrewboyson | 113:904b40231907 | 52 | if (ClkTimeIsSet()) return 1; |
| andrewboyson | 113:904b40231907 | 53 | else return 0; |
| andrewboyson | 113:904b40231907 | 54 | } |
| andrewboyson | 113:904b40231907 | 55 | static char* getIdent() |
| andrewboyson | 113:904b40231907 | 56 | { |
| andrewboyson | 113:904b40231907 | 57 | if (!ClkTimeIsSet() ) return "INIT"; |
| andrewboyson | 113:904b40231907 | 58 | if (!ClkGovIsSynced()) return "LOCL"; |
| andrewboyson | 113:904b40231907 | 59 | return NtpServerName; |
| andrewboyson | 113:904b40231907 | 60 | } |
| andrewboyson | 113:904b40231907 | 61 | static uint64_t getRefNtp() |
| andrewboyson | 113:904b40231907 | 62 | { |
| andrewboyson | 123:44fea08759af | 63 | return ClkTimeToNtpTimeStamp(ClkRefTai()); |
| andrewboyson | 113:904b40231907 | 64 | } |
| andrewboyson | 113:904b40231907 | 65 | int NtpServerRequest(void (*traceback)(void), struct NtpHeader* pHeaderRx, struct NtpHeader* pHeaderTx) |
| andrewboyson | 113:904b40231907 | 66 | { |
| andrewboyson | 113:904b40231907 | 67 | if (!NtpServerEnable) return DO_NOTHING; |
| andrewboyson | 113:904b40231907 | 68 | |
| andrewboyson | 113:904b40231907 | 69 | if (NtpTrace) |
| andrewboyson | 113:904b40231907 | 70 | { |
| andrewboyson | 113:904b40231907 | 71 | if (NetTraceNewLine) Log("\r\n"); |
| andrewboyson | 113:904b40231907 | 72 | LogTimeF("NTP received request\r\n"); |
| andrewboyson | 113:904b40231907 | 73 | if (NetTraceStack) traceback(); |
| andrewboyson | 113:904b40231907 | 74 | NtpLogHeader(pHeaderRx); |
| andrewboyson | 113:904b40231907 | 75 | } |
| andrewboyson | 113:904b40231907 | 76 | |
| andrewboyson | 113:904b40231907 | 77 | uint64_t refNtp = getRefNtp(); |
| andrewboyson | 113:904b40231907 | 78 | uint64_t nowNtp = ClkTimeToNtpTimeStamp(ClkTimeGet()); |
| andrewboyson | 113:904b40231907 | 79 | int stratum = getStratum(); |
| andrewboyson | 113:904b40231907 | 80 | char* ident = getIdent(); |
| andrewboyson | 113:904b40231907 | 81 | int li = getLi(); |
| andrewboyson | 113:904b40231907 | 82 | int precision = getPrecision(); |
| andrewboyson | 113:904b40231907 | 83 | |
| andrewboyson | 113:904b40231907 | 84 | pHeaderTx->Mode = NTP_SERVER; |
| andrewboyson | 113:904b40231907 | 85 | pHeaderTx->VN = pHeaderRx->VN; |
| andrewboyson | 113:904b40231907 | 86 | pHeaderTx->LI = li; |
| andrewboyson | 113:904b40231907 | 87 | pHeaderTx->Stratum = stratum; |
| andrewboyson | 113:904b40231907 | 88 | pHeaderTx->Poll = pHeaderRx->Poll; |
| andrewboyson | 113:904b40231907 | 89 | pHeaderTx->Precision = precision; |
| andrewboyson | 113:904b40231907 | 90 | pHeaderTx->RootDelay = 0; |
| andrewboyson | 113:904b40231907 | 91 | pHeaderTx->Dispersion = 0; |
| andrewboyson | 113:904b40231907 | 92 | pHeaderTx->RefIdentifier[0] = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string. |
| andrewboyson | 113:904b40231907 | 93 | pHeaderTx->RefIdentifier[1] = ident[1]; |
| andrewboyson | 113:904b40231907 | 94 | pHeaderTx->RefIdentifier[2] = ident[2]; |
| andrewboyson | 113:904b40231907 | 95 | pHeaderTx->RefIdentifier[3] = ident[3]; |
| andrewboyson | 113:904b40231907 | 96 | pHeaderTx->RefTimeStamp = NetToHost64(refNtp); |
| andrewboyson | 113:904b40231907 | 97 | pHeaderTx->OriTimeStamp = pHeaderRx->TraTimeStamp; |
| andrewboyson | 113:904b40231907 | 98 | pHeaderTx->RecTimeStamp = NetToHost64(nowNtp); |
| andrewboyson | 113:904b40231907 | 99 | pHeaderTx->TraTimeStamp = NetToHost64(nowNtp); |
| andrewboyson | 113:904b40231907 | 100 | |
| andrewboyson | 113:904b40231907 | 101 | if (NtpTrace) NtpLogHeader(pHeaderTx); |
| andrewboyson | 113:904b40231907 | 102 | return UNICAST; |
| andrewboyson | 113:904b40231907 | 103 | } |
| andrewboyson | 113:904b40231907 | 104 |