sntp implementation
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <networkAbstractionLayer_impl.h>
|
#include <networkAbstractionLayer_impl.h>
|
||||||
#include <logger.h>
|
#include <logger.h>
|
||||||
#include <PontCoopScheduler.h>
|
#include <PontCoopScheduler.h>
|
||||||
@ -14,57 +16,114 @@ static t_configBlock *config;
|
|||||||
|
|
||||||
|
|
||||||
static const uint64_t UNIX_NTP_EPOCH_DIFF = 2208988800;
|
static const uint64_t UNIX_NTP_EPOCH_DIFF = 2208988800;
|
||||||
|
static const uint16_t NTP_PORT = 123;
|
||||||
|
static const uint16_t MAX_SNTP_RETRIES = 100;
|
||||||
extern const uint8_t SNTP_SOCK;
|
extern const uint8_t SNTP_SOCK;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t SEND_LI_VN_MODE = 0xe3; // LI: unknown (3), VN: 4, Mode: Client (3)
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sntpBuffer[MAX_SNTP_BUF_SIZE];
|
uint8_t li_vn_mode;
|
||||||
|
uint8_t stratum;
|
||||||
|
uint8_t poll;
|
||||||
|
uint8_t precision;
|
||||||
|
uint32_t rootdelay;
|
||||||
|
uint32_t rootdisp;
|
||||||
|
uint32_t refid;
|
||||||
|
uint64_t reftime;
|
||||||
|
uint64_t org;
|
||||||
|
uint64_t rec;
|
||||||
|
uint64_t xmt;
|
||||||
|
} ntpMsg_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ntpMsg_t ntpMsg;
|
||||||
|
uint8_t ntpAddr[4];
|
||||||
|
uint16_t retryCount;
|
||||||
uint64_t seconds;
|
uint64_t seconds;
|
||||||
enum {
|
enum {
|
||||||
SNTP_STATE_IDLE,
|
SNTP_STATE_IDLE,
|
||||||
|
SNTP_STATE_START,
|
||||||
SNTP_STATE_SEND,
|
SNTP_STATE_SEND,
|
||||||
|
SNTP_STATE_RECV,
|
||||||
SNTP_STATE_DONE,
|
SNTP_STATE_DONE,
|
||||||
SNTP_STATE_ERROR
|
SNTP_STATE_ERROR
|
||||||
} sntpState;
|
} sntpState;
|
||||||
} sntpEngineHandle_t;
|
} sntpEngineHandle_t;
|
||||||
|
|
||||||
sntpEngineHandle_t sntpEngineHandle = { .seconds = 0, .sntpState = SNTP_STATE_IDLE };
|
sntpEngineHandle_t sntpEngineHandle = {
|
||||||
|
.seconds = 0,
|
||||||
|
.retryCount = 0,
|
||||||
|
.sntpState = SNTP_STATE_IDLE
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
void networkSntpEngine(void *handle) {
|
void networkSntpEngine(void *handle) {
|
||||||
sntpEngineHandle_t *localHandle = (sntpEngineHandle_t*) handle;
|
sntpEngineHandle_t *localHandle = (sntpEngineHandle_t*) handle;
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
switch (localHandle->sntpState) {
|
switch (localHandle->sntpState) {
|
||||||
case SNTP_STATE_SEND:
|
case SNTP_STATE_START:
|
||||||
coloredMsg(LOG_BLUE, "nes, about to call SNTP");
|
coloredMsg(LOG_BLUE, "nes, resolve ntp server");
|
||||||
|
if (! wizDnsQuery(config->ntpServer, localHandle->ntpAddr)) {
|
||||||
uint8_t ntpServer[4];
|
coloredMsg(LOG_BLUE, "nes, failed to resolve ntp server");
|
||||||
if (wizDnsQuery(config->ntpServer, ntpServer)) {
|
localHandle->sntpState = SNTP_STATE_ERROR;
|
||||||
SNTP_init(SNTP_SOCK, ntpServer, 0, localHandle->sntpBuffer);
|
} else {
|
||||||
uint16_t cycles = 0;
|
localHandle->sntpState = SNTP_STATE_SEND;
|
||||||
uint32_t startTime = HAL_GetTick();
|
schAdd(networkSntpEngine, (void*) localHandle, 10, 0);
|
||||||
while (1) {
|
|
||||||
cycles += 1;
|
|
||||||
datetime curTime;
|
|
||||||
if (1 == SNTP_run(&curTime)) {
|
|
||||||
localHandle->seconds = curTime.seconds - UNIX_NTP_EPOCH_DIFF;
|
|
||||||
coloredMsg(LOG_BLUE, "nes, cycles: %u, curTime: %lu", cycles, localHandle->seconds);
|
|
||||||
uint32_t stopTime = HAL_GetTick();
|
|
||||||
coloredMsg(LOG_BLUE, "nes, duration: %u ms", stopTime - startTime);
|
|
||||||
localHandle->sntpState = SNTP_STATE_DONE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
if (localHandle->seconds == 0) {
|
case SNTP_STATE_SEND:
|
||||||
coloredMsg(LOG_BLUE, "nes, time update failed");
|
coloredMsg(LOG_BLUE, "nes, about to call SNTP");
|
||||||
|
localHandle->retryCount = 0;
|
||||||
|
socket(SNTP_SOCK, Sn_MR_UDP, NTP_PORT, 0);
|
||||||
|
uint8_t sockState = getSn_SR(SNTP_SOCK);
|
||||||
|
if (sockState == SOCK_UDP) {
|
||||||
|
memset(&(localHandle->ntpMsg), 0, sizeof(localHandle->ntpMsg));
|
||||||
|
localHandle->ntpMsg.li_vn_mode = SEND_LI_VN_MODE;
|
||||||
|
sendto(SNTP_SOCK, (uint8_t*)(&(localHandle->ntpMsg)),
|
||||||
|
sizeof(localHandle->ntpMsg), localHandle->ntpAddr, NTP_PORT);
|
||||||
|
coloredMsg(LOG_BLUE, "nes, sent");
|
||||||
|
localHandle->sntpState = SNTP_STATE_RECV;
|
||||||
|
schAdd(networkSntpEngine, (void*) localHandle, 100, 0);
|
||||||
|
} else {
|
||||||
|
coloredMsg(LOG_BLUE, "nes, socket in unexpected state %d", sockState);
|
||||||
|
localHandle->sntpState = SNTP_STATE_ERROR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SNTP_STATE_RECV:
|
||||||
|
coloredMsg(LOG_BLUE, "nes, check receive");
|
||||||
|
uint16_t recvLen = getSn_RX_RSR(SNTP_SOCK);
|
||||||
|
if (recvLen == 0) {
|
||||||
|
localHandle->retryCount += 1;
|
||||||
|
if (localHandle->retryCount > MAX_SNTP_RETRIES) {
|
||||||
|
coloredMsg(LOG_BLUE, "nes, max retry count reached, failed");
|
||||||
localHandle->sntpState = SNTP_STATE_ERROR;
|
localHandle->sntpState = SNTP_STATE_ERROR;
|
||||||
|
} else {
|
||||||
|
coloredMsg(LOG_BLUE, "nes, nothing received yet, try again");
|
||||||
|
schAdd(networkSntpEngine, (void*) localHandle, 100, 0);
|
||||||
|
}
|
||||||
|
} else if (recvLen == sizeof(localHandle->ntpMsg)) {
|
||||||
|
memset(&(localHandle->ntpMsg), 0, sizeof(localHandle->ntpMsg));
|
||||||
|
uint8_t srcAddr[4];
|
||||||
|
uint16_t srcPort;
|
||||||
|
recvfrom(SNTP_SOCK, (uint8_t*)(&(localHandle->ntpMsg)),
|
||||||
|
sizeof(localHandle->ntpMsg), srcAddr, &srcPort);
|
||||||
|
close(SNTP_SOCK);
|
||||||
|
coloredMsg(LOG_BLUE, "nes, msg received from %d.%d.%d.%d:%d",
|
||||||
|
srcAddr[0], srcAddr[1], srcAddr[2], srcAddr[3],
|
||||||
|
srcPort);
|
||||||
|
coloredMsg(LOG_BLUE, "nes, received in the %d. cycles", localHandle->retryCount);
|
||||||
|
localHandle->seconds = localHandle->ntpMsg.rec - UNIX_NTP_EPOCH_DIFF;
|
||||||
|
coloredMsg(LOG_BLUE, "nes, seconds: %lu", localHandle->seconds);
|
||||||
|
localHandle->sntpState = SNTP_STATE_DONE;
|
||||||
|
} else {
|
||||||
|
coloredMsg(LOG_BLUE, "nes, invalid number of octets received: %d", recvLen);
|
||||||
|
localHandle->sntpState = SNTP_STATE_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
break;
|
||||||
coloredMsg(LOG_BLUE, "nes, error when querying ntp server name");
|
default:
|
||||||
localHandle->sntpState = SNTP_STATE_ERROR;
|
coloredMsg(LOG_BLUE, "nes, unexpected state");
|
||||||
}
|
|
||||||
default:
|
|
||||||
coloredMsg(LOG_BLUE, "nes, unexpected state");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
coloredMsg(LOG_BLUE, "nes, no network yet, try again");
|
coloredMsg(LOG_BLUE, "nes, no network yet, try again");
|
||||||
|
Reference in New Issue
Block a user