Dependents:   SimpleLCDClock readCard2Twitter_http AnalogClock_StepperMotor_NTP ServoCamV1

services/ntp/NtpClient.h

Committer:
donatien
Date:
2010-05-24
Revision:
0:a2dd0ba6cd2d
Child:
1:7043cc0db03c

File content as of revision 0:a2dd0ba6cd2d:

#ifndef SMTP_CLIENT_H
#define SMTP_CLIENT_H

#include "if/net/net.h"
#include "api/UdpSocket.h"
#include "api/DnsRequest.h"
#include "mbed.h"

#define NTP_PORT 123
#define NTP_REQUEST_TIMEOUT 15000
#define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)

enum NtpResult
{
  NTP_OK,
  NTP_PROCESSING,
  NTP_PRTCL, //Protocol error
  NTP_TIMEOUT, //Connection timeout
  NTP_DNS //Could not resolve DNS Addr
};

class NtpClient
{
public:
  NtpClient();
  virtual ~NtpClient();
  
  //High level setup functions
  NtpResult setTime(const Host& host); //Blocking
  NtpResult setTime(const Host& host, void (*pMethod)(NtpResult)); //Non blocking
  template<class T> 
  //Linker bug : Must be defined here :(
  NtpResult setTime(const Host& host, T* pItem, void (T::*pMethod)(NtpResult)) //Non blocking
  {
    setOnResult(pItem, pMethod);
    doSetTime(host);
    return NTP_PROCESSING;
  }
  
  void doSetTime(const Host& host);
  
  void setOnResult( void (*pMethod)(NtpResult) );
  class CDummy;
  template<class T> 
  //Linker bug : Must be defined here :(
  void setOnResult( T* pItem, void (T::*pMethod)(NtpResult) )
  {
    m_pCbItem = (CDummy*) pItem;
    m_pCbMeth = (void (CDummy::*)(NtpResult)) pMethod;
  }
  
  void init();
  void close();
  
private:
  __packed 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
    
    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;
  };

  void process(); //Main state-machine

  void setTimeout(int ms);
  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;

  enum NtpStep
  {
    NTP_PING,
    NTP_PONG
  };
  
  NtpStep m_state;
  
  CDummy* m_pCbItem;
  void (CDummy::*m_pCbMeth)(NtpResult);
  
  void (*m_pCb)(NtpResult);
  
  Timeout m_watchdog;
  int m_timeout;
  
  bool m_closed;
  
  Host m_host;
  
  DnsRequest* m_pDnsReq;
  
  NtpResult m_blockingResult; //Result if blocking mode

};

#endif