1 /*
2 * refclock_gpsdjson.c - clock driver as GPSD JSON client
3 * Juergen Perlinger (perlinger@ntp.org)
4 * Feb 11, 2014 for the NTP project.
5 * The contents of 'html/copyright.html' apply.
6 *
7 * Heavily inspired by refclock_nmea.c
8 *
9 * Special thanks to Gary Miller and Hal Murray for their comments and
10 * ideas.
11 *
12 * Note: This will currently NOT work with Windows due to some
13 * limitations:
14 *
15 * - There is no GPSD for Windows. (There is an unofficial port to
16 * cygwin, but Windows is not officially supported.)
17 *
18 * - To work properly, this driver needs PPS and TPV/TOFF sentences
19 * from GPSD. I don't see how the cygwin port should deal with the
20 * PPS signal.
21 *
22 * - The device name matching must be done in a different way for
23 * Windows. (Can be done with COMxx matching, as done for NMEA.)
24 *
25 * Apart from those minor hickups, once GPSD has been fully ported to
26 * Windows, there's no reason why this should not work there ;-) If this
27 * is ever to happen at all is a different question.
28 *
29 * ---------------------------------------------------------------------
30 *
31 * This driver works slightly different from most others, as the PPS
32 * information (if available) is also coming from GPSD via the data
33 * connection. This makes using both the PPS data and the serial data
34 * easier, but OTOH it's not possible to use the ATOM driver to feed a
35 * raw PPS stream to the core of NTPD.
36 *
37 * To go around this, the driver can use a secondary clock unit
38 * (units>=128) that operate in tandem with the primary clock unit
39 * (unit%128). The primary clock unit does all the IO stuff and data
40 * decoding; if a a secondary unit is attached to a primary unit, this
41 * secondary unit is feed with the PPS samples only and can act as a PPS
42 * source to the clock selection.
43 *
44 * The drawback is that the primary unit must be present for the
45 * secondary unit to work.
46 *
47 * This design is a compromise to reduce the IO load for both NTPD and
48 * GPSD; it also ensures that data is transmitted and evaluated only
49 * once on the side of NTPD.
50 *
51 * ---------------------------------------------------------------------
52 *
53 * trouble shooting hints:
54 *
55 * Enable and check the clock stats. Check if there are bad replies;
56 * there should be none. If there are actually bad replies, then the
57 * driver cannot parse all JSON records from GPSD, and some record
58 * types are vital for the operation of the driver. This indicates a
59 * problem on the protocol level.
60 *
61 * When started on the command line with a debug level >= 2, the
62 * driver dumps the raw received data and the parser input to
63 * stdout. Since the debug level is global, NTPD starts to create a
64 * *lot* of output. It makes sense to pipe it through '(f)grep
65 * GPSD_JSON' before writing the result to disk.
66 *
67 * A bit less intrusive is using netcat or telnet to connect to GPSD
68 * and snoop what NTPD would get. If you try this, you have to send a
69 * WATCH command to GPSD:
70 *
71 * ?WATCH={"device":"/dev/gps0","enable":true,"json":true,"pps":true};<CRLF>
72 *
73 * should show you what GPSD has to say to NTPD. Replace "/dev/gps0"
74 * with the device link used by GPSD, if necessary.
75 */
76
77
78 #ifdef HAVE_CONFIG_H
79 #include <config.h>
80 #endif
81
82 #include "ntp_types.h"
83
84 #if defined(REFCLOCK) && defined(CLOCK_GPSDJSON) && !defined(SYS_WINNT)
85
86 /* =====================================================================
87 * Get the little JSMN library directly into our guts. Use the 'parent
88 * link' feature for maximum speed.
89 */
90 #define JSMN_PARENT_LINKS
91 #include "../libjsmn/jsmn.c"
92
93 /* =====================================================================
94 * JSON parsing stuff
95 */
96
97 #define JSMN_MAXTOK 350
98 #define INVALID_TOKEN (-1)
99
100 typedef struct json_ctx {
101 char * buf;
102 int ntok;
103 jsmntok_t tok[JSMN_MAXTOK];
104 } json_ctx;
105
106 typedef int tok_ref;
107
108 /* Not all targets have 'long long', and not all of them have 'strtoll'.
109 * Sigh. We roll our own integer number parser.
110 */
111 #ifdef HAVE_LONG_LONG
112 typedef signed long long int json_int;
113 typedef unsigned long long int json_uint;
114 #define JSON_INT_MAX LLONG_MAX
115 #define JSON_INT_MIN LLONG_MIN
116 #else
117 typedef signed long int json_int;
118 typedef unsigned long int json_uint;
119 #define JSON_INT_MAX LONG_MAX
120 #define JSON_INT_MIN LONG_MIN
121 #endif
122
123 /* =====================================================================
124 * header stuff we need
125 */
126
127 #include <netdb.h>
128 #include <unistd.h>
129 #include <fcntl.h>
130 #include <string.h>
131 #include <ctype.h>
132 #include <math.h>
133
134 #include <sys/types.h>
135 #include <sys/socket.h>
136 #include <sys/stat.h>
137 #include <netinet/tcp.h>
138
139 #if defined(HAVE_SYS_POLL_H)
140 # include <sys/poll.h>
141 #elif defined(HAVE_SYS_SELECT_H)
142 # include <sys/select.h>
143 #else
144 # error need poll() or select()
145 #endif
146
147 #include "ntpd.h"
148 #include "ntp_io.h"
149 #include "ntp_unixtime.h"
150 #include "ntp_refclock.h"
151 #include "ntp_stdlib.h"
152 #include "ntp_calendar.h"
153 #include "timespecops.h"
154
155 /* get operation modes from mode word.
156
157 * + SERIAL (default) evaluates only serial time information ('STI') as
158 * provided by TPV and TOFF records. TPV evaluation suffers from a
159 * bigger jitter than TOFF, sine it does not contain the receive time
160 * from GPSD and therefore the receive time of NTPD must be
161 * substituted for it. The network latency makes this a second rate
162 * guess.
163 *
164 * If TOFF records are detected in the data stream, the timing
165 * information is gleaned from this record -- it contains the local
166 * receive time stamp from GPSD and therefore eliminates the
167 * transmission latency between GPSD and NTPD. The timing information
168 * from TPV is ignored once a TOFF is detected or expected.
169 *
170 * TPV is still used to check the fix status, so the driver can stop
171 * feeding samples when GPSD says that the time information is
172 * effectively unreliable.
173 *
174 * + STRICT means only feed clock samples when a valid STI/PPS pair is
175 * available. Combines the reference time from STI with the pulse time
176 * from PPS. Masks the serial data jitter as long PPS is available,
177 * but can rapidly deteriorate once PPS drops out.
178 *
179 * + AUTO tries to use STI/PPS pairs if available for some time, and if
180 * this fails for too long switches back to STI only until the PPS
181 * signal becomes available again. See the HTML docs for this driver
182 * about the gotchas and why this is not the default.
183 */
184 #define MODE_OP_MASK 0x03
185 #define MODE_OP_STI 0
186 #define MODE_OP_STRICT 1
187 #define MODE_OP_AUTO 2
188 #define MODE_OP_MAXVAL 2
189 #define MODE_OP_MODE(x) ((x) & MODE_OP_MASK)
190
191 #define PRECISION (-9) /* precision assumed (about 2 ms) */
192 #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */
193 #define REFID "GPSD" /* reference id */
194 #define DESCRIPTION "GPSD JSON client clock" /* who we are */
195
196 #define MAX_PDU_LEN 1600
197 #define TICKOVER_LOW 10
198 #define TICKOVER_HIGH 120
199 #define LOGTHROTTLE 3600
200
201 /* Primary channel PPS avilability dance:
202 * Every good PPS sample gets us a credit of PPS_INCCOUNT points, every
203 * bad/missing PPS sample costs us a debit of PPS_DECCOUNT points. When
204 * the account reaches the upper limit we change to a mode where only
205 * PPS-augmented samples are fed to the core; when the account drops to
206 * zero we switch to a mode where TPV-only timestamps are fed to the
207 * core.
208 * This reduces the chance of rapid alternation between raw and
209 * PPS-augmented time stamps.
210 */
211 #define PPS_MAXCOUNT 60 /* upper limit of account */
212 #define PPS_INCCOUNT 3 /* credit for good samples */
213 #define PPS_DECCOUNT 1 /* debit for bad samples */
214
215 /* The secondary (PPS) channel uses a different strategy to avoid old
216 * PPS samples in the median filter.
217 */
218 #define PPS2_MAXCOUNT 10
219
220 #ifndef BOOL
221 # define BOOL int
222 #endif
223 #ifndef TRUE
224 # define TRUE 1
225 #endif
226 #ifndef FALSE
227 # define FALSE 0
228 #endif
229
230 #define PROTO_VERSION(hi,lo) \
231 ((((uint32_t)(hi) << 16) & 0xFFFF0000u) | \
232 ((uint32_t)(lo) & 0x0FFFFu))
233
234 /* some local typedefs: The NTPD formatting style cries for short type
235 * names, and we provide them locally. Note:the suffix '_t' is reserved
236 * for the standard; I use a capital T instead.
237 */
238 typedef struct peer peerT;
239 typedef struct refclockproc clockprocT;
240 typedef struct addrinfo addrinfoT;
241
242 /* =====================================================================
243 * We use the same device name scheme as does the NMEA driver; since
244 * GPSD supports the same links, we can select devices by a fixed name.
245 */
246 static const char * s_dev_stem = "/dev/gps";
247
248 /* =====================================================================
249 * forward declarations for transfer vector and the vector itself
250 */
251
252 static void gpsd_init (void);
253 static int gpsd_start (int, peerT *);
254 static void gpsd_shutdown (int, peerT *);
255 static void gpsd_receive (struct recvbuf *);
256 static void gpsd_poll (int, peerT *);
257 static void gpsd_control (int, const struct refclockstat *,
258 struct refclockstat *, peerT *);
259 static void gpsd_timer (int, peerT *);
260
261 static int myasprintf(char**, char const*, ...) NTP_PRINTF(2, 3);
262
263 static void enter_opmode(peerT *peer, int mode);
264 static void leave_opmode(peerT *peer, int mode);
265
266 struct refclock refclock_gpsdjson = {
267 gpsd_start, /* start up driver */
268 gpsd_shutdown, /* shut down driver */
269 gpsd_poll, /* transmit poll message */
270 gpsd_control, /* fudge control */
271 gpsd_init, /* initialize driver */
272 noentry, /* buginfo */
273 gpsd_timer /* called once per second */
274 };
275
276 /* =====================================================================
277 * our local clock unit and data
278 */
279 struct gpsd_unit;
280 typedef struct gpsd_unit gpsd_unitT;
281
282 struct gpsd_unit {
283 /* links for sharing between master/slave units */
284 gpsd_unitT *next_unit;
285 size_t refcount;
286
287 /* data for the secondary PPS channel */
288 peerT *pps_peer;
289
290 /* unit and operation modes */
291 int unit;
292 int mode;
293 char *logname; /* cached name for log/print */
294 char * device; /* device name of unit */
295
296 /* current line protocol version */
297 uint32_t proto_version;
298
299 /* PPS time stamps primary + secondary channel */
300 l_fp pps_local; /* when we received the PPS message */
301 l_fp pps_stamp; /* related reference time */
302 l_fp pps_recvt; /* when GPSD detected the pulse */
303 l_fp pps_stamp2;/* related reference time (secondary) */
304 l_fp pps_recvt2;/* when GPSD detected the pulse (secondary)*/
305 int ppscount; /* PPS counter (primary unit) */
306 int ppscount2; /* PPS counter (secondary unit) */
307
308 /* TPV or TOFF serial time information */
309 l_fp sti_local; /* when we received the TPV/TOFF message */
310 l_fp sti_stamp; /* effective GPS time stamp */
311 l_fp sti_recvt; /* when GPSD got the fix */
312
313 /* precision estimates */
314 int16_t sti_prec; /* serial precision based on EPT */
315 int16_t pps_prec; /* PPS precision from GPSD or above */
316
317 /* fudge values for correction, mirrored as 'l_fp' */
318 l_fp pps_fudge; /* PPS fudge primary channel */
319 l_fp pps_fudge2; /* PPS fudge secondary channel */
320 l_fp sti_fudge; /* TPV/TOFF serial data fudge */
321
322 /* Flags to indicate available data */
323 int fl_nosync: 1; /* GPSD signals bad quality */
324 int fl_sti : 1; /* valid TPV/TOFF seen (have time) */
325 int fl_pps : 1; /* valid pulse seen */
326 int fl_pps2 : 1; /* valid pulse seen for PPS channel */
327 int fl_rawsti: 1; /* permit raw TPV/TOFF time stamps */
328 int fl_vers : 1; /* have protocol version */
329 int fl_watch : 1; /* watch reply seen */
330 /* protocol flags */
331 int pf_nsec : 1; /* have nanosec PPS info */
332 int pf_toff : 1; /* have TOFF record for timing */
333
334 /* admin stuff for sockets and device selection */
335 int fdt; /* current connecting socket */
336 addrinfoT * addr; /* next address to try */
337 u_int tickover; /* timeout countdown */
338 u_int tickpres; /* timeout preset */
339
340 /* tallies for the various events */
341 u_int tc_recv; /* received known records */
342 u_int tc_breply; /* bad replies / parsing errors */
343 u_int tc_nosync; /* TPV / sample cycles w/o fix */
344 u_int tc_sti_recv;/* received serial time info records */
345 u_int tc_sti_used;/* used --^-- */
346 u_int tc_pps_recv;/* received PPS timing info records */
347 u_int tc_pps_used;/* used --^-- */
348
349 /* log bloat throttle */
350 u_int logthrottle;/* seconds to next log slot */
351
352 /* The parse context for the current record */
353 json_ctx json_parse;
354
355 /* record assemby buffer and saved length */
356 int buflen;
357 char buffer[MAX_PDU_LEN];
358 };
359
360 /* =====================================================================
361 * static local helpers forward decls
362 */
363 static void gpsd_init_socket(peerT * const peer);
364 static void gpsd_test_socket(peerT * const peer);
365 static void gpsd_stop_socket(peerT * const peer);
366
367 static void gpsd_parse(peerT * const peer,
368 const l_fp * const rtime);
369 static BOOL convert_ascii_time(l_fp * fp, const char * gps_time);
370 static void save_ltc(clockprocT * const pp, const char * const tc);
371 static int syslogok(clockprocT * const pp, gpsd_unitT * const up);
372 static void log_data(peerT *peer, const char *what,
373 const char *buf, size_t len);
374 static int16_t clamped_precision(int rawprec);
375
376 /* =====================================================================
377 * local / static stuff
378 */
379
380 static const char * const s_req_version =
381 "?VERSION;\r\n";
382
383 /* We keep a static list of network addresses for 'localhost:gpsd' or a
384 * fallback alias of it, and we try to connect to them in round-robin
385 * fashion. The service lookup is done during the driver init
386 * function to minmise the impact of 'getaddrinfo()'.
387 *
388 * Alas, the init function is called even if there are no clocks
389 * configured for this driver. So it makes sense to defer the logging of
390 * any errors or other notifications until the first clock unit is
391 * started -- otherwise there might be syslog entries from a driver that
392 * is not used at all.
393 */
394 static addrinfoT *s_gpsd_addr;
395 static gpsd_unitT *s_clock_units;
396
397 /* list of service/socket names we want to resolve against */
398 static const char * const s_svctab[][2] = {
399 { "localhost", "gpsd" },
400 { "localhost", "2947" },
401 { "127.0.0.1", "2947" },
402 { NULL, NULL }
403 };
404
405 /* list of address resolution errors and index of service entry that
406 * finally worked.
407 */
408 static int s_svcerr[sizeof(s_svctab)/sizeof(s_svctab[0])];
409 static int s_svcidx;
410
411 /* =====================================================================
412 * log throttling
413 */
414 static int/*BOOL*/
syslogok(clockprocT * const pp,gpsd_unitT * const up)415 syslogok(
416 clockprocT * const pp,
417 gpsd_unitT * const up)
418 {
419 int res = (0 != (pp->sloppyclockflag & CLK_FLAG3))
420 || (0 == up->logthrottle )
421 || (LOGTHROTTLE == up->logthrottle );
422 if (res)
423 up->logthrottle = LOGTHROTTLE;
424 return res;
425 }
426
427 /* =====================================================================
428 * the clock functions
429 */
430
431 /* ---------------------------------------------------------------------
432 * Init: This currently just gets the socket address for the GPS daemon
433 */
434 static void
gpsd_init(void)435 gpsd_init(void)
436 {
437 addrinfoT hints;
438 int rc, idx;
439
440 memset(s_svcerr, 0, sizeof(s_svcerr));
441 memset(&hints, 0, sizeof(hints));
442 hints.ai_family = AF_UNSPEC;
443 hints.ai_protocol = IPPROTO_TCP;
444 hints.ai_socktype = SOCK_STREAM;
445
446 for (idx = 0; s_svctab[idx][0] && !s_gpsd_addr; idx++) {
447 rc = getaddrinfo(s_svctab[idx][0], s_svctab[idx][1],
448 &hints, &s_gpsd_addr);
449 s_svcerr[idx] = rc;
450 if (0 == rc)
451 break;
452 s_gpsd_addr = NULL;
453 }
454 s_svcidx = idx;
455 }
456
457 /* ---------------------------------------------------------------------
458 * Init Check: flush pending log messages and check if we can proceed
459 */
460 static int/*BOOL*/
gpsd_init_check(void)461 gpsd_init_check(void)
462 {
463 int idx;
464
465 /* Check if there is something to log */
466 if (s_svcidx == 0)
467 return (s_gpsd_addr != NULL);
468
469 /* spool out the resolver errors */
470 for (idx = 0; idx < s_svcidx; ++idx) {
471 msyslog(LOG_WARNING,
472 "GPSD_JSON: failed to resolve '%s:%s', rc=%d (%s)",
473 s_svctab[idx][0], s_svctab[idx][1],
474 s_svcerr[idx], gai_strerror(s_svcerr[idx]));
475 }
476
477 /* check if it was fatal, or if we can proceed */
478 if (s_gpsd_addr == NULL)
479 msyslog(LOG_ERR, "%s",
480 "GPSD_JSON: failed to get socket address, giving up.");
481 else if (idx != 0)
482 msyslog(LOG_WARNING,
483 "GPSD_JSON: using '%s:%s' instead of '%s:%s'",
484 s_svctab[idx][0], s_svctab[idx][1],
485 s_svctab[0][0], s_svctab[0][1]);
486
487 /* make sure this gets logged only once and tell if we can
488 * proceed or not
489 */
490 s_svcidx = 0;
491 return (s_gpsd_addr != NULL);
492 }
493
494 /* ---------------------------------------------------------------------
495 * Start: allocate a unit pointer and set up the runtime data
496 */
497 static int
gpsd_start(int unit,peerT * peer)498 gpsd_start(
499 int unit,
500 peerT * peer)
501 {
502 clockprocT * const pp = peer->procptr;
503 gpsd_unitT * up;
504 gpsd_unitT ** uscan = &s_clock_units;
505
506 struct stat sb;
507
508 /* check if we can proceed at all or if init failed */
509 if ( ! gpsd_init_check())
510 return FALSE;
511
512 /* search for matching unit */
513 while ((up = *uscan) != NULL && up->unit != (unit & 0x7F))
514 uscan = &up->next_unit;
515 if (up == NULL) {
516 /* alloc unit, add to list and increment use count ASAP. */
517 up = emalloc_zero(sizeof(*up));
518 *uscan = up;
519 ++up->refcount;
520
521 /* initialize the unit structure */
522 up->logname = estrdup(refnumtoa(&peer->srcadr));
523 up->unit = unit & 0x7F;
524 up->fdt = -1;
525 up->addr = s_gpsd_addr;
526 up->tickpres = TICKOVER_LOW;
527
528 /* Create the device name and check for a Character
529 * Device. It's assumed that GPSD was started with the
530 * same link, so the names match. (If this is not
531 * practicable, we will have to read the symlink, if
532 * any, so we can get the true device file.)
533 */
534 if (-1 == myasprintf(&up->device, "%s%u",
535 s_dev_stem, up->unit)) {
536 msyslog(LOG_ERR, "%s: clock device name too long",
537 up->logname);
538 goto dev_fail;
539 }
540 if (-1 == stat(up->device, &sb) || !S_ISCHR(sb.st_mode)) {
541 msyslog(LOG_ERR, "%s: '%s' is not a character device",
542 up->logname, up->device);
543 goto dev_fail;
544 }
545 } else {
546 /* All set up, just increment use count. */
547 ++up->refcount;
548 }
549
550 /* setup refclock processing */
551 pp->unitptr = (caddr_t)up;
552 pp->io.fd = -1;
553 pp->io.clock_recv = gpsd_receive;
554 pp->io.srcclock = peer;
555 pp->io.datalen = 0;
556 pp->a_lastcode[0] = '\0';
557 pp->lencode = 0;
558 pp->clockdesc = DESCRIPTION;
559 memcpy(&pp->refid, REFID, 4);
560
561 /* Initialize miscellaneous variables */
562 if (unit >= 128)
563 peer->precision = PPS_PRECISION;
564 else
565 peer->precision = PRECISION;
566
567 /* If the daemon name lookup failed, just give up now. */
568 if (NULL == up->addr) {
569 msyslog(LOG_ERR, "%s: no GPSD socket address, giving up",
570 up->logname);
571 goto dev_fail;
572 }
573
574 LOGIF(CLOCKINFO,
575 (LOG_NOTICE, "%s: startup, device is '%s'",
576 refnumtoa(&peer->srcadr), up->device));
577 up->mode = MODE_OP_MODE(peer->ttl);
578 if (up->mode > MODE_OP_MAXVAL)
579 up->mode = 0;
580 if (unit >= 128)
581 up->pps_peer = peer;
582 else
583 enter_opmode(peer, up->mode);
584 return TRUE;
585
586 dev_fail:
587 /* On failure, remove all UNIT ressources and declare defeat. */
588
589 INSIST (up);
590 if (!--up->refcount) {
591 *uscan = up->next_unit;
592 free(up->device);
593 free(up);
594 }
595
596 pp->unitptr = (caddr_t)NULL;
597 return FALSE;
598 }
599
600 /* ------------------------------------------------------------------ */
601
602 static void
gpsd_shutdown(int unit,peerT * peer)603 gpsd_shutdown(
604 int unit,
605 peerT * peer)
606 {
607 clockprocT * const pp = peer->procptr;
608 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
609 gpsd_unitT ** uscan = &s_clock_units;
610
611 UNUSED_ARG(unit);
612
613 /* The unit pointer might have been removed already. */
614 if (up == NULL)
615 return;
616
617 /* now check if we must close IO resources */
618 if (peer != up->pps_peer) {
619 if (-1 != pp->io.fd) {
620 DPRINTF(1, ("%s: closing clock, fd=%d\n",
621 up->logname, pp->io.fd));
622 io_closeclock(&pp->io);
623 pp->io.fd = -1;
624 }
625 if (up->fdt != -1)
626 close(up->fdt);
627 }
628 /* decrement use count and eventually remove this unit. */
629 if (!--up->refcount) {
630 /* unlink this unit */
631 while (*uscan != NULL)
632 if (*uscan == up)
633 *uscan = up->next_unit;
634 else
635 uscan = &(*uscan)->next_unit;
636 free(up->logname);
637 free(up->device);
638 free(up);
639 }
640 pp->unitptr = (caddr_t)NULL;
641 LOGIF(CLOCKINFO,
642 (LOG_NOTICE, "%s: shutdown", refnumtoa(&peer->srcadr)));
643 }
644
645 /* ------------------------------------------------------------------ */
646
647 static void
gpsd_receive(struct recvbuf * rbufp)648 gpsd_receive(
649 struct recvbuf * rbufp)
650 {
651 /* declare & init control structure ptrs */
652 peerT * const peer = rbufp->recv_peer;
653 clockprocT * const pp = peer->procptr;
654 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
655
656 const char *psrc, *esrc;
657 char *pdst, *edst, ch;
658
659 /* log the data stream, if this is enabled */
660 log_data(peer, "recv", (const char*)rbufp->recv_buffer,
661 (size_t)rbufp->recv_length);
662
663
664 /* Since we're getting a raw stream data, we must assemble lines
665 * in our receive buffer. We can't use neither 'refclock_gtraw'
666 * not 'refclock_gtlin' here... We process chars until we reach
667 * an EoL (that is, line feed) but we truncate the message if it
668 * does not fit the buffer. GPSD might truncate messages, too,
669 * so dealing with truncated buffers is necessary anyway.
670 */
671 psrc = (const char*)rbufp->recv_buffer;
672 esrc = psrc + rbufp->recv_length;
673
674 pdst = up->buffer + up->buflen;
675 edst = pdst + sizeof(up->buffer) - 1; /* for trailing NUL */
676
677 while (psrc != esrc) {
678 ch = *psrc++;
679 if (ch == '\n') {
680 /* trim trailing whitespace & terminate buffer */
681 while (pdst != up->buffer && pdst[-1] <= ' ')
682 --pdst;
683 *pdst = '\0';
684 /* process data and reset buffer */
685 up->buflen = pdst - up->buffer;
686 gpsd_parse(peer, &rbufp->recv_time);
687 pdst = up->buffer;
688 } else if (pdst != edst) {
689 /* add next char, ignoring leading whitespace */
690 if (ch > ' ' || pdst != up->buffer)
691 *pdst++ = ch;
692 }
693 }
694 up->buflen = pdst - up->buffer;
695 up->tickover = TICKOVER_LOW;
696 }
697
698 /* ------------------------------------------------------------------ */
699
700 static void
poll_primary(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)701 poll_primary(
702 peerT * const peer ,
703 clockprocT * const pp ,
704 gpsd_unitT * const up )
705 {
706 if (pp->coderecv != pp->codeproc) {
707 /* all is well */
708 pp->lastref = pp->lastrec;
709 refclock_report(peer, CEVNT_NOMINAL);
710 refclock_receive(peer);
711 } else {
712 /* Not working properly, admit to it. If we have no
713 * connection to GPSD, declare the clock as faulty. If
714 * there were bad replies, this is handled as the major
715 * cause, and everything else is just a timeout.
716 */
717 peer->precision = PRECISION;
718 if (-1 == pp->io.fd)
719 refclock_report(peer, CEVNT_FAULT);
720 else if (0 != up->tc_breply)
721 refclock_report(peer, CEVNT_BADREPLY);
722 else
723 refclock_report(peer, CEVNT_TIMEOUT);
724 }
725
726 if (pp->sloppyclockflag & CLK_FLAG4)
727 mprintf_clock_stats(
728 &peer->srcadr,"%u %u %u %u %u %u %u",
729 up->tc_recv,
730 up->tc_breply, up->tc_nosync,
731 up->tc_sti_recv, up->tc_sti_used,
732 up->tc_pps_recv, up->tc_pps_used);
733
734 /* clear tallies for next round */
735 up->tc_breply = 0;
736 up->tc_recv = 0;
737 up->tc_nosync = 0;
738 up->tc_sti_recv = 0;
739 up->tc_sti_used = 0;
740 up->tc_pps_recv = 0;
741 up->tc_pps_used = 0;
742 }
743
744 static void
poll_secondary(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)745 poll_secondary(
746 peerT * const peer ,
747 clockprocT * const pp ,
748 gpsd_unitT * const up )
749 {
750 if (pp->coderecv != pp->codeproc) {
751 /* all is well */
752 pp->lastref = pp->lastrec;
753 refclock_report(peer, CEVNT_NOMINAL);
754 refclock_receive(peer);
755 } else {
756 peer->precision = PPS_PRECISION;
757 peer->flags &= ~FLAG_PPS;
758 refclock_report(peer, CEVNT_TIMEOUT);
759 }
760 }
761
762 static void
gpsd_poll(int unit,peerT * peer)763 gpsd_poll(
764 int unit,
765 peerT * peer)
766 {
767 clockprocT * const pp = peer->procptr;
768 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
769
770 ++pp->polls;
771 if (peer == up->pps_peer)
772 poll_secondary(peer, pp, up);
773 else
774 poll_primary(peer, pp, up);
775 }
776
777 /* ------------------------------------------------------------------ */
778
779 static void
gpsd_control(int unit,const struct refclockstat * in_st,struct refclockstat * out_st,peerT * peer)780 gpsd_control(
781 int unit,
782 const struct refclockstat * in_st,
783 struct refclockstat * out_st,
784 peerT * peer )
785 {
786 clockprocT * const pp = peer->procptr;
787 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
788
789 if (peer == up->pps_peer) {
790 DTOLFP(pp->fudgetime1, &up->pps_fudge2);
791 if ( ! (pp->sloppyclockflag & CLK_FLAG1))
792 peer->flags &= ~FLAG_PPS;
793 } else {
794 /* save preprocessed fudge times */
795 DTOLFP(pp->fudgetime1, &up->pps_fudge);
796 DTOLFP(pp->fudgetime2, &up->sti_fudge);
797
798 if (MODE_OP_MODE(up->mode ^ peer->ttl)) {
799 leave_opmode(peer, up->mode);
800 up->mode = MODE_OP_MODE(peer->ttl);
801 enter_opmode(peer, up->mode);
802 }
803 }
804 }
805
806 /* ------------------------------------------------------------------ */
807
808 static void
timer_primary(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)809 timer_primary(
810 peerT * const peer ,
811 clockprocT * const pp ,
812 gpsd_unitT * const up )
813 {
814 int rc;
815
816 /* This is used for timeout handling. Nothing that needs
817 * sub-second precison happens here, so receive/connect/retry
818 * timeouts are simply handled by a count down, and then we
819 * decide what to do by the socket values.
820 *
821 * Note that the timer stays at zero here, unless some of the
822 * functions set it to another value.
823 */
824 if (up->logthrottle)
825 --up->logthrottle;
826 if (up->tickover)
827 --up->tickover;
828 switch (up->tickover) {
829 case 4:
830 /* If we are connected to GPSD, try to get a live signal
831 * by querying the version. Otherwise just check the
832 * socket to become ready.
833 */
834 if (-1 != pp->io.fd) {
835 size_t rlen = strlen(s_req_version);
836 DPRINTF(2, ("%s: timer livecheck: '%s'\n",
837 up->logname, s_req_version));
838 log_data(peer, "send", s_req_version, rlen);
839 rc = write(pp->io.fd, s_req_version, rlen);
840 (void)rc;
841 } else if (-1 != up->fdt) {
842 gpsd_test_socket(peer);
843 }
844 break;
845
846 case 0:
847 if (-1 != pp->io.fd)
848 gpsd_stop_socket(peer);
849 else if (-1 != up->fdt)
850 gpsd_test_socket(peer);
851 else if (NULL != s_gpsd_addr)
852 gpsd_init_socket(peer);
853 break;
854
855 default:
856 if (-1 == pp->io.fd && -1 != up->fdt)
857 gpsd_test_socket(peer);
858 }
859 }
860
861 static void
timer_secondary(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)862 timer_secondary(
863 peerT * const peer ,
864 clockprocT * const pp ,
865 gpsd_unitT * const up )
866 {
867 /* Reduce the count by one. Flush sample buffer and clear PPS
868 * flag when this happens.
869 */
870 up->ppscount2 = max(0, (up->ppscount2 - 1));
871 if (0 == up->ppscount2) {
872 if (pp->coderecv != pp->codeproc) {
873 refclock_report(peer, CEVNT_TIMEOUT);
874 pp->coderecv = pp->codeproc;
875 }
876 peer->flags &= ~FLAG_PPS;
877 }
878 }
879
880 static void
gpsd_timer(int unit,peerT * peer)881 gpsd_timer(
882 int unit,
883 peerT * peer)
884 {
885 clockprocT * const pp = peer->procptr;
886 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
887
888 if (peer == up->pps_peer)
889 timer_secondary(peer, pp, up);
890 else
891 timer_primary(peer, pp, up);
892 }
893
894 /* =====================================================================
895 * handle opmode switches
896 */
897
898 static void
enter_opmode(peerT * peer,int mode)899 enter_opmode(
900 peerT *peer,
901 int mode)
902 {
903 clockprocT * const pp = peer->procptr;
904 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
905
906 DPRINTF(1, ("%s: enter operation mode %d\n",
907 up->logname, MODE_OP_MODE(mode)));
908
909 if (MODE_OP_MODE(mode) == MODE_OP_AUTO) {
910 up->fl_rawsti = 0;
911 up->ppscount = PPS_MAXCOUNT / 2;
912 }
913 up->fl_pps = 0;
914 up->fl_sti = 0;
915 }
916
917 /* ------------------------------------------------------------------ */
918
919 static void
leave_opmode(peerT * peer,int mode)920 leave_opmode(
921 peerT *peer,
922 int mode)
923 {
924 clockprocT * const pp = peer->procptr;
925 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
926
927 DPRINTF(1, ("%s: leaving operation mode %d\n",
928 up->logname, MODE_OP_MODE(mode)));
929
930 if (MODE_OP_MODE(mode) == MODE_OP_AUTO) {
931 up->fl_rawsti = 0;
932 up->ppscount = 0;
933 }
934 up->fl_pps = 0;
935 up->fl_sti = 0;
936 }
937
938 /* =====================================================================
939 * operation mode specific evaluation
940 */
941
942 static void
add_clock_sample(peerT * const peer,clockprocT * const pp,l_fp stamp,l_fp recvt)943 add_clock_sample(
944 peerT * const peer ,
945 clockprocT * const pp ,
946 l_fp stamp,
947 l_fp recvt)
948 {
949 pp->lastref = stamp;
950 if (pp->coderecv == pp->codeproc)
951 refclock_report(peer, CEVNT_NOMINAL);
952 refclock_process_offset(pp, stamp, recvt, 0.0);
953 }
954
955 /* ------------------------------------------------------------------ */
956
957 static void
eval_strict(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)958 eval_strict(
959 peerT * const peer ,
960 clockprocT * const pp ,
961 gpsd_unitT * const up )
962 {
963 if (up->fl_sti && up->fl_pps) {
964 /* use TPV reference time + PPS receive time */
965 add_clock_sample(peer, pp, up->sti_stamp, up->pps_recvt);
966 peer->precision = up->pps_prec;
967 /* both packets consumed now... */
968 up->fl_pps = 0;
969 up->fl_sti = 0;
970 ++up->tc_sti_used;
971 }
972 }
973
974 /* ------------------------------------------------------------------ */
975 /* PPS processing for the secondary channel. GPSD provides us with full
976 * timing information, so there's no danger of PLL-locking to the wrong
977 * second. The belts and suspenders needed for the raw ATOM clock are
978 * unnecessary here.
979 */
980 static void
eval_pps_secondary(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)981 eval_pps_secondary(
982 peerT * const peer ,
983 clockprocT * const pp ,
984 gpsd_unitT * const up )
985 {
986 if (up->fl_pps2) {
987 /* feed data */
988 add_clock_sample(peer, pp, up->pps_stamp2, up->pps_recvt2);
989 peer->precision = up->pps_prec;
990 /* PPS peer flag logic */
991 up->ppscount2 = min(PPS2_MAXCOUNT, (up->ppscount2 + 2));
992 if ((PPS2_MAXCOUNT == up->ppscount2) &&
993 (pp->sloppyclockflag & CLK_FLAG1) )
994 peer->flags |= FLAG_PPS;
995 /* mark time stamp as burned... */
996 up->fl_pps2 = 0;
997 ++up->tc_pps_used;
998 }
999 }
1000
1001 /* ------------------------------------------------------------------ */
1002
1003 static void
eval_serial(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)1004 eval_serial(
1005 peerT * const peer ,
1006 clockprocT * const pp ,
1007 gpsd_unitT * const up )
1008 {
1009 if (up->fl_sti) {
1010 add_clock_sample(peer, pp, up->sti_stamp, up->sti_recvt);
1011 peer->precision = up->sti_prec;
1012 /* mark time stamp as burned... */
1013 up->fl_sti = 0;
1014 ++up->tc_sti_used;
1015 }
1016 }
1017
1018 /* ------------------------------------------------------------------ */
1019 static void
eval_auto(peerT * const peer,clockprocT * const pp,gpsd_unitT * const up)1020 eval_auto(
1021 peerT * const peer ,
1022 clockprocT * const pp ,
1023 gpsd_unitT * const up )
1024 {
1025 /* If there's no TPV available, stop working here... */
1026 if (!up->fl_sti)
1027 return;
1028
1029 /* check how to handle STI+PPS: Can PPS be used to augment STI
1030 * (or vice versae), do we drop the sample because there is a
1031 * temporary missing PPS signal, or do we feed on STI time
1032 * stamps alone?
1033 *
1034 * Do a counter/threshold dance to decide how to proceed.
1035 */
1036 if (up->fl_pps) {
1037 up->ppscount = min(PPS_MAXCOUNT,
1038 (up->ppscount + PPS_INCCOUNT));
1039 if ((PPS_MAXCOUNT == up->ppscount) && up->fl_rawsti) {
1040 up->fl_rawsti = 0;
1041 msyslog(LOG_INFO,
1042 "%s: expect valid PPS from now",
1043 up->logname);
1044 }
1045 } else {
1046 up->ppscount = max(0, (up->ppscount - PPS_DECCOUNT));
1047 if ((0 == up->ppscount) && !up->fl_rawsti) {
1048 up->fl_rawsti = -1;
1049 msyslog(LOG_WARNING,
1050 "%s: use TPV alone from now",
1051 up->logname);
1052 }
1053 }
1054
1055 /* now eventually feed the sample */
1056 if (up->fl_rawsti)
1057 eval_serial(peer, pp, up);
1058 else
1059 eval_strict(peer, pp, up);
1060 }
1061
1062 /* =====================================================================
1063 * JSON parsing stuff
1064 */
1065
1066 /* ------------------------------------------------------------------ */
1067 /* Parse a decimal integer with a possible sign. Works like 'strtoll()'
1068 * or 'strtol()', but with a fixed base of 10 and without eating away
1069 * leading whitespace. For the error codes, the handling of the end
1070 * pointer and the return values see 'strtol()'.
1071 */
1072 static json_int
strtojint(const char * cp,char ** ep)1073 strtojint(
1074 const char *cp, char **ep)
1075 {
1076 json_uint accu, limit_lo, limit_hi;
1077 int flags; /* bit 0: overflow; bit 1: sign */
1078 const char * hold;
1079
1080 /* pointer union to circumvent a tricky/sticky const issue */
1081 union { const char * c; char * v; } vep;
1082
1083 /* store initial value of 'cp' -- see 'strtol()' */
1084 vep.c = cp;
1085
1086 /* Eat away an optional sign and set the limits accordingly: The
1087 * high limit is the maximum absolute value that can be returned,
1088 * and the low limit is the biggest value that does not cause an
1089 * overflow when multiplied with 10. Avoid negation overflows.
1090 */
1091 if (*cp == '-') {
1092 cp += 1;
1093 flags = 2;
1094 limit_hi = (json_uint)-(JSON_INT_MIN + 1) + 1;
1095 } else {
1096 cp += (*cp == '+');
1097 flags = 0;
1098 limit_hi = (json_uint)JSON_INT_MAX;
1099 }
1100 limit_lo = limit_hi / 10;
1101
1102 /* Now try to convert a sequence of digits. */
1103 hold = cp;
1104 accu = 0;
1105 while (isdigit(*(const u_char*)cp)) {
1106 flags |= (accu > limit_lo);
1107 accu = accu * 10 + (*(const u_char*)cp++ - '0');
1108 flags |= (accu > limit_hi);
1109 }
1110 /* Check for empty conversion (no digits seen). */
1111 if (hold != cp)
1112 vep.c = cp;
1113 else
1114 errno = EINVAL; /* accu is still zero */
1115 /* Check for range overflow */
1116 if (flags & 1) {
1117 errno = ERANGE;
1118 accu = limit_hi;
1119 }
1120 /* If possible, store back the end-of-conversion pointer */
1121 if (ep)
1122 *ep = vep.v;
1123 /* If negative, return the negated result if the accu is not
1124 * zero. Avoid negation overflows.
1125 */
1126 if ((flags & 2) && accu)
1127 return -(json_int)(accu - 1) - 1;
1128 else
1129 return (json_int)accu;
1130 }
1131
1132 /* ------------------------------------------------------------------ */
1133
1134 static tok_ref
json_token_skip(const json_ctx * ctx,tok_ref tid)1135 json_token_skip(
1136 const json_ctx * ctx,
1137 tok_ref tid)
1138 {
1139 if (tid >= 0 && tid < ctx->ntok) {
1140 int len = ctx->tok[tid].size;
1141 /* For arrays and objects, the size is the number of
1142 * ITEMS in the compound. Thats the number of objects in
1143 * the array, and the number of key/value pairs for
1144 * objects. In theory, the key must be a string, and we
1145 * could simply skip one token before skipping the
1146 * value, which can be anything. We're a bit paranoid
1147 * and lazy at the same time: We simply double the
1148 * number of tokens to skip and fall through into the
1149 * array processing when encountering an object.
1150 */
1151 switch (ctx->tok[tid].type) {
1152 case JSMN_OBJECT:
1153 len *= 2;
1154 /* FALLTHROUGH */
1155 case JSMN_ARRAY:
1156 for (++tid; len; --len)
1157 tid = json_token_skip(ctx, tid);
1158 break;
1159
1160 default:
1161 ++tid;
1162 break;
1163 }
1164 /* The next condition should never be true, but paranoia
1165 * prevails...
1166 */
1167 if (tid < 0 || tid > ctx->ntok)
1168 tid = ctx->ntok;
1169 }
1170 return tid;
1171 }
1172
1173 /* ------------------------------------------------------------------ */
1174
1175 static int
json_object_lookup(const json_ctx * ctx,tok_ref tid,const char * key,int what)1176 json_object_lookup(
1177 const json_ctx * ctx ,
1178 tok_ref tid ,
1179 const char * key ,
1180 int what)
1181 {
1182 int len;
1183
1184 if (tid < 0 || tid >= ctx->ntok ||
1185 ctx->tok[tid].type != JSMN_OBJECT)
1186 return INVALID_TOKEN;
1187
1188 len = ctx->tok[tid].size;
1189 for (++tid; len && tid+1 < ctx->ntok; --len) {
1190 if (ctx->tok[tid].type != JSMN_STRING) { /* Blooper! */
1191 tid = json_token_skip(ctx, tid); /* skip key */
1192 tid = json_token_skip(ctx, tid); /* skip val */
1193 } else if (strcmp(key, ctx->buf + ctx->tok[tid].start)) {
1194 tid = json_token_skip(ctx, tid+1); /* skip key+val */
1195 } else if (what < 0 || (u_int)what == ctx->tok[tid+1].type) {
1196 return tid + 1;
1197 } else {
1198 break;
1199 }
1200 /* if skipping ahead returned an error, bail out here. */
1201 if (tid < 0)
1202 break;
1203 }
1204 return INVALID_TOKEN;
1205 }
1206
1207 /* ------------------------------------------------------------------ */
1208
1209 static const char*
json_object_lookup_primitive(const json_ctx * ctx,tok_ref tid,const char * key)1210 json_object_lookup_primitive(
1211 const json_ctx * ctx,
1212 tok_ref tid,
1213 const char * key)
1214 {
1215 tid = json_object_lookup(ctx, tid, key, JSMN_PRIMITIVE);
1216 if (INVALID_TOKEN != tid)
1217 return ctx->buf + ctx->tok[tid].start;
1218 else
1219 return NULL;
1220 }
1221 /* ------------------------------------------------------------------ */
1222 /* look up a boolean value. This essentially returns a tribool:
1223 * 0->false, 1->true, (-1)->error/undefined
1224 */
1225 static int
json_object_lookup_bool(const json_ctx * ctx,tok_ref tid,const char * key)1226 json_object_lookup_bool(
1227 const json_ctx * ctx,
1228 tok_ref tid,
1229 const char * key)
1230 {
1231 const char *cp;
1232 cp = json_object_lookup_primitive(ctx, tid, key);
1233 switch ( cp ? *cp : '\0') {
1234 case 't': return 1;
1235 case 'f': return 0;
1236 default : return -1;
1237 }
1238 }
1239
1240 /* ------------------------------------------------------------------ */
1241
1242 static const char*
json_object_lookup_string(const json_ctx * ctx,tok_ref tid,const char * key)1243 json_object_lookup_string(
1244 const json_ctx * ctx,
1245 tok_ref tid,
1246 const char * key)
1247 {
1248 tid = json_object_lookup(ctx, tid, key, JSMN_STRING);
1249 if (INVALID_TOKEN != tid)
1250 return ctx->buf + ctx->tok[tid].start;
1251 return NULL;
1252 }
1253
1254 static const char*
json_object_lookup_string_default(const json_ctx * ctx,tok_ref tid,const char * key,const char * def)1255 json_object_lookup_string_default(
1256 const json_ctx * ctx,
1257 tok_ref tid,
1258 const char * key,
1259 const char * def)
1260 {
1261 tid = json_object_lookup(ctx, tid, key, JSMN_STRING);
1262 if (INVALID_TOKEN != tid)
1263 return ctx->buf + ctx->tok[tid].start;
1264 return def;
1265 }
1266
1267 /* ------------------------------------------------------------------ */
1268
1269 static json_int
json_object_lookup_int(const json_ctx * ctx,tok_ref tid,const char * key)1270 json_object_lookup_int(
1271 const json_ctx * ctx,
1272 tok_ref tid,
1273 const char * key)
1274 {
1275 json_int ret;
1276 const char * cp;
1277 char * ep;
1278
1279 cp = json_object_lookup_primitive(ctx, tid, key);
1280 if (NULL != cp) {
1281 ret = strtojint(cp, &ep);
1282 if (cp != ep && '\0' == *ep)
1283 return ret;
1284 } else {
1285 errno = EINVAL;
1286 }
1287 return 0;
1288 }
1289
1290 static json_int
json_object_lookup_int_default(const json_ctx * ctx,tok_ref tid,const char * key,json_int def)1291 json_object_lookup_int_default(
1292 const json_ctx * ctx,
1293 tok_ref tid,
1294 const char * key,
1295 json_int def)
1296 {
1297 json_int ret;
1298 const char * cp;
1299 char * ep;
1300
1301 cp = json_object_lookup_primitive(ctx, tid, key);
1302 if (NULL != cp) {
1303 ret = strtojint(cp, &ep);
1304 if (cp != ep && '\0' == *ep)
1305 return ret;
1306 }
1307 return def;
1308 }
1309
1310 /* ------------------------------------------------------------------ */
1311 #if 0 /* currently unused */
1312 static double
1313 json_object_lookup_float(
1314 const json_ctx * ctx,
1315 tok_ref tid,
1316 const char * key)
1317 {
1318 double ret;
1319 const char * cp;
1320 char * ep;
1321
1322 cp = json_object_lookup_primitive(ctx, tid, key);
1323 if (NULL != cp) {
1324 ret = strtod(cp, &ep);
1325 if (cp != ep && '\0' == *ep)
1326 return ret;
1327 } else {
1328 errno = EINVAL;
1329 }
1330 return 0.0;
1331 }
1332 #endif
1333
1334 static double
json_object_lookup_float_default(const json_ctx * ctx,tok_ref tid,const char * key,double def)1335 json_object_lookup_float_default(
1336 const json_ctx * ctx,
1337 tok_ref tid,
1338 const char * key,
1339 double def)
1340 {
1341 double ret;
1342 const char * cp;
1343 char * ep;
1344
1345 cp = json_object_lookup_primitive(ctx, tid, key);
1346 if (NULL != cp) {
1347 ret = strtod(cp, &ep);
1348 if (cp != ep && '\0' == *ep)
1349 return ret;
1350 }
1351 return def;
1352 }
1353
1354 /* ------------------------------------------------------------------ */
1355
1356 static BOOL
json_parse_record(json_ctx * ctx,char * buf,size_t len)1357 json_parse_record(
1358 json_ctx * ctx,
1359 char * buf,
1360 size_t len)
1361 {
1362 jsmn_parser jsm;
1363 int idx, rc;
1364
1365 jsmn_init(&jsm);
1366 rc = jsmn_parse(&jsm, buf, len, ctx->tok, JSMN_MAXTOK);
1367 if (rc <= 0)
1368 return FALSE;
1369 ctx->buf = buf;
1370 ctx->ntok = rc;
1371
1372 if (JSMN_OBJECT != ctx->tok[0].type)
1373 return FALSE; /* not object!?! */
1374
1375 /* Make all tokens NUL terminated by overwriting the
1376 * terminator symbol. Makes string compares and number parsing a
1377 * lot easier!
1378 */
1379 for (idx = 0; idx < ctx->ntok; ++idx)
1380 if (ctx->tok[idx].end > ctx->tok[idx].start)
1381 ctx->buf[ctx->tok[idx].end] = '\0';
1382 return TRUE;
1383 }
1384
1385
1386 /* =====================================================================
1387 * static local helpers
1388 */
1389 static BOOL
get_binary_time(l_fp * const dest,json_ctx * const jctx,const char * const time_name,const char * const frac_name,long fscale)1390 get_binary_time(
1391 l_fp * const dest ,
1392 json_ctx * const jctx ,
1393 const char * const time_name,
1394 const char * const frac_name,
1395 long fscale )
1396 {
1397 BOOL retv = FALSE;
1398 struct timespec ts;
1399
1400 errno = 0;
1401 ts.tv_sec = (time_t)json_object_lookup_int(jctx, 0, time_name);
1402 ts.tv_nsec = (long )json_object_lookup_int(jctx, 0, frac_name);
1403 if (0 == errno) {
1404 ts.tv_nsec *= fscale;
1405 *dest = tspec_stamp_to_lfp(ts);
1406 retv = TRUE;
1407 }
1408 return retv;
1409 }
1410
1411 /* ------------------------------------------------------------------ */
1412 /* Process a WATCH record
1413 *
1414 * Currently this is only used to recognise that the device is present
1415 * and that we're listed subscribers.
1416 */
1417 static void
process_watch(peerT * const peer,json_ctx * const jctx,const l_fp * const rtime)1418 process_watch(
1419 peerT * const peer ,
1420 json_ctx * const jctx ,
1421 const l_fp * const rtime)
1422 {
1423 clockprocT * const pp = peer->procptr;
1424 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1425
1426 const char * path;
1427
1428 path = json_object_lookup_string(jctx, 0, "device");
1429 if (NULL == path || strcmp(path, up->device))
1430 return;
1431
1432 if (json_object_lookup_bool(jctx, 0, "enable") > 0 &&
1433 json_object_lookup_bool(jctx, 0, "json" ) > 0 )
1434 up->fl_watch = -1;
1435 else
1436 up->fl_watch = 0;
1437 DPRINTF(2, ("%s: process_watch, enabled=%d\n",
1438 up->logname, (up->fl_watch & 1)));
1439 }
1440
1441 /* ------------------------------------------------------------------ */
1442
1443 static void
process_version(peerT * const peer,json_ctx * const jctx,const l_fp * const rtime)1444 process_version(
1445 peerT * const peer ,
1446 json_ctx * const jctx ,
1447 const l_fp * const rtime)
1448 {
1449 clockprocT * const pp = peer->procptr;
1450 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1451
1452 int len;
1453 char * buf;
1454 const char *revision;
1455 const char *release;
1456 uint16_t pvhi, pvlo;
1457
1458 /* get protocol version number */
1459 revision = json_object_lookup_string_default(
1460 jctx, 0, "rev", "(unknown)");
1461 release = json_object_lookup_string_default(
1462 jctx, 0, "release", "(unknown)");
1463 errno = 0;
1464 pvhi = (uint16_t)json_object_lookup_int(jctx, 0, "proto_major");
1465 pvlo = (uint16_t)json_object_lookup_int(jctx, 0, "proto_minor");
1466
1467 if (0 == errno) {
1468 if ( ! up->fl_vers)
1469 msyslog(LOG_INFO,
1470 "%s: GPSD revision=%s release=%s protocol=%u.%u",
1471 up->logname, revision, release,
1472 pvhi, pvlo);
1473 up->proto_version = PROTO_VERSION(pvhi, pvlo);
1474 up->fl_vers = -1;
1475 } else {
1476 if (syslogok(pp, up))
1477 msyslog(LOG_INFO,
1478 "%s: could not evaluate version data",
1479 up->logname);
1480 return;
1481 }
1482 /* With the 3.9 GPSD protocol, '*_musec' vanished from the PPS
1483 * record and was replace by '*_nsec'.
1484 */
1485 up->pf_nsec = -(up->proto_version >= PROTO_VERSION(3,9));
1486
1487 /* With the 3.10 protocol we can get TOFF records for better
1488 * timing information.
1489 */
1490 up->pf_toff = -(up->proto_version >= PROTO_VERSION(3,10));
1491
1492 /* request watch for our GPS device if not yet watched.
1493 *
1494 * The version string is also sent as a life signal, if we have
1495 * seen useable data. So if we're already watching the device,
1496 * skip the request.
1497 *
1498 * Reuse the input buffer, which is no longer needed in the
1499 * current cycle. Also assume that we can write the watch
1500 * request in one sweep into the socket; since we do not do
1501 * output otherwise, this should always work. (Unless the
1502 * TCP/IP window size gets lower than the length of the
1503 * request. We handle that when it happens.)
1504 */
1505 if (up->fl_watch)
1506 return;
1507
1508 /* The logon string is actually the ?WATCH command of GPSD,
1509 * using JSON data and selecting the GPS device name we created
1510 * from our unit number. We have an old a newer version that
1511 * request PPS (and TOFF) transmission.
1512 */
1513 snprintf(up->buffer, sizeof(up->buffer),
1514 "?WATCH={\"device\":\"%s\",\"enable\":true,\"json\":true%s};\r\n",
1515 up->device, (up->pf_toff ? ",\"pps\":true" : ""));
1516 buf = up->buffer;
1517 len = strlen(buf);
1518 log_data(peer, "send", buf, len);
1519 if (len != write(pp->io.fd, buf, len) && (syslogok(pp, up))) {
1520 /* Note: if the server fails to read our request, the
1521 * resulting data timeout will take care of the
1522 * connection!
1523 */
1524 msyslog(LOG_ERR, "%s: failed to write watch request (%m)",
1525 up->logname);
1526 }
1527 }
1528
1529 /* ------------------------------------------------------------------ */
1530
1531 static void
process_tpv(peerT * const peer,json_ctx * const jctx,const l_fp * const rtime)1532 process_tpv(
1533 peerT * const peer ,
1534 json_ctx * const jctx ,
1535 const l_fp * const rtime)
1536 {
1537 clockprocT * const pp = peer->procptr;
1538 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1539
1540 const char * gps_time;
1541 int gps_mode;
1542 double ept;
1543 int xlog2;
1544
1545 gps_mode = (int)json_object_lookup_int_default(
1546 jctx, 0, "mode", 0);
1547
1548 gps_time = json_object_lookup_string(
1549 jctx, 0, "time");
1550
1551 /* accept time stamps only in 2d or 3d fix */
1552 if (gps_mode < 2 || NULL == gps_time) {
1553 /* receiver has no fix; tell about and avoid stale data */
1554 if ( ! up->pf_toff)
1555 ++up->tc_sti_recv;
1556 ++up->tc_nosync;
1557 up->fl_sti = 0;
1558 up->fl_pps = 0;
1559 up->fl_nosync = -1;
1560 return;
1561 }
1562 up->fl_nosync = 0;
1563
1564 /* convert clock and set resulting ref time, but only if the
1565 * TOFF sentence is *not* available
1566 */
1567 if ( ! up->pf_toff) {
1568 ++up->tc_sti_recv;
1569 /* save last time code to clock data */
1570 save_ltc(pp, gps_time);
1571 /* now parse the time string */
1572 if (convert_ascii_time(&up->sti_stamp, gps_time)) {
1573 DPRINTF(2, ("%s: process_tpv, stamp='%s',"
1574 " recvt='%s' mode=%u\n",
1575 up->logname,
1576 gmprettydate(&up->sti_stamp),
1577 gmprettydate(&up->sti_recvt),
1578 gps_mode));
1579
1580 /* have to use local receive time as substitute
1581 * for the real receive time: TPV does not tell
1582 * us.
1583 */
1584 up->sti_local = *rtime;
1585 up->sti_recvt = *rtime;
1586 L_SUB(&up->sti_recvt, &up->sti_fudge);
1587 up->fl_sti = -1;
1588 } else {
1589 ++up->tc_breply;
1590 up->fl_sti = 0;
1591 }
1592 }
1593
1594 /* Set the precision from the GPSD data
1595 * Use the ETP field for an estimation of the precision of the
1596 * serial data. If ETP is not available, use the default serial
1597 * data presion instead. (Note: The PPS branch has a different
1598 * precision estimation, since it gets the proper value directly
1599 * from GPSD!)
1600 */
1601 ept = json_object_lookup_float_default(jctx, 0, "ept", 2.0e-3);
1602 ept = frexp(fabs(ept)*0.70710678, &xlog2); /* ~ sqrt(0.5) */
1603 if (ept < 0.25)
1604 xlog2 = INT_MIN;
1605 if (ept > 2.0)
1606 xlog2 = INT_MAX;
1607 up->sti_prec = clamped_precision(xlog2);
1608 }
1609
1610 /* ------------------------------------------------------------------ */
1611
1612 static void
process_pps(peerT * const peer,json_ctx * const jctx,const l_fp * const rtime)1613 process_pps(
1614 peerT * const peer ,
1615 json_ctx * const jctx ,
1616 const l_fp * const rtime)
1617 {
1618 clockprocT * const pp = peer->procptr;
1619 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1620
1621 int xlog2;
1622
1623 ++up->tc_pps_recv;
1624
1625 /* Bail out if there's indication that time sync is bad or
1626 * if we're explicitely requested to ignore PPS data.
1627 */
1628 if (up->fl_nosync)
1629 return;
1630
1631 up->pps_local = *rtime;
1632 /* Now grab the time values. 'clock_*' is the event time of the
1633 * pulse measured on the local system clock; 'real_*' is the GPS
1634 * reference time GPSD associated with the pulse.
1635 */
1636 if (up->pf_nsec) {
1637 if ( ! get_binary_time(&up->pps_recvt2, jctx,
1638 "clock_sec", "clock_nsec", 1))
1639 goto fail;
1640 if ( ! get_binary_time(&up->pps_stamp2, jctx,
1641 "real_sec", "real_nsec", 1))
1642 goto fail;
1643 } else {
1644 if ( ! get_binary_time(&up->pps_recvt2, jctx,
1645 "clock_sec", "clock_musec", 1000))
1646 goto fail;
1647 if ( ! get_binary_time(&up->pps_stamp2, jctx,
1648 "real_sec", "real_musec", 1000))
1649 goto fail;
1650 }
1651
1652 /* Try to read the precision field from the PPS record. If it's
1653 * not there, take the precision from the serial data.
1654 */
1655 xlog2 = json_object_lookup_int_default(
1656 jctx, 0, "precision", up->sti_prec);
1657 up->pps_prec = clamped_precision(xlog2);
1658
1659 /* Get fudged receive times for primary & secondary unit */
1660 up->pps_recvt = up->pps_recvt2;
1661 L_SUB(&up->pps_recvt , &up->pps_fudge );
1662 L_SUB(&up->pps_recvt2, &up->pps_fudge2);
1663 pp->lastrec = up->pps_recvt;
1664
1665 /* Map to nearest full second as reference time stamp for the
1666 * primary channel. Sanity checks are done in evaluation step.
1667 */
1668 up->pps_stamp = up->pps_recvt;
1669 L_ADDUF(&up->pps_stamp, 0x80000000u);
1670 up->pps_stamp.l_uf = 0;
1671
1672 if (NULL != up->pps_peer)
1673 save_ltc(up->pps_peer->procptr,
1674 gmprettydate(&up->pps_stamp2));
1675 DPRINTF(2, ("%s: PPS record processed,"
1676 " stamp='%s', recvt='%s'\n",
1677 up->logname,
1678 gmprettydate(&up->pps_stamp2),
1679 gmprettydate(&up->pps_recvt2)));
1680
1681 up->fl_pps = (0 != (pp->sloppyclockflag & CLK_FLAG2)) - 1;
1682 up->fl_pps2 = -1;
1683 return;
1684
1685 fail:
1686 DPRINTF(1, ("%s: PPS record processing FAILED\n",
1687 up->logname));
1688 ++up->tc_breply;
1689 }
1690
1691 /* ------------------------------------------------------------------ */
1692
1693 static void
process_toff(peerT * const peer,json_ctx * const jctx,const l_fp * const rtime)1694 process_toff(
1695 peerT * const peer ,
1696 json_ctx * const jctx ,
1697 const l_fp * const rtime)
1698 {
1699 clockprocT * const pp = peer->procptr;
1700 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1701
1702 ++up->tc_sti_recv;
1703
1704 /* remember this! */
1705 up->pf_toff = -1;
1706
1707 /* bail out if there's indication that time sync is bad */
1708 if (up->fl_nosync)
1709 return;
1710
1711 if ( ! get_binary_time(&up->sti_recvt, jctx,
1712 "clock_sec", "clock_nsec", 1))
1713 goto fail;
1714 if ( ! get_binary_time(&up->sti_stamp, jctx,
1715 "real_sec", "real_nsec", 1))
1716 goto fail;
1717 L_SUB(&up->sti_recvt, &up->sti_fudge);
1718 up->sti_local = *rtime;
1719 up->fl_sti = -1;
1720
1721 save_ltc(pp, gmprettydate(&up->sti_stamp));
1722 DPRINTF(2, ("%s: TOFF record processed,"
1723 " stamp='%s', recvt='%s'\n",
1724 up->logname,
1725 gmprettydate(&up->sti_stamp),
1726 gmprettydate(&up->sti_recvt)));
1727 return;
1728
1729 fail:
1730 DPRINTF(1, ("%s: TOFF record processing FAILED\n",
1731 up->logname));
1732 ++up->tc_breply;
1733 }
1734
1735 /* ------------------------------------------------------------------ */
1736
1737 static void
gpsd_parse(peerT * const peer,const l_fp * const rtime)1738 gpsd_parse(
1739 peerT * const peer ,
1740 const l_fp * const rtime)
1741 {
1742 clockprocT * const pp = peer->procptr;
1743 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1744
1745 const char * clsid;
1746
1747 DPRINTF(2, ("%s: gpsd_parse: time %s '%.*s'\n",
1748 up->logname, ulfptoa(rtime, 6),
1749 up->buflen, up->buffer));
1750
1751 /* See if we can grab anything potentially useful. JSMN does not
1752 * need a trailing NUL, but it needs the number of bytes to
1753 * process. */
1754 if (!json_parse_record(&up->json_parse, up->buffer, up->buflen)) {
1755 ++up->tc_breply;
1756 return;
1757 }
1758
1759 /* Now dispatch over the objects we know */
1760 clsid = json_object_lookup_string(&up->json_parse, 0, "class");
1761 if (NULL == clsid) {
1762 ++up->tc_breply;
1763 return;
1764 }
1765
1766 if (!strcmp("TPV", clsid))
1767 process_tpv(peer, &up->json_parse, rtime);
1768 else if (!strcmp("PPS", clsid))
1769 process_pps(peer, &up->json_parse, rtime);
1770 else if (!strcmp("TOFF", clsid))
1771 process_toff(peer, &up->json_parse, rtime);
1772 else if (!strcmp("VERSION", clsid))
1773 process_version(peer, &up->json_parse, rtime);
1774 else if (!strcmp("WATCH", clsid))
1775 process_watch(peer, &up->json_parse, rtime);
1776 else
1777 return; /* nothing we know about... */
1778 ++up->tc_recv;
1779
1780 /* if possible, feed the PPS side channel */
1781 if (up->pps_peer)
1782 eval_pps_secondary(
1783 up->pps_peer, up->pps_peer->procptr, up);
1784
1785 /* check PPS vs. STI receive times:
1786 * If STI is before PPS, then clearly the STI is too old. If PPS
1787 * is before STI by more than one second, then PPS is too old.
1788 * Weed out stale time stamps & flags.
1789 */
1790 if (up->fl_pps && up->fl_sti) {
1791 l_fp diff;
1792 diff = up->sti_local;
1793 L_SUB(&diff, &up->pps_local);
1794 if (diff.l_i > 0)
1795 up->fl_pps = 0; /* pps too old */
1796 else if (diff.l_i < 0)
1797 up->fl_sti = 0; /* serial data too old */
1798 }
1799
1800 /* dispatch to the mode-dependent processing functions */
1801 switch (up->mode) {
1802 default:
1803 case MODE_OP_STI:
1804 eval_serial(peer, pp, up);
1805 break;
1806
1807 case MODE_OP_STRICT:
1808 eval_strict(peer, pp, up);
1809 break;
1810
1811 case MODE_OP_AUTO:
1812 eval_auto(peer, pp, up);
1813 break;
1814 }
1815 }
1816
1817 /* ------------------------------------------------------------------ */
1818
1819 static void
gpsd_stop_socket(peerT * const peer)1820 gpsd_stop_socket(
1821 peerT * const peer)
1822 {
1823 clockprocT * const pp = peer->procptr;
1824 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1825
1826 if (-1 != pp->io.fd) {
1827 if (syslogok(pp, up))
1828 msyslog(LOG_INFO,
1829 "%s: closing socket to GPSD, fd=%d",
1830 up->logname, pp->io.fd);
1831 else
1832 DPRINTF(1, ("%s: closing socket to GPSD, fd=%d\n",
1833 up->logname, pp->io.fd));
1834 io_closeclock(&pp->io);
1835 pp->io.fd = -1;
1836 }
1837 up->tickover = up->tickpres;
1838 up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
1839 up->fl_vers = 0;
1840 up->fl_sti = 0;
1841 up->fl_pps = 0;
1842 up->fl_watch = 0;
1843 }
1844
1845 /* ------------------------------------------------------------------ */
1846
1847 static void
gpsd_init_socket(peerT * const peer)1848 gpsd_init_socket(
1849 peerT * const peer)
1850 {
1851 clockprocT * const pp = peer->procptr;
1852 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1853 addrinfoT * ai;
1854 int rc;
1855 int ov;
1856
1857 /* draw next address to try */
1858 if (NULL == up->addr)
1859 up->addr = s_gpsd_addr;
1860 ai = up->addr;
1861 up->addr = ai->ai_next;
1862
1863 /* try to create a matching socket */
1864 up->fdt = socket(
1865 ai->ai_family, ai->ai_socktype, ai->ai_protocol);
1866 if (-1 == up->fdt) {
1867 if (syslogok(pp, up))
1868 msyslog(LOG_ERR,
1869 "%s: cannot create GPSD socket: %m",
1870 up->logname);
1871 goto no_socket;
1872 }
1873
1874 /* Make sure the socket is non-blocking. Connect/reconnect and
1875 * IO happen in an event-driven environment, and synchronous
1876 * operations wreak havoc on that.
1877 */
1878 rc = fcntl(up->fdt, F_SETFL, O_NONBLOCK, 1);
1879 if (-1 == rc) {
1880 if (syslogok(pp, up))
1881 msyslog(LOG_ERR,
1882 "%s: cannot set GPSD socket to non-blocking: %m",
1883 up->logname);
1884 goto no_socket;
1885 }
1886 /* Disable nagling. The way both GPSD and NTPD handle the
1887 * protocol makes it record-oriented, and in most cases
1888 * complete records (JSON serialised objects) will be sent in
1889 * one sweep. Nagling gives not much advantage but adds another
1890 * delay, which can worsen the situation for some packets.
1891 */
1892 ov = 1;
1893 rc = setsockopt(up->fdt, IPPROTO_TCP, TCP_NODELAY,
1894 (void *)&ov, sizeof(ov));
1895 if (-1 == rc) {
1896 if (syslogok(pp, up))
1897 msyslog(LOG_INFO,
1898 "%s: cannot disable TCP nagle: %m",
1899 up->logname);
1900 }
1901
1902 /* Start a non-blocking connect. There might be a synchronous
1903 * connection result we have to handle.
1904 */
1905 rc = connect(up->fdt, ai->ai_addr, ai->ai_addrlen);
1906 if (-1 == rc) {
1907 if (errno == EINPROGRESS) {
1908 DPRINTF(1, ("%s: async connect pending, fd=%d\n",
1909 up->logname, up->fdt));
1910 return;
1911 }
1912
1913 if (syslogok(pp, up))
1914 msyslog(LOG_ERR,
1915 "%s: cannot connect GPSD socket: %m",
1916 up->logname);
1917 goto no_socket;
1918 }
1919
1920 /* We had a successful synchronous connect, so we add the
1921 * refclock processing ASAP. We still have to wait for the
1922 * version string and apply the watch command later on, but we
1923 * might as well get the show on the road now.
1924 */
1925 DPRINTF(1, ("%s: new socket connection, fd=%d\n",
1926 up->logname, up->fdt));
1927
1928 pp->io.fd = up->fdt;
1929 up->fdt = -1;
1930 if (0 == io_addclock(&pp->io)) {
1931 if (syslogok(pp, up))
1932 msyslog(LOG_ERR,
1933 "%s: failed to register with I/O engine",
1934 up->logname);
1935 goto no_socket;
1936 }
1937
1938 return;
1939
1940 no_socket:
1941 if (-1 != pp->io.fd)
1942 close(pp->io.fd);
1943 if (-1 != up->fdt)
1944 close(up->fdt);
1945 pp->io.fd = -1;
1946 up->fdt = -1;
1947 up->tickover = up->tickpres;
1948 up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
1949 }
1950
1951 /* ------------------------------------------------------------------ */
1952
1953 static void
gpsd_test_socket(peerT * const peer)1954 gpsd_test_socket(
1955 peerT * const peer)
1956 {
1957 clockprocT * const pp = peer->procptr;
1958 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
1959
1960 int ec, rc;
1961 socklen_t lc;
1962
1963 /* Check if the non-blocking connect was finished by testing the
1964 * socket for writeability. Use the 'poll()' API if available
1965 * and 'select()' otherwise.
1966 */
1967 DPRINTF(2, ("%s: check connect, fd=%d\n",
1968 up->logname, up->fdt));
1969
1970 #if defined(HAVE_SYS_POLL_H)
1971 {
1972 struct pollfd pfd;
1973
1974 pfd.events = POLLOUT;
1975 pfd.fd = up->fdt;
1976 rc = poll(&pfd, 1, 0);
1977 if (1 != rc || !(pfd.revents & POLLOUT))
1978 return;
1979 }
1980 #elif defined(HAVE_SYS_SELECT_H)
1981 {
1982 struct timeval tout;
1983 fd_set wset;
1984
1985 memset(&tout, 0, sizeof(tout));
1986 FD_ZERO(&wset);
1987 FD_SET(up->fdt, &wset);
1988 rc = select(up->fdt+1, NULL, &wset, NULL, &tout);
1989 if (0 == rc || !(FD_ISSET(up->fdt, &wset)))
1990 return;
1991 }
1992 #else
1993 # error Blooper! That should have been found earlier!
1994 #endif
1995
1996 /* next timeout is a full one... */
1997 up->tickover = TICKOVER_LOW;
1998
1999 /* check for socket error */
2000 ec = 0;
2001 lc = sizeof(ec);
2002 rc = getsockopt(up->fdt, SOL_SOCKET, SO_ERROR, (void *)&ec, &lc);
2003 if (-1 == rc || 0 != ec) {
2004 const char *errtxt;
2005 if (0 == ec)
2006 ec = errno;
2007 errtxt = strerror(ec);
2008 if (syslogok(pp, up))
2009 msyslog(LOG_ERR,
2010 "%s: async connect to GPSD failed,"
2011 " fd=%d, ec=%d(%s)",
2012 up->logname, up->fdt, ec, errtxt);
2013 else
2014 DPRINTF(1, ("%s: async connect to GPSD failed,"
2015 " fd=%d, ec=%d(%s)\n",
2016 up->logname, up->fdt, ec, errtxt));
2017 goto no_socket;
2018 } else {
2019 DPRINTF(1, ("%s: async connect to GPSD succeeded, fd=%d\n",
2020 up->logname, up->fdt));
2021 }
2022
2023 /* swap socket FDs, and make sure the clock was added */
2024 pp->io.fd = up->fdt;
2025 up->fdt = -1;
2026 if (0 == io_addclock(&pp->io)) {
2027 if (syslogok(pp, up))
2028 msyslog(LOG_ERR,
2029 "%s: failed to register with I/O engine",
2030 up->logname);
2031 goto no_socket;
2032 }
2033 return;
2034
2035 no_socket:
2036 if (-1 != up->fdt) {
2037 DPRINTF(1, ("%s: closing socket, fd=%d\n",
2038 up->logname, up->fdt));
2039 close(up->fdt);
2040 }
2041 up->fdt = -1;
2042 up->tickover = up->tickpres;
2043 up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH);
2044 }
2045
2046 /* =====================================================================
2047 * helper stuff
2048 */
2049
2050 /* -------------------------------------------------------------------
2051 * store a properly clamped precision value
2052 */
2053 static int16_t
clamped_precision(int rawprec)2054 clamped_precision(
2055 int rawprec)
2056 {
2057 if (rawprec > 0)
2058 rawprec = 0;
2059 if (rawprec < -32)
2060 rawprec = -32;
2061 return (int16_t)rawprec;
2062 }
2063
2064 /* -------------------------------------------------------------------
2065 * Convert a GPSD timestamp (ISO8601 Format) to an l_fp
2066 */
2067 static BOOL
convert_ascii_time(l_fp * fp,const char * gps_time)2068 convert_ascii_time(
2069 l_fp * fp ,
2070 const char * gps_time)
2071 {
2072 char *ep;
2073 struct tm gd;
2074 struct timespec ts;
2075 uint32_t dw;
2076
2077 /* Use 'strptime' to take the brunt of the work, then parse
2078 * the fractional part manually, starting with a digit weight of
2079 * 10^8 nanoseconds.
2080 */
2081 ts.tv_nsec = 0;
2082 ep = strptime(gps_time, "%Y-%m-%dT%H:%M:%S", &gd);
2083 if (NULL == ep)
2084 return FALSE; /* could not parse the mandatory stuff! */
2085 if (*ep == '.') {
2086 dw = 100000000u;
2087 while (isdigit(*(u_char*)++ep)) {
2088 ts.tv_nsec += (*(u_char*)ep - '0') * dw;
2089 dw /= 10u;
2090 }
2091 }
2092 if (ep[0] != 'Z' || ep[1] != '\0')
2093 return FALSE; /* trailing garbage */
2094
2095 /* Now convert the whole thing into a 'l_fp'. We do not use
2096 * 'mkgmtime()' since its not standard and going through the
2097 * calendar routines is not much effort, either.
2098 */
2099 ts.tv_sec = (ntpcal_tm_to_rd(&gd) - DAY_NTP_STARTS) * SECSPERDAY
2100 + ntpcal_tm_to_daysec(&gd);
2101 *fp = tspec_intv_to_lfp(ts);
2102
2103 return TRUE;
2104 }
2105
2106 /* -------------------------------------------------------------------
2107 * Save the last timecode string, making sure it's properly truncated
2108 * if necessary and NUL terminated in any case.
2109 */
2110 static void
save_ltc(clockprocT * const pp,const char * const tc)2111 save_ltc(
2112 clockprocT * const pp,
2113 const char * const tc)
2114 {
2115 size_t len = 0;
2116
2117 if (tc) {
2118 len = strlen(tc);
2119 if (len >= sizeof(pp->a_lastcode))
2120 len = sizeof(pp->a_lastcode) - 1;
2121 memcpy(pp->a_lastcode, tc, len);
2122 }
2123 pp->lencode = (u_short)len;
2124 pp->a_lastcode[len] = '\0';
2125 }
2126
2127 /* -------------------------------------------------------------------
2128 * asprintf replacement... it's not available everywhere...
2129 */
2130 static int
myasprintf(char ** spp,char const * fmt,...)2131 myasprintf(
2132 char ** spp,
2133 char const * fmt,
2134 ... )
2135 {
2136 size_t alen, plen;
2137
2138 alen = 32;
2139 *spp = NULL;
2140 do {
2141 va_list va;
2142
2143 alen += alen;
2144 free(*spp);
2145 *spp = (char*)malloc(alen);
2146 if (NULL == *spp)
2147 return -1;
2148
2149 va_start(va, fmt);
2150 plen = (size_t)vsnprintf(*spp, alen, fmt, va);
2151 va_end(va);
2152 } while (plen >= alen);
2153
2154 return (int)plen;
2155 }
2156
2157 /* -------------------------------------------------------------------
2158 * dump a raw data buffer
2159 */
2160
2161 static char *
add_string(char * dp,char * ep,const char * sp)2162 add_string(
2163 char *dp,
2164 char *ep,
2165 const char *sp)
2166 {
2167 while (dp != ep && *sp)
2168 *dp++ = *sp++;
2169 return dp;
2170 }
2171
2172 static void
log_data(peerT * peer,const char * what,const char * buf,size_t len)2173 log_data(
2174 peerT *peer,
2175 const char *what,
2176 const char *buf ,
2177 size_t len )
2178 {
2179 /* we're running single threaded with regards to the clocks. */
2180 static char s_lbuf[2048];
2181
2182 clockprocT * const pp = peer->procptr;
2183 gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr;
2184
2185 if (debug > 1) {
2186 const char *sptr = buf;
2187 const char *stop = buf + len;
2188 char *dptr = s_lbuf;
2189 char *dtop = s_lbuf + sizeof(s_lbuf) - 1; /* for NUL */
2190
2191 while (sptr != stop && dptr != dtop) {
2192 u_char uch = (u_char)*sptr++;
2193 if (uch == '\\') {
2194 dptr = add_string(dptr, dtop, "\\\\");
2195 } else if (isprint(uch)) {
2196 *dptr++ = (char)uch;
2197 } else {
2198 char fbuf[6];
2199 snprintf(fbuf, sizeof(fbuf), "\\%03o", uch);
2200 dptr = add_string(dptr, dtop, fbuf);
2201 }
2202 }
2203 *dptr = '\0';
2204 mprintf("%s[%s]: '%s'\n", up->logname, what, s_lbuf);
2205 }
2206 }
2207
2208 #else
2209 NONEMPTY_TRANSLATION_UNIT
2210 #endif /* REFCLOCK && CLOCK_GPSDJSON */
2211