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.
Dependents: NTPClient_example mbed_vfd_ntp
Fork of NTPClient 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 00039 #include "UDPSocket.h" 00040 00041 #include "mbed.h" //time() and set_time() 00042 #include "def.h" 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(NetworkInterface& p_networkInterface) : m_sock(), m_net(p_networkInterface) { 00048 } 00049 00050 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout) 00051 { 00052 #ifdef __DEBUG__ 00053 time_t ctTime; 00054 ctTime = time(NULL); 00055 DBG("Time is set to (UTC): %s", ctime(&ctTime)); 00056 #endif 00057 00058 if( m_sock.open(&m_net) != 0){ DBG("Open"); return NTP_CONN;} 00059 00060 //Create & bind socket 00061 DBG("Binding socket"); 00062 if( m_sock.bind(99) != 0){ DBG("Bind"); return NTP_CONN;} 00063 00064 struct NTPPacket pkt; 00065 00066 //Now ping the server and wait for response 00067 DBG("Ping"); 00068 //Prepare NTP Packet: 00069 pkt.li = 0; //Leap Indicator : No warning 00070 pkt.vn = 4; //Version Number : 4 00071 pkt.mode = 3; //Client mode 00072 pkt.stratum = 0; //Not relevant here 00073 pkt.poll = 0; //Not significant as well 00074 pkt.precision = 0; //Neither this one is 00075 00076 pkt.rootDelay = 0; //Or this one 00077 pkt.rootDispersion = 0; //Or that one 00078 pkt.refId = 0; //... 00079 00080 pkt.refTm_s = 0; 00081 pkt.origTm_s = 0; 00082 pkt.rxTm_s = 0; 00083 pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE 00084 00085 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0; 00086 00087 SocketAddress outEndpoint (host, port); 00088 00089 //Set timeout, non-blocking and wait using select 00090 int ret = m_sock.sendto(host, port, (char*)&pkt, sizeof(NTPPacket) ); 00091 if (ret < 0 ) 00092 { 00093 ERR("Could not send packet (%d)", ret); 00094 m_sock.close(); 00095 return NTP_CONN; 00096 } 00097 00098 //Read response 00099 SocketAddress inEndpoint; 00100 00101 DBG("Pong"); 00102 //do 00103 //{ 00104 ret = m_sock.recvfrom( &inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name 00105 if(ret < 0) 00106 { 00107 ERR("Could not receive packet (%d)", ret); 00108 m_sock.close(); 00109 return NTP_CONN; 00110 } 00111 //} while( strcmp(outEndpoint.get_ip_address(), inEndpoint.get_ip_address()) != 0 ); 00112 00113 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks 00114 { 00115 ERR("Receive packet size does not match"); 00116 m_sock.close(); 00117 return NTP_PRTCL; 00118 } 00119 00120 if( pkt.stratum == 0) //Kiss of death message : Not good ! 00121 { 00122 ERR("Kissed to death!"); 00123 m_sock.close(); 00124 return NTP_PRTCL; 00125 } 00126 00127 //Correct Endianness 00128 pkt.refTm_s = ntohl( pkt.refTm_s ); 00129 pkt.refTm_f = ntohl( pkt.refTm_f ); 00130 pkt.origTm_s = ntohl( pkt.origTm_s ); 00131 pkt.origTm_f = ntohl( pkt.origTm_f ); 00132 pkt.rxTm_s = ntohl( pkt.rxTm_s ); 00133 pkt.rxTm_f = ntohl( pkt.rxTm_f ); 00134 pkt.txTm_s = ntohl( pkt.txTm_s ); 00135 pkt.txTm_f = ntohl( pkt.txTm_f ); 00136 00137 //Compute offset, see RFC 4330 p.13 00138 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL)); 00139 int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow 00140 DBG("Sent @%ul", pkt.txTm_s); 00141 DBG("Offset: %lld", offset); 00142 //Set time accordingly 00143 set_time( time(NULL) + offset ); 00144 00145 #ifdef __DEBUG__ 00146 ctTime = time(NULL); 00147 DBG("Time is now (UTC): %s", ctime(&ctTime)); 00148 #endif 00149 00150 m_sock.close(); 00151 00152 return NTP_OK; 00153 } 00154
Generated on Tue Jul 12 2022 20:10:35 by
1.7.2
