Vergil Cola / Mbed OS MQTTGatewayK64

Dependencies:   mbed-http

Committer:
vpcola
Date:
Sat Apr 08 14:45:51 2017 +0000
Revision:
0:f1d3878b8dd9
Initial commit

Who changed what in which revision?

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