Fork of my original MQTTGateway

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:43:14 2017 +0000
Revision:
0:a1734fe1ec4b
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vpcola 0:a1734fe1ec4b 1 /* NTPClient.cpp */
vpcola 0:a1734fe1ec4b 2 /* Copyright (C) 2012 mbed.org, MIT License
vpcola 0:a1734fe1ec4b 3 *
vpcola 0:a1734fe1ec4b 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
vpcola 0:a1734fe1ec4b 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
vpcola 0:a1734fe1ec4b 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
vpcola 0:a1734fe1ec4b 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
vpcola 0:a1734fe1ec4b 8 * furnished to do so, subject to the following conditions:
vpcola 0:a1734fe1ec4b 9 *
vpcola 0:a1734fe1ec4b 10 * The above copyright notice and this permission notice shall be included in all copies or
vpcola 0:a1734fe1ec4b 11 * substantial portions of the Software.
vpcola 0:a1734fe1ec4b 12 *
vpcola 0:a1734fe1ec4b 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
vpcola 0:a1734fe1ec4b 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
vpcola 0:a1734fe1ec4b 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
vpcola 0:a1734fe1ec4b 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
vpcola 0:a1734fe1ec4b 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
vpcola 0:a1734fe1ec4b 18 */
vpcola 0:a1734fe1ec4b 19
vpcola 0:a1734fe1ec4b 20 //Debug is disabled by default
vpcola 0:a1734fe1ec4b 21 #if 0
vpcola 0:a1734fe1ec4b 22 //Enable debug
vpcola 0:a1734fe1ec4b 23 #define __DEBUG__
vpcola 0:a1734fe1ec4b 24 #include <cstdio>
vpcola 0:a1734fe1ec4b 25 #define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
vpcola 0:a1734fe1ec4b 26 #define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
vpcola 0:a1734fe1ec4b 27 #define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
vpcola 0:a1734fe1ec4b 28
vpcola 0:a1734fe1ec4b 29 #else
vpcola 0:a1734fe1ec4b 30 //Disable debug
vpcola 0:a1734fe1ec4b 31 #define DBG(x, ...)
vpcola 0:a1734fe1ec4b 32 #define WARN(x, ...)
vpcola 0:a1734fe1ec4b 33 #define ERR(x, ...)
vpcola 0:a1734fe1ec4b 34
vpcola 0:a1734fe1ec4b 35 #endif
vpcola 0:a1734fe1ec4b 36 #include "NetworkInterface.h"
vpcola 0:a1734fe1ec4b 37 #include "NTPClient.h"
vpcola 0:a1734fe1ec4b 38
vpcola 0:a1734fe1ec4b 39 #include "UDPSocket.h"
vpcola 0:a1734fe1ec4b 40
vpcola 0:a1734fe1ec4b 41 #include "mbed.h" //time() and set_time()
vpcola 0:a1734fe1ec4b 42
vpcola 0:a1734fe1ec4b 43 #define NTP_PORT 123
vpcola 0:a1734fe1ec4b 44 #define NTP_CLIENT_PORT 0 //Random port
vpcola 0:a1734fe1ec4b 45 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
vpcola 0:a1734fe1ec4b 46
vpcola 0:a1734fe1ec4b 47 /*NTPClient::NTPClient() : m_sock()
vpcola 0:a1734fe1ec4b 48 {
vpcola 0:a1734fe1ec4b 49
vpcola 0:a1734fe1ec4b 50 }*/
vpcola 0:a1734fe1ec4b 51
vpcola 0:a1734fe1ec4b 52 NTPClient::NTPClient(NetworkInterface * _m_intf, int utcOffset)
vpcola 0:a1734fe1ec4b 53 : m_intf(_m_intf),
vpcola 0:a1734fe1ec4b 54 utc_offset(utcOffset)
vpcola 0:a1734fe1ec4b 55 {
vpcola 0:a1734fe1ec4b 56 }
vpcola 0:a1734fe1ec4b 57
vpcola 0:a1734fe1ec4b 58 #ifdef htons
vpcola 0:a1734fe1ec4b 59 #undef htons
vpcola 0:a1734fe1ec4b 60 #endif /* htons */
vpcola 0:a1734fe1ec4b 61 #ifdef htonl
vpcola 0:a1734fe1ec4b 62 #undef htonl
vpcola 0:a1734fe1ec4b 63 #endif /* htonl */
vpcola 0:a1734fe1ec4b 64 #ifdef ntohs
vpcola 0:a1734fe1ec4b 65 #undef ntohs
vpcola 0:a1734fe1ec4b 66 #endif /* ntohs */
vpcola 0:a1734fe1ec4b 67 #ifdef ntohl
vpcola 0:a1734fe1ec4b 68 #undef ntohl
vpcola 0:a1734fe1ec4b 69 #endif /* ntohl */
vpcola 0:a1734fe1ec4b 70
vpcola 0:a1734fe1ec4b 71
vpcola 0:a1734fe1ec4b 72 #if ((__BYTE_ORDER__) == (__ORDER_LITTLE_ENDIAN__))
vpcola 0:a1734fe1ec4b 73
vpcola 0:a1734fe1ec4b 74 #define htons(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
vpcola 0:a1734fe1ec4b 75 #define ntohs(x) htons(x)
vpcola 0:a1734fe1ec4b 76 #define htonl(x) ((((x) & 0xff) << 24) | \
vpcola 0:a1734fe1ec4b 77 (((x) & 0xff00) << 8) | \
vpcola 0:a1734fe1ec4b 78 (((x) & 0xff0000UL) >> 8) | \
vpcola 0:a1734fe1ec4b 79 (((x) & 0xff000000UL) >> 24))
vpcola 0:a1734fe1ec4b 80 #define ntohl(x) htonl(x)
vpcola 0:a1734fe1ec4b 81
vpcola 0:a1734fe1ec4b 82 #else
vpcola 0:a1734fe1ec4b 83
vpcola 0:a1734fe1ec4b 84 #define htons(x) (x)
vpcola 0:a1734fe1ec4b 85 #define htonl(x) (x)
vpcola 0:a1734fe1ec4b 86 #define ntohl(x) (x)
vpcola 0:a1734fe1ec4b 87 #define ntohs(x) (x)
vpcola 0:a1734fe1ec4b 88
vpcola 0:a1734fe1ec4b 89 #endif
vpcola 0:a1734fe1ec4b 90
vpcola 0:a1734fe1ec4b 91
vpcola 0:a1734fe1ec4b 92 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
vpcola 0:a1734fe1ec4b 93 {
vpcola 0:a1734fe1ec4b 94 #ifdef __DEBUG__
vpcola 0:a1734fe1ec4b 95 time_t ctTime;
vpcola 0:a1734fe1ec4b 96 ctTime = time(NULL);
vpcola 0:a1734fe1ec4b 97 set_time(ctTime);
vpcola 0:a1734fe1ec4b 98 DBG("Time is set to (UTC): %s", ctime(&ctTime));
vpcola 0:a1734fe1ec4b 99 #endif
vpcola 0:a1734fe1ec4b 100
vpcola 0:a1734fe1ec4b 101
vpcola 0:a1734fe1ec4b 102 SocketAddress address(0, port);
vpcola 0:a1734fe1ec4b 103 int r = m_intf->gethostbyname(host, &address);
vpcola 0:a1734fe1ec4b 104 if (r) {
vpcola 0:a1734fe1ec4b 105 printf("error: 'gethostbyname(\"%s\")' failed with code %d\r\n", host, r);
vpcola 0:a1734fe1ec4b 106 } else if (!address) {
vpcola 0:a1734fe1ec4b 107 printf("error: 'gethostbyname(\"%s\")' returned null IP address\r\n", host);
vpcola 0:a1734fe1ec4b 108 }
vpcola 0:a1734fe1ec4b 109 //printf ("address: %s\n\r",address.get_ip_address());
vpcola 0:a1734fe1ec4b 110
vpcola 0:a1734fe1ec4b 111 //Create & bind socket
vpcola 0:a1734fe1ec4b 112 if (m_sock.open(m_intf) < 0) printf ("ERROR sock open \n\r");
vpcola 0:a1734fe1ec4b 113 m_sock.set_timeout(timeout);
vpcola 0:a1734fe1ec4b 114
vpcola 0:a1734fe1ec4b 115 struct NTPPacket pkt;
vpcola 0:a1734fe1ec4b 116 memset (&pkt, 0, sizeof(NTPPacket));
vpcola 0:a1734fe1ec4b 117
vpcola 0:a1734fe1ec4b 118 //Now ping the server and wait for response
vpcola 0:a1734fe1ec4b 119 DBG("Ping");
vpcola 0:a1734fe1ec4b 120 //Prepare NTP Packet:
vpcola 0:a1734fe1ec4b 121 pkt.li = 0; //Leap Indicator : No warning
vpcola 0:a1734fe1ec4b 122 pkt.vn = 4; //Version Number : 4
vpcola 0:a1734fe1ec4b 123 pkt.mode = 3; //Client mode
vpcola 0:a1734fe1ec4b 124 pkt.stratum = 0; //Not relevant here
vpcola 0:a1734fe1ec4b 125 pkt.poll = 0; //Not significant as well
vpcola 0:a1734fe1ec4b 126 pkt.precision = 0; //Neither this one is
vpcola 0:a1734fe1ec4b 127
vpcola 0:a1734fe1ec4b 128 int ret = m_sock.sendto(address, (char*)&pkt, sizeof(NTPPacket) );
vpcola 0:a1734fe1ec4b 129 if (ret < 0 )
vpcola 0:a1734fe1ec4b 130 {
vpcola 0:a1734fe1ec4b 131 ERR("Could not send packet %d", ret);
vpcola 0:a1734fe1ec4b 132 m_sock.close();
vpcola 0:a1734fe1ec4b 133 return NTP_CONN;
vpcola 0:a1734fe1ec4b 134 }
vpcola 0:a1734fe1ec4b 135
vpcola 0:a1734fe1ec4b 136 //Read response
vpcola 0:a1734fe1ec4b 137 DBG("Pong");
vpcola 0:a1734fe1ec4b 138
vpcola 0:a1734fe1ec4b 139 ret = m_sock.recvfrom(&address, (char*)&pkt, sizeof(NTPPacket) ); // LICIO
vpcola 0:a1734fe1ec4b 140 if(ret < 0)
vpcola 0:a1734fe1ec4b 141 {
vpcola 0:a1734fe1ec4b 142 ERR("Could not receive packet %d", ret);
vpcola 0:a1734fe1ec4b 143 m_sock.close();
vpcola 0:a1734fe1ec4b 144 return NTP_CONN;
vpcola 0:a1734fe1ec4b 145 }
vpcola 0:a1734fe1ec4b 146
vpcola 0:a1734fe1ec4b 147 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks
vpcola 0:a1734fe1ec4b 148 {
vpcola 0:a1734fe1ec4b 149 ERR("Receive packet size does not match");
vpcola 0:a1734fe1ec4b 150 m_sock.close();
vpcola 0:a1734fe1ec4b 151 return NTP_PRTCL;
vpcola 0:a1734fe1ec4b 152 }
vpcola 0:a1734fe1ec4b 153
vpcola 0:a1734fe1ec4b 154 if( pkt.stratum == 0) //Kiss of death message : Not good !
vpcola 0:a1734fe1ec4b 155 {
vpcola 0:a1734fe1ec4b 156 ERR("Kissed to death!");
vpcola 0:a1734fe1ec4b 157 m_sock.close();
vpcola 0:a1734fe1ec4b 158 return NTP_PRTCL;
vpcola 0:a1734fe1ec4b 159 }
vpcola 0:a1734fe1ec4b 160
vpcola 0:a1734fe1ec4b 161 //Correct Endianness
vpcola 0:a1734fe1ec4b 162 pkt.refTm_s = ntohl( pkt.refTm_s );
vpcola 0:a1734fe1ec4b 163 pkt.refTm_f = ntohl( pkt.refTm_f );
vpcola 0:a1734fe1ec4b 164 pkt.origTm_s = ntohl( pkt.origTm_s );
vpcola 0:a1734fe1ec4b 165 pkt.origTm_f = ntohl( pkt.origTm_f );
vpcola 0:a1734fe1ec4b 166 pkt.rxTm_s = ntohl( pkt.rxTm_s );
vpcola 0:a1734fe1ec4b 167 pkt.rxTm_f = ntohl( pkt.rxTm_f );
vpcola 0:a1734fe1ec4b 168 pkt.txTm_s = ntohl( pkt.txTm_s );
vpcola 0:a1734fe1ec4b 169 pkt.txTm_f = ntohl( pkt.txTm_f );
vpcola 0:a1734fe1ec4b 170
vpcola 0:a1734fe1ec4b 171 // see RFC 4330 p.13
vpcola 0:a1734fe1ec4b 172 int timeoffset = utc_offset * 60 * 60;
vpcola 0:a1734fe1ec4b 173 time_t txTm = (time_t)((pkt.txTm_s - NTP_TIMESTAMP_DELTA) + timeoffset);
vpcola 0:a1734fe1ec4b 174
vpcola 0:a1734fe1ec4b 175 set_time(txTm);
vpcola 0:a1734fe1ec4b 176
vpcola 0:a1734fe1ec4b 177 #ifdef __DEBUG__
vpcola 0:a1734fe1ec4b 178 ctTime = time(NULL);
vpcola 0:a1734fe1ec4b 179 DBG("Time is now (UTC): %s", ctime(&ctTime));
vpcola 0:a1734fe1ec4b 180 #endif
vpcola 0:a1734fe1ec4b 181 m_sock.close();
vpcola 0:a1734fe1ec4b 182
vpcola 0:a1734fe1ec4b 183 return NTP_OK;
vpcola 0:a1734fe1ec4b 184 }
vpcola 0:a1734fe1ec4b 185