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 Jan 12 19:04:47 2020 +0000
Revision:
27:67e4e2ab048a
Parent:
21:f3818e2e0370
Child:
28:3fa154ab6ffd
Update working to code-align the OS2 and OS5 variant for the time query.

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 21:f3818e2e0370 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 27:67e4e2ab048a 90 #if 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 27:67e4e2ab048a 259 INFO("m_sock.sendto(...) returned %d", ret_send);
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 INFO(" inEndpoint instantiated: %s.", inEndpoint.get_address());
WiredHome 27:67e4e2ab048a 269
WiredHome 21:f3818e2e0370 270 // Set the inEndpoint address property
WiredHome 27:67e4e2ab048a 271 inEndpoint.set_address(nist.get_address(), 0);
WiredHome 21:f3818e2e0370 272
WiredHome 21:f3818e2e0370 273 int loopLimit = 20; // semi-randomly selected so it doesn't hang forever here...
WiredHome 21:f3818e2e0370 274 do {
WiredHome 21:f3818e2e0370 275 ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) );
WiredHome 21:f3818e2e0370 276 if(ret < 0) {
WiredHome 21:f3818e2e0370 277 ERR("Could not receive packet");
WiredHome 21:f3818e2e0370 278 m_sock.close();
WiredHome 21:f3818e2e0370 279 return NTP_CONN;
WiredHome 21:f3818e2e0370 280 }
WiredHome 21:f3818e2e0370 281 INFO(".");
WiredHome 21:f3818e2e0370 282 loopLimit--;
WiredHome 27:67e4e2ab048a 283 } while( strcmp(nist.get_address(), inEndpoint.get_address()) != 0 && loopLimit > 0);
WiredHome 21:f3818e2e0370 284
WiredHome 21:f3818e2e0370 285 if(ret < (int)sizeof(NTPPacket)) { //TODO: Accept chunks
WiredHome 21:f3818e2e0370 286 ERR("Receive packet size does not match");
WiredHome 21:f3818e2e0370 287 m_sock.close();
WiredHome 21:f3818e2e0370 288 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 289 }
WiredHome 21:f3818e2e0370 290
WiredHome 27:67e4e2ab048a 291 if (pkt.stratum == 0) { //Kiss of death message : Not good !
WiredHome 21:f3818e2e0370 292 ERR("Kissed to death!");
WiredHome 21:f3818e2e0370 293 m_sock.close();
WiredHome 21:f3818e2e0370 294 return NTP_PRTCL;
WiredHome 21:f3818e2e0370 295 }
WiredHome 21:f3818e2e0370 296
WiredHome 21:f3818e2e0370 297 HexDump("NTP Info", (uint8_t *)&pkt, sizeof(NTPPacket));
WiredHome 21:f3818e2e0370 298
WiredHome 21:f3818e2e0370 299 //Correct Endianness
WiredHome 21:f3818e2e0370 300 pkt.refTm_s = ntohl( pkt.refTm_s );
WiredHome 21:f3818e2e0370 301 pkt.refTm_f = ntohl( pkt.refTm_f );
WiredHome 21:f3818e2e0370 302 pkt.origTm_s = ntohl( pkt.origTm_s );
WiredHome 21:f3818e2e0370 303 pkt.origTm_f = ntohl( pkt.origTm_f );
WiredHome 21:f3818e2e0370 304 pkt.rxTm_s = ntohl( pkt.rxTm_s );
WiredHome 21:f3818e2e0370 305 pkt.rxTm_f = ntohl( pkt.rxTm_f );
WiredHome 21:f3818e2e0370 306 pkt.txTm_s = ntohl( pkt.txTm_s );
WiredHome 21:f3818e2e0370 307 pkt.txTm_f = ntohl( pkt.txTm_f );
WiredHome 21:f3818e2e0370 308
WiredHome 27:67e4e2ab048a 309 #ifdef DEBUG
WiredHome 27:67e4e2ab048a 310 const char *ModeList[] = {
WiredHome 27:67e4e2ab048a 311 "reserved", "symmetric active", "symmetric passive", "client",
WiredHome 27:67e4e2ab048a 312 "server", "broadcast", "reserved for NTP ctrl", "reserved for priv use"
WiredHome 27:67e4e2ab048a 313 };
WiredHome 27:67e4e2ab048a 314 INFO(" pkt.li (Leap Ind) %d", pkt.li);
WiredHome 27:67e4e2ab048a 315 INFO(" pkt.vn (Vers #) %d", pkt.vn);
WiredHome 27:67e4e2ab048a 316 INFO(" pkt.mode %d, mode %s", pkt.mode, ModeList[pkt.mode]);
WiredHome 27:67e4e2ab048a 317 INFO(" pkt.stratum %d, 0=kiss-o'-death, 1=prim, 2=secd", pkt.stratum);
WiredHome 27:67e4e2ab048a 318 INFO(" pkt.poll %d", pkt.poll);
WiredHome 27:67e4e2ab048a 319 INFO(" pkt.precision %d", pkt.precision);
WiredHome 27:67e4e2ab048a 320 INFO(" pkt.rootDelay %d", pkt.rootDelay);
WiredHome 27:67e4e2ab048a 321 INFO(" pkt.rootDispersion %d", pkt.rootDispersion);
WiredHome 27:67e4e2ab048a 322 INFO(" pkt.refId %08X, %u", pkt.refId, pkt.refId);
WiredHome 27:67e4e2ab048a 323 INFO(" pkt.refTm_s %08X, %u, ref time (last set)", pkt.refTm_s, pkt.refTm_s);
WiredHome 27:67e4e2ab048a 324 INFO(" pkt.origTm_s %08X, %u, time sent from client", pkt.origTm_s, pkt.origTm_s);
WiredHome 27:67e4e2ab048a 325 INFO(" pkt.rxTm_s %08X, %u, time rcvd at server", pkt.rxTm_s, pkt.rxTm_s);
WiredHome 27:67e4e2ab048a 326 INFO(" pkt.txTm_s %08X, %u, time sent from server", pkt.txTm_s, pkt.txTm_s);
WiredHome 27:67e4e2ab048a 327 INFO(" pkt.refTm_f %08X, %u, fraction", pkt.refTm_f, pkt.refTm_f);
WiredHome 27:67e4e2ab048a 328 #endif
WiredHome 27:67e4e2ab048a 329
WiredHome 21:f3818e2e0370 330 //Compute offset, see RFC 4330 p.13
WiredHome 21:f3818e2e0370 331 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
WiredHome 27:67e4e2ab048a 332
WiredHome 27:67e4e2ab048a 333
WiredHome 21:f3818e2e0370 334 // Modification by David Smart
WiredHome 21:f3818e2e0370 335 // The setTime function was computing the offset incorrectly as the value was promoted to 64-bit.
WiredHome 21:f3818e2e0370 336 // The side effect was that a negative offset ended up as a very large positive (e.g. jump from
WiredHome 21:f3818e2e0370 337 // 2016 to 2084). This change revises that computation.
WiredHome 21:f3818e2e0370 338 int64_t offset = ( ((int64_t)pkt.rxTm_s - pkt.origTm_s ) + ((int64_t) pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
WiredHome 21:f3818e2e0370 339 set_time( time(NULL) + offset );
WiredHome 21:f3818e2e0370 340
WiredHome 21:f3818e2e0370 341 m_sock.close();
WiredHome 27:67e4e2ab048a 342
WiredHome 21:f3818e2e0370 343 #endif // OS version
WiredHome 21:f3818e2e0370 344
WiredHome 21:f3818e2e0370 345 #ifdef DEBUG
WiredHome 21:f3818e2e0370 346 ctTime = time(NULL);
WiredHome 21:f3818e2e0370 347 INFO(" ctime: %s", ctime(&ctTime));
WiredHome 21:f3818e2e0370 348 #endif
WiredHome 21:f3818e2e0370 349 return NTP_OK;
WiredHome 21:f3818e2e0370 350 }
WiredHome 21:f3818e2e0370 351