📄 144
字号:
refclock_report(peer, CEVNT_BADREPLY); return; } /* 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) || (pp->day < 1) || (pp->day > 31) || (month < 1) || (month > 12) || (pp->year < 0) || (pp->year > 99)) { /* Data out of range. */ refclock_report(peer, CEVNT_BADREPLY); return; } /* Check that BST/UTC bits are the complement of one another. */ if(!(bst & 2) == !(bst & 4)) { refclock_report(peer, CEVNT_BADREPLY); return; } if(status & 0x8) { syslog(LOG_NOTICE, "ARCRON: battery low"); } /* Year-2000 alert! */ /* Attempt to wrap 2-digit date into sensible window. */ /* This code was written in 1997, so that is the window start. */ if(pp->year < 97) { pp->year += 2000; } else /* if(pp->year < 100) */ { pp->year += 1900; } /* Attempt to do the right thing by screaming that the code will soon break when we get to the end of its useful life. What a hero I am... PLEASE FIX LEAP-YEAR AND WRAP CODE IN 209X! */ if(pp->year >= 2090) { /* This should get attention B^> */ syslog(LOG_NOTICE,"ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!"); } if(debug) { printf("arc: n=%d %02d:%02d:%02d %02d/%02d/%04d %1d %1d\n", n, pp->hour, pp->minute, pp->second, pp->day, month, pp->year, bst, status); } /* The status value tested for is not strictly supported by the clock spec since the value of bit 2 (0x4) is claimed to be undefined for MSF, yet does seem to indicate if the last resync was successful or not. */ pp->leap = LEAP_NOWARNING; status &= 0x7; if(status == 0x3) { pp->lasttime = current_time; if(status != up->status) { syslog(LOG_NOTICE, "ARCRON: signal acquired"); } } else { if(status != up->status) { syslog(LOG_NOTICE, "ARCRON: signal lost"); pp->leap = LEAP_NOTINSYNC; /* MSF clock is free-running. */ refclock_report(peer, CEVNT_FAULT); return; } } up->status = status; pp->day += moff[month - 1]; /* Good 'til 1st March 2100 */ if(((pp->year % 4) == 0) && month > 2) { pp->day++; } /* Convert to UTC if required */ if(bst & 2) { pp->hour--; if (pp->hour < 0) { pp->hour = 23; pp->day--; /* If we try to wrap round the year (BST on 1st Jan), reject.*/ if(pp->day < 0) { refclock_report(peer, CEVNT_BADTIME); return; } } } /* If clock signal quality is unknown, revert to default PRECISION...*/ if(up->quality == QUALITY_UNKNOWN) { peer->precision = PRECISION; } /* ...else improve precision if flag3 is set... */ else { peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? HIGHPRECISION : PRECISION); } /* Notice and log any change (eg from initial defaults) for flags. */ if(up->saved_flags != pp->sloppyclockflag) { syslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s", ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."), ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."), ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."), ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : ".")); up->saved_flags = pp->sloppyclockflag; /* Note effects of flags changing... */ if(debug) { printf("arc: CHOSENSAMPLES(pp) = %d.\n", CHOSENSAMPLES(pp)); printf("arc: NKEEP(pp) = %d.\n", NKEEP(pp)); printf("arc: PRECISION = %d.\n", peer->precision); } } /* Note time of last believable timestamp. */ pp->lastrec = up->lastrec; /* * Process the new sample in the median filter and determine the * reference clock offset and dispersion. We use lastrec as both * the reference time and receive time in order to avoid being * cute, like setting the reference time later than the receive * time, which may cause a paranoid protocol module to chuck out * the data. */#ifdef ARCRON_OWN_FILTER if(!arc_refclock_process(pp, CHOSENSAMPLES(pp), NKEEP(pp)))#else if(!refclock_process(pp, CHOSENSAMPLES(pp), NKEEP(pp)))#endif { refclock_report(peer, CEVNT_BADTIME); return; } trtmp = pp->lastrec; refclock_receive(peer, &pp->offset, 0, pp->dispersion, &trtmp, &pp->lastrec, pp->leap);}/* request_time() sends a time request to the clock with given peer. *//* This automatically reports a fault if necessary. *//* No data should be sent after this until arc_poll() returns. */static void request_time P((int, struct peer *));static voidrequest_time(unit, peer) int unit; struct peer *peer;{ struct refclockproc *pp = peer->procptr; register struct arcunit *up = (struct arcunit *)pp->unitptr; if(debug) { printf("arc: unit %d: requesting time.\n", unit); } if (!send_slow(up, pp->io.fd, "o\r")) { syslog(LOG_NOTICE, "ARCRON: unit %d: problem sending", unit); refclock_report(peer, CEVNT_FAULT); return; } pp->polls++;}/* * arc_poll - called by the transmit procedure */static voidarc_poll(unit, peer) int unit; struct peer *peer;{ register struct arcunit *up; struct refclockproc *pp; pp = peer->procptr; up = (struct arcunit *)pp->unitptr; pp->lencode = 0; memset(pp->lastcode, 0, sizeof(pp->lastcode));#if 0 /* Flush input. */ tcflush(pp->io.fd, TCIFLUSH);#endif /* Resync if our next scheduled resync time is here or has passed. */ if(up->next_resync <= current_time) { /* First, reset quality value to `unknown' so we can detect */ /* when a quality message has been responded to by this */ /* being set to some other value. */ up->quality = QUALITY_UNKNOWN; /* Note that we are resyncing... */ up->resyncing = 1; /* Now actually send the resync command and an immediate poll. */ if(debug) { printf("arc: sending resync command (h\\r).\n"); } syslog(LOG_NOTICE, "ARCRON: unit %d: sending resync command", unit); send_slow(up, pp->io.fd, "h\r"); /* Schedule our next resync... */ up->next_resync = current_time + DEFAULT_RESYNC_TIME; /* Drop through to request time if appropriate. */ } /* If clock quality is too poor to trust, indicate a fault. */ /* If quality is QUALITY_UNKNOWN and ARCRON_KEEN is defined,*/ /* we'll cross our fingers and just hope that the thing */ /* synced so quickly we did not catch it---we'll */ /* double-check the clock is OK elsewhere. */ if(#ifdef ARCRON_KEEN (up->quality != QUALITY_UNKNOWN) &&#else (up->quality == QUALITY_UNKNOWN) ||#endif (up->quality < MIN_CLOCK_QUALITY_OK)) { if(debug) { printf("arc: clock quality %d too poor.\n", up->quality); } refclock_report(peer, CEVNT_FAULT); return; } if(debug) { printf("arc: *** poll: pollcnt=%d\n", up->pollcnt); } if(up->pollcnt == 0) { refclock_report(peer, CEVNT_TIMEOUT); return; } up->pollcnt--; /* This is the normal case: request a timestamp. */ request_time(unit, peer);}#ifdef ARCRON_OWN_FILTER/* Very small fixes to the 3-5.90 ntp_refclock.c code. */#include "ntp_unixtime.h" /* For TVUTOTSF, etc. */#define REFCLOCKMAXDISPERSE (FP_SECOND/4) /* max sample dispersion *//* * Compare two l_fp's - used with qsort() */static intarc_refclock_cmpl_fp(p1, p2) register const void *p1, *p2; /* l_fp to compare */{ if (!L_ISGEQ((l_fp *)p1, (l_fp *)p2)) return (-1); if (L_ISEQU((l_fp *)p1, (l_fp *)p2)) return (0); return (1);}/* * refclock_process - process a pile of samples from the clock * * This routine converts the timecode in the form days, hours, minutes, * seconds, milliseconds/microseconds to internal timestamp format. * Further processing is then delegated to refclock sample */static intarc_refclock_process(pp, nstart, nskeep) struct refclockproc *pp; /* peer structure pointer */ int nstart; /* stages of median filter */ int nskeep; /* stages after outlyer trim */{ l_fp offset; /* * Compute the timecode timestamp from the days, hours, minutes, * seconds and milliseconds/microseconds of the timecode. Use * clocktime() for the aggregate seconds and the msec/usec for * the fraction, when present. Note that this code relies on the * filesystem time for the years and does not use the years of * the timecode. */ if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) return (0); if (pp->usec) { TVUTOTSF(pp->usec, offset.l_uf); } else { MSUTOTSF(pp->msec, offset.l_uf); } L_ADD(&offset, &pp->fudgetime1); pp->lastref = offset; /* save last reference time */ /* * Include the configured fudgetime1 adjustment. */ L_SUB(&offset, &pp->lastrec); /* form true offset */ if(debug > 1) { /* DHD addition. */ printf("arc: raw offset %sms.\n", mfptoms(offset.l_i, offset.l_f, 2)); } return arc_refclock_sample(&offset, pp, nstart, nskeep);}/* * refclock_sample - process a pile of samples from the clock * * This routine converts the timecode in the form days, hours, miinutes, * seconds, milliseconds/microseconds to internal timestamp format. It * then calculates the difference from the receive timestamp and * assembles the samples in a shift register. It implements a recursive * median filter to suppress spikes in the data, as well as determine a * rough dispersion estimate. A configuration constant time adjustment * fudgetime1 can be added to the final offset to compensate for various * systematic errors. The routine returns one if success and zero if * failure due to invalid timecode data or very noisy offsets. * * This interface is needed to allow for clocks (e. g. parse) that can * provide the correct offset including year information (though NTP * usually gives up on offsets greater than 1000 seconds). */static intarc_refclock_sample(sample_offset, pp, nstart, nskeep) l_fp *sample_offset; /* input offset (offset! - not a time stamp) for filter machine */ struct refclockproc *pp; /* peer structure pointer */ int nstart; /* stages of median filter */ int nskeep; /* stages after outlyer trim */{ int i, n; l_fp offset, median, lftmp; l_fp off[MAXSTAGE]; u_fp disp; /* * Subtract the receive timestamp from the timecode timestamp * to form the raw offset. Insert in the median filter shift * register. */ pp->nstages = nstart; offset = *sample_offset; i = ((int)(pp->coderecv)) % pp->nstages; pp->filter[i] = offset; if (pp->coderecv == 0) for (i = 1; (u_int) i < pp->nstages; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -