From 444e118e54a3ab0f50c8353803bf4c9defd1528c Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Sun, 28 Feb 2021 20:55:21 +0100 Subject: [PATCH] sntp implementation --- cube/User/Src/networkAbstractionLayer_lan.c | 121 +++++++++++++++----- 1 file changed, 90 insertions(+), 31 deletions(-) diff --git a/cube/User/Src/networkAbstractionLayer_lan.c b/cube/User/Src/networkAbstractionLayer_lan.c index f02be17..1b96e0f 100644 --- a/cube/User/Src/networkAbstractionLayer_lan.c +++ b/cube/User/Src/networkAbstractionLayer_lan.c @@ -1,3 +1,5 @@ +#include + #include #include #include @@ -14,57 +16,114 @@ static t_configBlock *config; 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; + + +const uint8_t SEND_LI_VN_MODE = 0xe3; // LI: unknown (3), VN: 4, Mode: Client (3) 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; enum { - SNTP_STATE_IDLE, + SNTP_STATE_IDLE, + SNTP_STATE_START, SNTP_STATE_SEND, + SNTP_STATE_RECV, SNTP_STATE_DONE, SNTP_STATE_ERROR } sntpState; } 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) { sntpEngineHandle_t *localHandle = (sntpEngineHandle_t*) handle; if (isNetworkAvailable()) { switch (localHandle->sntpState) { - case SNTP_STATE_SEND: - coloredMsg(LOG_BLUE, "nes, about to call SNTP"); - - uint8_t ntpServer[4]; - if (wizDnsQuery(config->ntpServer, ntpServer)) { - SNTP_init(SNTP_SOCK, ntpServer, 0, localHandle->sntpBuffer); - uint16_t cycles = 0; - uint32_t startTime = HAL_GetTick(); - 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; - } + case SNTP_STATE_START: + coloredMsg(LOG_BLUE, "nes, resolve ntp server"); + if (! wizDnsQuery(config->ntpServer, localHandle->ntpAddr)) { + coloredMsg(LOG_BLUE, "nes, failed to resolve ntp server"); + localHandle->sntpState = SNTP_STATE_ERROR; + } else { + localHandle->sntpState = SNTP_STATE_SEND; + schAdd(networkSntpEngine, (void*) localHandle, 10, 0); } - - if (localHandle->seconds == 0) { - coloredMsg(LOG_BLUE, "nes, time update failed"); + break; + case SNTP_STATE_SEND: + 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; + } 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 { - coloredMsg(LOG_BLUE, "nes, error when querying ntp server name"); - localHandle->sntpState = SNTP_STATE_ERROR; - } - default: - coloredMsg(LOG_BLUE, "nes, unexpected state"); + break; + default: + coloredMsg(LOG_BLUE, "nes, unexpected state"); } } else { coloredMsg(LOG_BLUE, "nes, no network yet, try again");