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

Committer:
andrewboyson
Date:
Mon Jan 21 16:58:28 2019 +0000
Revision:
112:f8694d0b8858
Parent:
udp/ntp.c@106:e0f0e8ccb575
Child:
113:904b40231907
Added NTP client into library. Added NTP multicast to client.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewboyson 61:aad055f1b0d1 1 #include <stdint.h>
andrewboyson 61:aad055f1b0d1 2 #include <stdbool.h>
andrewboyson 61:aad055f1b0d1 3
andrewboyson 37:793b39683406 4 #include "log.h"
andrewboyson 37:793b39683406 5 #include "net.h"
andrewboyson 37:793b39683406 6 #include "action.h"
andrewboyson 37:793b39683406 7 #include "udp.h"
andrewboyson 112:f8694d0b8858 8 #include "ntpclient.h"
andrewboyson 112:f8694d0b8858 9 #include "clkntp.h"
andrewboyson 112:f8694d0b8858 10 #include "clktime.h"
andrewboyson 22:914b970356f0 11
andrewboyson 83:08c983006a6e 12
andrewboyson 37:793b39683406 13 bool NtpTrace = false;
andrewboyson 0:faa09bd4e6bf 14
andrewboyson 0:faa09bd4e6bf 15 #define CLIENT 3
andrewboyson 0:faa09bd4e6bf 16 #define SERVER 4
andrewboyson 0:faa09bd4e6bf 17
andrewboyson 22:914b970356f0 18 bool NtpServerEnable = false;
andrewboyson 104:871e65deaa5e 19 uint64_t (*NtpFunctionGetClockRef) ();
andrewboyson 104:871e65deaa5e 20 int (*NtpFunctionGetClockStratum) ();
andrewboyson 104:871e65deaa5e 21 char * (*NtpFunctionGetClockIdent) ();
andrewboyson 104:871e65deaa5e 22 int (*NtpFunctionGetClockLi) ();
andrewboyson 104:871e65deaa5e 23 int (*NtpFunctionGetClockPrecision)();
andrewboyson 22:914b970356f0 24
andrewboyson 35:93c39d260a83 25
andrewboyson 61:aad055f1b0d1 26 __packed struct header
andrewboyson 61:aad055f1b0d1 27 {
andrewboyson 0:faa09bd4e6bf 28 unsigned Mode : 3;
andrewboyson 0:faa09bd4e6bf 29 unsigned VN : 3;
andrewboyson 0:faa09bd4e6bf 30 unsigned LI : 2;
andrewboyson 0:faa09bd4e6bf 31 uint8_t Stratum;
andrewboyson 0:faa09bd4e6bf 32 int8_t Poll;
andrewboyson 0:faa09bd4e6bf 33 int8_t Precision;
andrewboyson 0:faa09bd4e6bf 34 uint32_t RootDelay;
andrewboyson 0:faa09bd4e6bf 35 uint32_t Dispersion;
andrewboyson 0:faa09bd4e6bf 36 char RefIdentifier[4];
andrewboyson 0:faa09bd4e6bf 37
andrewboyson 0:faa09bd4e6bf 38 uint64_t RefTimeStamp;
andrewboyson 0:faa09bd4e6bf 39 uint64_t OriTimeStamp;
andrewboyson 0:faa09bd4e6bf 40 uint64_t RecTimeStamp;
andrewboyson 0:faa09bd4e6bf 41 uint64_t TraTimeStamp;
andrewboyson 0:faa09bd4e6bf 42 };
andrewboyson 37:793b39683406 43 static void logHeader(struct header* pHeader)
andrewboyson 37:793b39683406 44 {
andrewboyson 61:aad055f1b0d1 45 if (NetTraceVerbose) Log ("NTP header\r\n ");
andrewboyson 61:aad055f1b0d1 46 else Log ("NTP header: ");
andrewboyson 61:aad055f1b0d1 47
andrewboyson 61:aad055f1b0d1 48 LogF("Mode %d", pHeader->Mode);
andrewboyson 61:aad055f1b0d1 49 LogF(", Version %d", pHeader->VN);
andrewboyson 61:aad055f1b0d1 50 LogF(", LI %d", pHeader->LI);
andrewboyson 61:aad055f1b0d1 51 LogF(", Stratum %d", pHeader->Stratum);
andrewboyson 61:aad055f1b0d1 52 LogF(", Poll %d", pHeader->Poll);
andrewboyson 61:aad055f1b0d1 53 LogF(", Precision %d", pHeader->Precision);
andrewboyson 61:aad055f1b0d1 54 LogF(", Root delay %d", NetToHost32(pHeader->RootDelay));
andrewboyson 61:aad055f1b0d1 55 LogF(", Dispersion %d", NetToHost32(pHeader->Dispersion));
andrewboyson 61:aad055f1b0d1 56 Log (", Ident ");
andrewboyson 61:aad055f1b0d1 57 for (int i = 0; i < 4; i++) if (pHeader->RefIdentifier[i]) LogPush(pHeader->RefIdentifier[i]);
andrewboyson 61:aad055f1b0d1 58 Log ("\r\n");
andrewboyson 61:aad055f1b0d1 59
andrewboyson 43:bc028d5a6424 60 if (NetTraceVerbose)
andrewboyson 43:bc028d5a6424 61 {
andrewboyson 43:bc028d5a6424 62 LogF(" REF %llu\r\n", NetToHost64(pHeader->RefTimeStamp));
andrewboyson 43:bc028d5a6424 63 LogF(" ORI %llu\r\n", NetToHost64(pHeader->OriTimeStamp));
andrewboyson 43:bc028d5a6424 64 LogF(" REC %llu\r\n", NetToHost64(pHeader->RecTimeStamp));
andrewboyson 43:bc028d5a6424 65 LogF(" TRA %llu\r\n", NetToHost64(pHeader->TraTimeStamp));
andrewboyson 43:bc028d5a6424 66 }
andrewboyson 37:793b39683406 67 }
andrewboyson 69:6b3c648e1452 68 static void (*pTraceBack)(void);
andrewboyson 59:e0e556c8bd46 69 static int handleRequest(struct header* pHeaderRx, struct header* pHeaderTx)
andrewboyson 0:faa09bd4e6bf 70 {
andrewboyson 22:914b970356f0 71 if (!NtpServerEnable) return DO_NOTHING;
andrewboyson 17:e475ab861365 72
andrewboyson 104:871e65deaa5e 73 if (!NtpFunctionGetClockRef ||
andrewboyson 104:871e65deaa5e 74 !NtpFunctionGetClockStratum ||
andrewboyson 104:871e65deaa5e 75 !NtpFunctionGetClockIdent ||
andrewboyson 104:871e65deaa5e 76 !NtpFunctionGetClockLi ||
andrewboyson 104:871e65deaa5e 77 !NtpFunctionGetClockPrecision)
andrewboyson 17:e475ab861365 78 {
andrewboyson 17:e475ab861365 79 LogTimeF("NtpHandleRequest - NTP server is enabled but has not been plumbed into a clock\r\n");
andrewboyson 17:e475ab861365 80 return DO_NOTHING;
andrewboyson 17:e475ab861365 81 }
andrewboyson 69:6b3c648e1452 82
andrewboyson 69:6b3c648e1452 83 if (NtpTrace)
andrewboyson 69:6b3c648e1452 84 {
andrewboyson 69:6b3c648e1452 85 if (NetTraceNewLine) Log("\r\n");
andrewboyson 69:6b3c648e1452 86 LogTimeF("NTP received request\r\n");
andrewboyson 69:6b3c648e1452 87 if (NetTraceStack) pTraceBack();
andrewboyson 69:6b3c648e1452 88 logHeader(pHeaderRx);
andrewboyson 69:6b3c648e1452 89 }
andrewboyson 69:6b3c648e1452 90
andrewboyson 104:871e65deaa5e 91 uint64_t refNtp = NtpFunctionGetClockRef();
andrewboyson 112:f8694d0b8858 92 uint64_t nowNtp = ClkTimeToNtpTimeStamp(ClkTimeGet());
andrewboyson 104:871e65deaa5e 93 int stratum = NtpFunctionGetClockStratum();
andrewboyson 104:871e65deaa5e 94 char* ident = NtpFunctionGetClockIdent();
andrewboyson 104:871e65deaa5e 95 int li = NtpFunctionGetClockLi();
andrewboyson 104:871e65deaa5e 96 int precision = NtpFunctionGetClockPrecision();
andrewboyson 22:914b970356f0 97
andrewboyson 59:e0e556c8bd46 98 pHeaderTx->Mode = SERVER;
andrewboyson 106:e0f0e8ccb575 99 pHeaderTx->VN = pHeaderRx->VN;
andrewboyson 101:a677d8aee6dd 100 pHeaderTx->LI = li;
andrewboyson 59:e0e556c8bd46 101 pHeaderTx->Stratum = stratum;
andrewboyson 106:e0f0e8ccb575 102 pHeaderTx->Poll = pHeaderRx->Poll;
andrewboyson 104:871e65deaa5e 103 pHeaderTx->Precision = precision;
andrewboyson 59:e0e556c8bd46 104 pHeaderTx->RootDelay = 0;
andrewboyson 59:e0e556c8bd46 105 pHeaderTx->Dispersion = 0;
andrewboyson 59:e0e556c8bd46 106 pHeaderTx->RefIdentifier[0] = ident[0]; //For stratum 1 (reference clock), this is a four-octet, left-justified, zero-padded ASCII string.
andrewboyson 59:e0e556c8bd46 107 pHeaderTx->RefIdentifier[1] = ident[1];
andrewboyson 59:e0e556c8bd46 108 pHeaderTx->RefIdentifier[2] = ident[2];
andrewboyson 59:e0e556c8bd46 109 pHeaderTx->RefIdentifier[3] = ident[3];
andrewboyson 59:e0e556c8bd46 110 pHeaderTx->RefTimeStamp = NetToHost64(refNtp);
andrewboyson 59:e0e556c8bd46 111 pHeaderTx->OriTimeStamp = pHeaderRx->TraTimeStamp;
andrewboyson 59:e0e556c8bd46 112 pHeaderTx->RecTimeStamp = NetToHost64(nowNtp);
andrewboyson 59:e0e556c8bd46 113 pHeaderTx->TraTimeStamp = NetToHost64(nowNtp);
andrewboyson 69:6b3c648e1452 114
andrewboyson 69:6b3c648e1452 115 if (NtpTrace) logHeader(pHeaderTx);
andrewboyson 22:914b970356f0 116 return UNICAST;
andrewboyson 22:914b970356f0 117 }
andrewboyson 59:e0e556c8bd46 118 static void handleReply(struct header* pHeader)
andrewboyson 22:914b970356f0 119 {
andrewboyson 37:793b39683406 120 if (NtpTrace)
andrewboyson 22:914b970356f0 121 {
andrewboyson 43:bc028d5a6424 122 if (NetTraceNewLine) Log("\r\n");
andrewboyson 22:914b970356f0 123 LogTimeF("NTP received reply\r\n");
andrewboyson 43:bc028d5a6424 124 if (NetTraceStack) pTraceBack();
andrewboyson 37:793b39683406 125 logHeader(pHeader);
andrewboyson 22:914b970356f0 126 }
andrewboyson 37:793b39683406 127
andrewboyson 22:914b970356f0 128 uint64_t ori = NetToHost64(pHeader->OriTimeStamp);
andrewboyson 22:914b970356f0 129 uint64_t rec = NetToHost64(pHeader->RecTimeStamp);
andrewboyson 101:a677d8aee6dd 130 int li = pHeader->LI;
andrewboyson 22:914b970356f0 131
andrewboyson 112:f8694d0b8858 132 NtpClientSetClockTime(ori, rec, li);
andrewboyson 22:914b970356f0 133 }
andrewboyson 112:f8694d0b8858 134 void NtpHdrWriteRequest(void* pPacket, int* pSize)
andrewboyson 112:f8694d0b8858 135 {
andrewboyson 112:f8694d0b8858 136 struct header* pHeader = (struct header*)pPacket;
andrewboyson 112:f8694d0b8858 137
andrewboyson 112:f8694d0b8858 138 pHeader->Mode = CLIENT;
andrewboyson 112:f8694d0b8858 139 pHeader->VN = 3;
andrewboyson 112:f8694d0b8858 140 pHeader->LI = 0;
andrewboyson 112:f8694d0b8858 141 pHeader->Stratum = 0;
andrewboyson 112:f8694d0b8858 142 pHeader->Poll = 0;
andrewboyson 112:f8694d0b8858 143 pHeader->Precision = 0;
andrewboyson 112:f8694d0b8858 144 pHeader->RootDelay = 0;
andrewboyson 112:f8694d0b8858 145 pHeader->Dispersion = 0;
andrewboyson 112:f8694d0b8858 146 pHeader->RefIdentifier[0] = 0;
andrewboyson 112:f8694d0b8858 147 pHeader->RefIdentifier[1] = 0;
andrewboyson 112:f8694d0b8858 148 pHeader->RefIdentifier[2] = 0;
andrewboyson 112:f8694d0b8858 149 pHeader->RefIdentifier[3] = 0;
andrewboyson 112:f8694d0b8858 150 pHeader->RefTimeStamp = 0;
andrewboyson 112:f8694d0b8858 151 pHeader->OriTimeStamp = 0;
andrewboyson 112:f8694d0b8858 152 pHeader->RecTimeStamp = 0;
andrewboyson 112:f8694d0b8858 153 pHeader->TraTimeStamp = NetToHost64(ClkTimeToNtpTimeStamp(ClkTimeGet()));
andrewboyson 112:f8694d0b8858 154
andrewboyson 112:f8694d0b8858 155 *pSize = sizeof(struct header);
andrewboyson 112:f8694d0b8858 156 }
andrewboyson 112:f8694d0b8858 157
andrewboyson 59:e0e556c8bd46 158 int NtpHandlePacketReceived(void (*traceback)(void), int sizeRx, void * pPacketRx, int* pSizeTx, void* pPacketTx)
andrewboyson 22:914b970356f0 159 {
andrewboyson 37:793b39683406 160 pTraceBack = traceback;
andrewboyson 37:793b39683406 161
andrewboyson 61:aad055f1b0d1 162 if (sizeRx != sizeof(struct header))
andrewboyson 22:914b970356f0 163 {
andrewboyson 59:e0e556c8bd46 164 LogTimeF("\r\nNTP packet wrong size %d\r\n", sizeRx);
andrewboyson 22:914b970356f0 165 return DO_NOTHING;
andrewboyson 22:914b970356f0 166 }
andrewboyson 59:e0e556c8bd46 167 struct header* pHeaderRx = (struct header*)pPacketRx;
andrewboyson 59:e0e556c8bd46 168 struct header* pHeaderTx = (struct header*)pPacketTx;
andrewboyson 17:e475ab861365 169
andrewboyson 59:e0e556c8bd46 170 int dest = DO_NOTHING;
andrewboyson 59:e0e556c8bd46 171 switch (pHeaderRx->Mode)
andrewboyson 0:faa09bd4e6bf 172 {
andrewboyson 59:e0e556c8bd46 173 case CLIENT: dest = handleRequest(pHeaderRx, pHeaderTx); break;
andrewboyson 59:e0e556c8bd46 174 case SERVER: handleReply (pHeaderRx); return DO_NOTHING;
andrewboyson 0:faa09bd4e6bf 175 default:
andrewboyson 59:e0e556c8bd46 176 LogTimeF("\r\nNTP packet unknown mode %d\r\n", pHeaderRx->Mode);
andrewboyson 22:914b970356f0 177 return DO_NOTHING;
andrewboyson 0:faa09bd4e6bf 178 }
andrewboyson 59:e0e556c8bd46 179
andrewboyson 59:e0e556c8bd46 180 if (dest == DO_NOTHING) return DO_NOTHING;
andrewboyson 61:aad055f1b0d1 181 *pSizeTx = sizeof(struct header);
andrewboyson 59:e0e556c8bd46 182
andrewboyson 59:e0e556c8bd46 183 return ActionMakeFromDestAndTrace(dest, NtpTrace && NetTraceStack);
andrewboyson 22:914b970356f0 184 }
andrewboyson 112:f8694d0b8858 185 int NtpPollForPacketToSend(int type, void* pPacket, int* pSize)
andrewboyson 112:f8694d0b8858 186 {
andrewboyson 112:f8694d0b8858 187 int dest = NtpClientPollForPacketToSend(type, pPacket, pSize);
andrewboyson 112:f8694d0b8858 188 if (!dest) return DO_NOTHING;
andrewboyson 36:900e24b27bfb 189
andrewboyson 42:222a4f45f916 190 if (NtpTrace)
andrewboyson 37:793b39683406 191 {
andrewboyson 43:bc028d5a6424 192 if (NetTraceNewLine) Log("\r\n");
andrewboyson 37:793b39683406 193 LogTimeF("Sending NTP request\r\n");
andrewboyson 42:222a4f45f916 194 logHeader((struct header*)pPacket);
andrewboyson 37:793b39683406 195 }
andrewboyson 43:bc028d5a6424 196 return ActionMakeFromDestAndTrace(dest, NtpTrace && NetTraceStack);
andrewboyson 112:f8694d0b8858 197
andrewboyson 112:f8694d0b8858 198
andrewboyson 22:914b970356f0 199 }
andrewboyson 22:914b970356f0 200