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.
Dependencies: azure_c_shared_utility azure_umqtt_c iothub_client iothub_mqtt_transport serializer wolfSSL
Fork of simplesample_mqtt by
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 1 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 #include "UDPSocket.h" 00039 #include "EthernetInterface.h" 00040 #include "mbed.h" //time() and set_time() 00041 00042 #define NTP_PORT 123 00043 #define NTP_CLIENT_PORT 0 //Random port 00044 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900) 00045 00046 NTPClient::NTPClient() 00047 { 00048 00049 } 00050 00051 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout) 00052 { 00053 00054 DBG("start to create socket"); 00055 EthernetInterface eth; 00056 eth.connect(); 00057 if(m_sock.open(ð)!=0) 00058 { 00059 DBG("unable to create socket");; 00060 } 00061 00062 #ifdef __DEBUG__ 00063 time_t ctTime; 00064 ctTime = time(NULL); 00065 DBG("Time is set to (UTC): %s", ctime(&ctTime)); 00066 #endif 00067 00068 //Create & bind socket 00069 DBG("Binding socket"); 00070 00071 m_sock.set_blocking(false); 00072 m_sock.set_timeout(timeout); 00073 00074 struct NTPPacket pkt; 00075 SocketAddress sendAddress(host,port); 00076 if(eth.gethostbyname(host, &sendAddress)!= 0) 00077 { 00078 printf("UNABLE TO GET THE HOST"); 00079 m_sock.close(); 00080 return NTP_DNS; 00081 } 00082 00083 const char *ip = sendAddress.get_ip_address(); 00084 printf("IP address is: %s\n", ip ? ip : "No IP"); 00085 00086 //Now ping the server and wait for response 00087 DBG("Ping"); 00088 //Prepare NTP Packet: 00089 pkt.li = 0; //Leap Indicator : No warning 00090 pkt.vn = 4; //Version Number : 4 00091 pkt.mode = 3; //Client mode 00092 pkt.stratum = 0; //Not relevant here 00093 pkt.poll = 0; //Not significant as well 00094 pkt.precision = 0; //Neither this one is 00095 00096 pkt.rootDelay = 0; //Or this one 00097 pkt.rootDispersion = 0; //Or that one 00098 pkt.refId = 0; //... 00099 00100 pkt.refTm_s = 0; 00101 pkt.origTm_s = 0; 00102 pkt.rxTm_s = 0; 00103 pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE 00104 00105 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0; 00106 00107 00108 00109 //Set timeout, non-blocking and wait using select 00110 int ret = m_sock.sendto( sendAddress, (char*)&pkt, sizeof(NTPPacket) ); 00111 if (ret < 0 ) 00112 { 00113 ERR("Could not send packet"); 00114 m_sock.close(); 00115 return NTP_CONN; 00116 } 00117 00118 DBG("Pong"); 00119 //Read response 00120 SocketAddress recvAddress; 00121 recvAddress.set_ip_address(sendAddress.get_ip_address()); 00122 recvAddress.set_port(port); 00123 00124 //do 00125 //{ 00126 ret = m_sock.recvfrom( &recvAddress, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name 00127 if(ret < 0) 00128 { 00129 ERR("Could not receive packet"); 00130 m_sock.close(); 00131 return NTP_CONN; 00132 } 00133 //} while( strcmp(sendAddress.get_ip_address(), recvAddress.get_ip_address()) != 0 ); 00134 00135 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks 00136 { 00137 ERR("Receive packet size does not match"); 00138 m_sock.close(); 00139 return NTP_PRTCL; 00140 } 00141 00142 if( pkt.stratum == 0) //Kiss of death message : Not good ! 00143 { 00144 ERR("Kissed to death!"); 00145 m_sock.close(); 00146 return NTP_PRTCL; 00147 } 00148 00149 //Correct Endianness 00150 pkt.refTm_s = ntohl( pkt.refTm_s ); 00151 pkt.refTm_f = ntohl( pkt.refTm_f ); 00152 pkt.origTm_s = ntohl( pkt.origTm_s ); 00153 pkt.origTm_f = ntohl( pkt.origTm_f ); 00154 pkt.rxTm_s = ntohl( pkt.rxTm_s ); 00155 pkt.rxTm_f = ntohl( pkt.rxTm_f ); 00156 pkt.txTm_s = ntohl( pkt.txTm_s ); 00157 pkt.txTm_f = ntohl( pkt.txTm_f ); 00158 00159 //Compute offset, see RFC 4330 p.13 00160 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL)); 00161 int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow 00162 DBG("Sent @%ul", pkt.txTm_s); 00163 DBG("Offset: %lld", offset); 00164 //Set time accordingly 00165 set_time( time(NULL) + offset ); 00166 00167 #ifdef __DEBUG__ 00168 ctTime = time(NULL); 00169 DBG("Time is now (UTC): %s", ctime(&ctTime)); 00170 #endif 00171 00172 m_sock.close(); 00173 00174 return NTP_OK; 00175 } 00176
Generated on Fri Jul 22 2022 19:10:54 by
1.7.2
