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

📄 refclock_arc.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Compute space left in buffer after any pending output. */	for(spaceleft = 0; spaceleft < CMDQUEUELEN; ++spaceleft)	{ if(up->cmdqueue[CMDQUEUELEN - 1 - spaceleft] != '\0') { break; } }	return(spaceleft);}/*Send command by copying into command buffer as far forward as possible,after any pending output.Indicate an error by returning 0 if there is not space for the command.*/static intsend_slow(	register struct arcunit *up,	int fd,	const char *s	){	int sl = strlen(s);	int spaceleft = space_left(up);#ifdef DEBUG	if(debug > 1) { printf("arc: spaceleft = %d.\n", spaceleft); }#endif	if(spaceleft < sl) { /* Should not normally happen... */#ifdef DEBUG		msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)",		       sl, spaceleft);#endif		return(0);                      /* FAILED! */	}	/* Copy in the command to be sent. */	while(*s) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; }	return(1);}static intget2(char *p, int *val){  if (!isdigit((int)p[0]) || !isdigit((int)p[1])) return 0;  *val = (p[0] - '0') * 10 + p[1] - '0';  return 1;}static intget1(char *p, int *val){  if (!isdigit((int)p[0])) return 0;  *val = p[0] - '0';  return 1;}/* Macro indicating action we will take for different quality values. */#define quality_action(q) \(((q) == QUALITY_UNKNOWN) ?         "UNKNOWN, will use clock anyway" : \ (((q) < MIN_CLOCK_QUALITY_OK) ? "TOO POOR, will not use clock" : \  "OK, will use clock"))     /* * arc_receive - receive data from the serial interface */     static voidarc_receive(	struct recvbuf *rbufp	){	register struct arcunit *up;	struct refclockproc *pp;	struct peer *peer;	char c;	int i, n, wday, month, flags, status;	int arc_last_offset;	static int quality_average = 0;	static int quality_sum = 0;	static int quality_polls = 0;	/*	 * Initialize pointers and read the timecode and timestamp	 */	peer = (struct peer *)rbufp->recv_srcclock;	pp = peer->procptr;	up = (struct arcunit *)pp->unitptr;	/*	  If the command buffer is empty, and we are resyncing, insert a	  g\r quality request into it to poll for signal quality again.	*/	if((up->resyncing) && (space_left(up) == CMDQUEUELEN)) {#ifdef DEBUG		if(debug > 1) { printf("arc: inserting signal-quality poll.\n"); }#endif		send_slow(up, pp->io.fd, "g\r");	}	/*	  The `arc_last_offset' is the offset in lastcode[] of the last byte	  received, and which we assume actually received the input	  timestamp.	  (When we get round to using tty_clk and it is available, we	  assume that we will receive the whole timecode with the	  trailing \r, and that that \r will be timestamped.  But this	  assumption also works if receive the characters one-by-one.)	*/	arc_last_offset = pp->lencode+rbufp->recv_length - 1;	/*	  We catch a timestamp iff:	  * The command code is `o' for a timestamp.	  * If ARCRON_MULTIPLE_SAMPLES is undefined then we must have	  exactly char in the buffer (the command code) so that we	  only sample the first character of the timecode as our	  `on-time' character.	  * The first character in the buffer is not the echoed `\r'	  from the `o` command (so if we are to timestamp an `\r' it	  must not be first in the receive buffer with lencode==1.	  (Even if we had other characters following it, we probably	  would have a premature timestamp on the '\r'.)	  * We have received at least one character (I cannot imagine	  how it could be otherwise, but anyway...).	*/	c = rbufp->recv_buffer[0];	if((pp->a_lastcode[0] == 'o') &&#ifndef ARCRON_MULTIPLE_SAMPLES	   (pp->lencode == 1) &&#endif	   ((pp->lencode != 1) || (c != '\r')) &&	   (arc_last_offset >= 1)) {		/* Note that the timestamp should be corrected if >1 char rcvd. */		l_fp timestamp;		timestamp = rbufp->recv_time;#ifdef DEBUG		if(debug) { /* Show \r as `R', other non-printing char as `?'. */			printf("arc: stamp -->%c<-- (%d chars rcvd)\n",			       ((c == '\r') ? 'R' : (isgraph((int)c) ? c : '?')),			       rbufp->recv_length);		}#endif		/*		  Now correct timestamp by offset of last byte received---we		  subtract from the receive time the delay implied by the		  extra characters received.		  Reject the input if the resulting code is too long, but		  allow for the trailing \r, normally not used but a good		  handle for tty_clk or somesuch kernel timestamper.		*/		if(arc_last_offset > LENARC) {#ifdef DEBUG			if(debug) {				printf("arc: input code too long (%d cf %d); rejected.\n",				       arc_last_offset, LENARC);			}#endif			pp->lencode = 0;			refclock_report(peer, CEVNT_BADREPLY);			return;		}		L_SUBUF(&timestamp, charoffsets[arc_last_offset]);#ifdef DEBUG		if(debug > 1) {			printf(				"arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n",				((rbufp->recv_length > 1) ? "*** " : ""),				rbufp->recv_length,				arc_last_offset,				mfptoms((unsigned long)0,					charoffsets[arc_last_offset],					1));		}#endif#ifdef ARCRON_MULTIPLE_SAMPLES		/*		  If taking multiple samples, capture the current adjusted		  sample iff:		  * No timestamp has yet been captured (it is zero), OR		  * This adjusted timestamp is earlier than the one already		  captured, on the grounds that this one suffered less		  delay in being delivered to us and is more accurate.		*/		if(L_ISZERO(&(up->lastrec)) ||		   L_ISGEQ(&(up->lastrec), &timestamp))#endif		{#ifdef DEBUG			if(debug > 1) {				printf("arc: system timestamp captured.\n");#ifdef ARCRON_MULTIPLE_SAMPLES				if(!L_ISZERO(&(up->lastrec))) {					l_fp diff;					diff = up->lastrec;					L_SUB(&diff, &timestamp);					printf("arc: adjusted timestamp by -%sms.\n",					       mfptoms(diff.l_i, diff.l_f, 3));				}#endif			}#endif			up->lastrec = timestamp;		}	}	/* Just in case we still have lots of rubbish in the buffer... */	/* ...and to avoid the same timestamp being reused by mistake, */	/* eg on receipt of the \r coming in on its own after the      */	/* timecode.                                                   */	if(pp->lencode >= LENARC) {#ifdef DEBUG		if(debug && (rbufp->recv_buffer[0] != '\r'))		{ printf("arc: rubbish in pp->a_lastcode[].\n"); }#endif		pp->lencode = 0;		return;	}	/* Append input to code buffer, avoiding overflow. */	for(i = 0; i < rbufp->recv_length; i++) {		if(pp->lencode >= LENARC) { break; } /* Avoid overflow... */		c = rbufp->recv_buffer[i];		/* Drop trailing '\r's and drop `h' command echo totally. */		if(c != '\r' && c != 'h') { pp->a_lastcode[pp->lencode++] = c; }		/*		  If we've just put an `o' in the lastcode[0], clear the		  timestamp in anticipation of a timecode arriving soon.		  We would expect to get to process this before any of the		  timecode arrives.		*/		if((c == 'o') && (pp->lencode == 1)) {			L_CLR(&(up->lastrec));#ifdef DEBUG			if(debug > 1) { printf("arc: clearing timestamp.\n"); }#endif		}	}	if (pp->lencode == 0) return;	/* Handle a quality message. */	if(pp->a_lastcode[0] == 'g') {		int r, q;		if(pp->lencode < 3) { return; } /* Need more data... */		r = (pp->a_lastcode[1] & 0x7f); /* Strip parity. */		q = (pp->a_lastcode[2] & 0x7f); /* Strip parity. */		if(((q & 0x70) != 0x30) || ((q & 0xf) > MAX_CLOCK_QUALITY) ||		   ((r & 0x70) != 0x30)) {			/* Badly formatted response. */#ifdef DEBUG			if(debug) { printf("arc: bad `g' response %2x %2x.\n", r, q); }#endif			return;		}		if(r == '3') { /* Only use quality value whilst sync in progress. */			if (up->quality_stamp < current_time) {				struct calendar cal;				l_fp new_stamp;							get_systime (&new_stamp);				caljulian (new_stamp.l_ui, &cal);				up->quality_stamp = 					current_time + 60 - cal.second + 5;				quality_sum = 0;				quality_polls = 0;			}			quality_sum += (q & 0xf);			quality_polls++;			quality_average = (quality_sum / quality_polls);#ifdef DEBUG			if(debug) { printf("arc: signal quality %d (%d).\n", quality_average, (q & 0xf)); }#endif		} else if( /* (r == '2') && */ up->resyncing) {			up->quality = quality_average;#ifdef DEBUG			if(debug)			{				printf("arc: sync finished, signal quality %d: %s\n",				       up->quality,				       quality_action(up->quality));			}#endif			msyslog(LOG_NOTICE,			       "ARCRON: sync finished, signal quality %d: %s",			       up->quality,			       quality_action(up->quality));			up->resyncing = 0; /* Resync is over. */			quality_average = 0;			quality_sum = 0;			quality_polls = 0;#ifdef ARCRON_KEEN			/* Clock quality dubious; resync earlier than usual. */			if((up->quality == QUALITY_UNKNOWN) ||			   (up->quality < MIN_CLOCK_QUALITY_OK))			{ up->next_resync = current_time + RETRY_RESYNC_TIME; }#endif		}		pp->lencode = 0;		return;	}	/* Stop now if this is not a timecode message. */	if(pp->a_lastcode[0] != 'o') {		pp->lencode = 0;		refclock_report(peer, CEVNT_BADREPLY);		return;	}	/* If we don't have enough data, wait for more... */	if(pp->lencode < LENARC) { return; }	/* WE HAVE NOW COLLECTED ONE TIMESTAMP (phew)... */#ifdef DEBUG	if(debug > 1) { printf("arc: NOW HAVE TIMESTAMP...\n"); }#endif	/* But check that we actually captured a system timestamp on it. */	if(L_ISZERO(&(up->lastrec))) {#ifdef DEBUG		if(debug) { printf("arc: FAILED TO GET SYSTEM TIMESTAMP\n"); }#endif		pp->lencode = 0;		refclock_report(peer, CEVNT_BADREPLY);		return;	}	/*	  Append a mark of the clock's received signal quality for the	  benefit of Derek Mulcahy's Tcl/Tk utility (we map the `unknown'	  quality value to `6' for his s/w) and terminate the string for	  sure.  This should not go off the buffer end.	*/	pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ?				       '6' : ('0' + up->quality));	pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */#ifdef PRE_NTP420	/* We don't use the micro-/milli- second part... */	pp->usec = 0;	pp->msec = 0;#else	/* We don't use the nano-second part... */	pp->nsec = 0;#endif		/* Validate format and numbers. */	if (pp->a_lastcode[0] != 'o'		|| !get2(pp->a_lastcode + 1, &pp->hour)		|| !get2(pp->a_lastcode + 3, &pp->minute)		|| !get2(pp->a_lastcode + 5, &pp->second)		|| !get1(pp->a_lastcode + 7, &wday)		|| !get2(pp->a_lastcode + 8, &pp->day)		|| !get2(pp->a_lastcode + 10, &month)		|| !get2(pp->a_lastcode + 12, &pp->year)) {#ifdef DEBUG		/* Would expect to have caught major problems already... */		if(debug) { printf("arc: badly formatted data.\n"); }#endif		pp->lencode = 0;		refclock_report(peer, CEVNT_BADREPLY);		return;	}	flags = pp->a_lastcode[14];	status = pp->a_lastcode[15];#ifdef DEBUG	if(debug) { printf("arc: status 0x%.2x flags 0x%.2x\n", flags, status); }#endif	n = 9;	/*	  Validate received values at least enough to prevent internal	  array-bounds problems, etc.	*/	if((pp->hour < 0) || (pp->hour > 23) ||	   (pp->minute < 0) || (pp->minute > 59) ||	   (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ ||	   (wday < 1) || (wday > 7) ||

⌨️ 快捷键说明

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