#include #include #include #include #include #include #include #include #include #include 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 s_ntpStruct { 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; uint32_t reftime_h; uint32_t reftime_l; //uint64_t org; uint32_t org_h; uint32_t org_l; //uint64_t rec; uint32_t rec_h; uint32_t rec_l; //uint64_t xmt; uint32_t xmt_h; uint32_t xmt_l; } t_ntpStruct; typedef union __attribute__((__packed__)) { t_ntpStruct s; uint8_t b[sizeof(t_ntpStruct)]; } ntpMsg_t; typedef struct { ntpMsg_t ntpMsg; uint8_t ntpAddr[4]; uint16_t retryCount; uint64_t seconds; enum { 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, .retryCount = 0, .sntpState = SNTP_STATE_IDLE }; void networkSntpEngine(void *handle) { sntpEngineHandle_t *localHandle = (sntpEngineHandle_t*) handle; if (isNetworkAvailable()) { switch (localHandle->sntpState) { 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); } 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.s.li_vn_mode = SEND_LI_VN_MODE; localHandle->ntpMsg.s.xmt_l = 1; sendto(SNTP_SOCK, &(localHandle->ntpMsg.b), sizeof(localHandle->ntpMsg.b), 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, &(localHandle->ntpMsg.b), sizeof(localHandle->ntpMsg.b), srcAddr, &srcPort); /* uint8_t buf[90]; memset(buf, 0, sizeof(buf)); recvfrom(SNTP_SOCK, buf, sizeof(buf), srcAddr, &srcPort); uint8_t x = 0; coloredMsg(LOG_BLUE, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[x+0], buf[x+1], buf[x+2], buf[x+3], buf[x+4], buf[x+5], buf[x+6], buf[x+7], buf[x+8], buf[x+9], buf[x+10], buf[x+11], buf[x+12], buf[x+13], buf[x+14], buf[x+15]); x += 16; coloredMsg(LOG_BLUE, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[x+0], buf[x+1], buf[x+2], buf[x+3], buf[x+4], buf[x+5], buf[x+6], buf[x+7], buf[x+8], buf[x+9], buf[x+10], buf[x+11], buf[x+12], buf[x+13], buf[x+14], buf[x+15]); x += 16; coloredMsg(LOG_BLUE, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[x+0], buf[x+1], buf[x+2], buf[x+3], buf[x+4], buf[x+5], buf[x+6], buf[x+7], buf[x+8], buf[x+9], buf[x+10], buf[x+11], buf[x+12], buf[x+13], buf[x+14], buf[x+15]); x += 16; coloredMsg(LOG_BLUE, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", buf[x+0], buf[x+1], buf[x+2], buf[x+3], buf[x+4], buf[x+5], buf[x+6], buf[x+7], buf[x+8], buf[x+9], buf[x+10], buf[x+11], buf[x+12], buf[x+13], buf[x+14], buf[x+15]); */ 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 = ((uint64_t)localHandle->ntpMsg.s.xmt_h) - UNIX_NTP_EPOCH_DIFF; coloredMsg(LOG_BLUE, "nes, seconds: %llu", localHandle->seconds); localHandle->sntpState = SNTP_STATE_DONE; } else { coloredMsg(LOG_BLUE, "nes, invalid number of octets received: %d", recvLen); localHandle->sntpState = SNTP_STATE_ERROR; } break; default: coloredMsg(LOG_BLUE, "nes, unexpected state"); } } else { coloredMsg(LOG_BLUE, "nes, no network yet, try again"); schAdd(networkSntpEngine, (void*) localHandle, 100, 0); } } uint64_t networkSntpQuery() { uint64_t res = 0; if (sntpEngineHandle.sntpState == SNTP_STATE_IDLE) { coloredMsg(LOG_BLUE, "nsq, start sntp request"); sntpEngineHandle.sntpState = SNTP_STATE_START; schAdd(networkSntpEngine, (void*) &sntpEngineHandle, 1, 0); } else if (sntpEngineHandle.sntpState == SNTP_STATE_DONE) { coloredMsg(LOG_BLUE, "nsq, start sntp done"); res = sntpEngineHandle.seconds; sntpEngineHandle.sntpState = SNTP_STATE_IDLE; } else if (sntpEngineHandle.sntpState == SNTP_STATE_ERROR) { coloredMsg(LOG_BLUE, "nsq, start sntp failed"); sntpEngineHandle.sntpState = SNTP_STATE_IDLE; } return res; } extern uint8_t SINK_SOCK; int8_t networkUdpSend(char *hostname, uint16_t port, uint8_t *buf, uint16_t bufLen) { uint8_t sinkAddr[4]; if (! wizDnsQuery(hostname, sinkAddr)) { coloredMsg(LOG_BLUE, "nus, failed to resolve sink server name"); return -1; } else { coloredMsg(LOG_BLUE, "nus, sink server at %d.%d.%d.%d", sinkAddr[0], sinkAddr[1], sinkAddr[2], sinkAddr[3]); } socket(SINK_SOCK, Sn_MR_UDP, port, 0); uint8_t sockState = getSn_SR(SINK_SOCK); if (sockState == SOCK_UDP) { sendto(SINK_SOCK, buf, bufLen, sinkAddr, port); coloredMsg(LOG_BLUE, "nus, sent"); } else { coloredMsg(LOG_BLUE, "nus, socket in unexpected state: %d", sockState); return -2; } close(SINK_SOCK); return 1; } bool isNetworkAvailable() { return wizIsNetworkAvailable(); } void networkImplInit() { config = getConfig(); wizInit(); }