Vergil Cola
/
MQTTGateway2
Fork of my original MQTTGateway
Embed:
(wiki syntax)
Show/hide line numbers
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 #include "NetworkInterface.h" 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 NTPClient::NTPClient(NetworkInterface * _m_intf, int utcOffset) 00053 : m_intf(_m_intf), 00054 utc_offset(utcOffset) 00055 { 00056 } 00057 00058 #ifdef htons 00059 #undef htons 00060 #endif /* htons */ 00061 #ifdef htonl 00062 #undef htonl 00063 #endif /* htonl */ 00064 #ifdef ntohs 00065 #undef ntohs 00066 #endif /* ntohs */ 00067 #ifdef ntohl 00068 #undef ntohl 00069 #endif /* ntohl */ 00070 00071 00072 #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__)) 00073 00074 #define htons(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) 00075 #define ntohs(x) htons(x) 00076 #define htonl(x) ((((x) & 0xff) << 24) | \ 00077 (((x) & 0xff00) << 8) | \ 00078 (((x) & 0xff0000UL) >> 8) | \ 00079 (((x) & 0xff000000UL) >> 24)) 00080 #define ntohl(x) htonl(x) 00081 00082 #else 00083 00084 #define htons(x) (x) 00085 #define htonl(x) (x) 00086 #define ntohl(x) (x) 00087 #define ntohs(x) (x) 00088 00089 #endif 00090 00091 00092 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout) 00093 { 00094 #ifdef __DEBUG__ 00095 time_t ctTime; 00096 ctTime = time(NULL); 00097 set_time(ctTime); 00098 DBG("Time is set to (UTC): %s", ctime(&ctTime)); 00099 #endif 00100 00101 00102 SocketAddress address(0, port); 00103 int r = m_intf->gethostbyname(host, &address); 00104 if (r) { 00105 printf("error: 'gethostbyname(\"%s\")' failed with code %d\r\n", host, r); 00106 } else if (!address) { 00107 printf("error: 'gethostbyname(\"%s\")' returned null IP address\r\n", host); 00108 } 00109 //printf ("address: %s\n\r",address.get_ip_address()); 00110 00111 //Create & bind socket 00112 if (m_sock.open(m_intf) < 0) printf ("ERROR sock open \n\r"); 00113 m_sock.set_timeout(timeout); 00114 00115 struct NTPPacket pkt; 00116 memset (&pkt, 0, sizeof(NTPPacket)); 00117 00118 //Now ping the server and wait for response 00119 DBG("Ping"); 00120 //Prepare NTP Packet: 00121 pkt.li = 0; //Leap Indicator : No warning 00122 pkt.vn = 4; //Version Number : 4 00123 pkt.mode = 3; //Client mode 00124 pkt.stratum = 0; //Not relevant here 00125 pkt.poll = 0; //Not significant as well 00126 pkt.precision = 0; //Neither this one is 00127 00128 int ret = m_sock.sendto(address, (char*)&pkt, sizeof(NTPPacket) ); 00129 if (ret < 0 ) 00130 { 00131 ERR("Could not send packet %d", ret); 00132 m_sock.close(); 00133 return NTP_CONN; 00134 } 00135 00136 //Read response 00137 DBG("Pong"); 00138 00139 ret = m_sock.recvfrom(&address, (char*)&pkt, sizeof(NTPPacket) ); // LICIO 00140 if(ret < 0) 00141 { 00142 ERR("Could not receive packet %d", ret); 00143 m_sock.close(); 00144 return NTP_CONN; 00145 } 00146 00147 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks 00148 { 00149 ERR("Receive packet size does not match"); 00150 m_sock.close(); 00151 return NTP_PRTCL; 00152 } 00153 00154 if( pkt.stratum == 0) //Kiss of death message : Not good ! 00155 { 00156 ERR("Kissed to death!"); 00157 m_sock.close(); 00158 return NTP_PRTCL; 00159 } 00160 00161 //Correct Endianness 00162 pkt.refTm_s = ntohl( pkt.refTm_s ); 00163 pkt.refTm_f = ntohl( pkt.refTm_f ); 00164 pkt.origTm_s = ntohl( pkt.origTm_s ); 00165 pkt.origTm_f = ntohl( pkt.origTm_f ); 00166 pkt.rxTm_s = ntohl( pkt.rxTm_s ); 00167 pkt.rxTm_f = ntohl( pkt.rxTm_f ); 00168 pkt.txTm_s = ntohl( pkt.txTm_s ); 00169 pkt.txTm_f = ntohl( pkt.txTm_f ); 00170 00171 // see RFC 4330 p.13 00172 int timeoffset = utc_offset * 60 * 60; 00173 time_t txTm = (time_t)((pkt.txTm_s - NTP_TIMESTAMP_DELTA) + timeoffset); 00174 00175 set_time(txTm); 00176 00177 #ifdef __DEBUG__ 00178 ctTime = time(NULL); 00179 DBG("Time is now (UTC): %s", ctime(&ctTime)); 00180 #endif 00181 m_sock.close(); 00182 00183 return NTP_OK; 00184 } 00185
Generated on Tue Jul 12 2022 18:06:46 by 1.7.2