From 13a67dc66023843314134f88f57c8a89b447bab4 Mon Sep 17 00:00:00 2001 From: Wolfgang Hottgenroth Date: Sat, 27 Feb 2021 22:48:54 +0100 Subject: [PATCH] new sntp implementation --- cube/User/Inc/networkAbstractionLayer_impl.h | 2 + cube/User/Src/networkAbstractionLayer_lan.c | 123 ++++++++++++++++++- cube/User/Src/wizHelper.c | 38 ------ 3 files changed, 123 insertions(+), 40 deletions(-) diff --git a/cube/User/Inc/networkAbstractionLayer_impl.h b/cube/User/Inc/networkAbstractionLayer_impl.h index 2a4df57..de1c1cd 100644 --- a/cube/User/Inc/networkAbstractionLayer_impl.h +++ b/cube/User/Inc/networkAbstractionLayer_impl.h @@ -4,6 +4,8 @@ #include uint64_t networkSntpQuery(); + + int8_t networkUdpSend(char *hostname, uint16_t port, uint8_t *buf, uint16_t bufLen); void networkImplInit(); diff --git a/cube/User/Src/networkAbstractionLayer_lan.c b/cube/User/Src/networkAbstractionLayer_lan.c index c1908b4..95ec262 100644 --- a/cube/User/Src/networkAbstractionLayer_lan.c +++ b/cube/User/Src/networkAbstractionLayer_lan.c @@ -1,14 +1,132 @@ +#include +#include + #include #include - +#include #include #include #include +#include +#include + +static t_configBlock *config; +const uint16_t MAX_RECV_RETRY_COUNT = 100; +const uint64_t UNIX_NTP_EPOCH_DIFF = 2208988800; + +const uint8_t SEND_LI_VN_MODE = 0xe3; // LI: unknown (3), VN: 4, Mode: Client (3) +typedef struct { + 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; + +extern uint8_t SNTP_SOCK; + +const uint16_t NTP_PORT = 123; + +enum { + SNTP_STATE_IDLE, + SNTP_STATE_START, + SNTP_STATE_SEND, + SNTP_STATE_RECV, + SNTP_STATE_ERROR, + SNTP_STATE_DONE +} sntpState; +uint64_t seconds; + +static void networkSntpEngine(void *handle) { + static uint16_t retryCount = 0; + + coloredMsg(LOG_BLUE, "nes, %u", sntpState); + + switch (sntpState) { + case SNTP_STATE_START: + socket(SNTP_SOCK, Sn_MR_UDP, NTP_PORT, 0); + retryCount = 0; + sntpState = SNTP_STATE_SEND; + schAdd(networkSntpEngine, NULL, 10, 0); + break; + case SNTP_STATE_SEND: + coloredMsg(LOG_BLUE, "nes, about to send"); + uint8_t sockState = getSn_SR(SNTP_SOCK); + if (sockState == SOCK_UDP) { + uint8_t ntpAddr[4]; + if (! wizDnsQuery(config->ntpServer, ntpAddr)) { + coloredMsg(LOG_BLUE, "nes, failed to resolve ntp server"); + sntpState = SNTP_STATE_ERROR; + } else { + ntpMsg_t ntpMsg; + memset(&ntpMsg, 0, sizeof(ntpMsg)); + ntpMsg.li_vn_mode = SEND_LI_VN_MODE; + sendto(SNTP_SOCK, (uint8_t*)&ntpMsg, sizeof(ntpMsg), ntpAddr, NTP_PORT); + coloredMsg(LOG_BLUE, "nes, sent"); + sntpState = SNTP_STATE_RECV; + schAdd(networkSntpEngine, NULL, 10, 0); + } + } else { + coloredMsg(LOG_BLUE, "nes, socket in unexpected state: %d", sockState); + 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) { + retryCount += 1; + if (retryCount > MAX_RECV_RETRY_COUNT) { + coloredMsg(LOG_BLUE, "nes max retry count reached, failed"); + sntpState = SNTP_STATE_ERROR; + } else { + coloredMsg(LOG_BLUE, "nes, nothing received yet, try again"); + schAdd(networkSntpEngine, NULL, 100, 0); + } + } else if (recvLen == sizeof(ntpMsg_t)) { + ntpMsg_t ntpMsg; + memset(&ntpMsg, 0, sizeof(ntpMsg_t)); + uint8_t srcAddr[4]; + uint16_t srcPort; + recvfrom(SNTP_SOCK, (uint8_t*)&ntpMsg, sizeof(ntpMsg_t), 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", retryCount); + seconds = ntpMsg.rec - UNIX_NTP_EPOCH_DIFF; + coloredMsg(LOG_BLUE, "nes, seconds: %lu", seconds); + sntpState = SNTP_STATE_DONE; + } else { + coloredMsg(LOG_BLUE, "nes, invalid number of octets received: %d", recvLen); + sntpState = SNTP_STATE_ERROR; + } + break; + default: + coloredMsg(LOG_BLUE, "nes, unexpected state"); + } +} uint64_t networkSntpQuery() { - return wizSntpQuery(); + uint64_t res = 0; + if (sntpState == SNTP_STATE_IDLE) { + sntpState = SNTP_STATE_START; + schAdd(networkSntpEngine, NULL, 1, 0); + } else if (sntpState == SNTP_STATE_ERROR) { + sntpState = SNTP_STATE_IDLE; + } else if (sntpState == SNTP_STATE_DONE) { + sntpState = SNTP_STATE_IDLE; + res = seconds; + } + return res; } @@ -39,5 +157,6 @@ int8_t networkUdpSend(char *hostname, uint16_t port, uint8_t *buf, uint16_t bufL } void networkImplInit() { + config = getConfig(); wizInit(); } diff --git a/cube/User/Src/wizHelper.c b/cube/User/Src/wizHelper.c index cee477e..1b9292a 100644 --- a/cube/User/Src/wizHelper.c +++ b/cube/User/Src/wizHelper.c @@ -26,13 +26,9 @@ static uint8_t dhcpBuffer[DHCP_BUFFER_SIZE]; static uint8_t dnsBuffer[DNS_BUFFER_SIZE]; -static uint8_t sntpBuffer[MAX_SNTP_BUF_SIZE]; -const uint64_t UNIX_NTP_EPOCH_DIFF = 2208988800; - extern const uint8_t DHCP_SOCK; extern const uint8_t DNS_SOCK; -extern const uint8_t SNTP_SOCK; static bool networkAvailable = false; @@ -133,40 +129,6 @@ bool wizDnsQuery(char *name, uint8_t *ip) { } -uint64_t wizSntpQuery() { - uint64_t seconds = 0; - - if (networkAvailable) { - coloredMsg(LOG_BLUE, "wizsq, about to call SNTP"); - - uint8_t ntpServer[4]; - if (wizDnsQuery(config->ntpServer, ntpServer)) { - SNTP_init(SNTP_SOCK, ntpServer, 0, sntpBuffer); - uint16_t cycles = 0; - uint32_t startTime = HAL_GetTick(); - while (1) { - cycles += 1; - datetime curTime; - if (1 == SNTP_run(&curTime)) { - seconds = curTime.seconds - UNIX_NTP_EPOCH_DIFF; - coloredMsg(LOG_BLUE, "wizsq, cycles: %u, curTime: %lu", cycles, seconds); - uint32_t stopTime = HAL_GetTick(); - coloredMsg(LOG_BLUE, "wizsq, duration: %u ms", stopTime - startTime); - break; - } - } - - if (seconds == 0) { - coloredMsg(LOG_BLUE, "wizsq, time update failed"); - } - } else { - coloredMsg(LOG_BLUE, "wizsq, error when querying ntp server name"); - } - } - - return seconds; -} - static void wizPhyLinkHandler(void *handle) { // this handler is anyhow called with a 1s period, so we reuse it for the DNS timer DNS_time_handler();