The extracted NTP client from Segundos NetServices library, for use with the [[http://mbed.org/users/hlipka/libraries/NetServicesMin|NetServicesMin]] library. The only fixed bug is the memory leak / OOM problem. Needs the [[http://mbed.org/users/hlipka/libraries/DNSResolver|DNSResolver]] library as well.

Dependents:   SPIVFDclock LPC1768_AppBoard_Internet_LCD_Clock

Files at this revision

API Documentation at this revision

Comitter:
hlipka
Date:
Mon Jan 24 23:07:27 2011 +0000
Parent:
0:ebea15f18f84
Commit message:
bugfix: re-added timeout handling

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	Mon Jan 10 22:38:49 2011 +0000
+++ b/NTPClient.cpp	Mon Jan 24 23:07:27 2011 +0000
@@ -22,6 +22,7 @@
 */
 
 #include "NTPClient.h"
+#include "dnsresolve.h"
 
 #include <stdio.h>
 
@@ -30,7 +31,7 @@
 
 #define NTP_PORT 123
 #define NTP_CLIENT_PORT 0//50420 //Random port
-#define NTP_REQUEST_TIMEOUT 15000
+#define NTP_REQUEST_TIMEOUT 5000
 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
 
 #define htons( x ) ( (( x << 8 ) & 0xFF00) | (( x >> 8 ) & 0x00FF) )
@@ -43,22 +44,20 @@
 #define ntohl( x ) (htonl(x))
 
 NTPClient::NTPClient() : 
-    m_state(NTP_PING), 
-//    m_watchdog(), 
-    m_timeout(NTP_REQUEST_TIMEOUT), 
-    m_closed(true), 
-    m_host(), 
-    m_pDnsReq(NULL), 
-    m_blockingResult(NTP_PROCESSING)
+    _state(NTP_PING), 
+    _timeout(NTP_REQUEST_TIMEOUT), 
+    _closed(true), 
+    _host(), 
+    _blockingResult(NTP_PROCESSING)
 {
-  m_watchdog=new Timer();
+  _watchdog=new Timer();
   DBG("\r\nNew NTPClient %p\r\n",this);
 }
 
 NTPClient::~NTPClient()
 {
   close();
-  delete m_watchdog;
+  delete _watchdog;
 }
 
 //High level setup functions
@@ -72,57 +71,46 @@
 {
   init();
   resetTimeout();
-  m_host = host;
-  if(!m_host.getPort())
+  _host = host;
+  if(!_host.getPort())
   {
-    m_host.setPort(NTP_PORT);
+    _host.setPort(NTP_PORT);
   }
-  if(m_host.getIp().isNull())
+  if(_host.getIp().isNull())
   {
-    //DNS query required
-    m_pDnsReq = new DNSRequest();
-    DBG("\r\nNTPClient : DNSRequest %p\r\n", m_pDnsReq);
-    m_pDnsReq->setOnReply(this, &NTPClient::onDNSReply);
-    m_pDnsReq->resolve(&m_host);
-    return;
+  
+    DNSResolver *dr=new DNSResolver();
+    IpAddr ad=dr->resolveName(host.getName());
+    delete dr;
+    if (ad.isNull())
+    {
+        onResult(NTP_DNS);
+        return;
+    }
+    _host.setIp(ad);
   }
   open();
 }
 
 void NTPClient::close()
 {
-  if(m_closed)
+  if(_closed)
     return;
-  m_closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
-  m_watchdog->stop();
-  m_pUDPSocket->resetOnEvent();
-  m_pUDPSocket->close();
-  delete m_pUDPSocket;
-  if( m_pDnsReq )
-  {
-    m_pDnsReq->close();
-    delete m_pDnsReq;
-    m_pDnsReq = NULL;
-  }
+  _closed = true; //Prevent recursive calling or calling on an object being destructed by someone else
+  _watchdog->stop();
+  _pUDPSocket->resetOnEvent();
+  _pUDPSocket->close();
+  delete _pUDPSocket;
 }
 
-/*
-void NTPClient::poll() //Called by NetServices
-{
-  if( (!m_closed) && (m_watchdog->read_ms() >= m_timeout) )
-  {
-    onTimeout();
-  }
-}
-*/
 void NTPClient::init() //Create and setup socket if needed
 {
-  if(!m_closed) //Already opened
+  if(!_closed) //Already opened
     return;
-  m_state = NTP_PING;
-  m_pUDPSocket = new UDPSocket;
-  m_pUDPSocket->setOnEvent(this, &NTPClient::onUDPSocketEvent);
-  m_closed = false;
+  _state = NTP_PING;
+  _pUDPSocket = new UDPSocket;
+  _pUDPSocket->setOnEvent(this, &NTPClient::onUDPSocketEvent);
+  _closed = false;
   DBG("NTPClient: Init OK\n");
 }
 
@@ -130,9 +118,9 @@
 {
   resetTimeout();
   DBG("Opening connection\n");
-  m_state = NTP_PING;
+  _state = NTP_PING;
   Host localhost(IpAddr(), NTP_CLIENT_PORT, "localhost"); //Any local address
-  m_pUDPSocket->bind(localhost);
+  _pUDPSocket->bind(localhost);
   if ((int)time(NULL) < 1280000000) set_time( 1280000000 ); //End of July 2010... just there to limit offset range
 
   process();
@@ -144,55 +132,54 @@
 {
   int len;
   Host host;
-  
-  switch(m_state)
+  switch(_state)
   {
   case NTP_PING:
     DBG("Ping\r\n");
     //Prepare NTP Packet:
-    m_pkt.li = 0; //Leap Indicator : No warning
-    m_pkt.vn = 4; //Version Number : 4
-    m_pkt.mode = 3; //Client mode
-    m_pkt.stratum = 0; //Not relevant here
-    m_pkt.poll = 0; //Not significant as well
-    m_pkt.precision = 0; //Neither this one is
+    _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
     
-    m_pkt.rootDelay = 0; //Or this one
-    m_pkt.rootDispersion = 0; //Or that one
-    m_pkt.refId = 0; //...
+    _pkt.rootDelay = 0; //Or this one
+    _pkt.rootDispersion = 0; //Or that one
+    _pkt.refId = 0; //...
     
-    m_pkt.refTm_s = 0;
-    m_pkt.origTm_s = 0;
-    m_pkt.rxTm_s = 0;
-    m_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
     
-    m_pkt.refTm_f = m_pkt.origTm_f = m_pkt.rxTm_f = m_pkt.txTm_f = 0;
+    _pkt.refTm_f = _pkt.origTm_f = _pkt.rxTm_f = _pkt.txTm_f = 0;
     
     #ifdef __DEBUG
     //Hex Dump:
     DBG("Dump Tx:\r\n");
     for(int i = 0; i< sizeof(NTPPacket); i++)
     {
-      DBGL("%02x ", *((char*)&m_pkt + i));
+      DBGL("%02x ", *((char*)&_pkt + i));
     }
     DBGL("\r\n");
     #endif
     
-    len = m_pUDPSocket->sendto( (char*)&m_pkt, sizeof(NTPPacket), &m_host );
+    len = _pUDPSocket->sendto( (char*)&_pkt, sizeof(NTPPacket), &_host );
     if(len < sizeof(NTPPacket))
       { onResult(NTP_PRTCL); close(); return; }
       
-    m_state = NTP_PONG; 
+    _state = NTP_PONG; 
           
     break;
   
   case NTP_PONG:
     DBG("Pong\r\n");
-    while( len = m_pUDPSocket->recvfrom( (char*)&m_pkt, sizeof(NTPPacket), &host ) )
+    while( len = _pUDPSocket->recvfrom( (char*)&_pkt, sizeof(NTPPacket), &host ) )
     {
       if( len <= 0 )
         break;
-      if( !host.getIp().isEq(m_host.getIp()) )
+      if( !host.getIp().isEq(_host.getIp()) )
         continue; //Not our packet
       if( len > 0 )
         break;
@@ -212,34 +199,34 @@
     DBG("Dump Rx:\r\n");
     for(int i = 0; i< sizeof(NTPPacket); i++)
     {
-      DBGL("%02x ", *((char*)&m_pkt + i));
+      DBGL("%02x ", *((char*)&_pkt + i));
     }
     DBGL("\r\n");
     #endif
       
-    if( m_pkt.stratum == 0)  //Kiss of death message : Not good !
+    if( _pkt.stratum == 0)  //Kiss of death message : Not good !
     {
       onResult(NTP_PRTCL); close(); return;
     }
     
     //Correct Endianness
-    m_pkt.refTm_s = ntohl( m_pkt.refTm_s );
-    m_pkt.refTm_f = ntohl( m_pkt.refTm_f );
-    m_pkt.origTm_s = ntohl( m_pkt.origTm_s );
-    m_pkt.origTm_f = ntohl( m_pkt.origTm_f );
-    m_pkt.rxTm_s = ntohl( m_pkt.rxTm_s );
-    m_pkt.rxTm_f = ntohl( m_pkt.rxTm_f );
-    m_pkt.txTm_s = ntohl( m_pkt.txTm_s );
-    m_pkt.txTm_f = ntohl( m_pkt.txTm_f );
+    _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));
-    //int32_t origTm = (int32_t) ((uint64_t) m_pkt.origTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
-    //int32_t rxTm = (int32_t) ((uint64_t) m_pkt.rxTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
-    //int32_t txTm = (int32_t) ((uint64_t) m_pkt.txTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
-   // int64_t offset = ( ( ( m_pkt.rxTm_s - m_pkt.origTm_s ) + ( m_pkt.txTm_s - destTm_s ) ) << 32 + ( ( m_pkt.rxTm_f - m_pkt.origTm_f ) + ( m_pkt.txTm_f - 0 ) ) ) / 2;
-    int64_t offset = ( (int64_t)( m_pkt.rxTm_s - m_pkt.origTm_s ) + (int64_t) ( m_pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
-    DBG("Sent @%d\r\n", m_pkt.txTm_s);
+    //int32_t origTm = (int32_t) ((uint64_t) _pkt.origTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+    //int32_t rxTm = (int32_t) ((uint64_t) _pkt.rxTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+    //int32_t txTm = (int32_t) ((uint64_t) _pkt.txTm - NTP_TIMESTAMP_DELTA); //Convert in local 32 bits timestamps
+   // int64_t offset = ( ( ( _pkt.rxT_s - m_pkt.origTm_s ) + ( m_pkt.txT_s - destTm_s ) ) << 32 + ( ( m_pkt.rxTm_f - m_pkt.origTm_f ) + ( m_pkt.txT_f - 0 ) ) ) / 2;
+    int64_t offset = ( (int64_t)( _pkt.rxTm_s - _pkt.origTm_s ) + (int64_t) ( _pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
+    DBG("Sent @%d\r\n", _pkt.txTm_s);
     DBG("Offset: %d\r\n", offset);
 
     //Set time accordingly
@@ -253,13 +240,13 @@
 
 void NTPClient::setTimeout(int ms)
 {
-  m_timeout = ms;
+  _timeout = ms;
 }
 
 void NTPClient::resetTimeout()
 {
-  m_watchdog->reset();
-  m_watchdog->start();
+  _watchdog->reset();
+  _watchdog->start();
 }
 
 void NTPClient::onTimeout() //Connection has timed out
@@ -268,36 +255,12 @@
   onResult(NTP_TIMEOUT);
 }
 
-void NTPClient::onDNSReply(DNSReply r)
-{
-  if(m_closed)
-  {
-    DBG("\r\nWARN: Discarded\r\n");
-    return;
-  }
-  
-  if( r != DNS_FOUND )
-  {
-    DBG("\r\nCould not resolve hostname.\r\n");
-    onResult(NTP_DNS);
-    close();
-    return;
-  }
-  DBG("\r\nDNS resolved.\r\n");
-  m_pDnsReq->close();
-  delete m_pDnsReq;
-  m_pDnsReq=NULL;
-
-  open();
-}
-  
 void NTPClient::onUDPSocketEvent(UDPSocketEvent e)
 {
   resetTimeout();
   switch(e)
   {
   case UDPSOCKET_READABLE: //The only event for now
-    resetTimeout();
     process();
     break;
   }
@@ -305,18 +268,21 @@
 
 void NTPClient::onResult(NTPResult r) //Must be called by impl when the request completes
 {
-  m_blockingResult = r; //Blocking mode
+  _blockingResult = r; //Blocking mode
 }
 
 NTPResult NTPClient::blockingProcess() //Called in blocking mode, calls Net::poll() until return code is available
 {
-  m_blockingResult = NTP_PROCESSING;
+  _blockingResult = NTP_PROCESSING;
   do
   {
     Net::poll();
-  } while(m_blockingResult == NTP_PROCESSING);
+    wait_us(100);
+    if (_watchdog->read_ms()>_timeout)
+        return NTP_TIMEOUT;
+  } while(_blockingResult == NTP_PROCESSING);
  
   Net::poll(); //Necessary for cleanup
 
-  return m_blockingResult;
+  return _blockingResult;
 }
--- a/NTPClient.h	Mon Jan 10 22:38:49 2011 +0000
+++ b/NTPClient.h	Mon Jan 24 23:07:27 2011 +0000
@@ -31,7 +31,6 @@
 #include "core/net.h"
 #include "core/netservice.h"
 #include "api/UDPSocket.h"
-#include "api/DNSRequest.h"
 #include "mbed.h"
 
 ///NTP Client results
@@ -108,13 +107,14 @@
   void resetTimeout();
   
   void onTimeout(); //Connection has timed out
-  void onDNSReply(DNSReply r);
   void onUDPSocketEvent(UDPSocketEvent e);
   void onResult(NTPResult r); //Called when exchange completed or on failure
   
   NTPResult blockingProcess(); //Called in blocking mode, calls Net::poll() until return code is available
 
-  UDPSocket* m_pUDPSocket;
+  UDPSocket* _pUDPSocket;
+  
+  
 
   enum NTPStep
   {
@@ -122,20 +122,18 @@
     NTP_PONG
   };
   
-  NTPStep m_state;
+  NTPStep _state;
   
-  NTPPacket m_pkt;
-  
-  Timer *m_watchdog;
-  int m_timeout;
+  NTPPacket _pkt;
   
-  bool m_closed;
-  
-  Host m_host;
+  Timer *_watchdog;
+  int _timeout;
   
-  DNSRequest* m_pDnsReq;
+  bool _closed;
   
-  NTPResult m_blockingResult; //Result if blocking mode
+  Host _host;
+  
+  NTPResult _blockingResult; //Result if blocking mode
 
 };