A stack which works with or without an Mbed os library. Provides IPv4 or IPv6 with a full 1500 byte buffer.

Dependents:   oldheating gps motorhome heating

udp/ntp/ntpclientquery.c

Committer:
andrewboyson
Date:
2019-02-22
Revision:
124:6e558721ec1c
Parent:
116:60521b29e4c9
Child:
125:8c84daac38ab

File content as of revision 124:6e558721ec1c:

#include <stdint.h>
#include <string.h>
#include <stdbool.h>

#include "log.h"
#include "clk.h"
#include "mstimer.h"
#include "clktime.h"
#include "ntptimestamp.h"
#include "clkutc.h"
#include "clkgov.h"
#include "clktm.h"
#include "net.h"
#include "ntp.h"
#include "ntpclient.h"
#include "dns.h"
#include "ip4.h"
#include "resolve.h"
#include "action.h"

#define ONE_BILLION 1000000000ULL
#define ONE_MILLION     1000000LL

char    NtpClientQueryServerName[DNS_MAX_LABEL_LENGTH+1]; 
int32_t NtpClientQueryInitialInterval;                    
int32_t NtpClientQueryNormalInterval;                     
int32_t NtpClientQueryRetryInterval;                      

bool       NtpClientQuerySendRequestsViaIp4 = false;
uint32_t   NtpClientQueryServerIp4;
char       NtpClientQueryServerIp6[16];

static uint64_t startNtpMs = 0;
static int  intervalTypeNtp = NTP_QUERY_INTERVAL_INITIAL;
static bool intervalCompleteNtp()
{
    uint32_t interval;
    switch(intervalTypeNtp)
    {
        case NTP_QUERY_INTERVAL_INITIAL: interval = NtpClientQueryInitialInterval; break;
        case NTP_QUERY_INTERVAL_NORMAL:  interval = NtpClientQueryNormalInterval;  break;
        case NTP_QUERY_INTERVAL_RETRY:   interval = NtpClientQueryRetryInterval;   break;
    }
    return MsTimerHasElapsed(startNtpMs, interval * 1000);
}
void NtpClientQueryStartInterval(int type)
{
    startNtpMs = MsTimerCount;
    intervalTypeNtp = type;
}

void writeRequest(void* pPacket, int* pSize)
{
    struct NtpHeader* pHeader = (struct NtpHeader*)pPacket;
    
    pHeader->Mode             = NTP_CLIENT;
    pHeader->VN               = 3;
    pHeader->LI               = 0;
    pHeader->Stratum          = 0;
    pHeader->Poll             = 0;
    pHeader->Precision        = 0;
    pHeader->RootDelay        = 0;
    pHeader->Dispersion       = 0;
    pHeader->RefIdentifier[0] = 0;
    pHeader->RefIdentifier[1] = 0;
    pHeader->RefIdentifier[2] = 0;
    pHeader->RefIdentifier[3] = 0;
    pHeader->RefTimeStamp     = 0;
    pHeader->OriTimeStamp     = 0;
    pHeader->RecTimeStamp     = 0;
    pHeader->TraTimeStamp     = NetToHost64(NtpTimeStampFromClkTime(ClkTimeGet()));

    *pSize = sizeof(struct NtpHeader);
}

int NtpClientQueryPoll(int type, void* pPacket, int* pSize)
{
    if (NtpClientQueryServerName[0]) //An empty name means ntp client is not enabled
    {
        if (intervalCompleteNtp()) //Wait for the time out
        {
            bool isMulticast = NtpClientQueryServerName[0] == '*';
            if (isMulticast || Resolve(NtpClientQueryServerName, type, &NtpClientQueryServerIp4, NtpClientQueryServerIp6))
            {
                ClkGovIsReceivingTime = false;
                NtpClientQueryStartInterval(NTP_QUERY_INTERVAL_RETRY);
                writeRequest(pPacket, pSize);
                
                if (isMulticast) return MULTICAST_NTP;
                else             return   UNICAST_NTP;
            }
        }
    }
    return DO_NOTHING;
}