// sntp_manager.h bool TCPIP_SNTP_Client(TCPIP_NET_IF* pNetIf) { NTP_PACKET pkt; uint16_t w; DNS_RESULT dnsRes; static SYS_TICK SNTPTimer; if(pSntpIf != 0 && pNetIf != pSntpIf) { // not our job return false; } switch(sntpState) { case SM_HOME: sntpSocket = INVALID_UDP_SOCKET; pSntpIf = pSntpDefIf; if(!TCPIP_STACK_NetworkIsLinked(pSntpIf)) { pSntpIf = _TCPIPStackAnyNetLinked(true); } if(TCPIP_DNS_UsageBegin(pSntpIf) != DNS_RES_OK) { ntpLastError = SNTP_RES_NTP_DNS_ERR; break; } TCPIP_DNS_Resolve(NTP_SERVER, ntpConnection ==IP_ADDRESS_TYPE_IPV6 ? DNS_TYPE_AAAA : DNS_TYPE_A); sntpState++; break; case SM_WAIT_DNS: dnsRes = TCPIP_DNS_IsResolved(NTP_SERVER, &serverIP); if(dnsRes == DNS_RES_PENDING) { // ongoing operation; break; } else if(dnsRes < 0) { // some DNS error occurred; retry after waiting a while SNTPTimer = SYS_TICK_Get(); sntpState = SM_SHORT_WAIT; ntpLastError = SNTP_RES_NTP_DNS_ERR; } else { sntpState++; } TCPIP_DNS_UsageEnd(pSntpIf); break; case SM_DNS_RESOLVED: sntpSocket = TCPIP_UDP_ClientOpen(ntpConnection, NTP_SERVER_PORT, &serverIP); if(sntpSocket != INVALID_UDP_SOCKET) { TCPIP_UDP_SocketNetSet(sntpSocket, pSntpIf); sntpState++; SNTPTimer = SYS_TICK_Get(); } else { ntpLastError = SNTP_RES_SKT_ERR; } break; case SM_UDP_IS_OPENED: if(TCPIP_UDP_IsOpened(sntpSocket) == true) { SNTPTimer = SYS_TICK_Get(); sntpState = SM_UDP_SEND; } else if((SYS_TICK_Get() - SNTPTimer > 1*SYS_TICK_TicksPerSecondGet())) { // failed to open TCPIP_UDP_Close(sntpSocket); sntpState = SM_DNS_RESOLVED; sntpSocket = INVALID_UDP_SOCKET; ntpLastError = SNTP_RES_SKT_ERR; } break; case SM_UDP_SEND: // Open up the sending UDP socket // Make certain the socket can be written to if(!TCPIP_UDP_TxPutIsReady(sntpSocket, sizeof(pkt))) { // Wait no more than 1 sec if((SYS_TICK_Get() - SNTPTimer > 1*SYS_TICK_TicksPerSecondGet())) { TCPIP_UDP_Close(sntpSocket); sntpState = SM_DNS_RESOLVED; sntpSocket = INVALID_UDP_SOCKET; ntpLastError = SNTP_RES_SKT_ERR; break; } } // Success // Transmit a time request packet memset(&pkt, 0, sizeof(pkt)); pkt.flags.versionNumber = NTP_VERSION; pkt.flags.mode = 3; // NTP Client pkt.orig_ts_secs = TCPIP_Helper_htonl(NTP_EPOCH); TCPIP_UDP_ArrayPut(sntpSocket, (uint8_t*) &pkt, sizeof(pkt)); TCPIP_UDP_Flush(sntpSocket); SNTPTimer = SYS_TICK_Get(); sntpState = SM_UDP_RECV; break; case SM_UDP_RECV: // Look for a response time packet if(!TCPIP_UDP_GetIsReady(sntpSocket)) { if((SYS_TICK_Get()) - SNTPTimer > NTP_REPLY_TIMEOUT * SYS_TICK_TicksPerSecondGet()) { // Abort the request and resume TCPIP_UDP_Close(sntpSocket); //SNTPTimer = SYS_TICK_Get(); //sntpState = SM_SHORT_WAIT; sntpState = SM_HOME; sntpSocket = INVALID_UDP_SOCKET; ntpLastError = SNTP_RES_NTP_SERVER_TMO; } break; } // Get the response time packet w = TCPIP_UDP_ArrayGet(sntpSocket, (uint8_t*) &pkt, sizeof(pkt)); TCPIP_UDP_Close(sntpSocket); SNTPTimer = SYS_TICK_Get(); sntpState = SM_WAIT; sntpSocket = INVALID_UDP_SOCKET; // sanity packet check if(w != sizeof(pkt) || pkt.flags.versionNumber != NTP_VERSION ) { ntpLastError = SNTP_RES_NTP_VERSION_ERR; break; } if((pkt.tx_ts_secs == 0 && pkt.tx_ts_fraq == 0)) { ntpLastError = SNTP_RES_NTP_TSTAMP_ERR; break; } if(pkt.stratum == 0 ) { ntpLastError = SNTP_RES_NTP_KOD_ERR; break; } if(pkt.stratum >= NTP_MAX_STRATUM || pkt.flags.leapIndicator == 3 ) { ntpLastError = SNTP_RES_NTP_SYNC_ERR; break; } // get the last timestamp ntpTimeStamp.tStampSeconds = pkt.tx_ts_secs; ntpTimeStamp.tStampFraction = pkt.tx_ts_fraq; ntpLastStampTick = SYS_TICK_Get(); // Set out local time to match the returned time dwLastUpdateTick = ntpLastStampTick; dwSNTPSeconds = TCPIP_Helper_ntohl(pkt.tx_ts_secs) - NTP_EPOCH; // Do rounding. If the partial seconds is > 0.5 then add 1 to the seconds count. if(((uint8_t*)&pkt.tx_ts_fraq)[0] & 0x80) dwSNTPSeconds++; break; case SM_SHORT_WAIT: // Attempt to requery the NTP server after a specified NTP_FAST_QUERY_INTERVAL time (ex: 8 seconds) has elapsed. if(SYS_TICK_Get() - SNTPTimer > (NTP_FAST_QUERY_INTERVAL * SYS_TICK_TicksPerSecondGet())) { sntpState = SM_HOME; sntpSocket = INVALID_UDP_SOCKET; } break; case SM_WAIT: // Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed. if(SYS_TICK_Get() - SNTPTimer > (NTP_QUERY_INTERVAL * SYS_TICK_TicksPerSecondGet())) { sntpState = SM_HOME; sntpSocket = INVALID_UDP_SOCKET; } break; } return true; }//TCPIP_SNTP_Client
void TCPIP_ANNOUNCE_Send(void) { UDP_SOCKET announceSocket; uint16_t dataLen; uint16_t minimumDataLen; uint16_t txLen; bool truncated; TCPIP_NET_IF *pNetIf; const char* interfaceName; ANNOUNCE_FIELD_PAYLOAD payloadType; int netIx; uint16_t terminatorLen = strlen ((const char *)announceFieldTerminator); #if defined (TCPIP_STACK_USE_IPV6) IPV6_INTERFACE_CONFIG* pIpv6Config; IPV6_ADDR_STRUCT * addressPointer; IPV6_HEAP_NDP_DR_ENTRY *defaultRouter; IPV6_ADDR *pGatewayAddr; #endif // create the socket announceSocket = TCPIP_UDP_ClientOpen(IP_ADDRESS_TYPE_IPV4, TCPIP_ANNOUNCE_PORT, 0); if (announceSocket == INVALID_UDP_SOCKET) { // keep the request pending, we'll try next time return; } for(netIx = 0; netIx < announceIfs; netIx++) { // reply to the request on the interface it arrived on if((announceRequestMask & (1 << netIx)) != 0) { pNetIf = (TCPIP_NET_IF*)TCPIP_STACK_IndexToNet(netIx); if(TCPIP_STACK_NetworkIsLinked(pNetIf)) { // reply only if this interface is up and running TCPIP_UDP_SocketNetSet (announceSocket, pNetIf); TCPIP_UDP_BcastIPV4AddressSet(announceSocket, UDP_BCAST_NETWORK_DIRECTED, pNetIf); #if defined (TCPIP_STACK_USE_IPV6) pIpv6Config = TCPIP_IPV6_InterfaceConfigGet(pNetIf); #endif interfaceName = TCPIP_STACK_MACIdToString(pNetIf->macId); truncated = false; dataLen = ((terminatorLen + 1) * 4) + sizeof (IPV4_ADDR) + sizeof (TCPIP_MAC_ADDR); dataLen += strlen(interfaceName); dataLen += strlen((char *)pNetIf->NetBIOSName); minimumDataLen = dataLen + 1 + terminatorLen; #if defined (TCPIP_STACK_USE_IPV6) addressPointer = (IPV6_ADDR_STRUCT *)pIpv6Config->listIpv6UnicastAddresses.head; while(addressPointer != NULL) { dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = addressPointer->next; } addressPointer = (IPV6_ADDR_STRUCT *)pIpv6Config->listIpv6MulticastAddresses.head; while(addressPointer != NULL) { dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = addressPointer->next; } defaultRouter = pIpv6Config->currentDefaultRouter; while(defaultRouter != NULL) { dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; defaultRouter = defaultRouter->next; } // For IPV6 gateway address dataLen += sizeof (IPV6_ADDR) + 1 + terminatorLen; #endif if (dataLen > ANNOUNCE_MAX_PAYLOAD) { dataLen = ANNOUNCE_MAX_PAYLOAD; } if ((txLen = TCPIP_UDP_TxPutIsReady(announceSocket, dataLen)) < dataLen) { truncated = true; if ((txLen = TCPIP_UDP_TxPutIsReady(announceSocket, minimumDataLen)) < minimumDataLen) { TCPIP_UDP_Close (announceSocket); return; } } // Put Mac Address payloadType = ANNOUNCE_FIELD_MAC_ADDR; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&pNetIf->netMACAddr, sizeof (TCPIP_MAC_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); if (truncated) { payloadType = ANNOUNCE_FIELD_TRUNCATED; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); } // Put Mac Type payloadType = ANNOUNCE_FIELD_MAC_TYPE; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)interfaceName, strlen (interfaceName)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); // Put Host Name payloadType = ANNOUNCE_FIELD_HOST_NAME; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&pNetIf->NetBIOSName, strlen((char*)pNetIf->NetBIOSName)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); // Put IPv4 Address payloadType = ANNOUNCE_FIELD_IPV4_ADDRESS; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&pNetIf->netIPAddr, sizeof (IPV4_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); #if defined (TCPIP_STACK_USE_IPV6) // Put IPv6 unicast addresses minimumDataLen = sizeof (IPV6_ADDR) + 1 + terminatorLen; addressPointer = (IPV6_ADDR_STRUCT *)pIpv6Config->listIpv6UnicastAddresses.head; payloadType = ANNOUNCE_FIELD_IPV6_UNICAST; while(addressPointer != NULL && (TCPIP_UDP_TxPutIsReady(announceSocket, minimumDataLen) >= minimumDataLen)) { TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); addressPointer = addressPointer->next; } // Put IPv6 multicast listeners addressPointer = (IPV6_ADDR_STRUCT *)pIpv6Config->listIpv6MulticastAddresses.head; payloadType = ANNOUNCE_FIELD_IPV6_MULTICAST; while(addressPointer != NULL && (TCPIP_UDP_TxPutIsReady(announceSocket, minimumDataLen) >= minimumDataLen)) { TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&addressPointer->address, sizeof (IPV6_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); addressPointer = addressPointer->next; } defaultRouter = pIpv6Config->currentDefaultRouter; payloadType = ANNOUNCE_FIELD_IPV6_DEFAULT_ROUTER; while(defaultRouter != NULL && (TCPIP_UDP_TxPutIsReady(announceSocket, minimumDataLen) >= minimumDataLen)) { TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)&defaultRouter->neighborInfo->remoteIPAddress, sizeof (IPV6_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); defaultRouter = defaultRouter->next; } pGatewayAddr = (IPV6_ADDR*)TCPIP_STACK_NetDefaultIPv6GatewayGet(pNetIf); if(pGatewayAddr) { payloadType = ANNOUNCE_FIELD_IPV6_DEFAULT_GATEWAY; TCPIP_UDP_Put (announceSocket, payloadType); TCPIP_UDP_ArrayPut(announceSocket, (const uint8_t *)pGatewayAddr, sizeof (IPV6_ADDR)); TCPIP_UDP_ArrayPut (announceSocket, announceFieldTerminator, terminatorLen); } #endif TCPIP_UDP_Flush (announceSocket); } announceRequestMask &= ~(1 << netIx); // clear requests on this interface } } TCPIP_UDP_Close (announceSocket); }