source: trunk/third/xntp/xntpd/refclock_acts.c @ 10832

Revision 10832, 32.9 KB checked in by brlewis, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10831, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * refclock_acts - clock driver for the NIST/PTB Automated Computer Time
3 *      Service aka Amalgamated Containerized Trash Service (ACTS)
4 */
5
6#ifdef HAVE_CONFIG_H
7#include <config.h>
8#endif
9
10#if defined(REFCLOCK) && (defined(ACTS) || defined(PTBACTS))
11
12#include <stdio.h>
13#include <ctype.h>
14#include <sys/time.h>
15#ifdef HAVE_SYS_IOCTL_H
16# include <sys/ioctl.h>
17#endif /* HAVE_SYS_IOCTL_H */
18
19#include "ntpd.h"
20#include "ntp_io.h"
21#include "ntp_unixtime.h"
22#include "ntp_refclock.h"
23#include "ntp_stdlib.h"
24#include "ntp_control.h"
25
26/* MUST BE AFTER LAST #include <config.h> !!! */
27
28#if defined(ACTS) && defined(PTBACTS)
29# if defined(KEEPPTBACTS)
30#   undef ACTS
31# else /* not KEEPPTBACTS */
32#   undef PTBACTS
33# endif /* not KEEPPTBACTS */
34#endif /* ACTS && PTBACTS */
35
36/*
37 * This driver supports the NIST Automated Computer Time Service (ACTS).
38 * It periodically dials a prespecified telephone number, receives the
39 * NIST timecode data and calculates the local clock correction. It is
40 * designed primarily for use as a backup when neither a radio clock nor
41 * connectivity to Internet time servers is available. For the best
42 * accuracy, the individual telephone line/modem delay needs to be
43 * calibrated using outside sources.
44 *
45 * The ACTS is located at NIST Boulder, CO, telephone 303 494 4774. A
46 * toll call from a residence telephone in Newark, DE, costs between 14
47 * and 27 cents, depending on time of day, and from a campus telephone
48 * between 3 and 4 cents, although it is not clear what carrier and time
49 * of day discounts apply in this case. The modem dial string will
50 * differ depending on local telephone configuration, etc., and is
51 * specified by the phone command in the configuration file. The
52 * argument to this command is an AT command for a Hayes compatible
53 * modem.
54 *
55 * The accuracy produced by this driver should be in the range of a
56 * millisecond or two, but may need correction due to the delay
57 * characteristics of the individual modem involved. For undetermined
58 * reasons, some modems work with the ACTS echo-delay measurement scheme
59 * and some don't. This driver tries to do the best it can with what it
60 * gets. Initial experiments with a Practical Peripherals 9600SA modem
61 * here in Delaware suggest an accuracy of a millisecond or two can be
62 * achieved without the scheme by using a fudge time1 value of 65.0 ms.
63 * In either case, the dispersion for a single call involving ten
64 * samples is about 1.3 ms.
65 *
66 * The driver can operate in either of three modes, as determined by
67 * the mode parameter in the server configuration command. In mode 0
68 * (automatic) the driver operates continuously at intervals depending
69 * on the prediction error, as measured by the driver, usually in the
70 * order of several hours. In mode 1 (backup) the driver is enabled in
71 * automatic mode only when no other source of synchronization is
72 * available and when more than MAXOUTAGE (3600 s) have elapsed since
73 * last synchronized by other sources. In mode 2 (manual) the driver
74 * operates only when enabled using a fudge flags switch, as described
75 * below.
76 *
77 * For reliable call management, this driver requires a 1200-bps modem
78 * with a Hayes-compatible command set and control over the modem data
79 * terminal ready (DTR) control line. Present restrictions require the
80 * use of a POSIX-compatible programming interface, although other
81 * interfaces may work as well. The modem setup string is hard-coded in
82 * the driver and may require changes for nonstandard modems or special
83 * circumstances.
84 *
85 * Further information can be found in the README.refclock file in the
86 * xntp3 distribution.
87 *
88 * Fudge Factors
89 *
90 * Ordinarily, the propagation time correction is computed automatically
91 * by ACTS and the driver. When this is not possible or erratic due to
92 * individual modem characteristics, the fudge flag2 switch should be
93 * set to disable the ACTS echo-delay scheme. In any case, the fudge
94 * time1 parameter can be used to adjust the propagation delay as
95 * required.
96 *
97 * The ACTS call interval is determined in one of three ways. In manual
98 * mode a call is initiated by setting fudge flag1 using xntpdc, either
99 * manually or via a cron job. In AUTO mode this flag is set by the peer
100 * timer, which is controlled by the sys_poll variable in response to
101 * measured errors. In backup mode the driver is ordinarily asleep, but
102 * awakes (in auto mode) if all other synchronization sources are lost.
103 * In either auto or backup modes, the call interval increases as long
104 * as the measured errors do not exceed the value of the fudge time2
105 * parameter.
106 *
107 * When the fudge flag1 is set, the ACTS calling program is activated.
108 * This program dials each number listed in the phones command of the
109 * configuration file in turn. If a call attempt fails, the next number
110 * in the list is dialed. The fudge flag1 and counter are reset and the
111 * calling program terminated if (a) a valid clock update has been
112 * determined, (b) no more numbers remain in the list, (c) a device
113 * fault or timeout occurs or (d) fudge flag1 is reset manually using
114 * xntpdc.
115 *
116 * In automatic and backup modes, the driver determines the call
117 * interval using a procedure depending on the measured prediction
118 * error and the fudge time2 parameter. If the error exceeds time2 for a
119 * number of times depending on the current interval, the interval is
120 * decreased, but not less than about 1000 s. If the error is less than
121 * time2 for some number of times, the interval is increased, but not
122 * more than about 18 h. With the default value of zero for fudge time2,
123 * the interval will increase from 1000 s to the 4000-8000-s range, in
124 * which the expected accuracy should be in the 1-2-ms range. Setting
125 * fudge time2 to a large value, like 0.1 s, may result in errors of
126 * that order, but increase the call interval to the maximum. The exact
127 * value for each configuration will depend on the modem and operating
128 * system involved, so some experimentation may be necessary.
129 */
130
131/*
132 * DESCRIPTION OF THE AUTOMATED COMPUTER TELEPHONE SERVICE (ACTS)
133 * (reformatted from ACTS on-line computer help information)
134 *
135 * The following is transmitted (at 1200 baud) following completion of
136 * the telephone connection.
137 *
138 * National Institute of Standards and Technology
139 * Telephone Time Service, Generator 3B
140 * Enter question mark "?" for HELP
141 *                         D  L D
142 *  MJD  YR MO DA H  M  S  ST S UT1 msADV        <OTM>
143 * 47999 90-04-18 21:39:15 50 0 +.1 045.0 UTC(NIST) *
144 * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) *
145 * 47999 90-04-18 21:39:17 50 0 +.1 045.0 UTC(NIST) *
146 * 47999 90-04-18 21:39:18 50 0 +.1 045.0 UTC(NIST) *
147 * 47999 90-04-18 21:39:19 50 0 +.1 037.6 UTC(NIST) #
148 * 47999 90-04-18 21:39:20 50 0 +.1 037.6 UTC(NIST) #
149 * etc..etc...etc.......
150 *
151 * UTC = Universal Time Coordinated, the official world time referred to
152 * the zero meridian.
153 *
154 * DST  Daylight savings time characters, valid for the continental
155 *      U.S., are set as follows:
156 *
157 *      00      We are on standard time (ST).
158 *      01-49   Now on DST, go to ST when your local time is 2:00 am and
159 *              the count is 01. The count is decremented daily at 00
160 *              (UTC).
161 *      50      We are on DST.
162 *      51-99   Now on ST, go to DST when your local time is 2:00 am and
163 *              the count is 51. The count is decremented daily at 00
164 *              (UTC).
165 *
166 *      The two DST characters provide up to 48 days advance notice of a
167 *      change in time. The count remains at 00 or 50 at other times.
168 *
169 * LS   Leap second flag is set to "1" to indicate that a leap second is
170 *      to be added as 23:59:60 (UTC) on the last day of the current UTC
171 *      month. The LS flag will be reset to "0" starting with 23:59:60
172 *      (UTC). The flag will remain on for the entire month before the
173 *      second is added. Leap seconds are added as needed at the end of
174 *      any month. Usually June and/or December are chosen.
175 *
176 *      The leap second flag will be set to a "2" to indicate that a
177 *      leap second is to be deleted at 23:59:58--00:00:00 on the last
178 *      day of the current month. (This latter provision is included per
179 *      international recommendation, however it is not likely to be
180 *      required in the near future.)
181 *
182 * DUT1 Approximate difference between earth rotation time (UT1) and
183 *      UTC, in steps of 0.1 second: DUT1 = UT1 - UTC.
184 *
185 * MJD  Modified Julian Date, often used to tag certain scientific data.
186 *
187 * The full time format is sent at 1200 baud, 8 bit, 1 stop, no parity.
188 * The format at 300 Baud is also 8 bit, 1 stop, no parity. At 300 Baud
189 * the MJD and DUT1 values are deleted and the time is transmitted only
190 * on even seconds.
191 *
192 * Maximum on line time will be 56 seconds. If all lines are busy at any
193 * time, the oldest call will be terminated if it has been on line more
194 * than 28 seconds, otherwise, the call that first reaches 28 seconds
195 * will be terminated.
196 *
197 * Current time is valid at the "on-time" marker (OTM), either "*" or
198 * "#". The nominal on-time marker (*) will be transmitted 45 ms early
199 * to account for the 8 ms required to send 1 character at 1200 Baud,
200 * plus an additional 7 ms for delay from NIST to the user, and
201 * approximately 30 ms "scrambler" delay inherent in 1200 Baud modems.
202 * If the caller echoes all characters, NIST will measure the round trip
203 * delay and advance the on-time marker so that the midpoint of the stop
204 * bit arrives at the user on time. The amount of msADV will reflect the
205 * actual required advance in milliseconds and the OTM will be a "#".
206 *
207 * (The NIST system requires 4 or 5 consecutive delay measurements which
208 * are consistent before switching from "*" to "#". If the user has a
209 * 1200 Baud modem with the same internal delay as that used by NIST,
210 * then the "#" OTM should arrive at the user within +-2 ms of the
211 * correct time.
212 *
213 * However, NIST has studied different brands of 1200 Baud modems and
214 * found internal delays from 24 ms to 40 ms and offsets of the "#" OTM
215 * of +-10 ms. For many computer users, +-10 ms accuracy should be more
216 * than adequate since many computer internal clocks can only be set
217 * with granularity of 20 to 50 ms. In any case, the repeatability of
218 * the offset for the "#" OTM should be within +-2 ms, if the dial-up
219 * path is reciprocal and the user doesn't change the brand or model of
220 * modem used.
221 *
222 * This should be true even if the dial-up path on one day is a land-
223 * line of less than 40 ms (one way) and on the next day is a satellite
224 * link of 260 to 300 ms. In the rare event that the path is one way by
225 * satellite and the other way by land line with a round trip
226 * measurement in the range of 90 to 260 ms, the OTM will remain a "*"
227 * indicating 45 ms advance.
228 *
229 * For user comments write:
230 * NIST-ACTS
231 * Time and Frequency Division
232 * Mail Stop 847
233 * 325 Broadway
234 * Boulder, CO 80303
235 *
236 * Software for setting (PC)DOS compatable machines is available on a
237 * 360-kbyte diskette for $35.00 from: NIST Office of Standard Reference
238 * Materials B311-Chemistry Bldg, NIST, Gaithersburg, MD, 20899, (301)
239 * 975-6776
240 *
241 * PTB timecode service (+49 531 512038)
242 * The Physikalisch-Technische Bundesanstalt (Germany)
243 * also supports a modem time service
244 * as the data formats are very similar this driver can also be compiled for
245 * utilizing the PTB time code service.
246 *
247 * Data format
248 * 0000000000111111111122222222223333333333444444444455555555556666666666777777777   7
249 * 0123456789012345678901234567890123456789012345678901234567890123456789012345678   9
250 * 1995-01-23 20:58:51 MEZ  10402303260219950123195849740+40000500              *
251 * A    B  C  D EF  G  H    IJ K  L M N O   P Q R S T    U V  W  XY             Z<CR><LF>
252 *
253 * A year
254 * B month
255 * C day
256 * D hour
257 * E : normally
258 *   A for DST to ST switch first hour
259 *   B for DST to ST switch second hour if not marked in H
260 * F minute
261 * G second
262 * H timezone
263 * I day of week
264 * J week of year
265 * K day of year
266 * L month for next ST/DST changes
267 * M day
268 * N hour
269 * O UTC year
270 * P UTC month
271 * Q UTC day
272 * R UTC hour
273 * S UTC minute
274 * T modified julian day (MJD)
275 * U DUT1
276 * V direction and month if leap second
277 * W signal delay (assumed/measured)
278 * X sequence number for additional text line in Y
279 * Y additional text
280 * Z on time marker (* - assumed delay / # measured delay)
281 * <CR>!<LF> ! is second change !
282 *
283 * This format is also used by the National Physical Laboratory (NPL)'s
284 * TRUETIME service in the UK.  In this case the timezone field is
285 * UTC+0 or UTC+1 for standard and daylight saving time.  The phone
286 * number for this service (a premium rate number) is 0891 516 333.
287 * It is not clear whether the echo check is implemented.
288 *
289 * For more detail, see http://www.npl.co.uk/npl/cetm/taf/truetime.html.
290 */
291
292/*
293 * Interface definitions
294 */
295#define SPEED232        B1200   /* uart speed (1200 cowardly baud) */
296#define PRECISION       (-10)   /* precision assumed (about 1 ms) */
297#ifdef ACTS
298# define REFID          "ACTS"  /* reference ID */
299# define DESCRIPTION    "NIST Automated Computer Time Service" /* WRU */
300# define LENCODE        50      /* length of valid timecode string */
301# define DEVICE         "/dev/acts%d" /* device name and unit */
302# define REF_ENTRY      refclock_acts
303#else  /* not ACTS */
304# define REFID          "TPTB"  /* reference ID */
305# define DESCRIPTION    "PTB Automated Computer Time Service"
306# define LENCODE        78      /* length of valid timecode string */
307# define DEVICE         "/dev/ptb%d" /* device name and unit */
308# define REF_ENTRY      refclock_ptb
309#endif /* not ACTS */
310#define MODE_AUTO       0       /* automatic mode */
311#define MODE_BACKUP     1       /* backup mode */
312#define MODE_MANUAL     2       /* manual mode */
313
314#define NSAMPLES        3       /* stages of median filter */
315#define MSGCNT          10      /* we need this many ACTS messages */
316#define SMAX            80      /* max token string length */
317#define ACTS_MINPOLL    10      /* log2 min poll interval (1024 s) */
318#define ACTS_MAXPOLL    14      /* log2 max poll interval (16384 s) */
319#define MAXOUTAGE       3600    /* max before ACTS kicks in (s) */
320
321/*
322 * Modem control strings. These may have to be changed for some modems.
323 *
324 * AT   command prefix
325 * B1   initiate call negotiation using Bell 212A
326 * &C1  enable carrier detect
327 * &D2  hang up and return to command mode on DTR transition
328 * E0   modem command echo disabled
329 * l1   set modem speaker volume to low level
330 * M1   speaker enabled untill carrier detect
331 * Q0   return result codes
332 * V1   return result codes as English words
333 */
334#define MODEM_SETUP     "ATB1&C1&D2E0L1M1Q0V1" /* modem setup */
335#define MODEM_HANGUP    "ATH"   /* modem disconnect */
336
337/*
338 * Timeouts
339 */
340#define IDLE            60      /* idle timeout (s) */
341#define WAIT            2       /* wait timeout (s) */
342#define ANSWER          30      /* answer timeout (s) */
343#define CONNECT         10      /* connect timeout (s) */
344#define TIMECODE        15      /* timecode timeout (s) */
345
346/*
347 * Imported from ntp_timer module
348 */
349extern  u_long  current_time;   /* current time (s) */
350extern  u_long  last_time;      /* last clock update time (s) */
351extern  struct event timerqueue[]; /* inner space */
352
353/*
354 * Imported from ntpd module
355 */
356extern  int     debug;          /* global debug flag */
357
358/*
359 * Imported from ntp_config module
360 */
361extern  char    sys_phone[][MAXDIAL]; /* modem dial strings */
362
363/*
364 * Imported from ntp_proto module
365 */
366extern  struct peer *sys_peer;  /* who is running the show */
367extern  u_char sys_poll;        /* log2 of system poll interval */
368extern  struct peer *sys_peer;  /* system peer structure pointer */
369
370/*
371 * Tables to compute the ddd of year form icky dd/mm timecode. Viva la
372 * leap.
373 */
374static int day1tab[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
375static int day2tab[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
376
377/*
378 * Unit control structure
379 */
380struct actsunit {
381        struct  event timer;    /* timeout timer */
382        int     pollcnt;        /* poll message counter */
383
384        int     state;          /* the first one was Delaware */
385        int     run;            /* call program run switch */
386        int     msgcnt;         /* count of ACTS messages received */
387        long    redial;         /* interval to next automatic call */
388        double  msADV;          /* millisecond advance of last message */
389};
390
391/*
392 * Function prototypes
393 */
394static  int     acts_start      P((int, struct peer *));
395static  void    acts_shutdown   P((int, struct peer *));
396static  void    acts_receive    P((struct recvbuf *));
397static  void    acts_poll       P((int, struct peer *));
398static  void    acts_timeout    P((struct peer *));
399static  void    acts_disc       P((struct peer *));
400static  int     acts_write      P((struct peer *, char *));
401
402/*
403 * Transfer vector (conditional structure name)
404 */
405struct  refclock REF_ENTRY = {
406        acts_start,             /* start up driver */
407        acts_shutdown,          /* shut down driver */
408        acts_poll,              /* transmit poll message */
409        noentry,                /* not used (old acts_control) */
410        noentry,                /* not used (old acts_init) */
411        noentry,                /* not used (old acts_buginfo) */
412        NOFLAGS                 /* not used */
413};
414
415
416/*
417 * acts_start - open the devices and initialize data for processing
418 */
419static int
420acts_start(unit, peer)
421        int unit;
422        struct peer *peer;
423{
424        register struct actsunit *up;
425        struct refclockproc *pp;
426        int fd;
427        char device[20];
428        int dtr = TIOCM_DTR;
429
430        /*
431         * Open serial port. Use ACTS line discipline, if available. It
432         * pumps a timestamp into the data stream at every on-time
433         * character '*' found. Note: the port must have modem control
434         * or deep pockets for the phone bill. HP-UX 9.03 users should
435         * have very deep pockets.
436         */
437        (void)sprintf(device, DEVICE, unit);
438        if (!(fd = refclock_open(device, SPEED232, LDISC_ACTS)))
439                return (0);
440        if (ioctl(fd, TIOCMBIS, (char *)&dtr) < 0) {
441                msyslog(LOG_ERR, "clock %s ACTS no modem control",
442                    ntoa(&peer->srcadr));
443                return (0);
444        }
445
446        /*
447         * Allocate and initialize unit structure
448         */
449        if (!(up = (struct actsunit *)
450            emalloc(sizeof(struct actsunit)))) {
451                (void) close(fd);
452                return (0);
453        }
454        memset((char *)up, 0, sizeof(struct actsunit));
455        pp = peer->procptr;
456        pp->io.clock_recv = acts_receive;
457        pp->io.srcclock = (caddr_t)peer;
458        pp->io.datalen = 0;
459        pp->io.fd = fd;
460        if (!io_addclock(&pp->io)) {
461                (void) close(fd);
462                free(up);
463                return (0);
464        }
465        pp->unitptr = (caddr_t)up;
466
467        /*
468         * Initialize miscellaneous variables
469         */
470        peer->precision = PRECISION;
471        pp->clockdesc = DESCRIPTION;
472        memcpy((char *)&pp->refid, REFID, 4);
473        peer->minpoll = ACTS_MINPOLL;
474        peer->maxpoll = ACTS_MAXPOLL;
475        peer->sstclktype = CTL_SST_TS_TELEPHONE;
476
477        /*
478         * Initialize modem and kill DTR. We skedaddle if this comes
479         * bum.
480         */
481        if (!acts_write(peer, MODEM_SETUP)) {
482                (void) close(fd);
483                free(up);
484                return (0);
485        }
486
487        /*
488         * Set up the driver timeout
489         */
490        up->timer.peer = (struct peer *)peer;
491        up->timer.event_handler = acts_timeout;
492        up->timer.event_time = current_time + WAIT;
493        TIMER_INSERT(timerqueue, &up->timer);
494        return (1);
495}
496
497
498/*
499 * acts_shutdown - shut down the clock
500 */
501static void
502acts_shutdown(unit, peer)
503        int unit;
504        struct peer *peer;
505{
506        register struct actsunit *up;
507        struct refclockproc *pp;
508
509        pp = peer->procptr;
510        up = (struct actsunit *)pp->unitptr;
511        TIMER_DEQUEUE(&up->timer);
512        io_closeclock(&pp->io);
513        free(up);
514}
515
516
517/*
518 * acts_receive - receive data from the serial interface
519 */
520static void
521acts_receive(rbufp)
522        struct recvbuf *rbufp;
523{
524        register struct actsunit *up;
525        struct refclockproc *pp;
526        struct peer *peer;
527        char str[SMAX];
528        int i;
529        l_fp tstmp;
530        u_fp disp;
531        char hangup = '%';      /* ACTS hangup */
532        int day;                /* day of the month */
533        int month;              /* month of the year */
534        u_long mjd;             /* Modified Julian Day */
535        double dut1;            /* DUT adjustment */
536        double msADV;           /* ACTS transmit advance (ms) */
537        char flag;              /* calibration flag */
538#ifndef PTBACTS
539        char utc[10];           /* this is NIST and you're not */
540        u_int dst;              /* daylight/standard time indicator */
541        u_int leap;             /* leap-second indicator */
542#else
543        char leapdir;           /* leap direction */
544        u_int leapmonth;        /* month of leap */
545#endif
546        /*
547         * Initialize pointers and read the timecode and timestamp. If
548         * the OK modem status code, leave it where folks can find it.
549         */
550        peer = (struct peer *)rbufp->recv_srcclock;
551        pp = peer->procptr;
552        up = (struct actsunit *)pp->unitptr;
553        pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
554            &pp->lastrec);
555        if (pp->lencode == 0) {
556                if (strcmp(pp->a_lastcode, "OK") == 0)
557                        pp->lencode = 2;
558                return;
559        }
560#ifdef DEBUG
561        if (debug)
562                printf("acts: state %d timecode %d %*s\n", up->state,
563                       pp->lencode, pp->lencode, pp->a_lastcode);
564#endif
565
566        switch (up->state) {
567
568                case 0:
569
570                /*
571                 * State 0. We are not expecting anything. Probably
572                 * modem disconnect noise. Go back to sleep.
573                 */
574                return;
575
576                case 1:
577
578                /*
579                 * State 1. We are waiting for the call to be answered.
580                 * All we care about here is CONNECT as the first token
581                 * in the string. If the modem signals BUSY, ERROR, NO
582                 * ANSWER, NO CARRIER or NO DIALTONE, we immediately
583                 * hang up the phone. If CONNECT doesn't happen after
584                 * ANSWER seconds, hang up the phone. If everything is
585                 * okay, start the connect timeout and slide into state
586                 * 2.
587                 */
588                if( strcmp(sys_phone[0],"DIRECT") != 0 ) {
589                        if (pp) {
590                          if (pp->a_lastcode[0]) {
591                            (void)strncpy(str, strtok(pp->a_lastcode, " "), SMAX);
592                          } else {
593                            msyslog(LOG_ERR, "clock %s ACTS: pp->a_lastcode was NIL",
594                                    ntoa(&peer->srcadr));
595                            *str = '\0';
596                          }
597                        } else {
598                          /* pp was NIL */
599                          msyslog(LOG_ERR, "clock %s ACTS: pp was NIL",
600                                  ntoa(&peer->srcadr));
601                          *str = '\0';
602                        }
603                        if (strcmp(str, "BUSY") == 0 || strcmp(str, "ERROR") ==
604                             0 || strcmp(str, "NO") == 0) {
605                                TIMER_DEQUEUE(&up->timer);
606                                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
607                                  msyslog(LOG_NOTICE,
608                                    "clock %s ACTS modem status %s",
609                                    ntoa(&peer->srcadr), pp->a_lastcode);
610                                acts_disc(peer);
611                        } else if (strcmp(str, "CONNECT") == 0) {
612                                TIMER_DEQUEUE(&up->timer);
613                                up->timer.event_time = current_time + CONNECT;
614                                TIMER_INSERT(timerqueue, &up->timer);
615                                up->msgcnt = 0;
616                                up->state++;
617                        }
618                } else {
619                        (void) strncpy(str,"CONNECT",7);
620                        TIMER_DEQUEUE(&up->timer);
621                        up->timer.event_time = current_time + CONNECT;
622                        TIMER_INSERT(timerqueue, &up->timer);
623                        up->msgcnt = 0;
624                        up->state++;
625                }
626                return;
627
628                case 2:
629
630                /*
631                 * State 2. The call has been answered and we are
632                 * waiting for the first ACTS message. If this doesn't
633                 * happen within the timecode timeout, hang up the
634                 * phone. We probably got a wrong number or ACTS is
635                 * down.
636                 */
637                TIMER_DEQUEUE(&up->timer);
638                up->timer.event_time = current_time + TIMECODE;
639                TIMER_INSERT(timerqueue, &up->timer);
640                up->state++;
641        }
642
643        /*
644         * Real yucky things here. Ignore everything except timecode
645         * messages, as determined by the message length. We told the
646         * terminal routines to end the line with '*' and the line
647         * discipline to strike a timestamp on that character. However,
648         * when the ACTS echo-delay scheme works, the '*' eventually
649         * becomes a '#'. In this case the message is ended by the <CR>
650         * that comes about 200 ms after the '#' and the '#' cannot be
651         * echoed at the proper time. But, this may not be a lose, since
652         * we already have good data from prior messages and only need
653         * the millisecond advance calculated by ACTS. So, if the
654         * message is long enough and has an on-time character at the
655         * right place, we consider the message (but not neccesarily the
656         * timestmap) to be valid.
657         */
658        if (pp->lencode != LENCODE)
659                return;
660
661#ifndef PTBACTS
662        /*
663         * We apparently have a valid timecode message, so dismember it
664         * with sscan(). This routine does a good job in spotting syntax
665         * errors without becoming overly pedantic.
666         *
667         *                         D  L D
668         *  MJD  YR MO DA H  M  S  ST S UT1 msADV         OTM
669         * 47222 88-03-02 21:39:15 83 0 +.3 045.0 UTC(NBS) *
670         */
671        if (sscanf(pp->a_lastcode,
672            "%5ld %2d-%2d-%2d %2d:%2d:%2d %2d %1d %3lf %5lf %s %c",
673            &mjd, &pp->year, &month, &day, &pp->hour, &pp->minute,
674            &pp->second, &dst, &leap, &dut1, &msADV, utc, &flag) != 13) {
675                refclock_report(peer, CEVNT_BADREPLY);
676                return;
677        }
678#else
679        /*
680         * Data format
681         * 0000000000111111111122222222223333333333444444444455555555556666666666777777777   7
682         * 0123456789012345678901234567890123456789012345678901234567890123456789012345678   9
683         * 1995-01-23 20:58:51 MEZ  10402303260219950123195849740+40000500              *
684         */
685        if (sscanf(pp->a_lastcode,
686            "%*4d-%*2d-%*2d %*2d:%*2d:%2d %*5c%*12c%4d%2d%2d%2d%2d%5ld%2lf%c%2d%3lf%*15c%c",
687            &pp->second, &pp->year, &month, &day, &pp->hour, &pp->minute, &mjd, &dut1, &leapdir, &leapmonth, &msADV, &flag) != 12) {
688                refclock_report(peer, CEVNT_BADREPLY);
689                return;
690        }
691#endif
692        /*
693         * Some modems can't be trusted (the Practical Peripherals
694         * 9600SA comes to mind) and, even if they manage to unstick
695         * ACTS, the millisecond advance is wrong, so we use CLK_FLAG2
696         * to disable echoes, if neccessary.
697         */
698        if ((flag == '*' || flag == '#') && !(pp->sloppyclockflag &
699            CLK_FLAG2))
700                (void)write(pp->io.fd, &flag, 1);
701
702        /*
703         * Yes, I know this code incorrectly thinks that 2000 is a leap
704         * year. The ACTS timecode format croaks then anyway. Life is
705         * short. Would only the timecode mavens resist the urge to
706         * express months of the year and days of the month in favor of
707         * days of the year.
708         */
709        if (month < 1 || month > 12 || day < 1) {
710                refclock_report(peer, CEVNT_BADTIME);
711                return;
712        }
713        if (pp->year % 4) {
714                if (day > day1tab[month - 1]) {
715                        refclock_report(peer, CEVNT_BADTIME);
716                        return;
717                }
718                for (i = 0; i < month - 1; i++)
719                        day += day1tab[i];
720        } else {
721                if (day > day2tab[month - 1]) {
722                        refclock_report(peer, CEVNT_BADTIME);
723                        return;
724                }
725                for (i = 0; i < month - 1; i++)
726                        day += day2tab[i];
727        }
728        pp->day = day;
729
730#ifndef PTBACTS
731        if (leap == 1)
732                pp->leap = LEAP_ADDSECOND;
733        else if (pp->leap == 2)
734                pp->leap = LEAP_DELSECOND;
735        else
736                pp->leap = 0;
737#else
738        if (leapmonth == month) {
739          if (leapdir == '+')
740            pp->leap = LEAP_ADDSECOND;
741          else if (leapdir == '-')
742            pp->leap = LEAP_DELSECOND;
743        }
744        else
745          pp->leap = 0;
746#endif
747        pp->lasttime = current_time;
748
749        /*
750         * Colossal hack here. We process each sample in a trimmed-mean
751         * filter and determine the reference clock offset and
752         * dispersion. The fudge time1 value is added to each sample as
753         * received. If we collect MSGCNT samples before the '#' on-time
754         * character, we use the results of the filter as is. If the '#'
755         * is found before that, the adjusted msADV is used to correct
756         * the propagation delay.
757         */
758        up->msgcnt++;
759        if (flag == '#') {
760                L_CLR(&tstmp);
761                TVUTOTSF((long)((msADV - up->msADV) * 1000.),
762                    tstmp.l_uf);
763                L_ADD(&pp->offset, &tstmp);
764        } else {
765                up->msADV = msADV;
766                if (!refclock_process(pp, up->msgcnt, up->msgcnt -
767                    up->msgcnt / 3)) {
768                        refclock_report(peer, CEVNT_BADTIME);
769                        return;
770                } else if (up->msgcnt < MSGCNT)
771                        return;
772        }
773
774        /*
775         * We have a filtered sample offset ready for peer processing.
776         * We use lastrec as both the reference time and receive time in
777         * order to avoid being cute, like setting the reference time
778         * later than the receive time, which may cause a paranoid
779         * protocol module to chuck out the data. Finaly, we unhook the
780         * timeout, arm for the next call, fold the tent and go home.
781         * The little dance with the '%' character is an undocumented
782         * ACTS feature that hangs up the phone real quick without
783         * waiting for carrier loss or long-space disconnect, but we do
784         * these clumsy things anyway.
785         */
786        disp = LFPTOFP(&pp->fudgetime2);
787        record_clock_stats(&peer->srcadr, pp->a_lastcode);
788        refclock_receive(peer, &pp->offset, 0, pp->dispersion +
789            (u_fp)disp, &pp->lastrec, &pp->lastrec, pp->leap);
790        pp->sloppyclockflag &= ~CLK_FLAG1;
791        up->pollcnt = 0;
792        TIMER_DEQUEUE(&up->timer);
793        (void)write(pp->io.fd, &hangup, 1);
794        up->state = 0;
795        acts_disc(peer);
796}
797
798
799/*
800 * acts_poll - called by the transmit routine
801 */
802static void
803acts_poll(unit, peer)
804        int unit;
805        struct peer *peer;
806{
807        register struct actsunit *up;
808        struct refclockproc *pp;
809
810        /*
811         * If the driver is running, we set the enable flag (fudge
812         * flag1), which causes the driver timeout routine to initiate a
813         * call to ACTS. If not, the enable flag can be set using
814         * xntpdc. If this is the sustem peer, then follow the system
815         * poll interval.
816         */
817        pp = peer->procptr;
818        up = (struct actsunit *)pp->unitptr;
819        if (up->run) {
820                pp->sloppyclockflag |= CLK_FLAG1;
821                if (peer == sys_peer)
822                        peer->hpoll = sys_poll;
823                else
824                        peer->hpoll = peer->minpoll;
825        }
826}
827
828
829/*
830 * acts_timeout - called by the timer interrupt
831 */
832static void
833acts_timeout(peer)
834        struct peer *peer;
835{
836        register struct actsunit *up;
837        struct refclockproc *pp;
838        int dtr = TIOCM_DTR;
839
840        /*
841         * If a timeout occurs in other than state 0, the call has
842         * failed. If in state 0, we just see if there is other work to
843         * do.
844         */
845        pp = peer->procptr;
846        up = (struct actsunit *)pp->unitptr;
847        if (up->state) {
848                acts_disc(peer);
849                return;
850        }
851        switch (peer->ttl) {
852
853                /*
854                 * In manual mode the ACTS calling program is activated
855                 * by the xntpdc program using the enable flag (fudge
856                 * flag1), either manually or by a cron job.
857                 */
858                case MODE_MANUAL:
859                up->run = 0;
860                break;
861
862                /*
863                 * In automatic mode the ACTS calling program runs
864                 * continuously at intervals determined by the sys_poll
865                 * variable.
866                 */
867                case MODE_AUTO:
868                if (!up->run)
869                        pp->sloppyclockflag |= CLK_FLAG1;
870                up->run = 1;
871                break;
872
873                /*
874                 * In backup mode the ACTS calling program is disabled,
875                 * unless no system peer has been selected for MAXOUTAGE
876                 * (3600 s). Once enabled, it runs until some other NTP
877                 * peer shows up.
878                 */
879                case MODE_BACKUP:
880                if (!up->run && sys_peer == 0) {
881                        if (current_time - last_time > MAXOUTAGE) {
882                                up->run = 1;
883                                peer->hpoll = peer->minpoll;
884                                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
885                                  msyslog(LOG_NOTICE,
886                                    "clock %s ACTS backup started ",
887                                    ntoa(&peer->srcadr));
888                        }
889                } else if (up->run && sys_peer->sstclktype != CTL_SST_TS_TELEPHONE) {
890                        peer->hpoll = peer->minpoll;
891                        up->run = 0;
892                        NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
893                          msyslog(LOG_NOTICE,
894                            "clock %s ACTS backup stopped",
895                            ntoa(&peer->srcadr));
896                }
897                break;
898
899                default:
900                msyslog(LOG_ERR,
901                       "clock %s ACTS invalid mode", ntoa(&peer->srcadr));
902               
903        }
904
905        /*
906         * The fudge flag1 is used as an enable/disable; if set either
907         * by the code or via xntpdc, the ACTS calling program is
908         * started; if reset, the phones stop ringing.
909         */
910        if (!(pp->sloppyclockflag & CLK_FLAG1)) {
911                up->pollcnt = 0;
912                up->timer.event_time = current_time + IDLE;
913                TIMER_INSERT(timerqueue, &up->timer);
914                return;
915        }
916
917        /*
918         * Initiate a call to the ACTS service. If we wind up here in
919         * other than state 0, a successful call could not be completed
920         * within minpoll seconds. We advance to the next modem dial
921         * string. If none are left, we log a notice and clear the
922         * enable flag. For future enhancement: call the site RP and
923         * leave an obscene message in his voicemail.
924         */
925        if (sys_phone[up->pollcnt][0] == '\0') {
926                refclock_report(peer, CEVNT_TIMEOUT);
927                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
928                  msyslog(LOG_NOTICE,
929                    "clock %s ACTS calling program terminated",
930                    ntoa(&peer->srcadr));
931                pp->sloppyclockflag &= ~CLK_FLAG1;
932#ifdef DEBUG
933                if (debug)
934                        printf("acts: calling program terminated\n");
935#endif
936                up->pollcnt = 0;
937                up->timer.event_time = current_time + IDLE;
938                TIMER_INSERT(timerqueue, &up->timer);
939                return;
940        }
941
942        /*
943         * Raise DTR, call ACTS and start the answer timeout. We think
944         * it strange if the OK status has not been received from the
945         * modem, but plow ahead anyway.
946         */
947        if (strcmp(pp->a_lastcode, "OK") != 0)
948                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
949                  msyslog(LOG_NOTICE, "clock %s ACTS no modem status",
950                    ntoa(&peer->srcadr));
951        (void)ioctl(pp->io.fd, TIOCMBIS, (char *)&dtr);
952        (void)acts_write(peer, sys_phone[up->pollcnt]);
953        NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
954          msyslog(LOG_NOTICE, "clock %s ACTS calling %s\n",
955            ntoa(&peer->srcadr), sys_phone[up->pollcnt]);
956        up->state = 1;
957        up->pollcnt++;
958        pp->polls++;
959        up->timer.event_time = current_time + ANSWER;
960        TIMER_INSERT(timerqueue, &up->timer);
961}
962
963
964/*
965 * acts_disc - disconnect the call and wait for the ruckus to cool
966 */
967static void
968acts_disc(peer)
969        struct peer *peer;
970{
971        register struct actsunit *up;
972        struct refclockproc *pp;
973        int dtr = TIOCM_DTR;
974
975        /*
976         * We should never get here other than in state 0, unless a call
977         * has timed out. We drop DTR, which will reliably get the modem
978         * off the air, even while ACTS is hammering away full tilt.
979         */
980        pp = peer->procptr;
981        up = (struct actsunit *)pp->unitptr;
982        (void)ioctl(pp->io.fd, TIOCMBIC, (char *)&dtr);
983        if (up->state > 0) {
984                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
985                  msyslog(LOG_NOTICE, "clock %s ACTS call failed %d",
986                    ntoa(&peer->srcadr), up->state);
987#ifdef DEBUG
988                if (debug)
989                        printf("acts: call failed %d\n", up->state);
990#endif
991                up->state = 0;
992        }
993        up->timer.event_time = current_time + WAIT;
994        TIMER_INSERT(timerqueue, &up->timer);
995}
996
997
998/*
999 * acts_write - write a message to the serial port
1000 */
1001static int
1002acts_write(peer, str)
1003        struct peer *peer;
1004        char *str;
1005{
1006        register struct actsunit *up;
1007        struct refclockproc *pp;
1008        int len;
1009        int code;
1010        char cr = '\r';
1011
1012        /*
1013         * Not much to do here, other than send the message, handle
1014         * debug and report faults.
1015         */
1016        pp = peer->procptr;
1017        up = (struct actsunit *)pp->unitptr;
1018        len = strlen(str);
1019#ifdef DEBUG
1020        if (debug)
1021                printf("acts: state %d send %d %s\n", up->state, len,
1022                    str);
1023#endif
1024        code = write(pp->io.fd, str, len) == len;
1025        code &= write(pp->io.fd, &cr, 1) == 1;
1026        if (!code)
1027                refclock_report(peer, CEVNT_FAULT);
1028        return (code);
1029}
1030
1031#else /* not (REFCLOCK && (ACTS || PTBACTS)) */
1032int refclock_acts_bs;
1033#endif /* not (REFCLOCK && (ACTS || PTBACTS)) */
Note: See TracBrowser for help on using the repository browser.