A minor bugfix. It prevents the library from entering an endless loop in case the NTP server droppes the request rather than sending a kiss of death message.
Dependents: STM32F746_iothub_client_sample_mqtt Iot_LCD_EC iothub_client_sample_mqtt simplesample_mqtt ... more
NTPClient.cpp
00001 /* NTPClient.cpp */ 00002 /* Copyright (C) 2012 mbed.org, MIT License 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00005 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00006 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00007 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in all copies or 00011 * substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00014 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00015 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00016 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00017 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00018 */ 00019 00020 //Debug is disabled by default 00021 #if 0 00022 //Enable debug 00023 #define __DEBUG__ 00024 #include <cstdio> 00025 #define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 00026 #define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 00027 #define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 00028 00029 #else 00030 //Disable debug 00031 #define DBG(x, ...) 00032 #define WARN(x, ...) 00033 #define ERR(x, ...) 00034 00035 #endif 00036 00037 #include "NTPClient.h" 00038 00039 #include "UDPSocket.h" 00040 00041 #include "mbed.h" //time() and set_time() 00042 00043 #define NTP_PORT 123 00044 #define NTP_CLIENT_PORT 0 //Random port 00045 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900) 00046 00047 NTPClient::NTPClient() : m_sock() 00048 { 00049 00050 00051 } 00052 00053 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout) 00054 { 00055 #ifdef __DEBUG__ 00056 time_t ctTime; 00057 ctTime = time(NULL); 00058 DBG("Time is set to (UTC): %s", ctime(&ctTime)); 00059 #endif 00060 00061 //Create & bind socket 00062 DBG("Binding socket"); 00063 m_sock.bind(0); //Bind to a random port 00064 00065 m_sock.set_blocking(false, timeout); //Set not blocking 00066 00067 struct NTPPacket pkt; 00068 00069 //Now ping the server and wait for response 00070 DBG("Ping"); 00071 //Prepare NTP Packet: 00072 pkt.li = 0; //Leap Indicator : No warning 00073 pkt.vn = 4; //Version Number : 4 00074 pkt.mode = 3; //Client mode 00075 pkt.stratum = 0; //Not relevant here 00076 pkt.poll = 0; //Not significant as well 00077 pkt.precision = 0; //Neither this one is 00078 00079 pkt.rootDelay = 0; //Or this one 00080 pkt.rootDispersion = 0; //Or that one 00081 pkt.refId = 0; //... 00082 00083 pkt.refTm_s = 0; 00084 pkt.origTm_s = 0; 00085 pkt.rxTm_s = 0; 00086 pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE 00087 00088 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0; 00089 00090 Endpoint outEndpoint; 00091 00092 if( outEndpoint.set_address(host, port) < 0) 00093 { 00094 m_sock.close(); 00095 return NTP_DNS; 00096 } 00097 00098 //Set timeout, non-blocking and wait using select 00099 int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) ); 00100 if (ret < 0 ) 00101 { 00102 ERR("Could not send packet"); 00103 m_sock.close(); 00104 return NTP_CONN; 00105 } 00106 00107 //Read response 00108 Endpoint inEndpoint; 00109 // Set the inEndpoint address property 00110 inEndpoint.set_address(outEndpoint.get_address(), 0); 00111 DBG("Pong"); 00112 do 00113 { 00114 ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name 00115 if(ret < 0) 00116 { 00117 ERR("Could not receive packet"); 00118 m_sock.close(); 00119 return NTP_CONN; 00120 } 00121 } while( strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 ); 00122 00123 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks 00124 { 00125 ERR("Receive packet size does not match"); 00126 m_sock.close(); 00127 return NTP_PRTCL; 00128 } 00129 00130 if( pkt.stratum == 0) //Kiss of death message : Not good ! 00131 { 00132 ERR("Kissed to death!"); 00133 m_sock.close(); 00134 return NTP_PRTCL; 00135 } 00136 00137 //Correct Endianness 00138 pkt.refTm_s = ntohl( pkt.refTm_s ); 00139 pkt.refTm_f = ntohl( pkt.refTm_f ); 00140 pkt.origTm_s = ntohl( pkt.origTm_s ); 00141 pkt.origTm_f = ntohl( pkt.origTm_f ); 00142 pkt.rxTm_s = ntohl( pkt.rxTm_s ); 00143 pkt.rxTm_f = ntohl( pkt.rxTm_f ); 00144 pkt.txTm_s = ntohl( pkt.txTm_s ); 00145 pkt.txTm_f = ntohl( pkt.txTm_f ); 00146 00147 //Compute offset, see RFC 4330 p.13 00148 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL)); 00149 int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow 00150 DBG("Sent @%ul", pkt.txTm_s); 00151 DBG("Offset: %lld", offset); 00152 //Set time accordingly 00153 set_time( time(NULL) + offset ); 00154 00155 #ifdef __DEBUG__ 00156 ctTime = time(NULL); 00157 DBG("Time is now (UTC): %s", ctime(&ctTime)); 00158 #endif 00159 00160 m_sock.close(); 00161 00162 return NTP_OK; 00163 } 00164
Generated on Mon Jul 18 2022 19:52:47 by 1.7.2