A time interface class. This class replicates the normal time functions, but goes a couple of steps further. mbed library 82 and prior has a defective gmtime function. Also, this class enables access to setting the time, and adjusting the accuracy of the RTC.

Dependencies:   CalendarPage

Dependents:   CI-data-logger-server WattEye X10Svr SSDP_Server

Committer:
WiredHome
Date:
Sun Sep 13 15:06:14 2020 +0000
Revision:
33:e49b25bdbfa5
Parent:
32:00ee2ad29da0
Correct gmtime and localtime apis.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 21:f3818e2e0370 1 /* NTPClient.cpp */
WiredHome 21:f3818e2e0370 2 /* Copyright (C) 2012 mbed.org, MIT License
WiredHome 21:f3818e2e0370 3 *
WiredHome 21:f3818e2e0370 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
WiredHome 21:f3818e2e0370 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
WiredHome 21:f3818e2e0370 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
WiredHome 21:f3818e2e0370 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
WiredHome 21:f3818e2e0370 8 * furnished to do so, subject to the following conditions:
WiredHome 21:f3818e2e0370 9 *
WiredHome 21:f3818e2e0370 10 * The above copyright notice and this permission notice shall be included in all copies or
WiredHome 21:f3818e2e0370 11 * substantial portions of the Software.
WiredHome 21:f3818e2e0370 12 *
WiredHome 21:f3818e2e0370 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
WiredHome 21:f3818e2e0370 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
WiredHome 21:f3818e2e0370 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
WiredHome 21:f3818e2e0370 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
WiredHome 21:f3818e2e0370 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
WiredHome 21:f3818e2e0370 18 */
WiredHome 21:f3818e2e0370 19 #include "mbed.h" //time() and set_time()
WiredHome 21:f3818e2e0370 20
WiredHome 21:f3818e2e0370 21 #include "EthernetInterface.h"
WiredHome 21:f3818e2e0370 22 #include "UDPSocket.h"
WiredHome 21:f3818e2e0370 23 #include "Socket.h"
WiredHome 21:f3818e2e0370 24 #include "NTPClient.h"
WiredHome 21:f3818e2e0370 25
WiredHome 21:f3818e2e0370 26
WiredHome 31:c692c48e79bb 27 //#define DEBUG "NTPc"
WiredHome 21:f3818e2e0370 28
WiredHome 21:f3818e2e0370 29 #if (defined(DEBUG))
WiredHome 21:f3818e2e0370 30 #include <cstdio>
WiredHome 21:f3818e2e0370 31 #define INFO(x, ...) std::printf("[INF %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 21:f3818e2e0370 32 #define WARN(x, ...) std::printf("[WRN %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 21:f3818e2e0370 33 #define ERR(x, ...) std::printf("[ERR %s %4d] "x"\r\n", DEBUG, __LINE__, ##__VA_ARGS__);
WiredHome 21:f3818e2e0370 34 static void HexDump(const char * title, void * pT, int count)
WiredHome 21:f3818e2e0370 35 {
WiredHome 21:f3818e2e0370 36 int i;
WiredHome 21:f3818e2e0370 37 uint8_t * p = (uint8_t *)pT;
WiredHome 21:f3818e2e0370 38 char buf[100] = "0000: ";
WiredHome 21:f3818e2e0370 39
WiredHome 21:f3818e2e0370 40 if (*title)
WiredHome 21:f3818e2e0370 41 INFO("%s", title);
WiredHome 21:f3818e2e0370 42 for (i=0; i<count; ) {
WiredHome 21:f3818e2e0370 43 sprintf(buf + strlen(buf), "%02X ", *(p+i));
WiredHome 21:f3818e2e0370 44 if ((++i & 0x0F) == 0x00) {
WiredHome 21:f3818e2e0370 45 INFO("%s", buf);
WiredHome 21:f3818e2e0370 46 if (i < count)
WiredHome 21:f3818e2e0370 47 sprintf(buf, "%04X: ", i);
WiredHome 21:f3818e2e0370 48 else
WiredHome 21:f3818e2e0370 49 buf[0] = '\0';
WiredHome 21:f3818e2e0370 50 }
WiredHome 21:f3818e2e0370 51 }
WiredHome 21:f3818e2e0370 52 if (strlen(buf))
WiredHome 21:f3818e2e0370 53 INFO("%s", buf);
WiredHome 21:f3818e2e0370 54 }
WiredHome 21:f3818e2e0370 55 #else
WiredHome 21:f3818e2e0370 56 //Disable debug
WiredHome 21:f3818e2e0370 57 #define INFO(x, ...)
WiredHome 21:f3818e2e0370 58 #define WARN(x, ...)
WiredHome 21:f3818e2e0370 59 #define ERR(x, ...)
WiredHome 21:f3818e2e0370 60 #define HexDump(a,b,c)
WiredHome 21:f3818e2e0370 61 #endif
WiredHome 21:f3818e2e0370 62
WiredHome 21:f3818e2e0370 63
WiredHome 21:f3818e2e0370 64 #define NTP_PORT 123
WiredHome 21:f3818e2e0370 65 #define NTP_CLIENT_PORT 0 //Random port
WiredHome 21:f3818e2e0370 66 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
WiredHome 21:f3818e2e0370 67
WiredHome 21:f3818e2e0370 68 #if 0 && MBED_MAJOR_VERSION == 5
WiredHome 21:f3818e2e0370 69 #define htonl(x) ((((x) & 0x000000ffUL) << 24) | \
WiredHome 21:f3818e2e0370 70 (((x) & 0x0000ff00UL) << 8) | \
WiredHome 21:f3818e2e0370 71 (((x) & 0x00ff0000UL) >> 8) | \
WiredHome 21:f3818e2e0370 72 (((x) & 0xff000000UL) >> 24))
WiredHome 21:f3818e2e0370 73 #define ntohl(x) htonl(x)
WiredHome 21:f3818e2e0370 74 #endif
WiredHome 21:f3818e2e0370 75
WiredHome 21:f3818e2e0370 76 NTPClient::NTPClient(EthernetInterface * _net) : m_sock()
WiredHome 21:f3818e2e0370 77 {
WiredHome 21:f3818e2e0370 78 net = _net;
WiredHome 21:f3818e2e0370 79 }
WiredHome 21:f3818e2e0370 80
WiredHome 21:f3818e2e0370 81
WiredHome 21:f3818e2e0370 82 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
WiredHome 21:f3818e2e0370 83 {
WiredHome 21:f3818e2e0370 84 #ifdef DEBUG
WiredHome 21:f3818e2e0370 85 time_t ctTime;
WiredHome 21:f3818e2e0370 86 ctTime = time(NULL);
WiredHome 21:f3818e2e0370 87 INFO("Time is currently (UTC): %s", ctime(&ctTime));
WiredHome 21:f3818e2e0370 88 #endif
WiredHome 21:f3818e2e0370 89
WiredHome 29:28180961841f 90 #if 0 && MBED_MAJOR_VERSION == 5
WiredHome 27:67e4e2ab048a 91
WiredHome 21:f3818e2e0370 92 //
WiredHome 21:f3818e2e0370 93 // MBED OS 5
WiredHome 21:f3818e2e0370 94 //
WiredHome 21:f3818e2e0370 95
WiredHome 21:f3818e2e0370 96 struct NTPPacket pkt;
WiredHome 21:f3818e2e0370 97
WiredHome 21:f3818e2e0370 98 SocketAddress nist;
WiredHome 21:f3818e2e0370 99 int ret_gethostbyname = net->gethostbyname(host, &nist);
WiredHome 21:f3818e2e0370 100 INFO("gethostbyname(%s) returned %d", host, ret_gethostbyname);
WiredHome 21:f3818e2e0370 101 if (ret_gethostbyname < 0) {
WiredHome 21:f3818e2e0370 102 return NTP_DNS; // Network error on DNS lookup
WiredHome 21:f3818e2e0370 103 }
WiredHome 21:f3818e2e0370 104
WiredHome 21:f3818e2e0370 105 nist.set_port(port);
WiredHome 21:f3818e2e0370 106 INFO("set_port(%d)", port);
WiredHome 21:f3818e2e0370 107
WiredHome 21:f3818e2e0370 108 time_t tQueryTime = time(NULL);
WiredHome 21:f3818e2e0370 109 //
WiredHome 21:f3818e2e0370 110 //Prepare NTP Packet for the query:
WiredHome 21:f3818e2e0370 111 //
WiredHome 21:f3818e2e0370 112 pkt.li = 0; //Leap Indicator : No warning
WiredHome 21:f3818e2e0370 113 pkt.vn = 4; //Version Number : 4
WiredHome 21:f3818e2e0370 114 pkt.mode = 3; //Client mode
WiredHome 21:f3818e2e0370 115 pkt.stratum = 0; //Not relevant here
WiredHome 21:f3818e2e0370 116 pkt.poll = 0; //Not significant as well
WiredHome 21:f3818e2e0370 117 pkt.precision = 0; //Neither this one is
WiredHome 21:f3818e2e0370 118 pkt.rootDelay = 0; //Or this one
WiredHome 21:f3818e2e0370 119 pkt.rootDispersion = 0; //Or that one
WiredHome 21:f3818e2e0370 120 pkt.refId = 0; //...
WiredHome 21:f3818e2e0370 121 pkt.refTm_s = 0;
WiredHome 21:f3818e2e0370 122 pkt.origTm_s = 0;
WiredHome 21:f3818e2e0370 123 pkt.rxTm_s = 0;
WiredHome 27:67e4e2ab048a 124 pkt.txTm_s = NTP_TIMESTAMP_DELTA + tQueryTime; //WARN: We are in LE format, network byte order is BE
WiredHome 21:f3818e2e0370 125 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
WiredHome 27:67e4e2ab048a 126 HexDump("NTP Post", (uint8_t *)&pkt, sizeof(NTPPacket));
WiredHome 27:67e4e2ab048a 127 pkt.txTm_s = htonl(pkt.txTm_s);
WiredHome 21:f3818e2e0370 128
WiredHome 27:67e4e2ab048a 129 // Contact the server
WiredHome 21:f3818e2e0370 130 UDPSocket sock;
WiredHome 21:f3818e2e0370 131 nsapi_error_t ret = sock.open(net);
WiredHome 21:f3818e2e0370 132 INFO("sock.open(...) returned %d", ret);
WiredHome 27:67e4e2ab048a 133 sock.set_timeout(timeout); //Set timeout, non-blocking and wait using select
WiredHome 21:f3818e2e0370 134
WiredHome 27:67e4e2ab048a 135 // Send the query
WiredHome 21:f3818e2e0370 136 int ret_send = sock.sendto(nist, (void *)&pkt, sizeof(NTPPacket));
WiredHome 21:f3818e2e0370 137 INFO("sock.sendto(...) returned %d", ret_send);
WiredHome 21:f3818e2e0370 138
WiredHome 21:f3818e2e0370 139 SocketAddress source;
WiredHome 27:67e4e2ab048a 140
WiredHome 27:67e4e2ab048a 141 // Set the inEndpoint address property
WiredHome 21:f3818e2e0370 142 source.set_ip_address(nist.get_ip_address());
WiredHome 21:f3818e2e0370 143 const int n = sock.recvfrom(&source, (void *)&pkt, sizeof(NTPPacket));
WiredHome 21:f3818e2e0370 144 uint32_t destTimeStamp = NTP_TIMESTAMP_DELTA + time(NULL);
WiredHome 21:f3818e2e0370 145 INFO("recvfrom(...) returned %d", n);
WiredHome 27:67e4e2ab048a 146
WiredHome 21:f3818e2e0370 147 if (pkt.stratum == 0) { //Kiss of death message : Not good !
WiredHome 21:f3818e2e0370 148 ERR("Kissed to death!");
WiredHome 27:67e4e2ab048a 149 sock.close();
WiredHome 21:f3818e2e0370 150 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 151 }
WiredHome 27:67e4e2ab048a 152
WiredHome 27:67e4e2ab048a 153 HexDump("NTP Info", (uint8_t *)&pkt, sizeof(NTPPacket));
WiredHome 27:67e4e2ab048a 154
WiredHome 21:f3818e2e0370 155 //Correct Endianness
WiredHome 21:f3818e2e0370 156 pkt.refTm_s = ntohl( pkt.refTm_s );
WiredHome 21:f3818e2e0370 157 pkt.refTm_f = ntohl( pkt.refTm_f );
WiredHome 21:f3818e2e0370 158 pkt.origTm_s = ntohl( pkt.origTm_s );
WiredHome 21:f3818e2e0370 159 pkt.origTm_f = ntohl( pkt.origTm_f );
WiredHome 21:f3818e2e0370 160 pkt.rxTm_s = ntohl( pkt.rxTm_s );
WiredHome 21:f3818e2e0370 161 pkt.rxTm_f = ntohl( pkt.rxTm_f );
WiredHome 21:f3818e2e0370 162 pkt.txTm_s = ntohl( pkt.txTm_s );
WiredHome 21:f3818e2e0370 163 pkt.txTm_f = ntohl( pkt.txTm_f );
WiredHome 21:f3818e2e0370 164
WiredHome 21:f3818e2e0370 165 #ifdef DEBUG
WiredHome 21:f3818e2e0370 166 const char *ModeList[] = {
WiredHome 21:f3818e2e0370 167 "reserved", "symmetric active", "symmetric passive", "client",
WiredHome 21:f3818e2e0370 168 "server", "broadcast", "reserved for NTP ctrl", "reserved for priv use"
WiredHome 21:f3818e2e0370 169 };
WiredHome 21:f3818e2e0370 170 INFO(" pkt.li (Leap Ind) %d", pkt.li);
WiredHome 21:f3818e2e0370 171 INFO(" pkt.vn (Vers #) %d", pkt.vn);
WiredHome 21:f3818e2e0370 172 INFO(" pkt.mode %d, mode %s", pkt.mode, ModeList[pkt.mode]);
WiredHome 21:f3818e2e0370 173 INFO(" pkt.stratum %d, 0=kiss-o'-death, 1=prim, 2=secd", pkt.stratum);
WiredHome 21:f3818e2e0370 174 INFO(" pkt.poll %d", pkt.poll);
WiredHome 21:f3818e2e0370 175 INFO(" pkt.precision %d", pkt.precision);
WiredHome 21:f3818e2e0370 176 INFO(" pkt.rootDelay %d", pkt.rootDelay);
WiredHome 21:f3818e2e0370 177 INFO(" pkt.rootDispersion %d", pkt.rootDispersion);
WiredHome 21:f3818e2e0370 178 INFO(" pkt.refId %08X, %u", pkt.refId, pkt.refId);
WiredHome 21:f3818e2e0370 179 INFO(" pkt.refTm_s %08X, %u, ref time (last set)", pkt.refTm_s, pkt.refTm_s);
WiredHome 21:f3818e2e0370 180 INFO(" pkt.origTm_s %08X, %u, time sent from client", pkt.origTm_s, pkt.origTm_s);
WiredHome 21:f3818e2e0370 181 INFO(" pkt.rxTm_s %08X, %u, time rcvd at server", pkt.rxTm_s, pkt.rxTm_s);
WiredHome 21:f3818e2e0370 182 INFO(" pkt.txTm_s %08X, %u, time sent from server", pkt.txTm_s, pkt.txTm_s);
WiredHome 21:f3818e2e0370 183 INFO(" pkt.refTm_f %08X, %u, fraction", pkt.refTm_f, pkt.refTm_f);
WiredHome 21:f3818e2e0370 184 #endif
WiredHome 21:f3818e2e0370 185
WiredHome 21:f3818e2e0370 186 ret = sock.close();
WiredHome 21:f3818e2e0370 187 INFO("sock.close() returned %d", ret);
WiredHome 21:f3818e2e0370 188
WiredHome 21:f3818e2e0370 189 if (n == sizeof(NTPPacket)) {
WiredHome 21:f3818e2e0370 190
WiredHome 21:f3818e2e0370 191 // Modification by David Smart
WiredHome 21:f3818e2e0370 192 // The setTime function was computing the offset incorrectly as the value was promoted to 64-bit.
WiredHome 21:f3818e2e0370 193 // The side effect was that a negative offset ended up as a very large positive (e.g. jump from
WiredHome 21:f3818e2e0370 194 // 2016 to 2084). This change revises that computation.
WiredHome 27:67e4e2ab048a 195 int64_t offset = (((int64_t)pkt.rxTm_s - pkt.origTm_s) + ((int64_t)pkt.txTm_s - destTimeStamp))/2;
WiredHome 27:67e4e2ab048a 196 set_time( time(NULL) + offset );
WiredHome 21:f3818e2e0370 197 } else {
WiredHome 21:f3818e2e0370 198 ERR("bad return from recvfrom() %d", n);
WiredHome 21:f3818e2e0370 199 if (n < 0) {
WiredHome 21:f3818e2e0370 200 // Network error
WiredHome 21:f3818e2e0370 201 return NTP_CONN;
WiredHome 21:f3818e2e0370 202 } else {
WiredHome 21:f3818e2e0370 203 // No or partial data returned
WiredHome 21:f3818e2e0370 204 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 205 }
WiredHome 21:f3818e2e0370 206 }
WiredHome 21:f3818e2e0370 207
WiredHome 21:f3818e2e0370 208 #else // MBED OS 2
WiredHome 21:f3818e2e0370 209
WiredHome 21:f3818e2e0370 210 //
WiredHome 21:f3818e2e0370 211 // MBED OS 2
WiredHome 21:f3818e2e0370 212 //
WiredHome 21:f3818e2e0370 213
WiredHome 21:f3818e2e0370 214 struct NTPPacket pkt;
WiredHome 21:f3818e2e0370 215
WiredHome 27:67e4e2ab048a 216 Endpoint nist;
WiredHome 27:67e4e2ab048a 217 int ret_gethostbyname = nist.set_address(host, port);
WiredHome 27:67e4e2ab048a 218 INFO("gethostbyname(%s) returned %d", host, ret_gethostbyname);
WiredHome 27:67e4e2ab048a 219 if (ret_gethostbyname < 0) {
WiredHome 27:67e4e2ab048a 220 m_sock.close();
WiredHome 27:67e4e2ab048a 221 return NTP_DNS; // Network error on DNS lookup
WiredHome 27:67e4e2ab048a 222 }
WiredHome 27:67e4e2ab048a 223 INFO("nist: %s:%d", nist.get_address(), nist.get_port());
WiredHome 27:67e4e2ab048a 224
WiredHome 27:67e4e2ab048a 225 //Create & bind socket
WiredHome 27:67e4e2ab048a 226 INFO("Binding socket");
WiredHome 27:67e4e2ab048a 227 m_sock.bind(0); //Bind to a random port
WiredHome 27:67e4e2ab048a 228 m_sock.set_blocking(false, timeout); //Set not blocking
WiredHome 21:f3818e2e0370 229
WiredHome 27:67e4e2ab048a 230 time_t tQueryTime = time(NULL);
WiredHome 27:67e4e2ab048a 231 //
WiredHome 27:67e4e2ab048a 232 //Prepare NTP Packet for the query:
WiredHome 27:67e4e2ab048a 233 //
WiredHome 27:67e4e2ab048a 234 pkt.li = 0; //Leap Indicator : No warning
WiredHome 27:67e4e2ab048a 235 pkt.vn = 4; //Version Number : 4
WiredHome 27:67e4e2ab048a 236 pkt.mode = 3; //Client mode
WiredHome 27:67e4e2ab048a 237 pkt.stratum = 0; //Not relevant here
WiredHome 27:67e4e2ab048a 238 pkt.poll = 0; //Not significant as well
WiredHome 27:67e4e2ab048a 239 pkt.precision = 0; //Neither this one is
WiredHome 27:67e4e2ab048a 240 pkt.rootDelay = 0; //Or this one
WiredHome 21:f3818e2e0370 241 pkt.rootDispersion = 0; //Or that one
WiredHome 27:67e4e2ab048a 242 pkt.refId = 0; //...
WiredHome 21:f3818e2e0370 243 pkt.refTm_s = 0;
WiredHome 21:f3818e2e0370 244 pkt.origTm_s = 0;
WiredHome 21:f3818e2e0370 245 pkt.rxTm_s = 0;
WiredHome 27:67e4e2ab048a 246 pkt.txTm_s = NTP_TIMESTAMP_DELTA + tQueryTime; //WARN: We are in LE format, network byte order is BE
WiredHome 21:f3818e2e0370 247 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
WiredHome 21:f3818e2e0370 248 HexDump("NTP Post", (uint8_t *)&pkt, sizeof(NTPPacket));
WiredHome 27:67e4e2ab048a 249 pkt.txTm_s = htonl(pkt.txTm_s);
WiredHome 27:67e4e2ab048a 250
WiredHome 27:67e4e2ab048a 251 // Contact the server
WiredHome 27:67e4e2ab048a 252 // UDPSocket sock;
WiredHome 27:67e4e2ab048a 253 // nsapi_error_t ret = sock.open(net);
WiredHome 27:67e4e2ab048a 254 // INFO("sock.open(...) returned %d", ret);
WiredHome 27:67e4e2ab048a 255 // sock.set_timeout(timeout); //Set timeout, non-blocking and wait using select
WiredHome 27:67e4e2ab048a 256
WiredHome 27:67e4e2ab048a 257 // Send the query
WiredHome 27:67e4e2ab048a 258 int ret = m_sock.sendTo(nist, (char*)&pkt, sizeof(NTPPacket));
WiredHome 28:3fa154ab6ffd 259 INFO("m_sock.sendto(...) returned %d", ret);
WiredHome 21:f3818e2e0370 260 if (ret < 0 ) {
WiredHome 21:f3818e2e0370 261 ERR("Could not send packet");
WiredHome 21:f3818e2e0370 262 m_sock.close();
WiredHome 21:f3818e2e0370 263 return NTP_CONN;
WiredHome 21:f3818e2e0370 264 }
WiredHome 21:f3818e2e0370 265
WiredHome 21:f3818e2e0370 266 //Read response
WiredHome 21:f3818e2e0370 267 Endpoint inEndpoint;
WiredHome 21:f3818e2e0370 268 // Set the inEndpoint address property
WiredHome 27:67e4e2ab048a 269 inEndpoint.set_address(nist.get_address(), 0);
WiredHome 29:28180961841f 270 INFO(" inEndpoint instantiated: %s.", inEndpoint.get_address());
WiredHome 21:f3818e2e0370 271
WiredHome 21:f3818e2e0370 272 int loopLimit = 20; // semi-randomly selected so it doesn't hang forever here...
WiredHome 21:f3818e2e0370 273 do {
WiredHome 21:f3818e2e0370 274 ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) );
WiredHome 21:f3818e2e0370 275 if(ret < 0) {
WiredHome 29:28180961841f 276 ERR("Could not receive packet, err: %d", ret);
WiredHome 21:f3818e2e0370 277 m_sock.close();
WiredHome 21:f3818e2e0370 278 return NTP_CONN;
WiredHome 21:f3818e2e0370 279 }
WiredHome 21:f3818e2e0370 280 INFO(".");
WiredHome 21:f3818e2e0370 281 loopLimit--;
WiredHome 27:67e4e2ab048a 282 } while( strcmp(nist.get_address(), inEndpoint.get_address()) != 0 && loopLimit > 0);
WiredHome 21:f3818e2e0370 283
WiredHome 21:f3818e2e0370 284 if(ret < (int)sizeof(NTPPacket)) { //TODO: Accept chunks
WiredHome 29:28180961841f 285 ERR("Receive packet size does not match, rcvd %d, expected %d", ret, (int)sizeof(NTPPacket));
WiredHome 21:f3818e2e0370 286 m_sock.close();
WiredHome 21:f3818e2e0370 287 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 288 }
WiredHome 21:f3818e2e0370 289
WiredHome 27:67e4e2ab048a 290 if (pkt.stratum == 0) { //Kiss of death message : Not good !
WiredHome 21:f3818e2e0370 291 ERR("Kissed to death!");
WiredHome 21:f3818e2e0370 292 m_sock.close();
WiredHome 21:f3818e2e0370 293 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 294 }
WiredHome 21:f3818e2e0370 295
WiredHome 21:f3818e2e0370 296 HexDump("NTP Info", (uint8_t *)&pkt, sizeof(NTPPacket));
WiredHome 21:f3818e2e0370 297
WiredHome 21:f3818e2e0370 298 //Correct Endianness
WiredHome 21:f3818e2e0370 299 pkt.refTm_s = ntohl( pkt.refTm_s );
WiredHome 21:f3818e2e0370 300 pkt.refTm_f = ntohl( pkt.refTm_f );
WiredHome 21:f3818e2e0370 301 pkt.origTm_s = ntohl( pkt.origTm_s );
WiredHome 21:f3818e2e0370 302 pkt.origTm_f = ntohl( pkt.origTm_f );
WiredHome 21:f3818e2e0370 303 pkt.rxTm_s = ntohl( pkt.rxTm_s );
WiredHome 21:f3818e2e0370 304 pkt.rxTm_f = ntohl( pkt.rxTm_f );
WiredHome 21:f3818e2e0370 305 pkt.txTm_s = ntohl( pkt.txTm_s );
WiredHome 21:f3818e2e0370 306 pkt.txTm_f = ntohl( pkt.txTm_f );
WiredHome 21:f3818e2e0370 307
WiredHome 28:3fa154ab6ffd 308 //Compute offset, see RFC 4330 p.13
WiredHome 28:3fa154ab6ffd 309 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
WiredHome 28:3fa154ab6ffd 310
WiredHome 28:3fa154ab6ffd 311 // Modification by David Smart
WiredHome 28:3fa154ab6ffd 312 // The setTime function was computing the offset incorrectly as the value was promoted to 64-bit.
WiredHome 28:3fa154ab6ffd 313 // The side effect was that a negative offset ended up as a very large positive (e.g. jump from
WiredHome 28:3fa154ab6ffd 314 // 2016 to 2084). This change revises that computation.
WiredHome 28:3fa154ab6ffd 315 int64_t offset = (((int64_t)pkt.rxTm_s - pkt.origTm_s) + ((int64_t)pkt.txTm_s - destTm_s)) / 2; //Avoid overflow
WiredHome 28:3fa154ab6ffd 316 set_time(time(NULL) + offset);
WiredHome 28:3fa154ab6ffd 317
WiredHome 27:67e4e2ab048a 318 #ifdef DEBUG
WiredHome 27:67e4e2ab048a 319 const char *ModeList[] = {
WiredHome 27:67e4e2ab048a 320 "reserved", "symmetric active", "symmetric passive", "client",
WiredHome 27:67e4e2ab048a 321 "server", "broadcast", "reserved for NTP ctrl", "reserved for priv use"
WiredHome 27:67e4e2ab048a 322 };
WiredHome 27:67e4e2ab048a 323 INFO(" pkt.li (Leap Ind) %d", pkt.li);
WiredHome 27:67e4e2ab048a 324 INFO(" pkt.vn (Vers #) %d", pkt.vn);
WiredHome 27:67e4e2ab048a 325 INFO(" pkt.mode %d, mode %s", pkt.mode, ModeList[pkt.mode]);
WiredHome 27:67e4e2ab048a 326 INFO(" pkt.stratum %d, 0=kiss-o'-death, 1=prim, 2=secd", pkt.stratum);
WiredHome 27:67e4e2ab048a 327 INFO(" pkt.poll %d", pkt.poll);
WiredHome 27:67e4e2ab048a 328 INFO(" pkt.precision %d", pkt.precision);
WiredHome 27:67e4e2ab048a 329 INFO(" pkt.rootDelay %d", pkt.rootDelay);
WiredHome 27:67e4e2ab048a 330 INFO(" pkt.rootDispersion %d", pkt.rootDispersion);
WiredHome 27:67e4e2ab048a 331 INFO(" pkt.refId %08X, %u", pkt.refId, pkt.refId);
WiredHome 27:67e4e2ab048a 332 INFO(" pkt.refTm_s %08X, %u, ref time (last set)", pkt.refTm_s, pkt.refTm_s);
WiredHome 27:67e4e2ab048a 333 INFO(" pkt.origTm_s %08X, %u, time sent from client", pkt.origTm_s, pkt.origTm_s);
WiredHome 27:67e4e2ab048a 334 INFO(" pkt.rxTm_s %08X, %u, time rcvd at server", pkt.rxTm_s, pkt.rxTm_s);
WiredHome 27:67e4e2ab048a 335 INFO(" pkt.txTm_s %08X, %u, time sent from server", pkt.txTm_s, pkt.txTm_s);
WiredHome 27:67e4e2ab048a 336 INFO(" pkt.refTm_f %08X, %u, fraction", pkt.refTm_f, pkt.refTm_f);
WiredHome 28:3fa154ab6ffd 337 INFO(" offset %08X, %u", destTm_s, destTm_s);
WiredHome 27:67e4e2ab048a 338 #endif
WiredHome 27:67e4e2ab048a 339
WiredHome 21:f3818e2e0370 340 m_sock.close();
WiredHome 27:67e4e2ab048a 341
WiredHome 21:f3818e2e0370 342 #endif // OS version
WiredHome 21:f3818e2e0370 343
WiredHome 21:f3818e2e0370 344 #ifdef DEBUG
WiredHome 21:f3818e2e0370 345 ctTime = time(NULL);
WiredHome 21:f3818e2e0370 346 INFO(" ctime: %s", ctime(&ctTime));
WiredHome 21:f3818e2e0370 347 #endif
WiredHome 21:f3818e2e0370 348 return NTP_OK;
WiredHome 21:f3818e2e0370 349 }
WiredHome 21:f3818e2e0370 350