📄 sntpclib.c
字号:
sntpSocket = socket (AF_INET, SOCK_DGRAM, 0); if (sntpSocket == -1) return (ERROR); /* * Enable broadcast option for socket in case that address is given. * This use of the SNTP client is not likely, so ignore errors. If * the broadcast address is used, and this call fails, the error will * be caught by sendto() below. */ optval = 1; result = setsockopt (sntpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof (optval)); /* Initialize SNTP message buffers. */ bzero ( (char *)&sntpRequest, sizeof (sntpRequest)); bzero ( (char *)&sntpReply, sizeof (sntpReply)); sntpRequest.leapVerMode = SNTP_CLIENT_REQUEST; bzero ( (char *) &servAddr, sizeof (servAddr)); servAddrLen = sizeof (servAddr); /* Transmit SNTP request. */ if (sendto (sntpSocket, (caddr_t)&sntpRequest, sizeof(sntpRequest), 0, (struct sockaddr *)&dstAddr, sizeof (dstAddr)) == -1) { close (sntpSocket); return (ERROR); } /* Convert timeout value to format needed by select() call. */ if (timeout != WAIT_FOREVER) { clockRate = sysClkRateGet (); sockTimeout.tv_sec = timeout / clockRate; sockTimeout.tv_usec = (1000000 * timeout % clockRate) / clockRate; } /* Wait for reply at the ephemeral port selected by the sendto () call. */ FD_ZERO (&readFds); FD_SET (sntpSocket, &readFds); if (timeout == WAIT_FOREVER) result = select (FD_SETSIZE, &readFds, NULL, NULL, NULL); else result = select (FD_SETSIZE, &readFds, NULL, NULL, &sockTimeout); if (result == -1) { close (sntpSocket); return (ERROR); } if (result == 0) /* Timeout interval expired. */ { close (sntpSocket); errnoSet (S_sntpcLib_TIMEOUT); return (ERROR); } result = recvfrom (sntpSocket, (caddr_t)&sntpReply, sizeof (sntpReply), 0, (struct sockaddr *)&servAddr, &servAddrLen); if (result == -1) { close (sntpSocket); return (ERROR); } close (sntpSocket); /* * Return error if the server clock is unsynchronized, or the version is * not supported. */ if ( (sntpReply.leapVerMode & SNTP_LI_MASK) == SNTP_LI_3 || sntpReply.transmitTimestampSec == 0) { errnoSet (S_sntpcLib_SERVER_UNSYNC); return (ERROR); } if ( (sntpReply.leapVerMode & SNTP_VN_MASK) == SNTP_VN_0 || (sntpReply.leapVerMode & SNTP_VN_MASK) > SNTP_VN_3) { errnoSet (S_sntpcLib_VERSION_UNSUPPORTED); return (ERROR); } /* Convert the NTP timestamp to the correct format and store in clock. */ /* Add test for 2036 base value here! */ sntpReply.transmitTimestampSec = ntohl (sntpReply.transmitTimestampSec) - SNTP_UNIX_OFFSET; /* * Adjust returned value if leap seconds are present. * This needs work! */ /* if ( (sntpReply.leapVerMode & SNTP_LI_MASK) == SNTP_LI_1) sntpReply.transmitTimestampSec += 1; else if ((sntpReply.leapVerMode & SNTP_LI_MASK) == SNTP_LI_2) sntpReply.transmitTimestampSec -= 1; */ sntpReply.transmitTimestampFrac = ntohl (sntpReply.transmitTimestampFrac); pCurrTime->tv_sec = sntpReply.transmitTimestampSec; pCurrTime->tv_nsec = sntpcFractionToNsec (sntpReply.transmitTimestampFrac); return (OK); }/********************************************************************************* sntpcListen - retrieve the time from an SNTP/NTP broadcast** This routine listens to the SNTP/NTP port for a valid message from any * SNTP/NTP server executing in broadcast mode, converts the returned NTP * timestamp to the POSIX-compliant clock format with the UNIX base value* (elapsed time since 00:00 GMT on January 1, 1970), and stores the result in * the location indicated by <pTime>.* * RETURNS: OK, or ERROR if unsuccessful.** ERRNO:* S_sntpcLib_TIMEOUT** NOMANUAL*/LOCAL STATUS sntpcListen ( u_int timeout, /* timeout in ticks */ struct timespec * pCurrTime /* storage for retrieved time value */ ) { SNTP_PACKET sntpMessage; /* buffer for message from server */ struct sockaddr_in srcAddr; int sntpSocket; struct timeval sockTimeout; int clockRate; fd_set readFds; int result; int srcAddrLen; /* Initialize source address. */ bzero ( (char *)&srcAddr, sizeof (srcAddr)); srcAddr.sin_addr.s_addr = INADDR_ANY; srcAddr.sin_family = AF_INET; srcAddr.sin_port = sntpcPort; /* Create socket for listening. */ sntpSocket = socket (AF_INET, SOCK_DGRAM, 0); if (sntpSocket == -1) return (ERROR); result = bind (sntpSocket, (struct sockaddr *)&srcAddr, sizeof (srcAddr)); if (result == -1) { close (sntpSocket); return (ERROR); } /* Convert timeout value to format needed by select() call. */ if (timeout != WAIT_FOREVER) { clockRate = sysClkRateGet (); sockTimeout.tv_sec = timeout / clockRate; sockTimeout.tv_usec = (1000000 * timeout % clockRate) / clockRate; } /* Wait for broadcast message from server. */ FD_ZERO (&readFds); FD_SET (sntpSocket, &readFds); if (timeout == WAIT_FOREVER) result = select (FD_SETSIZE, &readFds, NULL, NULL, NULL); else result = select (FD_SETSIZE, &readFds, NULL, NULL, &sockTimeout); if (result == -1) { close (sntpSocket); errnoSet (S_sntpcLib_TIMEOUT); return (ERROR); } if (result == 0) /* Timeout interval expired. */ { close (sntpSocket); errnoSet (S_sntpcLib_TIMEOUT); return (ERROR); } result = recvfrom (sntpSocket, (caddr_t) &sntpMessage, sizeof(sntpMessage), 0, (struct sockaddr *) &srcAddr, &srcAddrLen); if (result == -1) { close (sntpSocket); return (ERROR); } close (sntpSocket); /* * Return error if the server clock is unsynchronized, or the version is * not supported. */ if ( (sntpMessage.leapVerMode & SNTP_LI_MASK) == SNTP_LI_3 || sntpMessage.transmitTimestampSec == 0) { errnoSet (S_sntpcLib_SERVER_UNSYNC); return (ERROR); } if ( (sntpMessage.leapVerMode & SNTP_VN_MASK) == SNTP_VN_0 || (sntpMessage.leapVerMode & SNTP_VN_MASK) > SNTP_VN_3) { errnoSet (S_sntpcLib_VERSION_UNSUPPORTED); return (ERROR); } /* Convert the NTP timestamp to the correct format and store in clock. */ /* Add test for 2036 base value here! */ sntpMessage.transmitTimestampSec = ntohl (sntpMessage.transmitTimestampSec) - SNTP_UNIX_OFFSET; /* * Adjust returned value if leap seconds are present. * This needs work! */ /* if ( (sntpReply.leapVerMode & SNTP_LI_MASK) == SNTP_LI_1) sntpReply.transmitTimestampSec += 1; else if ((sntpReply.leapVerMode & SNTP_LI_MASK) == SNTP_LI_2) sntpReply.transmitTimestampSec -= 1; */ sntpMessage.transmitTimestampFrac = ntohl (sntpMessage.transmitTimestampFrac); pCurrTime->tv_sec = sntpMessage.transmitTimestampSec; pCurrTime->tv_nsec = sntpcFractionToNsec (sntpMessage.transmitTimestampFrac); return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -