NTP Client for the mbed networking libraries. The small change to this version is that there can be only one cause for the return value zero.

Dependents:   WattEye

Fork of NTPClient by Donatien Garnier

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Thu Nov 26 18:20:56 2015 +0000
Parent:
7:170915215fd4
Child:
9:2f607bafc29e
Commit message:
Update to fix a hang. Applied fix from Koen Kempeneers.

Changed in this revision

NTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
NTPClient.h Show annotated file Show diff for this revision Revisions of this file
--- a/NTPClient.cpp	Tue Jul 07 17:09:36 2015 +0000
+++ b/NTPClient.cpp	Thu Nov 26 18:20:56 2015 +0000
@@ -22,16 +22,14 @@
 //Enable debug
 #define __DEBUG__
 #include <cstdio>
-#define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
-#define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
-#define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
-
+#define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
+#define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
+#define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
 #else
 //Disable debug
-#define DBG(x, ...) 
+#define DBG(x, ...)
 #define WARN(x, ...)
-#define ERR(x, ...) 
-
+#define ERR(x, ...)
 #endif
 
 #include "NTPClient.h"
@@ -47,117 +45,114 @@
 NTPClient::NTPClient() : m_sock()
 {
 
-
 }
 
 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
 {
 #ifdef __DEBUG__
-  time_t ctTime;
-  ctTime = time(NULL);
-  DBG("Time is set to (UTC): %s", ctime(&ctTime));
+    time_t ctTime;
+    ctTime = time(NULL);
+    DBG("Time is set to (UTC): %s", ctime(&ctTime));
 #endif
 
-  //Create & bind socket
-  DBG("Binding socket");
-  m_sock.bind(0); //Bind to a random port
-  
-  m_sock.set_blocking(false, timeout); //Set not blocking
+    //Create & bind socket
+    DBG("Binding socket");
+    m_sock.bind(0); //Bind to a random port
 
-  struct NTPPacket pkt;
+    m_sock.set_blocking(false, timeout); //Set not blocking
+
+    struct NTPPacket pkt;
 
-  //Now ping the server and wait for response
-  DBG("Ping");
-  //Prepare NTP Packet:
-  pkt.li = 0; //Leap Indicator : No warning
-  pkt.vn = 4; //Version Number : 4
-  pkt.mode = 3; //Client mode
-  pkt.stratum = 0; //Not relevant here
-  pkt.poll = 0; //Not significant as well
-  pkt.precision = 0; //Neither this one is
+    //Now ping the server and wait for response
+    DBG("Ping");
+    //Prepare NTP Packet:
+    pkt.li = 0; //Leap Indicator : No warning
+    pkt.vn = 4; //Version Number : 4
+    pkt.mode = 3; //Client mode
+    pkt.stratum = 0; //Not relevant here
+    pkt.poll = 0; //Not significant as well
+    pkt.precision = 0; //Neither this one is
 
-  pkt.rootDelay = 0; //Or this one
-  pkt.rootDispersion = 0; //Or that one
-  pkt.refId = 0; //...
+    pkt.rootDelay = 0; //Or this one
+    pkt.rootDispersion = 0; //Or that one
+    pkt.refId = 0; //...
 
-  pkt.refTm_s = 0;
-  pkt.origTm_s = 0;
-  pkt.rxTm_s = 0;
-  pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
+    pkt.refTm_s = 0;
+    pkt.origTm_s = 0;
+    pkt.rxTm_s = 0;
+    pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
 
-  pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
+    pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
+
+    Endpoint outEndpoint;
 
-  Endpoint outEndpoint;
-  
-  if( outEndpoint.set_address(host, port) < 0)
-  {
-    m_sock.close();
-    return NTP_DNS;
-  }
-  
-  //Set timeout, non-blocking and wait using select
-  int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) );
-  if (ret < 0 )
-  {
-    ERR("Could not send packet");
-    m_sock.close();
-    return NTP_CONN;
-  }
+    if( outEndpoint.set_address(host, port) < 0) {
+        m_sock.close();
+        return NTP_DNS;
+    }
+
+    //Set timeout, non-blocking and wait using select
+    int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) );
+    if (ret < 0 ) {
+        ERR("Could not send packet");
+        m_sock.close();
+        return NTP_CONN;
+    }
 
-  //Read response
-  Endpoint inEndpoint;
+    //Read response
+    Endpoint inEndpoint;
+
+    // Set the inEndpoint address property
+    inEndpoint.set_address(outEndpoint.get_address(), 0);
 
-  DBG("Pong");
-  do
-  {
-    ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name
-    if(ret < 0)
-    {
-      ERR("Could not receive packet");
-      m_sock.close();
-      return NTP_CONN;
+    DBG("Pong");
+    do {
+        ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name
+        if(ret < 0) {
+            ERR("Could not receive packet");
+            m_sock.close();
+            return NTP_CONN;
+        }
+        DBG(".");
+    } while( strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 );
+
+    if(ret < (int)sizeof(NTPPacket)) { //TODO: Accept chunks
+        ERR("Receive packet size does not match");
+        m_sock.close();
+        return NTP_PRTCL;
     }
-  } while( strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 );
-
-  if(ret < (int)sizeof(NTPPacket)) //TODO: Accept chunks
-  {
-    ERR("Receive packet size does not match");
-    m_sock.close();
-    return NTP_PRTCL;
-  }
 
-  if( pkt.stratum == 0)  //Kiss of death message : Not good !
-  {
-    ERR("Kissed to death!");
-    m_sock.close();
-    return NTP_PRTCL;
-  }
+    if( pkt.stratum == 0) { //Kiss of death message : Not good !
+        ERR("Kissed to death!");
+        m_sock.close();
+        return NTP_PRTCL;
+    }
 
-  //Correct Endianness
-  pkt.refTm_s = ntohl( pkt.refTm_s );
-  pkt.refTm_f = ntohl( pkt.refTm_f );
-  pkt.origTm_s = ntohl( pkt.origTm_s );
-  pkt.origTm_f = ntohl( pkt.origTm_f );
-  pkt.rxTm_s = ntohl( pkt.rxTm_s );
-  pkt.rxTm_f = ntohl( pkt.rxTm_f );
-  pkt.txTm_s = ntohl( pkt.txTm_s );
-  pkt.txTm_f = ntohl( pkt.txTm_f );
+    //Correct Endianness
+    pkt.refTm_s = ntohl( pkt.refTm_s );
+    pkt.refTm_f = ntohl( pkt.refTm_f );
+    pkt.origTm_s = ntohl( pkt.origTm_s );
+    pkt.origTm_f = ntohl( pkt.origTm_f );
+    pkt.rxTm_s = ntohl( pkt.rxTm_s );
+    pkt.rxTm_f = ntohl( pkt.rxTm_f );
+    pkt.txTm_s = ntohl( pkt.txTm_s );
+    pkt.txTm_f = ntohl( pkt.txTm_f );
 
-  //Compute offset, see RFC 4330 p.13
-  uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
-  int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
-  DBG("Sent @%ul", pkt.txTm_s);
-  DBG("Offset: %lld", offset);
-  //Set time accordingly
-  set_time( time(NULL) + offset );
+    //Compute offset, see RFC 4330 p.13
+    uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
+    int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
+    DBG("Sent @%ul", pkt.txTm_s);
+    DBG("Offset: %lld", offset);
+    //Set time accordingly
+    set_time( time(NULL) + offset );
 
 #ifdef __DEBUG__
-  ctTime = time(NULL);
-  DBG("Time is now (UTC): %s", ctime(&ctTime));
+    ctTime = time(NULL);
+    DBG("Time is now (UTC): %s", ctime(&ctTime));
 #endif
 
-  m_sock.close();
+    m_sock.close();
 
-  return NTP_OK;
+    return NTP_OK;
 }
 
--- a/NTPClient.h	Tue Jul 07 17:09:36 2015 +0000
+++ b/NTPClient.h	Thu Nov 26 18:20:56 2015 +0000
@@ -36,13 +36,12 @@
 #define NTP_DEFAULT_TIMEOUT 4000
 
 ///NTP client results
-enum NTPResult
-{
-  NTP_OK = 0, ///<Success
-  NTP_DNS, ///<Could not resolve name
-  NTP_PRTCL, ///<Protocol error
-  NTP_TIMEOUT, ///<Connection timeout
-  NTP_CONN, ///<Connection error
+enum NTPResult {
+    NTP_OK = 0, ///<Success
+    NTP_DNS, ///<Could not resolve name
+    NTP_PRTCL, ///<Protocol error
+    NTP_TIMEOUT, ///<Connection timeout
+    NTP_CONN, ///<Connection error
 };
 
 /** NTP Client to update the mbed's RTC using a remote time server
@@ -51,51 +50,49 @@
 class NTPClient
 {
 public:
-  /**
-  Instantiate the NTP client
-  */
-  NTPClient();
+    /**
+    Instantiate the NTP client
+    */
+    NTPClient();
 
-  /**Get current time (blocking)
-  Update the time using the server host
-  Blocks until completion
-  @param[in] host NTP server IPv4 address or hostname (will be resolved via DNS)
-  @param[in] port port to use; defaults to 123
-  @param[in] timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
-  @return 0 on success, NTP error code (<0) on failure
-  */
-  NTPResult setTime(const char* host, uint16_t port = NTP_DEFAULT_PORT, uint32_t timeout = NTP_DEFAULT_TIMEOUT); //Blocking
+    /**Get current time (blocking)
+    Update the time using the server host
+    Blocks until completion
+    @param[in] host NTP server IPv4 address or hostname (will be resolved via DNS)
+    @param[in] port port to use; defaults to 123
+    @param[in] timeout waiting timeout in ms (osWaitForever for blocking function, not recommended)
+    @return 0 on success, NTP error code (<0) on failure
+    */
+    NTPResult setTime(const char* host, uint16_t port = NTP_DEFAULT_PORT, uint32_t timeout = NTP_DEFAULT_TIMEOUT); //Blocking
 
 private:
-  struct NTPPacket //See RFC 4330 for Simple NTP
-  {
-    //WARN: We are in LE! Network is BE!
-    //LSb first
-    unsigned mode : 3;
-    unsigned vn : 3;
-    unsigned li : 2;
+    struct NTPPacket { //See RFC 4330 for Simple NTP
+        //WARN: We are in LE! Network is BE!
+        //LSb first
+        unsigned mode : 3;
+        unsigned vn : 3;
+        unsigned li : 2;
 
-    uint8_t stratum;
-    uint8_t poll;
-    uint8_t precision;
-    //32 bits header
+        uint8_t stratum;
+        uint8_t poll;
+        uint8_t precision;
+        //32 bits header
 
-    uint32_t rootDelay;
-    uint32_t rootDispersion;
-    uint32_t refId;
+        uint32_t rootDelay;
+        uint32_t rootDispersion;
+        uint32_t refId;
 
-    uint32_t refTm_s;
-    uint32_t refTm_f;
-    uint32_t origTm_s;
-    uint32_t origTm_f;
-    uint32_t rxTm_s;
-    uint32_t rxTm_f;
-    uint32_t txTm_s;
-    uint32_t txTm_f;
-  } __attribute__ ((packed));
-  
-  UDPSocket m_sock;
+        uint32_t refTm_s;
+        uint32_t refTm_f;
+        uint32_t origTm_s;
+        uint32_t origTm_f;
+        uint32_t rxTm_s;
+        uint32_t rxTm_f;
+        uint32_t txTm_s;
+        uint32_t txTm_f;
+    } __attribute__ ((packed));
 
+    UDPSocket m_sock;
 };