sntp.c
来自「eCos操作系统源码」· C语言 代码 · 共 550 行 · 第 1/2 页
C
550 行
// Site-Local mreq.ipv6mr_multiaddr.s6_addr[1]=0x05; ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Site-Local"); // Global mreq.ipv6mr_multiaddr.s6_addr[1]=0x0e; ret = setsockopt(fd6, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)); CYG_ASSERT(0 == ret, "setsockopt(IPV6_JOIN_GROUP) Global"); memset(&local6,0,sizeof(local6)); local6.sin6_family = AF_INET6; local6.sin6_len = sizeof(local6); local6.sin6_port = serv->s_port; local6.sin6_addr = in6addr_any; ret = bind(fd6, (struct sockaddr *)&local6,sizeof(local6)); CYG_ASSERT(0 == ret, "Bind6 failed"); n = (n > fd6 ? n : fd6);#endif while (1) { FD_ZERO(&readfds); FD_SET(fd,&readfds);#ifdef CYGPKG_NET_INET6 FD_SET(fd6,&readfds);#endif #ifdef CYGPKG_NET_SNTP_UNICAST /* By default, we will let select() wait * for SNTP_WAITPERIOD to receive a packet. This * allows us to periodically wake up and check * if new servers have been configured. However, * if we are waiting to send an update request, * we will set ptimeout to something more * reasonable below. */ timeout.tv_sec = SNTP_WAITPERIOD; timeout.tv_usec = 0; ptimeout = &timeout; /* If we've already set the time, then * check to see if it's time to try and * update it. */ if (NextTimeUpdate != 0) { current_time = time(NULL); if (current_time < NextTimeUpdate) { /* Set the select() timeout to wake us * up when it's time to send more * requests. */ timeout.tv_sec = (SNTP_WAITPERIOD > (NextTimeUpdate - current_time)? (NextTimeUpdate - current_time):SNTP_WAITPERIOD); } else { /* It's already time for us to update our time */ NextTimeUpdate = 0; } } /* If we need to update our time and we have * a list of NTP servers, then send out some * time requests. */ if (NextTimeUpdate == 0 && (sntp_num_servers > 0)) { /* Send an NTP request to each NTP server * in our server list. Use version 3 * for v3 and v4 compatibility. */ memset(&ntp_pkt, 0, sizeof(ntp_pkt)); ntp_pkt.Control = NTP_LI_NOLEAP | NTP_MODE_SET(NTP_MODE_CLIENT) | NTP_VERSION_SET(3); /* Send a request packet to each of our * configured servers. */ cyg_mutex_lock(&sntp_mutex); for (i = 0; i < sntp_num_servers; i++) { /* Send the request packet using the * appropriate protocol. */ ntp_pkt.TransmitTimestamp.Seconds = htonl(TIME_LOCAL_TO_NTP(time(NULL))); if (sntp_servers[i].sa_family == AF_INET) { sendto(fd, &ntp_pkt, sizeof(ntp_pkt), 0, &sntp_servers[i], sntp_servers[i].sa_len);#ifdef CYGPKG_NET_INET6 } else if (sntp_servers[i].sa_family == AF_INET6) { sendto(fd6, &ntp_pkt, sizeof(ntp_pkt), 0, &sntp_servers[i], sntp_servers[i].sa_len);#endif } } cyg_mutex_unlock(&sntp_mutex); /* Set the NextTimeUpdate so that we don't * send any more requests until the next * poll period. And we've already configured * the select() timeout above to wait for * replies. */ NextTimeUpdate = time(NULL) + SNTP_WAITPERIOD; }#endif /* CYGPKG_NET_SNTP_UNICAST */ ret = select(n+1, &readfds, NULL, NULL, ptimeout); CYG_ASSERT(-1 != ret, "Select");#ifdef CYGPKG_NET_SNTP_UNICAST /* If we timed out, then try resending requests */ if (ret == 0) continue;#endif /* CYGPKG_NET_SNTP_UNICAST */ len = sizeof(new_srv.addr); if (FD_ISSET(fd,&readfds)) { ret=recvfrom(fd,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); }#ifdef CYGPKG_NET_INET6 if (FD_ISSET(fd6,&readfds)) { ret=recvfrom(fd6,&ntp_pkt,sizeof(ntp_pkt),0,(struct sockaddr *)&new_srv.addr,&len); }#endif CYG_ASSERT(0 < ret,"recvfrom"); /* We expect at least enough bytes to fill the buffer */ if (ret < NTP_PACKET_MINLEN) continue; new_srv.version = NTP_VERSION_GET(&ntp_pkt); new_srv.stratum = ntp_pkt.Stratum; new_srv.timestamp = ntohl(ntp_pkt.TransmitTimestamp.Seconds); mode = NTP_MODE_GET(&ntp_pkt); /* Only support protocol versions 3 or 4 */ if (new_srv.version < 3 || new_srv.version > 4) { CYG_TRACE1(1, "Unsupported version of NTP. Version %d",new_srv.version); continue; } /* Only process broadcast and server packets */ if (mode != NTP_MODE_BROADCAST && mode != NTP_MODE_SERVER) continue; /* Is the packet from a better server than our current one */ if (is_better(&new_srv,&best_srv)) { best_srv = new_srv; /* Work out the difference between server and our time. * TODO: Implement RFC2030 recommendations for * calculating propagation delay between the client * and server. */ new_time = TIME_NTP_TO_LOCAL(best_srv.timestamp); current_time = time(NULL); diff = current_time - new_time; if (diff < 0) diff = -diff; if (diff > 2) cyg_libc_time_settime(new_time); }#ifdef CYGPKG_NET_SNTP_UNICAST NextTimeUpdate = time(NULL) + SNTP_UPDATEPERIOD;#endif }}/* Start the SNTP server */void cyg_sntp_start(void) { static char sntp_stack[CYGNUM_SNTP_STACK_SIZE]; static cyg_thread sntp_thread_data; static cyg_handle_t sntp_handle; /* Only initialize things once */ if (sntp_initialized) return; sntp_initialized = 1;#ifdef CYGPKG_NET_SNTP_UNICAST /* Initialize the SNTP mutex */ cyg_mutex_init(&sntp_mutex);#endif cyg_thread_create(CYGPKG_NET_THREAD_PRIORITY+1, sntp_fn, // entry 0, // entry parameter "SNTP Client", // Name &sntp_stack, // stack sizeof(sntp_stack), // stack size &sntp_handle, // Handle &sntp_thread_data); // Thread data structure cyg_thread_resume(sntp_handle);}#ifdef CYGPKG_NET_SNTP_UNICAST/* * FUNCTION cyg_sntp_set_servers * * DESCRIPTION * Sets the list of SNTP/NTP servers to use * for SNTP unicast requests. The list is * specified as a list of sockaddr structures * and can contain both IPv4 and IPv6 * addresses and UDP port numbers. * * The server_list array must be maintained * by the caller and must not be modified after * it is registered by this function. The * array can be unregistered by calling this * function again with different parameters. * * NOTE: If cyg_sntp_start() has not been called * already, and this function is called with a * list of 1 or more servers, then cyg_sntp_start() * will be called by this function to start the client. * * PARAMETERS * server_list - Array of IPv4 and/or IPv6 sockaddr's * num_servers - Number of sockaddr's in array (0 to disable) * * RETURN VALUES * None */void cyg_sntp_set_servers(struct sockaddr *server_list, cyg_uint32 num_servers){ /* If we haven't already started the SNTP client, then * start it now. */ if (!sntp_initialized) { /* If we haven't started already and we don't * have a list of servers, then don't start * anything up. */ if (num_servers == 0) return; cyg_sntp_start(); } /* Get the server list mutex */ cyg_mutex_lock(&sntp_mutex); /* Record the new server list */ sntp_num_servers = num_servers; if (num_servers == 0) { server_list = NULL; } else { /* reset the waiting time to force a new update <= SNTP_WAITPERIOD*/ NextTimeUpdate = 0; } sntp_servers = server_list; /* Free the mutex */ cyg_mutex_unlock(&sntp_mutex);}#endif /* CYGPKG_NET_SNTP_UNICAST */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?