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

📄 87

📁 Unix/Linux 网络时间协议版本3 Network Time Protocol Version 3 (NTP) distribution for Unix systems
💻
📖 第 1 页 / 共 4 页
字号:
		 * later than the receive time, which may cause a paranoid		 * protocol module to chuck out the data.		 */		mx4200_debug(peer, "mx4200_receive: process time: ");		mx4200_debug(peer, "%4d-%03d %02d:%02d:%02d at %s, %s\n",			pp->year, pp->day, pp->hour, pp->minute, pp->second,			prettydate(pp->lastrec), lfptoa(&pp->offset, 6));		refclock_receive(peer, &pp->offset, 0, pp->dispersion,			&pp->lastrec, &pp->lastrec, pp->leap);		/*		 * We have succeeded in answering the poll.		 * Turn off the flag and return		 */		up->polled = 0;		return;	}	/*	 * Ignore all other sentence types	 */	return;}/* * mx4200_offset - Calculate the offset, and add to the rolling filter. */static char *mx4200_offset(peer)	struct peer *peer;{	register struct mx4200unit *up;	struct refclockproc *pp;	register int i;	l_fp offset;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/*	 * Calculate the offset	 */	if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,		pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) {		return ("mx4200_process: clocktime failed");	}	if (pp->usec) {		TVUTOTSF(pp->usec, offset.l_uf);	} else {		MSUTOTSF(pp->msec, offset.l_uf);	}	L_ADD(&offset, &pp->fudgetime1);	up->lastref = offset;   /* save last reference time */	L_SUB(&offset, &pp->lastrec); /* form true offset */	/*	 * A rolling filter.  Initialize first time around.	 */	i = ((up->coderecv)) % NSAMPLES;	up->filter[i] = offset;	if (up->coderecv == 0)		for (i = 1; (u_int) i < NSAMPLES; i++)			up->filter[i] = up->filter[0];	up->coderecv++;	return (NULL);}/* * mx4200_process - process the sample from the clock, * passing it through a median filter and optionally averaging * the samples.  Returns offset and dispersion in "up" structure. */static char *mx4200_process(peer)	struct peer *peer;{	register struct mx4200unit *up;	struct refclockproc *pp;	register int i, n;	int j, k;	l_fp offset, median, lftmp;	u_fp disp;	l_fp off[NSAMPLES];	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	/*	 * Copy the raw offsets and sort into ascending order	 */	for (i = 0; i < NSAMPLES; i++)		off[i] = up->filter[i];	qsort((char *)off, NSAMPLES, sizeof(l_fp), mx4200_cmpl_fp);	/*	 * Reject the furthest from the median of NSAMPLES samples until	 * NKEEP samples remain.	 */	i = 0;	n = NSAMPLES;	while ((n - i) > up->nkeep) {		lftmp = off[n - 1];		median = off[(n + i) / 2];		L_SUB(&lftmp, &median);		L_SUB(&median, &off[i]);		if (L_ISHIS(&median, &lftmp)) {			/* reject low end */			i++;		} else {			/* reject high end */			n--;		}	}	/*	 * Copy key values to the billboard to measure performance.	 */	pp->lastref = up->lastref;	pp->coderecv = up->coderecv;	pp->nstages = up->nkeep + 2;	pp->filter[0] = off[0];			/* smallest offset */	pp->filter[1] = off[NSAMPLES-1];	/* largest offset */	for (j=2, k=i; k < n; j++, k++)		pp->filter[j] = off[k];		/* offsets actually examined */	/*	 * Compute the dispersion based on the difference between the	 * extremes of the remaining offsets. Add to this the time since	 * the last clock update, which represents the dispersion	 * increase with time. We know that NTP_MAXSKEW is 16. If the	 * sum is greater than the allowed sample dispersion, bail out.	 * If the loop is unlocked, return the most recent offset;	 * otherwise, return the median offset.	 */	lftmp = off[n - 1];	L_SUB(&lftmp, &off[i]);	disp = LFPTOFP(&lftmp);	if (disp > REFCLOCKMAXDISPERSE) {		return("Maximum dispersion exceeded");	}	/*	 * Now compute the offset estimate.  If the sloppy clock	 * flag 1 is set, average the remainder, otherwise pick the	 * median.	 */	if (pp->sloppyclockflag && CLK_FLAG1) {		L_CLR(&lftmp);		while (i < n) {			L_ADD(&lftmp, &off[i]);			i++;		}		i = up->rshift;		while (i > 0) {			L_RSHIFT(&lftmp);			i--;		}		offset = lftmp;	} else {		i = (n + i) / 2;		offset = off[i];	}	/*	 * The payload: filtered offset and dispersion.	 */	pp->offset = offset;	pp->dispersion = disp;	return(NULL);}/* Compare two l_fp's, used with qsort() */int#ifdef QSORT_USES_VOID_Pmx4200_cmpl_fp(p1, p2)	const void *p1, *p2;{	register const l_fp *fp1 = (const l_fp *)p1;	register const l_fp *fp2 = (const l_fp *)p2;#elsemx4200_cmpl_fp(fp1, fp2)	register const l_fp *fp1;	register const l_fp *fp2;{#endif /* not QSORT_USES_VOID_P */	if (!L_ISGEQ(fp1, fp2))		return (-1);	if (L_ISEQU(fp1, fp2))		return (0);	return (1);}/* * Parse a mx4200 time recovery message. Returns a string if error. * * A typical message looks like this.  Checksum has already been stripped. * *    $PMVXG,830,T,YYYY,MM,DD,HH:MM:SS,U,S,FFFFFF,PPPPP,BBBBBB,LL * *	Field	Field Contents *	-----	-------------- *		Block Label: $PMVXG *		Sentence Type: 830=Time Recovery Results *			This sentence is output approximately 1 second *			preceding the 1PPS output.  It indicates the *			exact time of the next pulse, whether or not the *			time mark will be valid (based on operator-specified *			error tolerance), the time to which the pulse is *			synchronized, the receiver operating mode, *			and the time error of the *last* 1PPS output. *	1	Time Mark Valid: T=Valid, F=Not Valid *	2	Year: 1993- *	3	Month of Year: 1-12 *	4	Day of Month: 1-31 *	5	Time of Day: HH:MM:SS *	6	Time Synchronization: U=UTC, G=GPS *	7	Time Recovery Mode: D=Dynamic, S=Static, *			K=Known Position, N=No Time Recovery *	8	Oscillator Offset: The filter's estimate of the oscillator *			frequency error, in parts per billion (ppb). *	9	Time Mark Error: The computed error of the *last* pulse *			output, in nanoseconds. *	10	User Time Bias: Operator specified bias, in nanoseconds *	11	Leap Second Flag: Indicates that a leap second will *			occur.  This value is usually zero, except during *			the week prior to the leap second occurence, when *			this value will be set to +1 or -1.  A value of *			+1 indicates that GPS time will be 1 second *			further ahead of UTC time. * */static char *mx4200_parse_t(peer)	struct peer *peer;{	struct refclockproc *pp;	struct mx4200unit *up;	int sentence_type, valid;	int year, yearday, month, monthday, hour, minute, second, leapsec;	char *cp;	pp = peer->procptr;	up = (struct mx4200unit *)pp->unitptr;	cp = pp->lastcode;	if ((cp = strchr(cp, ',')) == NULL)		return ("no rec-type");	cp++;	/* Sentence type */	sentence_type = strtol(cp, &cp, 10);	if (sentence_type != PMVXG_D_TRECOVOUT)		return ("wrong rec-type");	/* Pulse valid indicator */	if (*cp++ != ',')		return ("no pulse-valid");	if (*cp == 'T')		valid = 1;	else if (*cp == 'F')		valid = 0;	else		return ("bad pulse-valid");	cp++;	/* Year */	if (*cp++ != ',')		return ("no year");	year = strtol(cp, &cp, 10);	/* Month of year */	if (*cp++ != ',')		return ("no month");	month = strtol(cp, &cp, 10);	/* Day of month */	if (*cp++ != ',')		return ("no month day");	monthday = strtol(cp, &cp, 10);	/* Hour */	if (*cp++ != ',')		return ("no hour");	hour = strtol(cp, &cp, 10);	/* Minute */	if (*cp++ != ':')		return ("no minute");	minute = strtol(cp, &cp, 10);	/* Second */	if (*cp++ != ':')		return ("no second");	second = strtol(cp, &cp, 10);	/* Time indicator */	if (*cp++ != ',')		return ("no time indicator");	if (*cp == 'G')		return ("synchronized to GPS; should be UTC");	else if (*cp != 'U')		return ("not synchronized to UTC");	cp++;	/* Time recovery mode */	if (*cp++ != ',' || *cp++ == '\0')		return ("no time mode");	/* Oscillator offset */	if ((cp = strchr(cp, ',')) == NULL)		return ("no osc off");	cp++;	/* Time mark error */	/* (by request, always less than 0.5 usec (500 nsec), so ignore) */	if ((cp = strchr(cp, ',')) == NULL)		return ("no time mark err");	cp++;	/* User time bias */	/* (by request, always zero, so ignore */	if ((cp = strchr(cp, ',')) == NULL)		return ("no user bias");	cp++;	/* Leap second flag */	if ((cp = strchr(cp, ',')) == NULL)		return ("no leap");	cp++;	leapsec = strtol(cp, &cp, 10);	/*	 * Check for insane time (allow for possible leap seconds)	 */	if (second > 60 || minute > 59 || hour > 23 ||	    second <  0 || minute <  0 || hour <  0) {		mx4200_debug(peer,			"mx4200_parse_t: bad time %02d:%02d:%02d",			hour, minute, second);		if (leapsec != 0)			mx4200_debug(peer, " (leap %+d\n)", leapsec);		mx4200_debug(peer, "\n");		refclock_report(peer, CEVNT_BADTIME);		return ("bad time");	}	/*	 * Check for insane date	 */	if (monthday > 31 || month > 12 ||	    monthday <  1 || month <  1 || year < 1996) {		mx4200_debug(peer,			"mx4200_parse_t: bad date (%4d-%02d-%02d)\n",			year, month, monthday);		refclock_report(peer, CEVNT_BADDATE);		return;	}	/*	 * Silly Hack for MX4200:	 * ASCII message is for *next* 1PPS signal, but we have the	 * timestamp for the *last* 1PPS signal.  So we have to subtract	 * a second.  Discard if we are on a month boundary to avoid	 * possible leap seconds and leap days.	 */	second--;	if (second < 0) {		second = 59;		minute--;		if (minute < 0) {			minute = 59;			hour--;			if (hour < 0) {				hour = 23;				monthday--;				if (monthday < 1) {					return ("sorry, month boundary");				}			}		}	}	/*	 * Calculate Julian date	 */	if (!(yearday = mx4200_jday(year, month, monthday))) {		mx4200_debug(peer,			"mx4200_parse_t: bad julian date %d (%4d-%02d-%02d)\n",			yearday, year, month, monthday);		refclock_report(peer, CEVNT_BADDATE);		return("invalid julian date");	}	/*	 * Setup leap second indicator	 */	if (leapsec == 0)		pp->leap = LEAP_NOWARNING;	else if (leapsec == 1)		pp->leap = LEAP_ADDSECOND;	else if (leapsec == -1)		pp->leap = LEAP_DELSECOND;	else		pp->leap = LEAP_NOTINSYNC;	/* shouldn't happen */	/*	 * Copy time data for billboard monitoring.	 */	pp->year   = year;	pp->day    = yearday;	pp->hour   = hour;	pp->minute = minute;	pp->second = second;	pp->msec   = 0;	pp->usec   = 0;	/*	 * Toss if sentence is marked invalid	 */	if (!valid || pp->leap == LEAP_NOTINSYNC) {		mx4200_debug(peer, "mx4200_parse_t: time mark not valid\n");		refclock_report(peer, CEVNT_BADTIME);		return ("pulse invalid");	}	return (NULL);}/* * Calculate the checksum */static u_charmx4200_cksum(cp, n)	register char *cp;	register u_int n;{	register u_char ck;	for (ck = 0; n-- > 0; cp++)		ck ^= *cp;	return (ck);}/* * Tables to compute the day of year.  Viva la leap. */static day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};static day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};/* * Calculate the the Julian Day */static intmx4200_jday(year, month, monthday)	int year;	int month;	int monthday;{	register int day, i;	int leap_year;	/*	 * Is this a leap year ?	 */	if (year % 4) {		leap_year = 0; /* FALSE */	} else {		if (year % 100) {			leap_year = 1; /* TRUE */		} else {			if (year % 400) {				leap_year = 0; /* FALSE */			} else {				leap_year = 1; /* TRUE */			}		}	}	/*	 * Calculate the Julian Date	 */	day = monthday;	if (leap_year) {		/* a leap year */		if (day > day2tab[month - 1]) {			return (0);		}		for (i = 0; i < month - 1; i++)			day += day2tab[i];	} else {		/* not a leap year */		if (day > day1tab[month - 1]) {

⌨️ 快捷键说明

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