⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 refclock_acts.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 2 页
字号:
	 */	case 1:		if (*str == '*' && up->msgcnt > 0) 			break;		return;		/*	 * ACTS format: "jjjjj yy-mm-dd hh:mm:ss ds l uuu aaaaa	 * UTC(NIST) *"	 */	case LENACTS:		if (sscanf(str,		    "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %9s %c",		    &mjd, &pp->year, &month, &day, &pp->hour,		    &pp->minute, &pp->second, &dst, &leap, &dut1,		    &msADV, utc, &flag) != 13) {			refclock_report(peer, CEVNT_BADREPLY);			return;		}		/*		 * Wait until ACTS has calculated the roundtrip delay.		 * We don't need to do anything, as ACTS adjusts the		 * on-time epoch.		 */		if (flag != '#')			return;		pp->day = ymd2yd(pp->year, month, day);		pp->leap = LEAP_NOWARNING;		if (leap == 1)	    		pp->leap = LEAP_ADDSECOND;		else if (pp->leap == 2)	    		pp->leap = LEAP_DELSECOND;		memcpy(&pp->refid, REFACTS, 4);		if (up->msgcnt == 0)			record_clock_stats(&peer->srcadr, str);		up->msgcnt++;		break;	/*	 * USNO format: "jjjjj nnn hhmmss UTC"	 */	case LENUSNO:		if (sscanf(str, "%5ld %3d %2d%2d%2d %3s",		    &mjd, &pp->day, &pp->hour, &pp->minute,		    &pp->second, utc) != 6) {			refclock_report(peer, CEVNT_BADREPLY);			return;		}		/*		 * Wait for the on-time character, which follows in a		 * separate message. There is no provision for leap		 * warning.		 */		pp->leap = LEAP_NOWARNING;		memcpy(&pp->refid, REFUSNO, 4);		if (up->msgcnt == 0)			record_clock_stats(&peer->srcadr, str);		up->msgcnt++;		return;	/*	 * PTB/NPL format: "yyyy-mm-dd hh:mm:ss MEZ" 	 */	case LENPTB:		if (sscanf(str,		    "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c",		    &pp->second, &pp->year, &month, &day, &pp->hour,		    &pp->minute, &mjd, &dut1, &leapdir, &leapmonth,		    &msADV, &flag) != 12) {			refclock_report(peer, CEVNT_BADREPLY);			return;		}		pp->leap = LEAP_NOWARNING;		if (leapmonth == month) {			if (leapdir == '+')		    		pp->leap = LEAP_ADDSECOND;			else if (leapdir == '-')		    		pp->leap = LEAP_DELSECOND;		}		pp->day = ymd2yd(pp->year, month, day);		memcpy(&pp->refid, REFPTB, 4);		if (up->msgcnt == 0)			record_clock_stats(&peer->srcadr, str);		up->msgcnt++;		break;	/*	 * WWVB format 0: "I  ddd hh:mm:ss DTZ=nn"	 */	case LENWWVB0:		if (sscanf(str, "%c %3d %2d:%2d:%2d %cTZ=%2d",		    &synchar, &pp->day, &pp->hour, &pp->minute,		    &pp->second, &dstchar, &tz) != 7) {			refclock_report(peer, CEVNT_BADREPLY);			return;		}		pp->leap = LEAP_NOWARNING;		if (synchar != ' ')			pp->leap = LEAP_NOTINSYNC;		memcpy(&pp->refid, REFWWVB, 4);		if (up->msgcnt == 0)			record_clock_stats(&peer->srcadr, str);		up->msgcnt++;		break;	/*	 * WWVB format 2: "IQyy ddd hh:mm:ss.mmm LD"	 */	case LENWWVB2:		if (sscanf(str, "%c%c%2d %3d %2d:%2d:%2d.%3ld%c%c%c",		    &synchar, &qualchar, &pp->year, &pp->day,		    &pp->hour, &pp->minute, &pp->second, &pp->nsec,		    &dstchar, &leapchar, &dstchar) != 11) {			refclock_report(peer, CEVNT_BADREPLY);			return;		}		pp->nsec *= 1000000;		pp->leap = LEAP_NOWARNING;		if (synchar != ' ')			pp->leap = LEAP_NOTINSYNC;		else if (leapchar == 'L')			pp->leap = LEAP_ADDSECOND;		memcpy(&pp->refid, REFWWVB, 4);		if (up->msgcnt == 0)			record_clock_stats(&peer->srcadr, str);		up->msgcnt++;		break;	/*	 * None of the above. Just forget about it and wait for the next	 * message or timeout.	 */	default:		return;	}	/*	 * We have a valid timecode. The fudge time1 value is added to	 * each sample by the main line routines. Note that in current	 * telephone networks the propatation time can be different for	 * each call and can reach 200 ms for some calls.	 */	peer->refid = pp->refid;	pp->lastrec = up->tstamp;	if (!refclock_process(pp)) {		refclock_report(peer, CEVNT_BADTIME);		return;			}	pp->lastref = pp->lastrec;	if (peer->disp > MAXDISTANCE)		refclock_receive(peer);	if (up->state != S_MSG) {		up->state = S_MSG;		up->timer = TIMECODE;	}}/* * acts_poll - called by the transmit routine */static voidacts_poll (	int	unit,	struct peer *peer	){	struct actsunit *up;	struct refclockproc *pp;	/*	 * This routine is called at every system poll. All it does is	 * set flag1 under certain conditions. The real work is done by	 * the timeout routine and state machine.	 */	pp = peer->procptr;	up = (struct actsunit *)pp->unitptr;	switch (peer->ttl) {	/*	 * In manual mode the calling program is activated by the ntpdc	 * program using the enable flag (fudge flag1), either manually	 * or by a cron job.	 */	case MODE_MANUAL:		/* fall through */		break;	/*	 * In automatic mode the calling program runs continuously at	 * intervals determined by the poll event or specified timeout.	 */	case MODE_AUTO:		pp->sloppyclockflag |= CLK_FLAG1;		break;	/*	 * In backup mode the calling program runs continuously as long	 * as either no peers are available or this peer is selected.	 */	case MODE_BACKUP:		if (sys_peer == NULL || sys_peer == peer)			pp->sloppyclockflag |= CLK_FLAG1;		break;	}}/* * acts_timer - called at one-second intervals */static voidacts_timer(	int	unit,	struct peer *peer	){	struct actsunit *up;	struct refclockproc *pp;	/*	 * This routine implments a timeout which runs for a programmed	 * interval. The counter is initialized by the state machine and	 * counts down to zero. Upon reaching zero, the state machine is	 * called. If flag1 is set while in S_IDLE state, force a	 * timeout.	 */	pp = peer->procptr;	up = (struct actsunit *)pp->unitptr;	if (pp->sloppyclockflag & CLK_FLAG1 && up->state == S_IDLE) {		acts_timeout(peer);		return;	}	if (up->timer == 0)		return;	up->timer--;	if (up->timer == 0)		acts_timeout(peer);}/* * acts_timeout - called on timeout */static voidacts_timeout(	struct peer *peer	){	struct actsunit *up;	struct refclockproc *pp;	int	fd;	char	device[20];	char	lockfile[128], pidbuf[8];	char	tbuf[BMAX];	/*	 * The state machine is driven by messages from the modem, when	 * first stated and at timeout.	 */	pp = peer->procptr;	up = (struct actsunit *)pp->unitptr;	pp->sloppyclockflag &= ~CLK_FLAG1;	if (sys_phone[up->retry] == NULL && !(pp->sloppyclockflag &	    CLK_FLAG3)) {		msyslog(LOG_ERR, "acts: no phones");		return;	}	switch(up->state) {	/*	 * System poll event. Lock the modem port and open the device.	 */	case S_IDLE:		/*		 * Lock the modem port. If busy, retry later. Note: if		 * something fails between here and the close, the lock		 * file may not be removed.		 */		if (pp->sloppyclockflag & CLK_FLAG2) {			sprintf(lockfile, LOCKFILE, up->unit);			fd = open(lockfile, O_WRONLY | O_CREAT | O_EXCL,			    0644);			if (!fd) {				msyslog(LOG_ERR, "acts: port busy");				return;			}			sprintf(pidbuf, "%d\n", (u_int)getpid());			write(fd, pidbuf, strlen(pidbuf));			close(fd);		}		/*		 * Open the device in raw mode and link the I/O.		 */		if (!pp->io.fd) {			sprintf(device, DEVICE, up->unit);			fd = refclock_open(device, SPEED232,			    LDISC_ACTS | LDISC_RAW | LDISC_REMOTE);			if (fd == 0) {				return;			}			pp->io.fd = fd;			if (!io_addclock(&pp->io)) {				msyslog(LOG_ERR,				    "acts: addclock fails");				close(fd);				pp->io.fd = 0;				return;			}		}		/*		 * If the port is directly connected to the device, skip		 * the modem business and send 'T' for Spectrabum.		 */		if (pp->sloppyclockflag & CLK_FLAG3) {			if (write(pp->io.fd, "T", 1) < 0) {				msyslog(LOG_ERR, "acts: write %m");				return;			}			up->state = S_FIRST;			up->timer = CONNECT;			return;		}		/*		 * Initialize the modem. This works with Hayes commands.		 */#ifdef DEBUG		if (debug)			printf("acts: setup %s\n", MODEM_SETUP);#endif		if (write(pp->io.fd, MODEM_SETUP, strlen(MODEM_SETUP)) <		    0) {			msyslog(LOG_ERR, "acts: write %m");			return;		}		up->state = S_OK;		up->timer = SETUP;		return;	/*	 * In OK state the modem did not respond to setup.	 */	case S_OK:		msyslog(LOG_ERR, "acts: no modem");		break;	/*	 * In DTR state we are waiting for the modem to settle down	 * before hammering it with a dial command.	 */	case S_DTR:		sprintf(tbuf, "DIAL #%d %s", up->retry,		    sys_phone[up->retry]);		record_clock_stats(&peer->srcadr, tbuf);#ifdef DEBUG		if (debug)			printf("%s\n", tbuf);#endif		write(pp->io.fd, sys_phone[up->retry],		    strlen(sys_phone[up->retry]));		write(pp->io.fd, "\r", 1);		up->state = S_CONNECT;		up->timer = ANSWER;		return;	/*	 * In CONNECT state the call did not complete.	 */	case S_CONNECT:		msyslog(LOG_ERR, "acts: no answer");		break;	/*	 * In FIRST state no messages were received.	 */	case S_FIRST:		msyslog(LOG_ERR, "acts: no messages");		break;	/*	 * In CLOSE state hangup is complete. Close the doors and	 * windows and get some air.	 */	case S_CLOSE:		/*		 * Close the device and unlock a shared modem.		 */		if (pp->io.fd) {			io_closeclock(&pp->io);			close(pp->io.fd);			if (pp->sloppyclockflag & CLK_FLAG2) {				sprintf(lockfile, LOCKFILE, up->unit);				unlink(lockfile);			}			pp->io.fd = 0;		}		/*		 * If messages were received, fold the tent and wait for		 * the next poll. If no messages and there are more		 * numbers to dial, retry after a short wait.		 */		up->bufptr = pp->a_lastcode;		up->timer = 0;		up->state = S_IDLE;		if ( up->msgcnt == 0) {			up->retry++;			if (sys_phone[up->retry] == NULL)				up->retry = 0;			else				up->timer = SETUP;		} else {			up->retry = 0;		}		up->msgcnt = 0;		return;	}	acts_disc(peer);}/* * acts_disc - disconnect the call and clean the place up. */static voidacts_disc (	struct peer *peer	){	struct actsunit *up;	struct refclockproc *pp;	int	dtr = TIOCM_DTR;	/*	 * We get here if the call terminated successfully or if an	 * error occured. If the median filter has something in it,feed	 * the data to the clock filter. If a modem port, drop DTR to	 * force command mode and send modem hangup.	 */	pp = peer->procptr;	up = (struct actsunit *)pp->unitptr;	if (up->msgcnt > 0)		refclock_receive(peer);	if (!(pp->sloppyclockflag & CLK_FLAG3)) {		ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);		write(pp->io.fd, MODEM_HANGUP, strlen(MODEM_HANGUP));	}	up->timer = SETUP;	up->state = S_CLOSE;}#elseint refclock_acts_bs;#endif /* REFCLOCK */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -