12b15cb3dSCy Schubert /* 22b15cb3dSCy Schubert * refclock_gpsdjson.c - clock driver as GPSD JSON client 32b15cb3dSCy Schubert * Juergen Perlinger (perlinger@ntp.org) 42b15cb3dSCy Schubert * Feb 11, 2014 for the NTP project. 52b15cb3dSCy Schubert * The contents of 'html/copyright.html' apply. 62b15cb3dSCy Schubert * 72b15cb3dSCy Schubert * Heavily inspired by refclock_nmea.c 82b15cb3dSCy Schubert * 9*276da39aSCy Schubert * Special thanks to Gary Miller and Hal Murray for their comments and 10*276da39aSCy Schubert * ideas. 11*276da39aSCy Schubert * 122b15cb3dSCy Schubert * Note: This will currently NOT work with Windows due to some 132b15cb3dSCy Schubert * limitations: 142b15cb3dSCy Schubert * 152b15cb3dSCy Schubert * - There is no GPSD for Windows. (There is an unofficial port to 162b15cb3dSCy Schubert * cygwin, but Windows is not officially supported.) 172b15cb3dSCy Schubert * 18*276da39aSCy Schubert * - To work properly, this driver needs PPS and TPV/TOFF sentences 19*276da39aSCy Schubert * from GPSD. I don't see how the cygwin port should deal with the 20*276da39aSCy Schubert * PPS signal. 212b15cb3dSCy Schubert * 222b15cb3dSCy Schubert * - The device name matching must be done in a different way for 232b15cb3dSCy Schubert * Windows. (Can be done with COMxx matching, as done for NMEA.) 242b15cb3dSCy Schubert * 252b15cb3dSCy Schubert * Apart from those minor hickups, once GPSD has been fully ported to 26*276da39aSCy Schubert * Windows, there's no reason why this should not work there ;-) If this 27*276da39aSCy Schubert * is ever to happen at all is a different question. 28*276da39aSCy Schubert * 29*276da39aSCy Schubert * --------------------------------------------------------------------- 30*276da39aSCy Schubert * 31*276da39aSCy Schubert * This driver works slightly different from most others, as the PPS 32*276da39aSCy Schubert * information (if available) is also coming from GPSD via the data 33*276da39aSCy Schubert * connection. This makes using both the PPS data and the serial data 34*276da39aSCy Schubert * easier, but OTOH it's not possible to use the ATOM driver to feed a 35*276da39aSCy Schubert * raw PPS stream to the core of NTPD. 36*276da39aSCy Schubert * 37*276da39aSCy Schubert * To go around this, the driver can use a secondary clock unit 38*276da39aSCy Schubert * (units>=128) that operate in tandem with the primary clock unit 39*276da39aSCy Schubert * (unit%128). The primary clock unit does all the IO stuff and data 40*276da39aSCy Schubert * decoding; if a a secondary unit is attached to a primary unit, this 41*276da39aSCy Schubert * secondary unit is feed with the PPS samples only and can act as a PPS 42*276da39aSCy Schubert * source to the clock selection. 43*276da39aSCy Schubert * 44*276da39aSCy Schubert * The drawback is that the primary unit must be present for the 45*276da39aSCy Schubert * secondary unit to work. 46*276da39aSCy Schubert * 47*276da39aSCy Schubert * This design is a compromise to reduce the IO load for both NTPD and 48*276da39aSCy Schubert * GPSD; it also ensures that data is transmitted and evaluated only 49*276da39aSCy Schubert * once on the side of NTPD. 50*276da39aSCy Schubert * 51*276da39aSCy Schubert * --------------------------------------------------------------------- 52*276da39aSCy Schubert * 53*276da39aSCy Schubert * trouble shooting hints: 54*276da39aSCy Schubert * 55*276da39aSCy Schubert * Enable and check the clock stats. Check if there are bad replies; 56*276da39aSCy Schubert * there should be none. If there are actually bad replies, then the 57*276da39aSCy Schubert * driver cannot parse all JSON records from GPSD, and some record 58*276da39aSCy Schubert * types are vital for the operation of the driver. This indicates a 59*276da39aSCy Schubert * problem on the protocol level. 60*276da39aSCy Schubert * 61*276da39aSCy Schubert * When started on the command line with a debug level >= 2, the 62*276da39aSCy Schubert * driver dumps the raw received data and the parser input to 63*276da39aSCy Schubert * stdout. Since the debug level is global, NTPD starts to create a 64*276da39aSCy Schubert * *lot* of output. It makes sense to pipe it through '(f)grep 65*276da39aSCy Schubert * GPSD_JSON' before writing the result to disk. 66*276da39aSCy Schubert * 67*276da39aSCy Schubert * A bit less intrusive is using netcat or telnet to connect to GPSD 68*276da39aSCy Schubert * and snoop what NTPD would get. If you try this, you have to send a 69*276da39aSCy Schubert * WATCH command to GPSD: 70*276da39aSCy Schubert * 71*276da39aSCy Schubert * ?WATCH={"device":"/dev/gps0","enable":true,"json":true,"pps":true};<CRLF> 72*276da39aSCy Schubert * 73*276da39aSCy Schubert * should show you what GPSD has to say to NTPD. Replace "/dev/gps0" 74*276da39aSCy Schubert * with the device link used by GPSD, if necessary. 752b15cb3dSCy Schubert */ 762b15cb3dSCy Schubert 77*276da39aSCy Schubert 782b15cb3dSCy Schubert #ifdef HAVE_CONFIG_H 792b15cb3dSCy Schubert #include <config.h> 802b15cb3dSCy Schubert #endif 812b15cb3dSCy Schubert 822b15cb3dSCy Schubert #include "ntp_types.h" 832b15cb3dSCy Schubert 842b15cb3dSCy Schubert #if defined(REFCLOCK) && defined(CLOCK_GPSDJSON) && !defined(SYS_WINNT) 852b15cb3dSCy Schubert 862b15cb3dSCy Schubert /* ===================================================================== 87*276da39aSCy Schubert * Get the little JSMN library directly into our guts. Use the 'parent 88*276da39aSCy Schubert * link' feature for maximum speed. 892b15cb3dSCy Schubert */ 90*276da39aSCy Schubert #define JSMN_PARENT_LINKS 912b15cb3dSCy Schubert #include "../libjsmn/jsmn.c" 922b15cb3dSCy Schubert 932b15cb3dSCy Schubert /* ===================================================================== 94*276da39aSCy Schubert * JSON parsing stuff 95*276da39aSCy Schubert */ 96*276da39aSCy Schubert 97*276da39aSCy Schubert #define JSMN_MAXTOK 350 98*276da39aSCy Schubert #define INVALID_TOKEN (-1) 99*276da39aSCy Schubert 100*276da39aSCy Schubert typedef struct json_ctx { 101*276da39aSCy Schubert char * buf; 102*276da39aSCy Schubert int ntok; 103*276da39aSCy Schubert jsmntok_t tok[JSMN_MAXTOK]; 104*276da39aSCy Schubert } json_ctx; 105*276da39aSCy Schubert 106*276da39aSCy Schubert typedef int tok_ref; 107*276da39aSCy Schubert 108*276da39aSCy Schubert /* Not all targets have 'long long', and not all of them have 'strtoll'. 109*276da39aSCy Schubert * Sigh. We roll our own integer number parser. 110*276da39aSCy Schubert */ 111*276da39aSCy Schubert #ifdef HAVE_LONG_LONG 112*276da39aSCy Schubert typedef signed long long int json_int; 113*276da39aSCy Schubert typedef unsigned long long int json_uint; 114*276da39aSCy Schubert #define JSON_INT_MAX LLONG_MAX 115*276da39aSCy Schubert #define JSON_INT_MIN LLONG_MIN 116*276da39aSCy Schubert #else 117*276da39aSCy Schubert typedef signed long int json_int; 118*276da39aSCy Schubert typedef unsigned long int json_uint; 119*276da39aSCy Schubert #define JSON_INT_MAX LONG_MAX 120*276da39aSCy Schubert #define JSON_INT_MIN LONG_MIN 121*276da39aSCy Schubert #endif 122*276da39aSCy Schubert 123*276da39aSCy Schubert /* ===================================================================== 1242b15cb3dSCy Schubert * header stuff we need 1252b15cb3dSCy Schubert */ 1262b15cb3dSCy Schubert 1272b15cb3dSCy Schubert #include <netdb.h> 1282b15cb3dSCy Schubert #include <unistd.h> 1292b15cb3dSCy Schubert #include <fcntl.h> 1302b15cb3dSCy Schubert #include <string.h> 1312b15cb3dSCy Schubert #include <ctype.h> 132*276da39aSCy Schubert #include <math.h> 1332b15cb3dSCy Schubert 1342b15cb3dSCy Schubert #include <sys/types.h> 1352b15cb3dSCy Schubert #include <sys/socket.h> 1362b15cb3dSCy Schubert #include <sys/stat.h> 1372b15cb3dSCy Schubert #include <netinet/tcp.h> 1382b15cb3dSCy Schubert 1392b15cb3dSCy Schubert #if defined(HAVE_SYS_POLL_H) 1402b15cb3dSCy Schubert # include <sys/poll.h> 1412b15cb3dSCy Schubert #elif defined(HAVE_SYS_SELECT_H) 1422b15cb3dSCy Schubert # include <sys/select.h> 1432b15cb3dSCy Schubert #else 1442b15cb3dSCy Schubert # error need poll() or select() 1452b15cb3dSCy Schubert #endif 1462b15cb3dSCy Schubert 1472b15cb3dSCy Schubert #include "ntpd.h" 1482b15cb3dSCy Schubert #include "ntp_io.h" 1492b15cb3dSCy Schubert #include "ntp_unixtime.h" 1502b15cb3dSCy Schubert #include "ntp_refclock.h" 1512b15cb3dSCy Schubert #include "ntp_stdlib.h" 1522b15cb3dSCy Schubert #include "ntp_calendar.h" 1532b15cb3dSCy Schubert #include "timespecops.h" 1542b15cb3dSCy Schubert 155*276da39aSCy Schubert /* get operation modes from mode word. 156*276da39aSCy Schubert 157*276da39aSCy Schubert * + SERIAL (default) evaluates only serial time information ('STI') as 158*276da39aSCy Schubert * provided by TPV and TOFF records. TPV evaluation suffers from a 159*276da39aSCy Schubert * bigger jitter than TOFF, sine it does not contain the receive time 160*276da39aSCy Schubert * from GPSD and therefore the receive time of NTPD must be 161*276da39aSCy Schubert * substituted for it. The network latency makes this a second rate 162*276da39aSCy Schubert * guess. 163*276da39aSCy Schubert * 164*276da39aSCy Schubert * If TOFF records are detected in the data stream, the timing 165*276da39aSCy Schubert * information is gleaned from this record -- it contains the local 166*276da39aSCy Schubert * receive time stamp from GPSD and therefore eliminates the 167*276da39aSCy Schubert * transmission latency between GPSD and NTPD. The timing information 168*276da39aSCy Schubert * from TPV is ignored once a TOFF is detected or expected. 169*276da39aSCy Schubert * 170*276da39aSCy Schubert * TPV is still used to check the fix status, so the driver can stop 171*276da39aSCy Schubert * feeding samples when GPSD says that the time information is 172*276da39aSCy Schubert * effectively unreliable. 173*276da39aSCy Schubert * 174*276da39aSCy Schubert * + STRICT means only feed clock samples when a valid STI/PPS pair is 175*276da39aSCy Schubert * available. Combines the reference time from STI with the pulse time 176*276da39aSCy Schubert * from PPS. Masks the serial data jitter as long PPS is available, 177*276da39aSCy Schubert * but can rapidly deteriorate once PPS drops out. 178*276da39aSCy Schubert * 179*276da39aSCy Schubert * + AUTO tries to use STI/PPS pairs if available for some time, and if 180*276da39aSCy Schubert * this fails for too long switches back to STI only until the PPS 181*276da39aSCy Schubert * signal becomes available again. See the HTML docs for this driver 182*276da39aSCy Schubert * about the gotchas and why this is not the default. 183*276da39aSCy Schubert */ 184*276da39aSCy Schubert #define MODE_OP_MASK 0x03 185*276da39aSCy Schubert #define MODE_OP_STI 0 186*276da39aSCy Schubert #define MODE_OP_STRICT 1 187*276da39aSCy Schubert #define MODE_OP_AUTO 2 188*276da39aSCy Schubert #define MODE_OP_MAXVAL 2 189*276da39aSCy Schubert #define MODE_OP_MODE(x) ((x) & MODE_OP_MASK) 190*276da39aSCy Schubert 1912b15cb3dSCy Schubert #define PRECISION (-9) /* precision assumed (about 2 ms) */ 1922b15cb3dSCy Schubert #define PPS_PRECISION (-20) /* precision assumed (about 1 us) */ 1932b15cb3dSCy Schubert #define REFID "GPSD" /* reference id */ 1942b15cb3dSCy Schubert #define DESCRIPTION "GPSD JSON client clock" /* who we are */ 1952b15cb3dSCy Schubert 1962b15cb3dSCy Schubert #define MAX_PDU_LEN 1600 1972b15cb3dSCy Schubert #define TICKOVER_LOW 10 1982b15cb3dSCy Schubert #define TICKOVER_HIGH 120 1992b15cb3dSCy Schubert #define LOGTHROTTLE 3600 2002b15cb3dSCy Schubert 201*276da39aSCy Schubert /* Primary channel PPS avilability dance: 202*276da39aSCy Schubert * Every good PPS sample gets us a credit of PPS_INCCOUNT points, every 203*276da39aSCy Schubert * bad/missing PPS sample costs us a debit of PPS_DECCOUNT points. When 204*276da39aSCy Schubert * the account reaches the upper limit we change to a mode where only 205*276da39aSCy Schubert * PPS-augmented samples are fed to the core; when the account drops to 206*276da39aSCy Schubert * zero we switch to a mode where TPV-only timestamps are fed to the 207*276da39aSCy Schubert * core. 208*276da39aSCy Schubert * This reduces the chance of rapid alternation between raw and 209*276da39aSCy Schubert * PPS-augmented time stamps. 210*276da39aSCy Schubert */ 211*276da39aSCy Schubert #define PPS_MAXCOUNT 60 /* upper limit of account */ 212*276da39aSCy Schubert #define PPS_INCCOUNT 3 /* credit for good samples */ 213*276da39aSCy Schubert #define PPS_DECCOUNT 1 /* debit for bad samples */ 214*276da39aSCy Schubert 215*276da39aSCy Schubert /* The secondary (PPS) channel uses a different strategy to avoid old 216*276da39aSCy Schubert * PPS samples in the median filter. 217*276da39aSCy Schubert */ 218*276da39aSCy Schubert #define PPS2_MAXCOUNT 10 2192b15cb3dSCy Schubert 2202b15cb3dSCy Schubert #ifndef BOOL 2212b15cb3dSCy Schubert # define BOOL int 2222b15cb3dSCy Schubert #endif 2232b15cb3dSCy Schubert #ifndef TRUE 2242b15cb3dSCy Schubert # define TRUE 1 2252b15cb3dSCy Schubert #endif 2262b15cb3dSCy Schubert #ifndef FALSE 2272b15cb3dSCy Schubert # define FALSE 0 2282b15cb3dSCy Schubert #endif 2292b15cb3dSCy Schubert 230*276da39aSCy Schubert #define PROTO_VERSION(hi,lo) \ 231*276da39aSCy Schubert ((((uint32_t)(hi) << 16) & 0xFFFF0000u) | \ 232*276da39aSCy Schubert ((uint32_t)(lo) & 0x0FFFFu)) 233*276da39aSCy Schubert 2342b15cb3dSCy Schubert /* some local typedefs: The NTPD formatting style cries for short type 2352b15cb3dSCy Schubert * names, and we provide them locally. Note:the suffix '_t' is reserved 2362b15cb3dSCy Schubert * for the standard; I use a capital T instead. 2372b15cb3dSCy Schubert */ 2382b15cb3dSCy Schubert typedef struct peer peerT; 2392b15cb3dSCy Schubert typedef struct refclockproc clockprocT; 2402b15cb3dSCy Schubert typedef struct addrinfo addrinfoT; 2412b15cb3dSCy Schubert 2422b15cb3dSCy Schubert /* ===================================================================== 2432b15cb3dSCy Schubert * We use the same device name scheme as does the NMEA driver; since 2442b15cb3dSCy Schubert * GPSD supports the same links, we can select devices by a fixed name. 2452b15cb3dSCy Schubert */ 2462b15cb3dSCy Schubert static const char * s_dev_stem = "/dev/gps"; 2472b15cb3dSCy Schubert 2482b15cb3dSCy Schubert /* ===================================================================== 2492b15cb3dSCy Schubert * forward declarations for transfer vector and the vector itself 2502b15cb3dSCy Schubert */ 2512b15cb3dSCy Schubert 2522b15cb3dSCy Schubert static void gpsd_init (void); 2532b15cb3dSCy Schubert static int gpsd_start (int, peerT *); 2542b15cb3dSCy Schubert static void gpsd_shutdown (int, peerT *); 2552b15cb3dSCy Schubert static void gpsd_receive (struct recvbuf *); 2562b15cb3dSCy Schubert static void gpsd_poll (int, peerT *); 2572b15cb3dSCy Schubert static void gpsd_control (int, const struct refclockstat *, 2582b15cb3dSCy Schubert struct refclockstat *, peerT *); 2592b15cb3dSCy Schubert static void gpsd_timer (int, peerT *); 2602b15cb3dSCy Schubert 261*276da39aSCy Schubert static int myasprintf(char**, char const*, ...) NTP_PRINTF(2, 3); 262*276da39aSCy Schubert 263*276da39aSCy Schubert static void enter_opmode(peerT *peer, int mode); 264*276da39aSCy Schubert static void leave_opmode(peerT *peer, int mode); 2652b15cb3dSCy Schubert 2662b15cb3dSCy Schubert struct refclock refclock_gpsdjson = { 2672b15cb3dSCy Schubert gpsd_start, /* start up driver */ 2682b15cb3dSCy Schubert gpsd_shutdown, /* shut down driver */ 2692b15cb3dSCy Schubert gpsd_poll, /* transmit poll message */ 2702b15cb3dSCy Schubert gpsd_control, /* fudge control */ 2712b15cb3dSCy Schubert gpsd_init, /* initialize driver */ 2722b15cb3dSCy Schubert noentry, /* buginfo */ 2732b15cb3dSCy Schubert gpsd_timer /* called once per second */ 2742b15cb3dSCy Schubert }; 2752b15cb3dSCy Schubert 2762b15cb3dSCy Schubert /* ===================================================================== 2772b15cb3dSCy Schubert * our local clock unit and data 2782b15cb3dSCy Schubert */ 279*276da39aSCy Schubert struct gpsd_unit; 280*276da39aSCy Schubert typedef struct gpsd_unit gpsd_unitT; 2812b15cb3dSCy Schubert 282*276da39aSCy Schubert struct gpsd_unit { 283*276da39aSCy Schubert /* links for sharing between master/slave units */ 284*276da39aSCy Schubert gpsd_unitT *next_unit; 285*276da39aSCy Schubert size_t refcount; 286*276da39aSCy Schubert 287*276da39aSCy Schubert /* data for the secondary PPS channel */ 288*276da39aSCy Schubert peerT *pps_peer; 289*276da39aSCy Schubert 290*276da39aSCy Schubert /* unit and operation modes */ 291*276da39aSCy Schubert int unit; 292*276da39aSCy Schubert int mode; 293*276da39aSCy Schubert char *logname; /* cached name for log/print */ 294*276da39aSCy Schubert char * device; /* device name of unit */ 295*276da39aSCy Schubert 296*276da39aSCy Schubert /* current line protocol version */ 297*276da39aSCy Schubert uint32_t proto_version; 298*276da39aSCy Schubert 299*276da39aSCy Schubert /* PPS time stamps primary + secondary channel */ 3002b15cb3dSCy Schubert l_fp pps_local; /* when we received the PPS message */ 3012b15cb3dSCy Schubert l_fp pps_stamp; /* related reference time */ 3022b15cb3dSCy Schubert l_fp pps_recvt; /* when GPSD detected the pulse */ 303*276da39aSCy Schubert l_fp pps_stamp2;/* related reference time (secondary) */ 304*276da39aSCy Schubert l_fp pps_recvt2;/* when GPSD detected the pulse (secondary)*/ 305*276da39aSCy Schubert int ppscount; /* PPS counter (primary unit) */ 306*276da39aSCy Schubert int ppscount2; /* PPS counter (secondary unit) */ 3072b15cb3dSCy Schubert 308*276da39aSCy Schubert /* TPV or TOFF serial time information */ 309*276da39aSCy Schubert l_fp sti_local; /* when we received the TPV/TOFF message */ 310*276da39aSCy Schubert l_fp sti_stamp; /* effective GPS time stamp */ 311*276da39aSCy Schubert l_fp sti_recvt; /* when GPSD got the fix */ 312*276da39aSCy Schubert 313*276da39aSCy Schubert /* precision estimates */ 314*276da39aSCy Schubert int16_t sti_prec; /* serial precision based on EPT */ 315*276da39aSCy Schubert int16_t pps_prec; /* PPS precision from GPSD or above */ 3162b15cb3dSCy Schubert 3172b15cb3dSCy Schubert /* fudge values for correction, mirrored as 'l_fp' */ 318*276da39aSCy Schubert l_fp pps_fudge; /* PPS fudge primary channel */ 319*276da39aSCy Schubert l_fp pps_fudge2; /* PPS fudge secondary channel */ 320*276da39aSCy Schubert l_fp sti_fudge; /* TPV/TOFF serial data fudge */ 3212b15cb3dSCy Schubert 3222b15cb3dSCy Schubert /* Flags to indicate available data */ 323*276da39aSCy Schubert int fl_nosync: 1; /* GPSD signals bad quality */ 324*276da39aSCy Schubert int fl_sti : 1; /* valid TPV/TOFF seen (have time) */ 3252b15cb3dSCy Schubert int fl_pps : 1; /* valid pulse seen */ 326*276da39aSCy Schubert int fl_pps2 : 1; /* valid pulse seen for PPS channel */ 327*276da39aSCy Schubert int fl_rawsti: 1; /* permit raw TPV/TOFF time stamps */ 3282b15cb3dSCy Schubert int fl_vers : 1; /* have protocol version */ 3292b15cb3dSCy Schubert int fl_watch : 1; /* watch reply seen */ 330*276da39aSCy Schubert /* protocol flags */ 331*276da39aSCy Schubert int pf_nsec : 1; /* have nanosec PPS info */ 332*276da39aSCy Schubert int pf_toff : 1; /* have TOFF record for timing */ 3332b15cb3dSCy Schubert 3342b15cb3dSCy Schubert /* admin stuff for sockets and device selection */ 3352b15cb3dSCy Schubert int fdt; /* current connecting socket */ 3362b15cb3dSCy Schubert addrinfoT * addr; /* next address to try */ 3372b15cb3dSCy Schubert u_int tickover; /* timeout countdown */ 3382b15cb3dSCy Schubert u_int tickpres; /* timeout preset */ 3392b15cb3dSCy Schubert 3402b15cb3dSCy Schubert /* tallies for the various events */ 3412b15cb3dSCy Schubert u_int tc_recv; /* received known records */ 342*276da39aSCy Schubert u_int tc_breply; /* bad replies / parsing errors */ 343*276da39aSCy Schubert u_int tc_nosync; /* TPV / sample cycles w/o fix */ 344*276da39aSCy Schubert u_int tc_sti_recv;/* received serial time info records */ 345*276da39aSCy Schubert u_int tc_sti_used;/* used --^-- */ 346*276da39aSCy Schubert u_int tc_pps_recv;/* received PPS timing info records */ 347*276da39aSCy Schubert u_int tc_pps_used;/* used --^-- */ 3482b15cb3dSCy Schubert 3492b15cb3dSCy Schubert /* log bloat throttle */ 3502b15cb3dSCy Schubert u_int logthrottle;/* seconds to next log slot */ 3512b15cb3dSCy Schubert 352*276da39aSCy Schubert /* The parse context for the current record */ 353*276da39aSCy Schubert json_ctx json_parse; 354*276da39aSCy Schubert 3552b15cb3dSCy Schubert /* record assemby buffer and saved length */ 3562b15cb3dSCy Schubert int buflen; 3572b15cb3dSCy Schubert char buffer[MAX_PDU_LEN]; 358*276da39aSCy Schubert }; 3592b15cb3dSCy Schubert 3602b15cb3dSCy Schubert /* ===================================================================== 3612b15cb3dSCy Schubert * static local helpers forward decls 3622b15cb3dSCy Schubert */ 3632b15cb3dSCy Schubert static void gpsd_init_socket(peerT * const peer); 3642b15cb3dSCy Schubert static void gpsd_test_socket(peerT * const peer); 3652b15cb3dSCy Schubert static void gpsd_stop_socket(peerT * const peer); 3662b15cb3dSCy Schubert 3672b15cb3dSCy Schubert static void gpsd_parse(peerT * const peer, 3682b15cb3dSCy Schubert const l_fp * const rtime); 3692b15cb3dSCy Schubert static BOOL convert_ascii_time(l_fp * fp, const char * gps_time); 3702b15cb3dSCy Schubert static void save_ltc(clockprocT * const pp, const char * const tc); 3712b15cb3dSCy Schubert static int syslogok(clockprocT * const pp, gpsd_unitT * const up); 372*276da39aSCy Schubert static void log_data(peerT *peer, const char *what, 373*276da39aSCy Schubert const char *buf, size_t len); 374*276da39aSCy Schubert static int16_t clamped_precision(int rawprec); 3752b15cb3dSCy Schubert 3762b15cb3dSCy Schubert /* ===================================================================== 3772b15cb3dSCy Schubert * local / static stuff 3782b15cb3dSCy Schubert */ 3792b15cb3dSCy Schubert 3802b15cb3dSCy Schubert /* The logon string is actually the ?WATCH command of GPSD, using JSON 3812b15cb3dSCy Schubert * data and selecting the GPS device name we created from our unit 382*276da39aSCy Schubert * number. We have an old a newer version that request PPS (and TOFF) 383*276da39aSCy Schubert * transmission. 384*276da39aSCy Schubert * Note: These are actually format strings! 3852b15cb3dSCy Schubert */ 386*276da39aSCy Schubert static const char * const s_req_watch[2] = { 387*276da39aSCy Schubert "?WATCH={\"device\":\"%s\",\"enable\":true,\"json\":true};\r\n", 388*276da39aSCy Schubert "?WATCH={\"device\":\"%s\",\"enable\":true,\"json\":true,\"pps\":true};\r\n" 389*276da39aSCy Schubert }; 3902b15cb3dSCy Schubert 391*276da39aSCy Schubert static const char * const s_req_version = 392*276da39aSCy Schubert "?VERSION;\r\n"; 393*276da39aSCy Schubert 394*276da39aSCy Schubert /* We keep a static list of network addresses for 'localhost:gpsd' or a 395*276da39aSCy Schubert * fallback alias of it, and we try to connect to them in round-robin 396*276da39aSCy Schubert * fashion. The service lookup is done during the driver init 397*276da39aSCy Schubert * function to minmise the impact of 'getaddrinfo()'. 398*276da39aSCy Schubert * 399*276da39aSCy Schubert * Alas, the init function is called even if there are no clocks 400*276da39aSCy Schubert * configured for this driver. So it makes sense to defer the logging of 401*276da39aSCy Schubert * any errors or other notifications until the first clock unit is 402*276da39aSCy Schubert * started -- otherwise there might be syslog entries from a driver that 403*276da39aSCy Schubert * is not used at all. 4042b15cb3dSCy Schubert */ 4052b15cb3dSCy Schubert static addrinfoT *s_gpsd_addr; 406*276da39aSCy Schubert static gpsd_unitT *s_clock_units; 407*276da39aSCy Schubert 408*276da39aSCy Schubert /* list of service/socket names we want to resolve against */ 409*276da39aSCy Schubert static const char * const s_svctab[][2] = { 410*276da39aSCy Schubert { "localhost", "gpsd" }, 411*276da39aSCy Schubert { "localhost", "2947" }, 412*276da39aSCy Schubert { "127.0.0.1", "2947" }, 413*276da39aSCy Schubert { NULL, NULL } 414*276da39aSCy Schubert }; 415*276da39aSCy Schubert 416*276da39aSCy Schubert /* list of address resolution errors and index of service entry that 417*276da39aSCy Schubert * finally worked. 418*276da39aSCy Schubert */ 419*276da39aSCy Schubert static int s_svcerr[sizeof(s_svctab)/sizeof(s_svctab[0])]; 420*276da39aSCy Schubert static int s_svcidx; 4212b15cb3dSCy Schubert 4222b15cb3dSCy Schubert /* ===================================================================== 4232b15cb3dSCy Schubert * log throttling 4242b15cb3dSCy Schubert */ 4252b15cb3dSCy Schubert static int/*BOOL*/ 4262b15cb3dSCy Schubert syslogok( 4272b15cb3dSCy Schubert clockprocT * const pp, 4282b15cb3dSCy Schubert gpsd_unitT * const up) 4292b15cb3dSCy Schubert { 4302b15cb3dSCy Schubert int res = (0 != (pp->sloppyclockflag & CLK_FLAG3)) 4312b15cb3dSCy Schubert || (0 == up->logthrottle ) 4322b15cb3dSCy Schubert || (LOGTHROTTLE == up->logthrottle ); 4332b15cb3dSCy Schubert if (res) 4342b15cb3dSCy Schubert up->logthrottle = LOGTHROTTLE; 4352b15cb3dSCy Schubert return res; 4362b15cb3dSCy Schubert } 4372b15cb3dSCy Schubert 4382b15cb3dSCy Schubert /* ===================================================================== 4392b15cb3dSCy Schubert * the clock functions 4402b15cb3dSCy Schubert */ 4412b15cb3dSCy Schubert 4422b15cb3dSCy Schubert /* --------------------------------------------------------------------- 4432b15cb3dSCy Schubert * Init: This currently just gets the socket address for the GPS daemon 4442b15cb3dSCy Schubert */ 4452b15cb3dSCy Schubert static void 4462b15cb3dSCy Schubert gpsd_init(void) 4472b15cb3dSCy Schubert { 4482b15cb3dSCy Schubert addrinfoT hints; 449*276da39aSCy Schubert int rc, idx; 4502b15cb3dSCy Schubert 451*276da39aSCy Schubert memset(s_svcerr, 0, sizeof(s_svcerr)); 4522b15cb3dSCy Schubert memset(&hints, 0, sizeof(hints)); 4532b15cb3dSCy Schubert hints.ai_family = AF_UNSPEC; 4542b15cb3dSCy Schubert hints.ai_protocol = IPPROTO_TCP; 4552b15cb3dSCy Schubert hints.ai_socktype = SOCK_STREAM; 4562b15cb3dSCy Schubert 457*276da39aSCy Schubert for (idx = 0; s_svctab[idx][0] && !s_gpsd_addr; idx++) { 458*276da39aSCy Schubert rc = getaddrinfo(s_svctab[idx][0], s_svctab[idx][1], 459*276da39aSCy Schubert &hints, &s_gpsd_addr); 460*276da39aSCy Schubert s_svcerr[idx] = rc; 461*276da39aSCy Schubert if (0 == rc) 462*276da39aSCy Schubert break; 4632b15cb3dSCy Schubert s_gpsd_addr = NULL; 4642b15cb3dSCy Schubert } 465*276da39aSCy Schubert s_svcidx = idx; 466*276da39aSCy Schubert } 467*276da39aSCy Schubert 468*276da39aSCy Schubert /* --------------------------------------------------------------------- 469*276da39aSCy Schubert * Init Check: flush pending log messages and check if we can proceed 470*276da39aSCy Schubert */ 471*276da39aSCy Schubert static int/*BOOL*/ 472*276da39aSCy Schubert gpsd_init_check(void) 473*276da39aSCy Schubert { 474*276da39aSCy Schubert int idx; 475*276da39aSCy Schubert 476*276da39aSCy Schubert /* Check if there is something to log */ 477*276da39aSCy Schubert if (s_svcidx == 0) 478*276da39aSCy Schubert return (s_gpsd_addr != NULL); 479*276da39aSCy Schubert 480*276da39aSCy Schubert /* spool out the resolver errors */ 481*276da39aSCy Schubert for (idx = 0; idx < s_svcidx; ++idx) { 482*276da39aSCy Schubert msyslog(LOG_WARNING, 483*276da39aSCy Schubert "GPSD_JSON: failed to resolve '%s:%s', rc=%d (%s)", 484*276da39aSCy Schubert s_svctab[idx][0], s_svctab[idx][1], 485*276da39aSCy Schubert s_svcerr[idx], gai_strerror(s_svcerr[idx])); 486*276da39aSCy Schubert } 487*276da39aSCy Schubert 488*276da39aSCy Schubert /* check if it was fatal, or if we can proceed */ 489*276da39aSCy Schubert if (s_gpsd_addr == NULL) 490*276da39aSCy Schubert msyslog(LOG_ERR, "%s", 491*276da39aSCy Schubert "GPSD_JSON: failed to get socket address, giving up."); 492*276da39aSCy Schubert else if (idx != 0) 493*276da39aSCy Schubert msyslog(LOG_WARNING, 494*276da39aSCy Schubert "GPSD_JSON: using '%s:%s' instead of '%s:%s'", 495*276da39aSCy Schubert s_svctab[idx][0], s_svctab[idx][1], 496*276da39aSCy Schubert s_svctab[0][0], s_svctab[0][1]); 497*276da39aSCy Schubert 498*276da39aSCy Schubert /* make sure this gets logged only once and tell if we can 499*276da39aSCy Schubert * proceed or not 500*276da39aSCy Schubert */ 501*276da39aSCy Schubert s_svcidx = 0; 502*276da39aSCy Schubert return (s_gpsd_addr != NULL); 503*276da39aSCy Schubert } 5042b15cb3dSCy Schubert 5052b15cb3dSCy Schubert /* --------------------------------------------------------------------- 5062b15cb3dSCy Schubert * Start: allocate a unit pointer and set up the runtime data 5072b15cb3dSCy Schubert */ 5082b15cb3dSCy Schubert static int 5092b15cb3dSCy Schubert gpsd_start( 5102b15cb3dSCy Schubert int unit, 5112b15cb3dSCy Schubert peerT * peer) 5122b15cb3dSCy Schubert { 5132b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 514*276da39aSCy Schubert gpsd_unitT * up; 515*276da39aSCy Schubert gpsd_unitT ** uscan = &s_clock_units; 5162b15cb3dSCy Schubert 5172b15cb3dSCy Schubert struct stat sb; 5182b15cb3dSCy Schubert 519*276da39aSCy Schubert /* check if we can proceed at all or if init failed */ 520*276da39aSCy Schubert if ( ! gpsd_init_check()) 521*276da39aSCy Schubert return FALSE; 522*276da39aSCy Schubert 523*276da39aSCy Schubert /* search for matching unit */ 524*276da39aSCy Schubert while ((up = *uscan) != NULL && up->unit != (unit & 0x7F)) 525*276da39aSCy Schubert uscan = &up->next_unit; 526*276da39aSCy Schubert if (up == NULL) { 527*276da39aSCy Schubert /* alloc unit, add to list and increment use count ASAP. */ 528*276da39aSCy Schubert up = emalloc_zero(sizeof(*up)); 529*276da39aSCy Schubert *uscan = up; 530*276da39aSCy Schubert ++up->refcount; 531*276da39aSCy Schubert 5322b15cb3dSCy Schubert /* initialize the unit structure */ 533*276da39aSCy Schubert up->logname = estrdup(refnumtoa(&peer->srcadr)); 534*276da39aSCy Schubert up->unit = unit & 0x7F; 5352b15cb3dSCy Schubert up->fdt = -1; 5362b15cb3dSCy Schubert up->addr = s_gpsd_addr; 5372b15cb3dSCy Schubert up->tickpres = TICKOVER_LOW; 5382b15cb3dSCy Schubert 539*276da39aSCy Schubert /* Create the device name and check for a Character 540*276da39aSCy Schubert * Device. It's assumed that GPSD was started with the 541*276da39aSCy Schubert * same link, so the names match. (If this is not 542*276da39aSCy Schubert * practicable, we will have to read the symlink, if 543*276da39aSCy Schubert * any, so we can get the true device file.) 544*276da39aSCy Schubert */ 545*276da39aSCy Schubert if (-1 == myasprintf(&up->device, "%s%u", 546*276da39aSCy Schubert s_dev_stem, up->unit)) { 547*276da39aSCy Schubert msyslog(LOG_ERR, "%s: clock device name too long", 548*276da39aSCy Schubert up->logname); 549*276da39aSCy Schubert goto dev_fail; 550*276da39aSCy Schubert } 551*276da39aSCy Schubert if (-1 == stat(up->device, &sb) || !S_ISCHR(sb.st_mode)) { 552*276da39aSCy Schubert msyslog(LOG_ERR, "%s: '%s' is not a character device", 553*276da39aSCy Schubert up->logname, up->device); 554*276da39aSCy Schubert goto dev_fail; 555*276da39aSCy Schubert } 556*276da39aSCy Schubert } else { 557*276da39aSCy Schubert /* All set up, just increment use count. */ 558*276da39aSCy Schubert ++up->refcount; 559*276da39aSCy Schubert } 560*276da39aSCy Schubert 5612b15cb3dSCy Schubert /* setup refclock processing */ 5622b15cb3dSCy Schubert pp->unitptr = (caddr_t)up; 5632b15cb3dSCy Schubert pp->io.fd = -1; 5642b15cb3dSCy Schubert pp->io.clock_recv = gpsd_receive; 5652b15cb3dSCy Schubert pp->io.srcclock = peer; 5662b15cb3dSCy Schubert pp->io.datalen = 0; 5672b15cb3dSCy Schubert pp->a_lastcode[0] = '\0'; 5682b15cb3dSCy Schubert pp->lencode = 0; 5692b15cb3dSCy Schubert pp->clockdesc = DESCRIPTION; 5702b15cb3dSCy Schubert memcpy(&pp->refid, REFID, 4); 5712b15cb3dSCy Schubert 5722b15cb3dSCy Schubert /* Initialize miscellaneous variables */ 573*276da39aSCy Schubert if (unit >= 128) 574*276da39aSCy Schubert peer->precision = PPS_PRECISION; 575*276da39aSCy Schubert else 5762b15cb3dSCy Schubert peer->precision = PRECISION; 5772b15cb3dSCy Schubert 578*276da39aSCy Schubert /* If the daemon name lookup failed, just give up now. */ 579*276da39aSCy Schubert if (NULL == up->addr) { 580*276da39aSCy Schubert msyslog(LOG_ERR, "%s: no GPSD socket address, giving up", 581*276da39aSCy Schubert up->logname); 5822b15cb3dSCy Schubert goto dev_fail; 5832b15cb3dSCy Schubert } 584*276da39aSCy Schubert 5852b15cb3dSCy Schubert LOGIF(CLOCKINFO, 5862b15cb3dSCy Schubert (LOG_NOTICE, "%s: startup, device is '%s'", 5872b15cb3dSCy Schubert refnumtoa(&peer->srcadr), up->device)); 588*276da39aSCy Schubert up->mode = MODE_OP_MODE(peer->ttl); 589*276da39aSCy Schubert if (up->mode > MODE_OP_MAXVAL) 590*276da39aSCy Schubert up->mode = 0; 591*276da39aSCy Schubert if (unit >= 128) 592*276da39aSCy Schubert up->pps_peer = peer; 593*276da39aSCy Schubert else 594*276da39aSCy Schubert enter_opmode(peer, up->mode); 5952b15cb3dSCy Schubert return TRUE; 5962b15cb3dSCy Schubert 5972b15cb3dSCy Schubert dev_fail: 5982b15cb3dSCy Schubert /* On failure, remove all UNIT ressources and declare defeat. */ 5992b15cb3dSCy Schubert 6002b15cb3dSCy Schubert INSIST (up); 601*276da39aSCy Schubert if (!--up->refcount) { 602*276da39aSCy Schubert *uscan = up->next_unit; 6032b15cb3dSCy Schubert free(up->device); 6042b15cb3dSCy Schubert free(up); 605*276da39aSCy Schubert } 6062b15cb3dSCy Schubert 6072b15cb3dSCy Schubert pp->unitptr = (caddr_t)NULL; 6082b15cb3dSCy Schubert return FALSE; 6092b15cb3dSCy Schubert } 6102b15cb3dSCy Schubert 6112b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 6122b15cb3dSCy Schubert 6132b15cb3dSCy Schubert static void 6142b15cb3dSCy Schubert gpsd_shutdown( 6152b15cb3dSCy Schubert int unit, 6162b15cb3dSCy Schubert peerT * peer) 6172b15cb3dSCy Schubert { 6182b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 6192b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 620*276da39aSCy Schubert gpsd_unitT ** uscan = &s_clock_units; 6212b15cb3dSCy Schubert 6222b15cb3dSCy Schubert UNUSED_ARG(unit); 6232b15cb3dSCy Schubert 624*276da39aSCy Schubert /* The unit pointer might have been removed already. */ 625*276da39aSCy Schubert if (up == NULL) 626*276da39aSCy Schubert return; 627*276da39aSCy Schubert 628*276da39aSCy Schubert /* now check if we must close IO resources */ 629*276da39aSCy Schubert if (peer != up->pps_peer) { 630*276da39aSCy Schubert if (-1 != pp->io.fd) { 631*276da39aSCy Schubert DPRINTF(1, ("%s: closing clock, fd=%d\n", 632*276da39aSCy Schubert up->logname, pp->io.fd)); 633*276da39aSCy Schubert io_closeclock(&pp->io); 634*276da39aSCy Schubert pp->io.fd = -1; 635*276da39aSCy Schubert } 636*276da39aSCy Schubert if (up->fdt != -1) 637*276da39aSCy Schubert close(up->fdt); 638*276da39aSCy Schubert } 639*276da39aSCy Schubert /* decrement use count and eventually remove this unit. */ 640*276da39aSCy Schubert if (!--up->refcount) { 641*276da39aSCy Schubert /* unlink this unit */ 642*276da39aSCy Schubert while (*uscan != NULL) 643*276da39aSCy Schubert if (*uscan == up) 644*276da39aSCy Schubert *uscan = up->next_unit; 645*276da39aSCy Schubert else 646*276da39aSCy Schubert uscan = &(*uscan)->next_unit; 647*276da39aSCy Schubert free(up->logname); 6482b15cb3dSCy Schubert free(up->device); 6492b15cb3dSCy Schubert free(up); 6502b15cb3dSCy Schubert } 6512b15cb3dSCy Schubert pp->unitptr = (caddr_t)NULL; 6522b15cb3dSCy Schubert LOGIF(CLOCKINFO, 6532b15cb3dSCy Schubert (LOG_NOTICE, "%s: shutdown", refnumtoa(&peer->srcadr))); 6542b15cb3dSCy Schubert } 6552b15cb3dSCy Schubert 6562b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 6572b15cb3dSCy Schubert 6582b15cb3dSCy Schubert static void 6592b15cb3dSCy Schubert gpsd_receive( 6602b15cb3dSCy Schubert struct recvbuf * rbufp) 6612b15cb3dSCy Schubert { 6622b15cb3dSCy Schubert /* declare & init control structure ptrs */ 6632b15cb3dSCy Schubert peerT * const peer = rbufp->recv_peer; 6642b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 6652b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 6662b15cb3dSCy Schubert 6672b15cb3dSCy Schubert const char *psrc, *esrc; 6682b15cb3dSCy Schubert char *pdst, *edst, ch; 6692b15cb3dSCy Schubert 670*276da39aSCy Schubert /* log the data stream, if this is enabled */ 671*276da39aSCy Schubert log_data(peer, "recv", (const char*)rbufp->recv_buffer, 672*276da39aSCy Schubert (size_t)rbufp->recv_length); 673*276da39aSCy Schubert 674*276da39aSCy Schubert 6752b15cb3dSCy Schubert /* Since we're getting a raw stream data, we must assemble lines 6762b15cb3dSCy Schubert * in our receive buffer. We can't use neither 'refclock_gtraw' 6772b15cb3dSCy Schubert * not 'refclock_gtlin' here... We process chars until we reach 6782b15cb3dSCy Schubert * an EoL (that is, line feed) but we truncate the message if it 6792b15cb3dSCy Schubert * does not fit the buffer. GPSD might truncate messages, too, 6802b15cb3dSCy Schubert * so dealing with truncated buffers is necessary anyway. 6812b15cb3dSCy Schubert */ 6822b15cb3dSCy Schubert psrc = (const char*)rbufp->recv_buffer; 6832b15cb3dSCy Schubert esrc = psrc + rbufp->recv_length; 6842b15cb3dSCy Schubert 6852b15cb3dSCy Schubert pdst = up->buffer + up->buflen; 6862b15cb3dSCy Schubert edst = pdst + sizeof(up->buffer) - 1; /* for trailing NUL */ 6872b15cb3dSCy Schubert 6882b15cb3dSCy Schubert while (psrc != esrc) { 6892b15cb3dSCy Schubert ch = *psrc++; 6902b15cb3dSCy Schubert if (ch == '\n') { 6912b15cb3dSCy Schubert /* trim trailing whitespace & terminate buffer */ 6922b15cb3dSCy Schubert while (pdst != up->buffer && pdst[-1] <= ' ') 6932b15cb3dSCy Schubert --pdst; 6942b15cb3dSCy Schubert *pdst = '\0'; 6952b15cb3dSCy Schubert /* process data and reset buffer */ 696*276da39aSCy Schubert up->buflen = pdst - up->buffer; 6972b15cb3dSCy Schubert gpsd_parse(peer, &rbufp->recv_time); 6982b15cb3dSCy Schubert pdst = up->buffer; 6992b15cb3dSCy Schubert } else if (pdst != edst) { 7002b15cb3dSCy Schubert /* add next char, ignoring leading whitespace */ 7012b15cb3dSCy Schubert if (ch > ' ' || pdst != up->buffer) 7022b15cb3dSCy Schubert *pdst++ = ch; 7032b15cb3dSCy Schubert } 7042b15cb3dSCy Schubert } 7052b15cb3dSCy Schubert up->buflen = pdst - up->buffer; 7062b15cb3dSCy Schubert up->tickover = TICKOVER_LOW; 7072b15cb3dSCy Schubert } 7082b15cb3dSCy Schubert 7092b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 7102b15cb3dSCy Schubert 7112b15cb3dSCy Schubert static void 712*276da39aSCy Schubert poll_primary( 713*276da39aSCy Schubert peerT * const peer , 714*276da39aSCy Schubert clockprocT * const pp , 715*276da39aSCy Schubert gpsd_unitT * const up ) 716*276da39aSCy Schubert { 717*276da39aSCy Schubert if (pp->coderecv != pp->codeproc) { 718*276da39aSCy Schubert /* all is well */ 719*276da39aSCy Schubert pp->lastref = pp->lastrec; 720*276da39aSCy Schubert refclock_report(peer, CEVNT_NOMINAL); 721*276da39aSCy Schubert refclock_receive(peer); 722*276da39aSCy Schubert } else { 723*276da39aSCy Schubert /* Not working properly, admit to it. If we have no 724*276da39aSCy Schubert * connection to GPSD, declare the clock as faulty. If 725*276da39aSCy Schubert * there were bad replies, this is handled as the major 726*276da39aSCy Schubert * cause, and everything else is just a timeout. 727*276da39aSCy Schubert */ 728*276da39aSCy Schubert peer->precision = PRECISION; 729*276da39aSCy Schubert if (-1 == pp->io.fd) 730*276da39aSCy Schubert refclock_report(peer, CEVNT_FAULT); 731*276da39aSCy Schubert else if (0 != up->tc_breply) 732*276da39aSCy Schubert refclock_report(peer, CEVNT_BADREPLY); 733*276da39aSCy Schubert else 734*276da39aSCy Schubert refclock_report(peer, CEVNT_TIMEOUT); 735*276da39aSCy Schubert } 736*276da39aSCy Schubert 737*276da39aSCy Schubert if (pp->sloppyclockflag & CLK_FLAG4) 738*276da39aSCy Schubert mprintf_clock_stats( 739*276da39aSCy Schubert &peer->srcadr,"%u %u %u %u %u %u %u", 740*276da39aSCy Schubert up->tc_recv, 741*276da39aSCy Schubert up->tc_breply, up->tc_nosync, 742*276da39aSCy Schubert up->tc_sti_recv, up->tc_sti_used, 743*276da39aSCy Schubert up->tc_pps_recv, up->tc_pps_used); 744*276da39aSCy Schubert 745*276da39aSCy Schubert /* clear tallies for next round */ 746*276da39aSCy Schubert up->tc_breply = 0; 747*276da39aSCy Schubert up->tc_recv = 0; 748*276da39aSCy Schubert up->tc_nosync = 0; 749*276da39aSCy Schubert up->tc_sti_recv = 0; 750*276da39aSCy Schubert up->tc_sti_used = 0; 751*276da39aSCy Schubert up->tc_pps_recv = 0; 752*276da39aSCy Schubert up->tc_pps_used = 0; 753*276da39aSCy Schubert } 754*276da39aSCy Schubert 755*276da39aSCy Schubert static void 756*276da39aSCy Schubert poll_secondary( 757*276da39aSCy Schubert peerT * const peer , 758*276da39aSCy Schubert clockprocT * const pp , 759*276da39aSCy Schubert gpsd_unitT * const up ) 760*276da39aSCy Schubert { 761*276da39aSCy Schubert if (pp->coderecv != pp->codeproc) { 762*276da39aSCy Schubert /* all is well */ 763*276da39aSCy Schubert pp->lastref = pp->lastrec; 764*276da39aSCy Schubert refclock_report(peer, CEVNT_NOMINAL); 765*276da39aSCy Schubert refclock_receive(peer); 766*276da39aSCy Schubert } else { 767*276da39aSCy Schubert peer->precision = PPS_PRECISION; 768*276da39aSCy Schubert peer->flags &= ~FLAG_PPS; 769*276da39aSCy Schubert refclock_report(peer, CEVNT_TIMEOUT); 770*276da39aSCy Schubert } 771*276da39aSCy Schubert } 772*276da39aSCy Schubert 773*276da39aSCy Schubert static void 7742b15cb3dSCy Schubert gpsd_poll( 7752b15cb3dSCy Schubert int unit, 7762b15cb3dSCy Schubert peerT * peer) 7772b15cb3dSCy Schubert { 7782b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 7792b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 7802b15cb3dSCy Schubert 7812b15cb3dSCy Schubert ++pp->polls; 782*276da39aSCy Schubert if (peer == up->pps_peer) 783*276da39aSCy Schubert poll_secondary(peer, pp, up); 784*276da39aSCy Schubert else 785*276da39aSCy Schubert poll_primary(peer, pp, up); 7862b15cb3dSCy Schubert } 7872b15cb3dSCy Schubert 7882b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 7892b15cb3dSCy Schubert 7902b15cb3dSCy Schubert static void 7912b15cb3dSCy Schubert gpsd_control( 7922b15cb3dSCy Schubert int unit, 7932b15cb3dSCy Schubert const struct refclockstat * in_st, 7942b15cb3dSCy Schubert struct refclockstat * out_st, 7952b15cb3dSCy Schubert peerT * peer ) 7962b15cb3dSCy Schubert { 7972b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 7982b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 7992b15cb3dSCy Schubert 800*276da39aSCy Schubert if (peer == up->pps_peer) { 801*276da39aSCy Schubert DTOLFP(pp->fudgetime1, &up->pps_fudge2); 802*276da39aSCy Schubert if ( ! (pp->sloppyclockflag & CLK_FLAG1)) 803*276da39aSCy Schubert peer->flags &= ~FLAG_PPS; 804*276da39aSCy Schubert } else { 8052b15cb3dSCy Schubert /* save preprocessed fudge times */ 8062b15cb3dSCy Schubert DTOLFP(pp->fudgetime1, &up->pps_fudge); 807*276da39aSCy Schubert DTOLFP(pp->fudgetime2, &up->sti_fudge); 808*276da39aSCy Schubert 809*276da39aSCy Schubert if (MODE_OP_MODE(up->mode ^ peer->ttl)) { 810*276da39aSCy Schubert leave_opmode(peer, up->mode); 811*276da39aSCy Schubert up->mode = MODE_OP_MODE(peer->ttl); 812*276da39aSCy Schubert enter_opmode(peer, up->mode); 813*276da39aSCy Schubert } 814*276da39aSCy Schubert } 8152b15cb3dSCy Schubert } 8162b15cb3dSCy Schubert 8172b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 8182b15cb3dSCy Schubert 8192b15cb3dSCy Schubert static void 820*276da39aSCy Schubert timer_primary( 821*276da39aSCy Schubert peerT * const peer , 822*276da39aSCy Schubert clockprocT * const pp , 823*276da39aSCy Schubert gpsd_unitT * const up ) 8242b15cb3dSCy Schubert { 8252b15cb3dSCy Schubert int rc; 8262b15cb3dSCy Schubert 8272b15cb3dSCy Schubert /* This is used for timeout handling. Nothing that needs 8282b15cb3dSCy Schubert * sub-second precison happens here, so receive/connect/retry 8292b15cb3dSCy Schubert * timeouts are simply handled by a count down, and then we 8302b15cb3dSCy Schubert * decide what to do by the socket values. 8312b15cb3dSCy Schubert * 8322b15cb3dSCy Schubert * Note that the timer stays at zero here, unless some of the 8332b15cb3dSCy Schubert * functions set it to another value. 8342b15cb3dSCy Schubert */ 8352b15cb3dSCy Schubert if (up->logthrottle) 8362b15cb3dSCy Schubert --up->logthrottle; 8372b15cb3dSCy Schubert if (up->tickover) 8382b15cb3dSCy Schubert --up->tickover; 8392b15cb3dSCy Schubert switch (up->tickover) { 8402b15cb3dSCy Schubert case 4: 841*276da39aSCy Schubert /* If we are connected to GPSD, try to get a live signal 842*276da39aSCy Schubert * by querying the version. Otherwise just check the 843*276da39aSCy Schubert * socket to become ready. 8442b15cb3dSCy Schubert */ 8452b15cb3dSCy Schubert if (-1 != pp->io.fd) { 846*276da39aSCy Schubert size_t rlen = strlen(s_req_version); 847*276da39aSCy Schubert DPRINTF(2, ("%s: timer livecheck: '%s'\n", 848*276da39aSCy Schubert up->logname, s_req_version)); 849*276da39aSCy Schubert log_data(peer, "send", s_req_version, rlen); 850*276da39aSCy Schubert rc = write(pp->io.fd, s_req_version, rlen); 8512b15cb3dSCy Schubert (void)rc; 8522b15cb3dSCy Schubert } else if (-1 != up->fdt) { 8532b15cb3dSCy Schubert gpsd_test_socket(peer); 8542b15cb3dSCy Schubert } 8552b15cb3dSCy Schubert break; 8562b15cb3dSCy Schubert 8572b15cb3dSCy Schubert case 0: 8582b15cb3dSCy Schubert if (-1 != pp->io.fd) 8592b15cb3dSCy Schubert gpsd_stop_socket(peer); 8602b15cb3dSCy Schubert else if (-1 != up->fdt) 8612b15cb3dSCy Schubert gpsd_test_socket(peer); 8622b15cb3dSCy Schubert else if (NULL != s_gpsd_addr) 8632b15cb3dSCy Schubert gpsd_init_socket(peer); 8642b15cb3dSCy Schubert break; 8652b15cb3dSCy Schubert 8662b15cb3dSCy Schubert default: 8672b15cb3dSCy Schubert if (-1 == pp->io.fd && -1 != up->fdt) 8682b15cb3dSCy Schubert gpsd_test_socket(peer); 8692b15cb3dSCy Schubert } 870*276da39aSCy Schubert } 8712b15cb3dSCy Schubert 872*276da39aSCy Schubert static void 873*276da39aSCy Schubert timer_secondary( 874*276da39aSCy Schubert peerT * const peer , 875*276da39aSCy Schubert clockprocT * const pp , 876*276da39aSCy Schubert gpsd_unitT * const up ) 877*276da39aSCy Schubert { 878*276da39aSCy Schubert /* Reduce the count by one. Flush sample buffer and clear PPS 879*276da39aSCy Schubert * flag when this happens. 880*276da39aSCy Schubert */ 881*276da39aSCy Schubert up->ppscount2 = max(0, (up->ppscount2 - 1)); 882*276da39aSCy Schubert if (0 == up->ppscount2) { 883*276da39aSCy Schubert if (pp->coderecv != pp->codeproc) { 884*276da39aSCy Schubert refclock_report(peer, CEVNT_TIMEOUT); 885*276da39aSCy Schubert pp->coderecv = pp->codeproc; 886*276da39aSCy Schubert } 8872b15cb3dSCy Schubert peer->flags &= ~FLAG_PPS; 8882b15cb3dSCy Schubert } 889*276da39aSCy Schubert } 890*276da39aSCy Schubert 891*276da39aSCy Schubert static void 892*276da39aSCy Schubert gpsd_timer( 893*276da39aSCy Schubert int unit, 894*276da39aSCy Schubert peerT * peer) 895*276da39aSCy Schubert { 896*276da39aSCy Schubert clockprocT * const pp = peer->procptr; 897*276da39aSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 898*276da39aSCy Schubert 899*276da39aSCy Schubert if (peer == up->pps_peer) 900*276da39aSCy Schubert timer_secondary(peer, pp, up); 901*276da39aSCy Schubert else 902*276da39aSCy Schubert timer_primary(peer, pp, up); 903*276da39aSCy Schubert } 904*276da39aSCy Schubert 905*276da39aSCy Schubert /* ===================================================================== 906*276da39aSCy Schubert * handle opmode switches 907*276da39aSCy Schubert */ 908*276da39aSCy Schubert 909*276da39aSCy Schubert static void 910*276da39aSCy Schubert enter_opmode( 911*276da39aSCy Schubert peerT *peer, 912*276da39aSCy Schubert int mode) 913*276da39aSCy Schubert { 914*276da39aSCy Schubert clockprocT * const pp = peer->procptr; 915*276da39aSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 916*276da39aSCy Schubert 917*276da39aSCy Schubert DPRINTF(1, ("%s: enter operation mode %d\n", 918*276da39aSCy Schubert up->logname, MODE_OP_MODE(mode))); 919*276da39aSCy Schubert 920*276da39aSCy Schubert if (MODE_OP_MODE(mode) == MODE_OP_AUTO) { 921*276da39aSCy Schubert up->fl_rawsti = 0; 922*276da39aSCy Schubert up->ppscount = PPS_MAXCOUNT / 2; 923*276da39aSCy Schubert } 924*276da39aSCy Schubert up->fl_pps = 0; 925*276da39aSCy Schubert up->fl_sti = 0; 926*276da39aSCy Schubert } 927*276da39aSCy Schubert 928*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 929*276da39aSCy Schubert 930*276da39aSCy Schubert static void 931*276da39aSCy Schubert leave_opmode( 932*276da39aSCy Schubert peerT *peer, 933*276da39aSCy Schubert int mode) 934*276da39aSCy Schubert { 935*276da39aSCy Schubert clockprocT * const pp = peer->procptr; 936*276da39aSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 937*276da39aSCy Schubert 938*276da39aSCy Schubert DPRINTF(1, ("%s: leaving operation mode %d\n", 939*276da39aSCy Schubert up->logname, MODE_OP_MODE(mode))); 940*276da39aSCy Schubert 941*276da39aSCy Schubert if (MODE_OP_MODE(mode) == MODE_OP_AUTO) { 942*276da39aSCy Schubert up->fl_rawsti = 0; 943*276da39aSCy Schubert up->ppscount = 0; 944*276da39aSCy Schubert } 945*276da39aSCy Schubert up->fl_pps = 0; 946*276da39aSCy Schubert up->fl_sti = 0; 947*276da39aSCy Schubert } 948*276da39aSCy Schubert 949*276da39aSCy Schubert /* ===================================================================== 950*276da39aSCy Schubert * operation mode specific evaluation 951*276da39aSCy Schubert */ 952*276da39aSCy Schubert 953*276da39aSCy Schubert static void 954*276da39aSCy Schubert add_clock_sample( 955*276da39aSCy Schubert peerT * const peer , 956*276da39aSCy Schubert clockprocT * const pp , 957*276da39aSCy Schubert l_fp stamp, 958*276da39aSCy Schubert l_fp recvt) 959*276da39aSCy Schubert { 960*276da39aSCy Schubert pp->lastref = stamp; 961*276da39aSCy Schubert if (pp->coderecv == pp->codeproc) 962*276da39aSCy Schubert refclock_report(peer, CEVNT_NOMINAL); 963*276da39aSCy Schubert refclock_process_offset(pp, stamp, recvt, 0.0); 964*276da39aSCy Schubert } 965*276da39aSCy Schubert 966*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 967*276da39aSCy Schubert 968*276da39aSCy Schubert static void 969*276da39aSCy Schubert eval_strict( 970*276da39aSCy Schubert peerT * const peer , 971*276da39aSCy Schubert clockprocT * const pp , 972*276da39aSCy Schubert gpsd_unitT * const up ) 973*276da39aSCy Schubert { 974*276da39aSCy Schubert if (up->fl_sti && up->fl_pps) { 975*276da39aSCy Schubert /* use TPV reference time + PPS receive time */ 976*276da39aSCy Schubert add_clock_sample(peer, pp, up->sti_stamp, up->pps_recvt); 977*276da39aSCy Schubert peer->precision = up->pps_prec; 978*276da39aSCy Schubert /* both packets consumed now... */ 979*276da39aSCy Schubert up->fl_pps = 0; 980*276da39aSCy Schubert up->fl_sti = 0; 981*276da39aSCy Schubert ++up->tc_sti_used; 982*276da39aSCy Schubert } 983*276da39aSCy Schubert } 984*276da39aSCy Schubert 985*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 986*276da39aSCy Schubert /* PPS processing for the secondary channel. GPSD provides us with full 987*276da39aSCy Schubert * timing information, so there's no danger of PLL-locking to the wrong 988*276da39aSCy Schubert * second. The belts and suspenders needed for the raw ATOM clock are 989*276da39aSCy Schubert * unnecessary here. 990*276da39aSCy Schubert */ 991*276da39aSCy Schubert static void 992*276da39aSCy Schubert eval_pps_secondary( 993*276da39aSCy Schubert peerT * const peer , 994*276da39aSCy Schubert clockprocT * const pp , 995*276da39aSCy Schubert gpsd_unitT * const up ) 996*276da39aSCy Schubert { 997*276da39aSCy Schubert if (up->fl_pps2) { 998*276da39aSCy Schubert /* feed data */ 999*276da39aSCy Schubert add_clock_sample(peer, pp, up->pps_stamp2, up->pps_recvt2); 1000*276da39aSCy Schubert peer->precision = up->pps_prec; 1001*276da39aSCy Schubert /* PPS peer flag logic */ 1002*276da39aSCy Schubert up->ppscount2 = min(PPS2_MAXCOUNT, (up->ppscount2 + 2)); 1003*276da39aSCy Schubert if ((PPS2_MAXCOUNT == up->ppscount2) && 1004*276da39aSCy Schubert (pp->sloppyclockflag & CLK_FLAG1) ) 1005*276da39aSCy Schubert peer->flags |= FLAG_PPS; 1006*276da39aSCy Schubert /* mark time stamp as burned... */ 1007*276da39aSCy Schubert up->fl_pps2 = 0; 1008*276da39aSCy Schubert ++up->tc_pps_used; 1009*276da39aSCy Schubert } 1010*276da39aSCy Schubert } 1011*276da39aSCy Schubert 1012*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1013*276da39aSCy Schubert 1014*276da39aSCy Schubert static void 1015*276da39aSCy Schubert eval_serial( 1016*276da39aSCy Schubert peerT * const peer , 1017*276da39aSCy Schubert clockprocT * const pp , 1018*276da39aSCy Schubert gpsd_unitT * const up ) 1019*276da39aSCy Schubert { 1020*276da39aSCy Schubert if (up->fl_sti) { 1021*276da39aSCy Schubert add_clock_sample(peer, pp, up->sti_stamp, up->sti_recvt); 1022*276da39aSCy Schubert peer->precision = up->sti_prec; 1023*276da39aSCy Schubert /* mark time stamp as burned... */ 1024*276da39aSCy Schubert up->fl_sti = 0; 1025*276da39aSCy Schubert ++up->tc_sti_used; 1026*276da39aSCy Schubert } 1027*276da39aSCy Schubert } 1028*276da39aSCy Schubert 1029*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1030*276da39aSCy Schubert static void 1031*276da39aSCy Schubert eval_auto( 1032*276da39aSCy Schubert peerT * const peer , 1033*276da39aSCy Schubert clockprocT * const pp , 1034*276da39aSCy Schubert gpsd_unitT * const up ) 1035*276da39aSCy Schubert { 1036*276da39aSCy Schubert /* If there's no TPV available, stop working here... */ 1037*276da39aSCy Schubert if (!up->fl_sti) 1038*276da39aSCy Schubert return; 1039*276da39aSCy Schubert 1040*276da39aSCy Schubert /* check how to handle STI+PPS: Can PPS be used to augment STI 1041*276da39aSCy Schubert * (or vice versae), do we drop the sample because there is a 1042*276da39aSCy Schubert * temporary missing PPS signal, or do we feed on STI time 1043*276da39aSCy Schubert * stamps alone? 1044*276da39aSCy Schubert * 1045*276da39aSCy Schubert * Do a counter/threshold dance to decide how to proceed. 1046*276da39aSCy Schubert */ 1047*276da39aSCy Schubert if (up->fl_pps) { 1048*276da39aSCy Schubert up->ppscount = min(PPS_MAXCOUNT, 1049*276da39aSCy Schubert (up->ppscount + PPS_INCCOUNT)); 1050*276da39aSCy Schubert if ((PPS_MAXCOUNT == up->ppscount) && up->fl_rawsti) { 1051*276da39aSCy Schubert up->fl_rawsti = 0; 1052*276da39aSCy Schubert msyslog(LOG_INFO, 1053*276da39aSCy Schubert "%s: expect valid PPS from now", 1054*276da39aSCy Schubert up->logname); 1055*276da39aSCy Schubert } 1056*276da39aSCy Schubert } else { 1057*276da39aSCy Schubert up->ppscount = max(0, (up->ppscount - PPS_DECCOUNT)); 1058*276da39aSCy Schubert if ((0 == up->ppscount) && !up->fl_rawsti) { 1059*276da39aSCy Schubert up->fl_rawsti = -1; 1060*276da39aSCy Schubert msyslog(LOG_WARNING, 1061*276da39aSCy Schubert "%s: use TPV alone from now", 1062*276da39aSCy Schubert up->logname); 1063*276da39aSCy Schubert } 1064*276da39aSCy Schubert } 1065*276da39aSCy Schubert 1066*276da39aSCy Schubert /* now eventually feed the sample */ 1067*276da39aSCy Schubert if (up->fl_rawsti) 1068*276da39aSCy Schubert eval_serial(peer, pp, up); 1069*276da39aSCy Schubert else 1070*276da39aSCy Schubert eval_strict(peer, pp, up); 1071*276da39aSCy Schubert } 10722b15cb3dSCy Schubert 10732b15cb3dSCy Schubert /* ===================================================================== 10742b15cb3dSCy Schubert * JSON parsing stuff 10752b15cb3dSCy Schubert */ 10762b15cb3dSCy Schubert 1077*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1078*276da39aSCy Schubert /* Parse a decimal integer with a possible sign. Works like 'strtoll()' 1079*276da39aSCy Schubert * or 'strtol()', but with a fixed base of 10 and without eating away 1080*276da39aSCy Schubert * leading whitespace. For the error codes, the handling of the end 1081*276da39aSCy Schubert * pointer and the return values see 'strtol()'. 1082*276da39aSCy Schubert */ 1083*276da39aSCy Schubert static json_int 1084*276da39aSCy Schubert strtojint( 1085*276da39aSCy Schubert const char *cp, char **ep) 1086*276da39aSCy Schubert { 1087*276da39aSCy Schubert json_uint accu, limit_lo, limit_hi; 1088*276da39aSCy Schubert int flags; /* bit 0: overflow; bit 1: sign */ 1089*276da39aSCy Schubert const char * hold; 10902b15cb3dSCy Schubert 1091*276da39aSCy Schubert /* pointer union to circumvent a tricky/sticky const issue */ 1092*276da39aSCy Schubert union { const char * c; char * v; } vep; 10932b15cb3dSCy Schubert 1094*276da39aSCy Schubert /* store initial value of 'cp' -- see 'strtol()' */ 1095*276da39aSCy Schubert vep.c = cp; 10962b15cb3dSCy Schubert 1097*276da39aSCy Schubert /* Eat away an optional sign and set the limits accordingly: The 1098*276da39aSCy Schubert * high limit is the maximum absolute value that can be returned, 1099*276da39aSCy Schubert * and the low limit is the biggest value that does not cause an 1100*276da39aSCy Schubert * overflow when multiplied with 10. Avoid negation overflows. 1101*276da39aSCy Schubert */ 1102*276da39aSCy Schubert if (*cp == '-') { 1103*276da39aSCy Schubert cp += 1; 1104*276da39aSCy Schubert flags = 2; 1105*276da39aSCy Schubert limit_hi = (json_uint)-(JSON_INT_MIN + 1) + 1; 1106*276da39aSCy Schubert } else { 1107*276da39aSCy Schubert cp += (*cp == '+'); 1108*276da39aSCy Schubert flags = 0; 1109*276da39aSCy Schubert limit_hi = (json_uint)JSON_INT_MAX; 1110*276da39aSCy Schubert } 1111*276da39aSCy Schubert limit_lo = limit_hi / 10; 1112*276da39aSCy Schubert 1113*276da39aSCy Schubert /* Now try to convert a sequence of digits. */ 1114*276da39aSCy Schubert hold = cp; 1115*276da39aSCy Schubert accu = 0; 1116*276da39aSCy Schubert while (isdigit(*(const unsigned char*)cp)) { 1117*276da39aSCy Schubert flags |= (accu > limit_lo); 1118*276da39aSCy Schubert accu = accu * 10 + (*(const unsigned char*)cp++ - '0'); 1119*276da39aSCy Schubert flags |= (accu > limit_hi); 1120*276da39aSCy Schubert } 1121*276da39aSCy Schubert /* Check for empty conversion (no digits seen). */ 1122*276da39aSCy Schubert if (hold != cp) 1123*276da39aSCy Schubert vep.c = cp; 1124*276da39aSCy Schubert else 1125*276da39aSCy Schubert errno = EINVAL; /* accu is still zero */ 1126*276da39aSCy Schubert /* Check for range overflow */ 1127*276da39aSCy Schubert if (flags & 1) { 1128*276da39aSCy Schubert errno = ERANGE; 1129*276da39aSCy Schubert accu = limit_hi; 1130*276da39aSCy Schubert } 1131*276da39aSCy Schubert /* If possible, store back the end-of-conversion pointer */ 1132*276da39aSCy Schubert if (ep) 1133*276da39aSCy Schubert *ep = vep.v; 1134*276da39aSCy Schubert /* If negative, return the negated result if the accu is not 1135*276da39aSCy Schubert * zero. Avoid negation overflows. 1136*276da39aSCy Schubert */ 1137*276da39aSCy Schubert if ((flags & 2) && accu) 1138*276da39aSCy Schubert return -(json_int)(accu - 1) - 1; 1139*276da39aSCy Schubert else 1140*276da39aSCy Schubert return (json_int)accu; 1141*276da39aSCy Schubert } 11422b15cb3dSCy Schubert 11432b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 11442b15cb3dSCy Schubert 11452b15cb3dSCy Schubert static tok_ref 11462b15cb3dSCy Schubert json_token_skip( 11472b15cb3dSCy Schubert const json_ctx * ctx, 11482b15cb3dSCy Schubert tok_ref tid) 11492b15cb3dSCy Schubert { 1150*276da39aSCy Schubert if (tid >= 0 && tid < ctx->ntok) { 1151*276da39aSCy Schubert int len = ctx->tok[tid].size; 1152*276da39aSCy Schubert /* For arrays and objects, the size is the number of 1153*276da39aSCy Schubert * ITEMS in the compound. Thats the number of objects in 1154*276da39aSCy Schubert * the array, and the number of key/value pairs for 1155*276da39aSCy Schubert * objects. In theory, the key must be a string, and we 1156*276da39aSCy Schubert * could simply skip one token before skipping the 1157*276da39aSCy Schubert * value, which can be anything. We're a bit paranoid 1158*276da39aSCy Schubert * and lazy at the same time: We simply double the 1159*276da39aSCy Schubert * number of tokens to skip and fall through into the 1160*276da39aSCy Schubert * array processing when encountering an object. 1161*276da39aSCy Schubert */ 1162*276da39aSCy Schubert switch (ctx->tok[tid].type) { 1163*276da39aSCy Schubert case JSMN_OBJECT: 1164*276da39aSCy Schubert len *= 2; 1165*276da39aSCy Schubert /* FALLTHROUGH */ 1166*276da39aSCy Schubert case JSMN_ARRAY: 11672b15cb3dSCy Schubert for (++tid; len; --len) 11682b15cb3dSCy Schubert tid = json_token_skip(ctx, tid); 11692b15cb3dSCy Schubert break; 1170*276da39aSCy Schubert 1171*276da39aSCy Schubert default: 1172*276da39aSCy Schubert ++tid; 1173*276da39aSCy Schubert break; 1174*276da39aSCy Schubert } 1175*276da39aSCy Schubert if (tid > ctx->ntok) /* Impossible? Paranoia rulez. */ 11762b15cb3dSCy Schubert tid = ctx->ntok; 1177*276da39aSCy Schubert } 11782b15cb3dSCy Schubert return tid; 11792b15cb3dSCy Schubert } 11802b15cb3dSCy Schubert 11812b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 11822b15cb3dSCy Schubert 11832b15cb3dSCy Schubert static int 11842b15cb3dSCy Schubert json_object_lookup( 11852b15cb3dSCy Schubert const json_ctx * ctx , 11862b15cb3dSCy Schubert tok_ref tid , 1187*276da39aSCy Schubert const char * key , 1188*276da39aSCy Schubert int what) 11892b15cb3dSCy Schubert { 11902b15cb3dSCy Schubert int len; 11912b15cb3dSCy Schubert 1192*276da39aSCy Schubert if (tid < 0 || tid >= ctx->ntok || 1193*276da39aSCy Schubert ctx->tok[tid].type != JSMN_OBJECT) 11942b15cb3dSCy Schubert return INVALID_TOKEN; 1195*276da39aSCy Schubert 11962b15cb3dSCy Schubert len = ctx->tok[tid].size; 1197*276da39aSCy Schubert for (++tid; len && tid+1 < ctx->ntok; --len) { 1198*276da39aSCy Schubert if (ctx->tok[tid].type != JSMN_STRING) { /* Blooper! */ 1199*276da39aSCy Schubert tid = json_token_skip(ctx, tid); /* skip key */ 1200*276da39aSCy Schubert tid = json_token_skip(ctx, tid); /* skip val */ 1201*276da39aSCy Schubert } else if (strcmp(key, ctx->buf + ctx->tok[tid].start)) { 1202*276da39aSCy Schubert tid = json_token_skip(ctx, tid+1); /* skip key+val */ 1203*276da39aSCy Schubert } else if (what < 0 || what == ctx->tok[tid+1].type) { 12042b15cb3dSCy Schubert return tid + 1; 1205*276da39aSCy Schubert } else { 1206*276da39aSCy Schubert break; 1207*276da39aSCy Schubert } 1208*276da39aSCy Schubert /* if skipping ahead returned an error, bail out here. */ 1209*276da39aSCy Schubert if (tid < 0) 1210*276da39aSCy Schubert break; 12112b15cb3dSCy Schubert } 12122b15cb3dSCy Schubert return INVALID_TOKEN; 12132b15cb3dSCy Schubert } 12142b15cb3dSCy Schubert 12152b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 12162b15cb3dSCy Schubert 1217*276da39aSCy Schubert static const char* 1218*276da39aSCy Schubert json_object_lookup_primitive( 1219*276da39aSCy Schubert const json_ctx * ctx, 1220*276da39aSCy Schubert tok_ref tid, 1221*276da39aSCy Schubert const char * key) 1222*276da39aSCy Schubert { 1223*276da39aSCy Schubert tid = json_object_lookup(ctx, tid, key, JSMN_PRIMITIVE); 1224*276da39aSCy Schubert if (INVALID_TOKEN != tid) 1225*276da39aSCy Schubert return ctx->buf + ctx->tok[tid].start; 1226*276da39aSCy Schubert else 1227*276da39aSCy Schubert return NULL; 1228*276da39aSCy Schubert } 1229*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1230*276da39aSCy Schubert /* look up a boolean value. This essentially returns a tribool: 1231*276da39aSCy Schubert * 0->false, 1->true, (-1)->error/undefined 1232*276da39aSCy Schubert */ 1233*276da39aSCy Schubert static int 1234*276da39aSCy Schubert json_object_lookup_bool( 1235*276da39aSCy Schubert const json_ctx * ctx, 1236*276da39aSCy Schubert tok_ref tid, 1237*276da39aSCy Schubert const char * key) 1238*276da39aSCy Schubert { 1239*276da39aSCy Schubert const char *cp; 1240*276da39aSCy Schubert cp = json_object_lookup_primitive(ctx, tid, key); 1241*276da39aSCy Schubert switch ( cp ? *cp : '\0') { 1242*276da39aSCy Schubert case 't': return 1; 1243*276da39aSCy Schubert case 'f': return 0; 1244*276da39aSCy Schubert default : return -1; 1245*276da39aSCy Schubert } 1246*276da39aSCy Schubert } 1247*276da39aSCy Schubert 1248*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1249*276da39aSCy Schubert 12502b15cb3dSCy Schubert static const char* 12512b15cb3dSCy Schubert json_object_lookup_string( 12522b15cb3dSCy Schubert const json_ctx * ctx, 12532b15cb3dSCy Schubert tok_ref tid, 12542b15cb3dSCy Schubert const char * key) 12552b15cb3dSCy Schubert { 1256*276da39aSCy Schubert tid = json_object_lookup(ctx, tid, key, JSMN_STRING); 1257*276da39aSCy Schubert if (INVALID_TOKEN != tid) 1258*276da39aSCy Schubert return ctx->buf + ctx->tok[tid].start; 12592b15cb3dSCy Schubert return NULL; 12602b15cb3dSCy Schubert } 12612b15cb3dSCy Schubert 12622b15cb3dSCy Schubert static const char* 12632b15cb3dSCy Schubert json_object_lookup_string_default( 12642b15cb3dSCy Schubert const json_ctx * ctx, 12652b15cb3dSCy Schubert tok_ref tid, 12662b15cb3dSCy Schubert const char * key, 12672b15cb3dSCy Schubert const char * def) 12682b15cb3dSCy Schubert { 1269*276da39aSCy Schubert tid = json_object_lookup(ctx, tid, key, JSMN_STRING); 1270*276da39aSCy Schubert if (INVALID_TOKEN != tid) 1271*276da39aSCy Schubert return ctx->buf + ctx->tok[tid].start; 12722b15cb3dSCy Schubert return def; 12732b15cb3dSCy Schubert } 12742b15cb3dSCy Schubert 12752b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 12762b15cb3dSCy Schubert 12772b15cb3dSCy Schubert static json_int 12782b15cb3dSCy Schubert json_object_lookup_int( 12792b15cb3dSCy Schubert const json_ctx * ctx, 12802b15cb3dSCy Schubert tok_ref tid, 12812b15cb3dSCy Schubert const char * key) 12822b15cb3dSCy Schubert { 12832b15cb3dSCy Schubert json_int ret; 1284*276da39aSCy Schubert const char * cp; 12852b15cb3dSCy Schubert char * ep; 12862b15cb3dSCy Schubert 1287*276da39aSCy Schubert cp = json_object_lookup_primitive(ctx, tid, key); 1288*276da39aSCy Schubert if (NULL != cp) { 1289*276da39aSCy Schubert ret = strtojint(cp, &ep); 1290*276da39aSCy Schubert if (cp != ep && '\0' == *ep) 12912b15cb3dSCy Schubert return ret; 1292*276da39aSCy Schubert } else { 12932b15cb3dSCy Schubert errno = EINVAL; 1294*276da39aSCy Schubert } 12952b15cb3dSCy Schubert return 0; 12962b15cb3dSCy Schubert } 12972b15cb3dSCy Schubert 12982b15cb3dSCy Schubert static json_int 12992b15cb3dSCy Schubert json_object_lookup_int_default( 13002b15cb3dSCy Schubert const json_ctx * ctx, 13012b15cb3dSCy Schubert tok_ref tid, 13022b15cb3dSCy Schubert const char * key, 13032b15cb3dSCy Schubert json_int def) 13042b15cb3dSCy Schubert { 1305*276da39aSCy Schubert json_int ret; 1306*276da39aSCy Schubert const char * cp; 1307*276da39aSCy Schubert char * ep; 13082b15cb3dSCy Schubert 1309*276da39aSCy Schubert cp = json_object_lookup_primitive(ctx, tid, key); 1310*276da39aSCy Schubert if (NULL != cp) { 1311*276da39aSCy Schubert ret = strtojint(cp, &ep); 1312*276da39aSCy Schubert if (cp != ep && '\0' == *ep) 1313*276da39aSCy Schubert return ret; 1314*276da39aSCy Schubert } 1315*276da39aSCy Schubert return def; 13162b15cb3dSCy Schubert } 13172b15cb3dSCy Schubert 13182b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 1319*276da39aSCy Schubert #if 0 /* currently unused */ 13202b15cb3dSCy Schubert static double 13212b15cb3dSCy Schubert json_object_lookup_float( 13222b15cb3dSCy Schubert const json_ctx * ctx, 13232b15cb3dSCy Schubert tok_ref tid, 13242b15cb3dSCy Schubert const char * key) 13252b15cb3dSCy Schubert { 13262b15cb3dSCy Schubert double ret; 1327*276da39aSCy Schubert const char * cp; 13282b15cb3dSCy Schubert char * ep; 13292b15cb3dSCy Schubert 1330*276da39aSCy Schubert cp = json_object_lookup_primitive(ctx, tid, key); 1331*276da39aSCy Schubert if (NULL != cp) { 1332*276da39aSCy Schubert ret = strtod(cp, &ep); 1333*276da39aSCy Schubert if (cp != ep && '\0' == *ep) 13342b15cb3dSCy Schubert return ret; 1335*276da39aSCy Schubert } else { 13362b15cb3dSCy Schubert errno = EINVAL; 1337*276da39aSCy Schubert } 13382b15cb3dSCy Schubert return 0.0; 13392b15cb3dSCy Schubert } 1340*276da39aSCy Schubert #endif 13412b15cb3dSCy Schubert 13422b15cb3dSCy Schubert static double 13432b15cb3dSCy Schubert json_object_lookup_float_default( 13442b15cb3dSCy Schubert const json_ctx * ctx, 13452b15cb3dSCy Schubert tok_ref tid, 13462b15cb3dSCy Schubert const char * key, 13472b15cb3dSCy Schubert double def) 13482b15cb3dSCy Schubert { 1349*276da39aSCy Schubert double ret; 1350*276da39aSCy Schubert const char * cp; 1351*276da39aSCy Schubert char * ep; 13522b15cb3dSCy Schubert 1353*276da39aSCy Schubert cp = json_object_lookup_primitive(ctx, tid, key); 1354*276da39aSCy Schubert if (NULL != cp) { 1355*276da39aSCy Schubert ret = strtod(cp, &ep); 1356*276da39aSCy Schubert if (cp != ep && '\0' == *ep) 1357*276da39aSCy Schubert return ret; 1358*276da39aSCy Schubert } 1359*276da39aSCy Schubert return def; 13602b15cb3dSCy Schubert } 13612b15cb3dSCy Schubert 13622b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 13632b15cb3dSCy Schubert 13642b15cb3dSCy Schubert static BOOL 13652b15cb3dSCy Schubert json_parse_record( 13662b15cb3dSCy Schubert json_ctx * ctx, 1367*276da39aSCy Schubert char * buf, 1368*276da39aSCy Schubert size_t len) 13692b15cb3dSCy Schubert { 13702b15cb3dSCy Schubert jsmn_parser jsm; 13712b15cb3dSCy Schubert int idx, rc; 13722b15cb3dSCy Schubert 13732b15cb3dSCy Schubert jsmn_init(&jsm); 1374*276da39aSCy Schubert rc = jsmn_parse(&jsm, buf, len, ctx->tok, JSMN_MAXTOK); 1375*276da39aSCy Schubert if (rc <= 0) 1376*276da39aSCy Schubert return FALSE; 13772b15cb3dSCy Schubert ctx->buf = buf; 1378*276da39aSCy Schubert ctx->ntok = rc; 1379*276da39aSCy Schubert 1380*276da39aSCy Schubert if (JSMN_OBJECT != ctx->tok[0].type) 1381*276da39aSCy Schubert return FALSE; /* not object!?! */ 13822b15cb3dSCy Schubert 13832b15cb3dSCy Schubert /* Make all tokens NUL terminated by overwriting the 1384*276da39aSCy Schubert * terminator symbol. Makes string compares and number parsing a 1385*276da39aSCy Schubert * lot easier! 13862b15cb3dSCy Schubert */ 1387*276da39aSCy Schubert for (idx = 0; idx < ctx->ntok; ++idx) 13882b15cb3dSCy Schubert if (ctx->tok[idx].end > ctx->tok[idx].start) 13892b15cb3dSCy Schubert ctx->buf[ctx->tok[idx].end] = '\0'; 13902b15cb3dSCy Schubert return TRUE; 13912b15cb3dSCy Schubert } 13922b15cb3dSCy Schubert 13932b15cb3dSCy Schubert 13942b15cb3dSCy Schubert /* ===================================================================== 13952b15cb3dSCy Schubert * static local helpers 13962b15cb3dSCy Schubert */ 1397*276da39aSCy Schubert static BOOL 1398*276da39aSCy Schubert get_binary_time( 1399*276da39aSCy Schubert l_fp * const dest , 1400*276da39aSCy Schubert json_ctx * const jctx , 1401*276da39aSCy Schubert const char * const time_name, 1402*276da39aSCy Schubert const char * const frac_name, 1403*276da39aSCy Schubert long fscale ) 1404*276da39aSCy Schubert { 1405*276da39aSCy Schubert BOOL retv = FALSE; 1406*276da39aSCy Schubert struct timespec ts; 1407*276da39aSCy Schubert 1408*276da39aSCy Schubert errno = 0; 1409*276da39aSCy Schubert ts.tv_sec = (time_t)json_object_lookup_int(jctx, 0, time_name); 1410*276da39aSCy Schubert ts.tv_nsec = (long )json_object_lookup_int(jctx, 0, frac_name); 1411*276da39aSCy Schubert if (0 == errno) { 1412*276da39aSCy Schubert ts.tv_nsec *= fscale; 1413*276da39aSCy Schubert *dest = tspec_stamp_to_lfp(ts); 1414*276da39aSCy Schubert retv = TRUE; 1415*276da39aSCy Schubert } 1416*276da39aSCy Schubert return retv; 1417*276da39aSCy Schubert } 14182b15cb3dSCy Schubert 14192b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 14202b15cb3dSCy Schubert /* Process a WATCH record 14212b15cb3dSCy Schubert * 14222b15cb3dSCy Schubert * Currently this is only used to recognise that the device is present 14232b15cb3dSCy Schubert * and that we're listed subscribers. 14242b15cb3dSCy Schubert */ 14252b15cb3dSCy Schubert static void 14262b15cb3dSCy Schubert process_watch( 14272b15cb3dSCy Schubert peerT * const peer , 14282b15cb3dSCy Schubert json_ctx * const jctx , 14292b15cb3dSCy Schubert const l_fp * const rtime) 14302b15cb3dSCy Schubert { 14312b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 14322b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 14332b15cb3dSCy Schubert 1434*276da39aSCy Schubert const char * path; 1435*276da39aSCy Schubert 1436*276da39aSCy Schubert path = json_object_lookup_string(jctx, 0, "device"); 1437*276da39aSCy Schubert if (NULL == path || strcmp(path, up->device)) 1438*276da39aSCy Schubert return; 1439*276da39aSCy Schubert 1440*276da39aSCy Schubert if (json_object_lookup_bool(jctx, 0, "enable") > 0 && 1441*276da39aSCy Schubert json_object_lookup_bool(jctx, 0, "json" ) > 0 ) 14422b15cb3dSCy Schubert up->fl_watch = -1; 1443*276da39aSCy Schubert else 1444*276da39aSCy Schubert up->fl_watch = 0; 1445*276da39aSCy Schubert DPRINTF(2, ("%s: process_watch, enabled=%d\n", 1446*276da39aSCy Schubert up->logname, (up->fl_watch & 1))); 14472b15cb3dSCy Schubert } 14482b15cb3dSCy Schubert 14492b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 14502b15cb3dSCy Schubert 14512b15cb3dSCy Schubert static void 14522b15cb3dSCy Schubert process_version( 14532b15cb3dSCy Schubert peerT * const peer , 14542b15cb3dSCy Schubert json_ctx * const jctx , 14552b15cb3dSCy Schubert const l_fp * const rtime) 14562b15cb3dSCy Schubert { 14572b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 14582b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 14592b15cb3dSCy Schubert 14602b15cb3dSCy Schubert int len; 14612b15cb3dSCy Schubert char * buf; 14622b15cb3dSCy Schubert const char *revision; 14632b15cb3dSCy Schubert const char *release; 1464*276da39aSCy Schubert uint16_t pvhi, pvlo; 14652b15cb3dSCy Schubert 14662b15cb3dSCy Schubert /* get protocol version number */ 14672b15cb3dSCy Schubert revision = json_object_lookup_string_default( 14682b15cb3dSCy Schubert jctx, 0, "rev", "(unknown)"); 14692b15cb3dSCy Schubert release = json_object_lookup_string_default( 14702b15cb3dSCy Schubert jctx, 0, "release", "(unknown)"); 14712b15cb3dSCy Schubert errno = 0; 1472*276da39aSCy Schubert pvhi = (uint16_t)json_object_lookup_int(jctx, 0, "proto_major"); 1473*276da39aSCy Schubert pvlo = (uint16_t)json_object_lookup_int(jctx, 0, "proto_minor"); 1474*276da39aSCy Schubert 14752b15cb3dSCy Schubert if (0 == errno) { 1476*276da39aSCy Schubert if ( ! up->fl_vers) 14772b15cb3dSCy Schubert msyslog(LOG_INFO, 14782b15cb3dSCy Schubert "%s: GPSD revision=%s release=%s protocol=%u.%u", 1479*276da39aSCy Schubert up->logname, revision, release, 1480*276da39aSCy Schubert pvhi, pvlo); 1481*276da39aSCy Schubert up->proto_version = PROTO_VERSION(pvhi, pvlo); 1482*276da39aSCy Schubert up->fl_vers = -1; 1483*276da39aSCy Schubert } else { 1484*276da39aSCy Schubert if (syslogok(pp, up)) 1485*276da39aSCy Schubert msyslog(LOG_INFO, 1486*276da39aSCy Schubert "%s: could not evaluate version data", 1487*276da39aSCy Schubert up->logname); 1488*276da39aSCy Schubert return; 14892b15cb3dSCy Schubert } 1490*276da39aSCy Schubert /* With the 3.9 GPSD protocol, '*_musec' vanished from the PPS 1491*276da39aSCy Schubert * record and was replace by '*_nsec'. 14922b15cb3dSCy Schubert */ 1493*276da39aSCy Schubert up->pf_nsec = -(up->proto_version >= PROTO_VERSION(3,9)); 14942b15cb3dSCy Schubert 1495*276da39aSCy Schubert /* With the 3.10 protocol we can get TOFF records for better 1496*276da39aSCy Schubert * timing information. 1497*276da39aSCy Schubert */ 1498*276da39aSCy Schubert up->pf_toff = -(up->proto_version >= PROTO_VERSION(3,10)); 14992b15cb3dSCy Schubert 1500*276da39aSCy Schubert /* request watch for our GPS device if not yet watched. 1501*276da39aSCy Schubert * 1502*276da39aSCy Schubert * The version string is also sent as a life signal, if we have 1503*276da39aSCy Schubert * seen useable data. So if we're already watching the device, 1504*276da39aSCy Schubert * skip the request. 1505*276da39aSCy Schubert * 15062b15cb3dSCy Schubert * Reuse the input buffer, which is no longer needed in the 15072b15cb3dSCy Schubert * current cycle. Also assume that we can write the watch 15082b15cb3dSCy Schubert * request in one sweep into the socket; since we do not do 15092b15cb3dSCy Schubert * output otherwise, this should always work. (Unless the 15102b15cb3dSCy Schubert * TCP/IP window size gets lower than the length of the 15112b15cb3dSCy Schubert * request. We handle that when it happens.) 15122b15cb3dSCy Schubert */ 1513*276da39aSCy Schubert if (up->fl_watch) 1514*276da39aSCy Schubert return; 1515*276da39aSCy Schubert 15162b15cb3dSCy Schubert snprintf(up->buffer, sizeof(up->buffer), 1517*276da39aSCy Schubert s_req_watch[up->pf_toff != 0], up->device); 15182b15cb3dSCy Schubert buf = up->buffer; 15192b15cb3dSCy Schubert len = strlen(buf); 1520*276da39aSCy Schubert log_data(peer, "send", buf, len); 1521*276da39aSCy Schubert if (len != write(pp->io.fd, buf, len) && (syslogok(pp, up))) { 15222b15cb3dSCy Schubert /* Note: if the server fails to read our request, the 15232b15cb3dSCy Schubert * resulting data timeout will take care of the 15242b15cb3dSCy Schubert * connection! 15252b15cb3dSCy Schubert */ 1526*276da39aSCy Schubert msyslog(LOG_ERR, "%s: failed to write watch request (%m)", 1527*276da39aSCy Schubert up->logname); 15282b15cb3dSCy Schubert } 15292b15cb3dSCy Schubert } 15302b15cb3dSCy Schubert 15312b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 15322b15cb3dSCy Schubert 15332b15cb3dSCy Schubert static void 15342b15cb3dSCy Schubert process_tpv( 15352b15cb3dSCy Schubert peerT * const peer , 15362b15cb3dSCy Schubert json_ctx * const jctx , 15372b15cb3dSCy Schubert const l_fp * const rtime) 15382b15cb3dSCy Schubert { 15392b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 15402b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 15412b15cb3dSCy Schubert 15422b15cb3dSCy Schubert const char * gps_time; 15432b15cb3dSCy Schubert int gps_mode; 1544*276da39aSCy Schubert double ept; 15452b15cb3dSCy Schubert int xlog2; 15462b15cb3dSCy Schubert 15472b15cb3dSCy Schubert gps_mode = (int)json_object_lookup_int_default( 15482b15cb3dSCy Schubert jctx, 0, "mode", 0); 15492b15cb3dSCy Schubert 1550*276da39aSCy Schubert gps_time = json_object_lookup_string( 1551*276da39aSCy Schubert jctx, 0, "time"); 15522b15cb3dSCy Schubert 1553*276da39aSCy Schubert /* accept time stamps only in 2d or 3d fix */ 1554*276da39aSCy Schubert if (gps_mode < 2 || NULL == gps_time) { 15552b15cb3dSCy Schubert /* receiver has no fix; tell about and avoid stale data */ 1556*276da39aSCy Schubert if ( ! up->pf_toff) 1557*276da39aSCy Schubert ++up->tc_sti_recv; 1558*276da39aSCy Schubert ++up->tc_nosync; 1559*276da39aSCy Schubert up->fl_sti = 0; 15602b15cb3dSCy Schubert up->fl_pps = 0; 1561*276da39aSCy Schubert up->fl_nosync = -1; 15622b15cb3dSCy Schubert return; 15632b15cb3dSCy Schubert } 1564*276da39aSCy Schubert up->fl_nosync = 0; 15652b15cb3dSCy Schubert 1566*276da39aSCy Schubert /* convert clock and set resulting ref time, but only if the 1567*276da39aSCy Schubert * TOFF sentence is *not* available 1568*276da39aSCy Schubert */ 1569*276da39aSCy Schubert if ( ! up->pf_toff) { 1570*276da39aSCy Schubert ++up->tc_sti_recv; 15712b15cb3dSCy Schubert /* save last time code to clock data */ 15722b15cb3dSCy Schubert save_ltc(pp, gps_time); 1573*276da39aSCy Schubert /* now parse the time string */ 1574*276da39aSCy Schubert if (convert_ascii_time(&up->sti_stamp, gps_time)) { 1575*276da39aSCy Schubert DPRINTF(2, ("%s: process_tpv, stamp='%s'," 1576*276da39aSCy Schubert " recvt='%s' mode=%u\n", 1577*276da39aSCy Schubert up->logname, 1578*276da39aSCy Schubert gmprettydate(&up->sti_stamp), 1579*276da39aSCy Schubert gmprettydate(&up->sti_recvt), 15802b15cb3dSCy Schubert gps_mode)); 15812b15cb3dSCy Schubert 1582*276da39aSCy Schubert /* have to use local receive time as substitute 1583*276da39aSCy Schubert * for the real receive time: TPV does not tell 1584*276da39aSCy Schubert * us. 1585*276da39aSCy Schubert */ 1586*276da39aSCy Schubert up->sti_local = *rtime; 1587*276da39aSCy Schubert up->sti_recvt = *rtime; 1588*276da39aSCy Schubert L_SUB(&up->sti_recvt, &up->sti_fudge); 1589*276da39aSCy Schubert up->fl_sti = -1; 15902b15cb3dSCy Schubert } else { 1591*276da39aSCy Schubert ++up->tc_breply; 1592*276da39aSCy Schubert up->fl_sti = 0; 1593*276da39aSCy Schubert } 15942b15cb3dSCy Schubert } 15952b15cb3dSCy Schubert 15962b15cb3dSCy Schubert /* Set the precision from the GPSD data 1597*276da39aSCy Schubert * Use the ETP field for an estimation of the precision of the 1598*276da39aSCy Schubert * serial data. If ETP is not available, use the default serial 1599*276da39aSCy Schubert * data presion instead. (Note: The PPS branch has a different 1600*276da39aSCy Schubert * precision estimation, since it gets the proper value directly 1601*276da39aSCy Schubert * from GPSD!) 16022b15cb3dSCy Schubert */ 1603*276da39aSCy Schubert ept = json_object_lookup_float_default(jctx, 0, "ept", 2.0e-3); 1604*276da39aSCy Schubert ept = frexp(fabs(ept)*0.70710678, &xlog2); /* ~ sqrt(0.5) */ 1605*276da39aSCy Schubert if (ept < 0.25) 1606*276da39aSCy Schubert xlog2 = INT_MIN; 1607*276da39aSCy Schubert if (ept > 2.0) 1608*276da39aSCy Schubert xlog2 = INT_MAX; 1609*276da39aSCy Schubert up->sti_prec = clamped_precision(xlog2); 16102b15cb3dSCy Schubert } 16112b15cb3dSCy Schubert 16122b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 16132b15cb3dSCy Schubert 16142b15cb3dSCy Schubert static void 16152b15cb3dSCy Schubert process_pps( 16162b15cb3dSCy Schubert peerT * const peer , 16172b15cb3dSCy Schubert json_ctx * const jctx , 16182b15cb3dSCy Schubert const l_fp * const rtime) 16192b15cb3dSCy Schubert { 16202b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 16212b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 16222b15cb3dSCy Schubert 1623*276da39aSCy Schubert int xlog2; 16242b15cb3dSCy Schubert 1625*276da39aSCy Schubert ++up->tc_pps_recv; 16262b15cb3dSCy Schubert 1627*276da39aSCy Schubert /* Bail out if there's indication that time sync is bad or 1628*276da39aSCy Schubert * if we're explicitely requested to ignore PPS data. 1629*276da39aSCy Schubert */ 1630*276da39aSCy Schubert if (up->fl_nosync) 1631*276da39aSCy Schubert return; 16322b15cb3dSCy Schubert 16332b15cb3dSCy Schubert up->pps_local = *rtime; 1634*276da39aSCy Schubert /* Now grab the time values. 'clock_*' is the event time of the 1635*276da39aSCy Schubert * pulse measured on the local system clock; 'real_*' is the GPS 1636*276da39aSCy Schubert * reference time GPSD associated with the pulse. 1637*276da39aSCy Schubert */ 1638*276da39aSCy Schubert if (up->pf_nsec) { 1639*276da39aSCy Schubert if ( ! get_binary_time(&up->pps_recvt2, jctx, 1640*276da39aSCy Schubert "clock_sec", "clock_nsec", 1)) 1641*276da39aSCy Schubert goto fail; 1642*276da39aSCy Schubert if ( ! get_binary_time(&up->pps_stamp2, jctx, 1643*276da39aSCy Schubert "real_sec", "real_nsec", 1)) 1644*276da39aSCy Schubert goto fail; 1645*276da39aSCy Schubert } else { 1646*276da39aSCy Schubert if ( ! get_binary_time(&up->pps_recvt2, jctx, 1647*276da39aSCy Schubert "clock_sec", "clock_musec", 1000)) 1648*276da39aSCy Schubert goto fail; 1649*276da39aSCy Schubert if ( ! get_binary_time(&up->pps_stamp2, jctx, 1650*276da39aSCy Schubert "real_sec", "real_musec", 1000)) 1651*276da39aSCy Schubert goto fail; 1652*276da39aSCy Schubert } 16532b15cb3dSCy Schubert 1654*276da39aSCy Schubert /* Try to read the precision field from the PPS record. If it's 1655*276da39aSCy Schubert * not there, take the precision from the serial data. 1656*276da39aSCy Schubert */ 1657*276da39aSCy Schubert xlog2 = json_object_lookup_int_default( 1658*276da39aSCy Schubert jctx, 0, "precision", up->sti_prec); 1659*276da39aSCy Schubert up->pps_prec = clamped_precision(xlog2); 1660*276da39aSCy Schubert 1661*276da39aSCy Schubert /* Get fudged receive times for primary & secondary unit */ 1662*276da39aSCy Schubert up->pps_recvt = up->pps_recvt2; 1663*276da39aSCy Schubert L_SUB(&up->pps_recvt , &up->pps_fudge ); 1664*276da39aSCy Schubert L_SUB(&up->pps_recvt2, &up->pps_fudge2); 1665*276da39aSCy Schubert pp->lastrec = up->pps_recvt; 1666*276da39aSCy Schubert 1667*276da39aSCy Schubert /* Map to nearest full second as reference time stamp for the 1668*276da39aSCy Schubert * primary channel. Sanity checks are done in evaluation step. 1669*276da39aSCy Schubert */ 16702b15cb3dSCy Schubert up->pps_stamp = up->pps_recvt; 16712b15cb3dSCy Schubert L_ADDUF(&up->pps_stamp, 0x80000000u); 16722b15cb3dSCy Schubert up->pps_stamp.l_uf = 0; 16732b15cb3dSCy Schubert 1674*276da39aSCy Schubert if (NULL != up->pps_peer) 1675*276da39aSCy Schubert save_ltc(up->pps_peer->procptr, 1676*276da39aSCy Schubert gmprettydate(&up->pps_stamp2)); 1677*276da39aSCy Schubert DPRINTF(2, ("%s: PPS record processed," 1678*276da39aSCy Schubert " stamp='%s', recvt='%s'\n", 1679*276da39aSCy Schubert up->logname, 1680*276da39aSCy Schubert gmprettydate(&up->pps_stamp2), 1681*276da39aSCy Schubert gmprettydate(&up->pps_recvt2))); 16822b15cb3dSCy Schubert 1683*276da39aSCy Schubert up->fl_pps = (0 != (pp->sloppyclockflag & CLK_FLAG2)) - 1; 1684*276da39aSCy Schubert up->fl_pps2 = -1; 16852b15cb3dSCy Schubert return; 16862b15cb3dSCy Schubert 16872b15cb3dSCy Schubert fail: 1688*276da39aSCy Schubert DPRINTF(1, ("%s: PPS record processing FAILED\n", 1689*276da39aSCy Schubert up->logname)); 1690*276da39aSCy Schubert ++up->tc_breply; 1691*276da39aSCy Schubert } 1692*276da39aSCy Schubert 1693*276da39aSCy Schubert /* ------------------------------------------------------------------ */ 1694*276da39aSCy Schubert 1695*276da39aSCy Schubert static void 1696*276da39aSCy Schubert process_toff( 1697*276da39aSCy Schubert peerT * const peer , 1698*276da39aSCy Schubert json_ctx * const jctx , 1699*276da39aSCy Schubert const l_fp * const rtime) 1700*276da39aSCy Schubert { 1701*276da39aSCy Schubert clockprocT * const pp = peer->procptr; 1702*276da39aSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 1703*276da39aSCy Schubert 1704*276da39aSCy Schubert ++up->tc_sti_recv; 1705*276da39aSCy Schubert 1706*276da39aSCy Schubert /* remember this! */ 1707*276da39aSCy Schubert up->pf_toff = -1; 1708*276da39aSCy Schubert 1709*276da39aSCy Schubert /* bail out if there's indication that time sync is bad */ 1710*276da39aSCy Schubert if (up->fl_nosync) 1711*276da39aSCy Schubert return; 1712*276da39aSCy Schubert 1713*276da39aSCy Schubert if ( ! get_binary_time(&up->sti_recvt, jctx, 1714*276da39aSCy Schubert "clock_sec", "clock_nsec", 1)) 1715*276da39aSCy Schubert goto fail; 1716*276da39aSCy Schubert if ( ! get_binary_time(&up->sti_stamp, jctx, 1717*276da39aSCy Schubert "real_sec", "real_nsec", 1)) 1718*276da39aSCy Schubert goto fail; 1719*276da39aSCy Schubert L_SUB(&up->sti_recvt, &up->sti_fudge); 1720*276da39aSCy Schubert up->sti_local = *rtime; 1721*276da39aSCy Schubert up->fl_sti = -1; 1722*276da39aSCy Schubert 1723*276da39aSCy Schubert save_ltc(pp, gmprettydate(&up->sti_stamp)); 1724*276da39aSCy Schubert DPRINTF(2, ("%s: TOFF record processed," 1725*276da39aSCy Schubert " stamp='%s', recvt='%s'\n", 1726*276da39aSCy Schubert up->logname, 1727*276da39aSCy Schubert gmprettydate(&up->sti_stamp), 1728*276da39aSCy Schubert gmprettydate(&up->sti_recvt))); 1729*276da39aSCy Schubert return; 1730*276da39aSCy Schubert 1731*276da39aSCy Schubert fail: 1732*276da39aSCy Schubert DPRINTF(1, ("%s: TOFF record processing FAILED\n", 1733*276da39aSCy Schubert up->logname)); 1734*276da39aSCy Schubert ++up->tc_breply; 17352b15cb3dSCy Schubert } 17362b15cb3dSCy Schubert 17372b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 17382b15cb3dSCy Schubert 17392b15cb3dSCy Schubert static void 17402b15cb3dSCy Schubert gpsd_parse( 17412b15cb3dSCy Schubert peerT * const peer , 17422b15cb3dSCy Schubert const l_fp * const rtime) 17432b15cb3dSCy Schubert { 17442b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 17452b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 17462b15cb3dSCy Schubert 17472b15cb3dSCy Schubert const char * clsid; 17482b15cb3dSCy Schubert 1749*276da39aSCy Schubert DPRINTF(2, ("%s: gpsd_parse: time %s '%.*s'\n", 1750*276da39aSCy Schubert up->logname, ulfptoa(rtime, 6), 1751*276da39aSCy Schubert up->buflen, up->buffer)); 17522b15cb3dSCy Schubert 1753*276da39aSCy Schubert /* See if we can grab anything potentially useful. JSMN does not 1754*276da39aSCy Schubert * need a trailing NUL, but it needs the number of bytes to 1755*276da39aSCy Schubert * process. */ 1756*276da39aSCy Schubert if (!json_parse_record(&up->json_parse, up->buffer, up->buflen)) { 1757*276da39aSCy Schubert ++up->tc_breply; 17582b15cb3dSCy Schubert return; 1759*276da39aSCy Schubert } 17602b15cb3dSCy Schubert 17612b15cb3dSCy Schubert /* Now dispatch over the objects we know */ 1762*276da39aSCy Schubert clsid = json_object_lookup_string(&up->json_parse, 0, "class"); 1763*276da39aSCy Schubert if (NULL == clsid) { 1764*276da39aSCy Schubert ++up->tc_breply; 1765*276da39aSCy Schubert return; 1766*276da39aSCy Schubert } 17672b15cb3dSCy Schubert 1768*276da39aSCy Schubert if (!strcmp("TPV", clsid)) 1769*276da39aSCy Schubert process_tpv(peer, &up->json_parse, rtime); 17702b15cb3dSCy Schubert else if (!strcmp("PPS", clsid)) 1771*276da39aSCy Schubert process_pps(peer, &up->json_parse, rtime); 1772*276da39aSCy Schubert else if (!strcmp("TOFF", clsid)) 1773*276da39aSCy Schubert process_toff(peer, &up->json_parse, rtime); 1774*276da39aSCy Schubert else if (!strcmp("VERSION", clsid)) 1775*276da39aSCy Schubert process_version(peer, &up->json_parse, rtime); 17762b15cb3dSCy Schubert else if (!strcmp("WATCH", clsid)) 1777*276da39aSCy Schubert process_watch(peer, &up->json_parse, rtime); 17782b15cb3dSCy Schubert else 17792b15cb3dSCy Schubert return; /* nothing we know about... */ 1780*276da39aSCy Schubert ++up->tc_recv; 17812b15cb3dSCy Schubert 1782*276da39aSCy Schubert /* if possible, feed the PPS side channel */ 1783*276da39aSCy Schubert if (up->pps_peer) 1784*276da39aSCy Schubert eval_pps_secondary( 1785*276da39aSCy Schubert up->pps_peer, up->pps_peer->procptr, up); 17862b15cb3dSCy Schubert 1787*276da39aSCy Schubert /* check PPS vs. STI receive times: 1788*276da39aSCy Schubert * If STI is before PPS, then clearly the STI is too old. If PPS 1789*276da39aSCy Schubert * is before STI by more than one second, then PPS is too old. 1790*276da39aSCy Schubert * Weed out stale time stamps & flags. 1791*276da39aSCy Schubert */ 1792*276da39aSCy Schubert if (up->fl_pps && up->fl_sti) { 1793*276da39aSCy Schubert l_fp diff; 1794*276da39aSCy Schubert diff = up->sti_local; 1795*276da39aSCy Schubert L_SUB(&diff, &up->pps_local); 1796*276da39aSCy Schubert if (diff.l_i > 0) 1797*276da39aSCy Schubert up->fl_pps = 0; /* pps too old */ 1798*276da39aSCy Schubert else if (diff.l_i < 0) 1799*276da39aSCy Schubert up->fl_sti = 0; /* serial data too old */ 18002b15cb3dSCy Schubert } 1801*276da39aSCy Schubert 1802*276da39aSCy Schubert /* dispatch to the mode-dependent processing functions */ 1803*276da39aSCy Schubert switch (up->mode) { 1804*276da39aSCy Schubert default: 1805*276da39aSCy Schubert case MODE_OP_STI: 1806*276da39aSCy Schubert eval_serial(peer, pp, up); 1807*276da39aSCy Schubert break; 1808*276da39aSCy Schubert 1809*276da39aSCy Schubert case MODE_OP_STRICT: 1810*276da39aSCy Schubert eval_strict(peer, pp, up); 1811*276da39aSCy Schubert break; 1812*276da39aSCy Schubert 1813*276da39aSCy Schubert case MODE_OP_AUTO: 1814*276da39aSCy Schubert eval_auto(peer, pp, up); 1815*276da39aSCy Schubert break; 18162b15cb3dSCy Schubert } 18172b15cb3dSCy Schubert } 18182b15cb3dSCy Schubert 18192b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 18202b15cb3dSCy Schubert 18212b15cb3dSCy Schubert static void 18222b15cb3dSCy Schubert gpsd_stop_socket( 18232b15cb3dSCy Schubert peerT * const peer) 18242b15cb3dSCy Schubert { 18252b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 18262b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 18272b15cb3dSCy Schubert 1828*276da39aSCy Schubert if (-1 != pp->io.fd) { 18292b15cb3dSCy Schubert if (syslogok(pp, up)) 18302b15cb3dSCy Schubert msyslog(LOG_INFO, 1831*276da39aSCy Schubert "%s: closing socket to GPSD, fd=%d", 1832*276da39aSCy Schubert up->logname, pp->io.fd); 1833*276da39aSCy Schubert else 1834*276da39aSCy Schubert DPRINTF(1, ("%s: closing socket to GPSD, fd=%d\n", 1835*276da39aSCy Schubert up->logname, pp->io.fd)); 1836*276da39aSCy Schubert io_closeclock(&pp->io); 1837*276da39aSCy Schubert pp->io.fd = -1; 1838*276da39aSCy Schubert } 18392b15cb3dSCy Schubert up->tickover = up->tickpres; 18402b15cb3dSCy Schubert up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH); 18412b15cb3dSCy Schubert up->fl_vers = 0; 1842*276da39aSCy Schubert up->fl_sti = 0; 18432b15cb3dSCy Schubert up->fl_pps = 0; 18442b15cb3dSCy Schubert up->fl_watch = 0; 18452b15cb3dSCy Schubert } 18462b15cb3dSCy Schubert 18472b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 18482b15cb3dSCy Schubert 18492b15cb3dSCy Schubert static void 18502b15cb3dSCy Schubert gpsd_init_socket( 18512b15cb3dSCy Schubert peerT * const peer) 18522b15cb3dSCy Schubert { 18532b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 18542b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 18552b15cb3dSCy Schubert addrinfoT * ai; 18562b15cb3dSCy Schubert int rc; 18572b15cb3dSCy Schubert int ov; 18582b15cb3dSCy Schubert 18592b15cb3dSCy Schubert /* draw next address to try */ 18602b15cb3dSCy Schubert if (NULL == up->addr) 18612b15cb3dSCy Schubert up->addr = s_gpsd_addr; 18622b15cb3dSCy Schubert ai = up->addr; 18632b15cb3dSCy Schubert up->addr = ai->ai_next; 18642b15cb3dSCy Schubert 18652b15cb3dSCy Schubert /* try to create a matching socket */ 18662b15cb3dSCy Schubert up->fdt = socket( 18672b15cb3dSCy Schubert ai->ai_family, ai->ai_socktype, ai->ai_protocol); 18682b15cb3dSCy Schubert if (-1 == up->fdt) { 18692b15cb3dSCy Schubert if (syslogok(pp, up)) 18702b15cb3dSCy Schubert msyslog(LOG_ERR, 18712b15cb3dSCy Schubert "%s: cannot create GPSD socket: %m", 1872*276da39aSCy Schubert up->logname); 18732b15cb3dSCy Schubert goto no_socket; 18742b15cb3dSCy Schubert } 18752b15cb3dSCy Schubert 1876*276da39aSCy Schubert /* Make sure the socket is non-blocking. Connect/reconnect and 1877*276da39aSCy Schubert * IO happen in an event-driven environment, and synchronous 1878*276da39aSCy Schubert * operations wreak havoc on that. 1879*276da39aSCy Schubert */ 18802b15cb3dSCy Schubert rc = fcntl(up->fdt, F_SETFL, O_NONBLOCK, 1); 18812b15cb3dSCy Schubert if (-1 == rc) { 18822b15cb3dSCy Schubert if (syslogok(pp, up)) 18832b15cb3dSCy Schubert msyslog(LOG_ERR, 18842b15cb3dSCy Schubert "%s: cannot set GPSD socket to non-blocking: %m", 1885*276da39aSCy Schubert up->logname); 18862b15cb3dSCy Schubert goto no_socket; 18872b15cb3dSCy Schubert } 1888*276da39aSCy Schubert /* Disable nagling. The way both GPSD and NTPD handle the 1889*276da39aSCy Schubert * protocol makes it record-oriented, and in most cases 1890*276da39aSCy Schubert * complete records (JSON serialised objects) will be sent in 1891*276da39aSCy Schubert * one sweep. Nagling gives not much advantage but adds another 1892*276da39aSCy Schubert * delay, which can worsen the situation for some packets. 1893*276da39aSCy Schubert */ 18942b15cb3dSCy Schubert ov = 1; 18952b15cb3dSCy Schubert rc = setsockopt(up->fdt, IPPROTO_TCP, TCP_NODELAY, 18962b15cb3dSCy Schubert (char*)&ov, sizeof(ov)); 18972b15cb3dSCy Schubert if (-1 == rc) { 18982b15cb3dSCy Schubert if (syslogok(pp, up)) 18992b15cb3dSCy Schubert msyslog(LOG_INFO, 19002b15cb3dSCy Schubert "%s: cannot disable TCP nagle: %m", 1901*276da39aSCy Schubert up->logname); 19022b15cb3dSCy Schubert } 19032b15cb3dSCy Schubert 1904*276da39aSCy Schubert /* Start a non-blocking connect. There might be a synchronous 1905*276da39aSCy Schubert * connection result we have to handle. 1906*276da39aSCy Schubert */ 19072b15cb3dSCy Schubert rc = connect(up->fdt, ai->ai_addr, ai->ai_addrlen); 1908*276da39aSCy Schubert if (-1 == rc) { 1909*276da39aSCy Schubert if (errno == EINPROGRESS) { 1910*276da39aSCy Schubert DPRINTF(1, ("%s: async connect pending, fd=%d\n", 1911*276da39aSCy Schubert up->logname, up->fdt)); 1912*276da39aSCy Schubert return; 1913*276da39aSCy Schubert } 1914*276da39aSCy Schubert 19152b15cb3dSCy Schubert if (syslogok(pp, up)) 19162b15cb3dSCy Schubert msyslog(LOG_ERR, 19172b15cb3dSCy Schubert "%s: cannot connect GPSD socket: %m", 1918*276da39aSCy Schubert up->logname); 1919*276da39aSCy Schubert goto no_socket; 1920*276da39aSCy Schubert } 1921*276da39aSCy Schubert 1922*276da39aSCy Schubert /* We had a successful synchronous connect, so we add the 1923*276da39aSCy Schubert * refclock processing ASAP. We still have to wait for the 1924*276da39aSCy Schubert * version string and apply the watch command later on, but we 1925*276da39aSCy Schubert * might as well get the show on the road now. 1926*276da39aSCy Schubert */ 1927*276da39aSCy Schubert DPRINTF(1, ("%s: new socket connection, fd=%d\n", 1928*276da39aSCy Schubert up->logname, up->fdt)); 1929*276da39aSCy Schubert 1930*276da39aSCy Schubert pp->io.fd = up->fdt; 1931*276da39aSCy Schubert up->fdt = -1; 1932*276da39aSCy Schubert if (0 == io_addclock(&pp->io)) { 1933*276da39aSCy Schubert if (syslogok(pp, up)) 1934*276da39aSCy Schubert msyslog(LOG_ERR, 1935*276da39aSCy Schubert "%s: failed to register with I/O engine", 1936*276da39aSCy Schubert up->logname); 19372b15cb3dSCy Schubert goto no_socket; 19382b15cb3dSCy Schubert } 19392b15cb3dSCy Schubert 19402b15cb3dSCy Schubert return; 19412b15cb3dSCy Schubert 19422b15cb3dSCy Schubert no_socket: 1943*276da39aSCy Schubert if (-1 != pp->io.fd) 1944*276da39aSCy Schubert close(pp->io.fd); 19452b15cb3dSCy Schubert if (-1 != up->fdt) 19462b15cb3dSCy Schubert close(up->fdt); 1947*276da39aSCy Schubert pp->io.fd = -1; 19482b15cb3dSCy Schubert up->fdt = -1; 19492b15cb3dSCy Schubert up->tickover = up->tickpres; 19502b15cb3dSCy Schubert up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH); 19512b15cb3dSCy Schubert } 19522b15cb3dSCy Schubert 19532b15cb3dSCy Schubert /* ------------------------------------------------------------------ */ 19542b15cb3dSCy Schubert 19552b15cb3dSCy Schubert static void 19562b15cb3dSCy Schubert gpsd_test_socket( 19572b15cb3dSCy Schubert peerT * const peer) 19582b15cb3dSCy Schubert { 19592b15cb3dSCy Schubert clockprocT * const pp = peer->procptr; 19602b15cb3dSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 19612b15cb3dSCy Schubert 19622b15cb3dSCy Schubert int ec, rc; 19632b15cb3dSCy Schubert socklen_t lc; 19642b15cb3dSCy Schubert 19652b15cb3dSCy Schubert /* Check if the non-blocking connect was finished by testing the 19662b15cb3dSCy Schubert * socket for writeability. Use the 'poll()' API if available 19672b15cb3dSCy Schubert * and 'select()' otherwise. 19682b15cb3dSCy Schubert */ 1969*276da39aSCy Schubert DPRINTF(2, ("%s: check connect, fd=%d\n", 1970*276da39aSCy Schubert up->logname, up->fdt)); 19712b15cb3dSCy Schubert 19722b15cb3dSCy Schubert #if defined(HAVE_SYS_POLL_H) 19732b15cb3dSCy Schubert { 19742b15cb3dSCy Schubert struct pollfd pfd; 19752b15cb3dSCy Schubert 19762b15cb3dSCy Schubert pfd.events = POLLOUT; 19772b15cb3dSCy Schubert pfd.fd = up->fdt; 19782b15cb3dSCy Schubert rc = poll(&pfd, 1, 0); 19792b15cb3dSCy Schubert if (1 != rc || !(pfd.revents & POLLOUT)) 19802b15cb3dSCy Schubert return; 19812b15cb3dSCy Schubert } 19822b15cb3dSCy Schubert #elif defined(HAVE_SYS_SELECT_H) 19832b15cb3dSCy Schubert { 19842b15cb3dSCy Schubert struct timeval tout; 19852b15cb3dSCy Schubert fd_set wset; 19862b15cb3dSCy Schubert 19872b15cb3dSCy Schubert memset(&tout, 0, sizeof(tout)); 19882b15cb3dSCy Schubert FD_ZERO(&wset); 19892b15cb3dSCy Schubert FD_SET(up->fdt, &wset); 19902b15cb3dSCy Schubert rc = select(up->fdt+1, NULL, &wset, NULL, &tout); 19912b15cb3dSCy Schubert if (0 == rc || !(FD_ISSET(up->fdt, &wset))) 19922b15cb3dSCy Schubert return; 19932b15cb3dSCy Schubert } 19942b15cb3dSCy Schubert #else 19952b15cb3dSCy Schubert # error Blooper! That should have been found earlier! 19962b15cb3dSCy Schubert #endif 19972b15cb3dSCy Schubert 19982b15cb3dSCy Schubert /* next timeout is a full one... */ 19992b15cb3dSCy Schubert up->tickover = TICKOVER_LOW; 20002b15cb3dSCy Schubert 20012b15cb3dSCy Schubert /* check for socket error */ 20022b15cb3dSCy Schubert ec = 0; 20032b15cb3dSCy Schubert lc = sizeof(ec); 20042b15cb3dSCy Schubert rc = getsockopt(up->fdt, SOL_SOCKET, SO_ERROR, &ec, &lc); 20052b15cb3dSCy Schubert if (-1 == rc || 0 != ec) { 2006*276da39aSCy Schubert const char *errtxt; 2007*276da39aSCy Schubert if (0 == ec) 2008*276da39aSCy Schubert ec = errno; 2009*276da39aSCy Schubert errtxt = strerror(ec); 20102b15cb3dSCy Schubert if (syslogok(pp, up)) 20112b15cb3dSCy Schubert msyslog(LOG_ERR, 2012*276da39aSCy Schubert "%s: async connect to GPSD failed," 2013*276da39aSCy Schubert " fd=%d, ec=%d(%s)", 2014*276da39aSCy Schubert up->logname, up->fdt, ec, errtxt); 2015*276da39aSCy Schubert else 2016*276da39aSCy Schubert DPRINTF(1, ("%s: async connect to GPSD failed," 2017*276da39aSCy Schubert " fd=%d, ec=%d(%s)\n", 2018*276da39aSCy Schubert up->logname, up->fdt, ec, errtxt)); 20192b15cb3dSCy Schubert goto no_socket; 2020*276da39aSCy Schubert } else { 2021*276da39aSCy Schubert DPRINTF(1, ("%s: async connect to GPSD succeeded, fd=%d\n", 2022*276da39aSCy Schubert up->logname, up->fdt)); 20232b15cb3dSCy Schubert } 2024*276da39aSCy Schubert 20252b15cb3dSCy Schubert /* swap socket FDs, and make sure the clock was added */ 20262b15cb3dSCy Schubert pp->io.fd = up->fdt; 20272b15cb3dSCy Schubert up->fdt = -1; 20282b15cb3dSCy Schubert if (0 == io_addclock(&pp->io)) { 20292b15cb3dSCy Schubert if (syslogok(pp, up)) 20302b15cb3dSCy Schubert msyslog(LOG_ERR, 20312b15cb3dSCy Schubert "%s: failed to register with I/O engine", 2032*276da39aSCy Schubert up->logname); 20332b15cb3dSCy Schubert goto no_socket; 20342b15cb3dSCy Schubert } 20352b15cb3dSCy Schubert return; 20362b15cb3dSCy Schubert 20372b15cb3dSCy Schubert no_socket: 2038*276da39aSCy Schubert if (-1 != up->fdt) { 2039*276da39aSCy Schubert DPRINTF(1, ("%s: closing socket, fd=%d\n", 2040*276da39aSCy Schubert up->logname, up->fdt)); 20412b15cb3dSCy Schubert close(up->fdt); 2042*276da39aSCy Schubert } 20432b15cb3dSCy Schubert up->fdt = -1; 20442b15cb3dSCy Schubert up->tickover = up->tickpres; 20452b15cb3dSCy Schubert up->tickpres = min(up->tickpres + 5, TICKOVER_HIGH); 20462b15cb3dSCy Schubert } 20472b15cb3dSCy Schubert 20482b15cb3dSCy Schubert /* ===================================================================== 20492b15cb3dSCy Schubert * helper stuff 20502b15cb3dSCy Schubert */ 20512b15cb3dSCy Schubert 2052*276da39aSCy Schubert /* ------------------------------------------------------------------- 2053*276da39aSCy Schubert * store a properly clamped precision value 20542b15cb3dSCy Schubert */ 2055*276da39aSCy Schubert static int16_t 2056*276da39aSCy Schubert clamped_precision( 2057*276da39aSCy Schubert int rawprec) 20582b15cb3dSCy Schubert { 2059*276da39aSCy Schubert if (rawprec > 0) 2060*276da39aSCy Schubert rawprec = 0; 2061*276da39aSCy Schubert if (rawprec < -32) 2062*276da39aSCy Schubert rawprec = -32; 2063*276da39aSCy Schubert return (int16_t)rawprec; 20642b15cb3dSCy Schubert } 20652b15cb3dSCy Schubert 20662b15cb3dSCy Schubert /* ------------------------------------------------------------------- 2067*276da39aSCy Schubert * Convert a GPSD timestamp (ISO8601 Format) to an l_fp 20682b15cb3dSCy Schubert */ 20692b15cb3dSCy Schubert static BOOL 20702b15cb3dSCy Schubert convert_ascii_time( 20712b15cb3dSCy Schubert l_fp * fp , 20722b15cb3dSCy Schubert const char * gps_time) 20732b15cb3dSCy Schubert { 20742b15cb3dSCy Schubert char *ep; 20752b15cb3dSCy Schubert struct tm gd; 20762b15cb3dSCy Schubert struct timespec ts; 2077*276da39aSCy Schubert uint32_t dw; 20782b15cb3dSCy Schubert 20792b15cb3dSCy Schubert /* Use 'strptime' to take the brunt of the work, then parse 20802b15cb3dSCy Schubert * the fractional part manually, starting with a digit weight of 20812b15cb3dSCy Schubert * 10^8 nanoseconds. 20822b15cb3dSCy Schubert */ 20832b15cb3dSCy Schubert ts.tv_nsec = 0; 20842b15cb3dSCy Schubert ep = strptime(gps_time, "%Y-%m-%dT%H:%M:%S", &gd); 2085*276da39aSCy Schubert if (NULL == ep) 2086*276da39aSCy Schubert return FALSE; /* could not parse the mandatory stuff! */ 20872b15cb3dSCy Schubert if (*ep == '.') { 2088*276da39aSCy Schubert dw = 100000000u; 2089*276da39aSCy Schubert while (isdigit(*(unsigned char*)++ep)) { 2090*276da39aSCy Schubert ts.tv_nsec += (*(unsigned char*)ep - '0') * dw; 2091*276da39aSCy Schubert dw /= 10u; 20922b15cb3dSCy Schubert } 20932b15cb3dSCy Schubert } 20942b15cb3dSCy Schubert if (ep[0] != 'Z' || ep[1] != '\0') 2095*276da39aSCy Schubert return FALSE; /* trailing garbage */ 20962b15cb3dSCy Schubert 2097*276da39aSCy Schubert /* Now convert the whole thing into a 'l_fp'. We do not use 2098*276da39aSCy Schubert * 'mkgmtime()' since its not standard and going through the 2099*276da39aSCy Schubert * calendar routines is not much effort, either. 2100*276da39aSCy Schubert */ 21012b15cb3dSCy Schubert ts.tv_sec = (ntpcal_tm_to_rd(&gd) - DAY_NTP_STARTS) * SECSPERDAY 21022b15cb3dSCy Schubert + ntpcal_tm_to_daysec(&gd); 21032b15cb3dSCy Schubert *fp = tspec_intv_to_lfp(ts); 21042b15cb3dSCy Schubert 21052b15cb3dSCy Schubert return TRUE; 21062b15cb3dSCy Schubert } 21072b15cb3dSCy Schubert 21082b15cb3dSCy Schubert /* ------------------------------------------------------------------- 21092b15cb3dSCy Schubert * Save the last timecode string, making sure it's properly truncated 21102b15cb3dSCy Schubert * if necessary and NUL terminated in any case. 21112b15cb3dSCy Schubert */ 21122b15cb3dSCy Schubert static void 21132b15cb3dSCy Schubert save_ltc( 21142b15cb3dSCy Schubert clockprocT * const pp, 21152b15cb3dSCy Schubert const char * const tc) 21162b15cb3dSCy Schubert { 21172b15cb3dSCy Schubert size_t len; 21182b15cb3dSCy Schubert 21192b15cb3dSCy Schubert len = (tc) ? strlen(tc) : 0; 21202b15cb3dSCy Schubert if (len >= sizeof(pp->a_lastcode)) 21212b15cb3dSCy Schubert len = sizeof(pp->a_lastcode) - 1; 21222b15cb3dSCy Schubert pp->lencode = (u_short)len; 21232b15cb3dSCy Schubert memcpy(pp->a_lastcode, tc, len); 21242b15cb3dSCy Schubert pp->a_lastcode[len] = '\0'; 21252b15cb3dSCy Schubert } 21262b15cb3dSCy Schubert 2127*276da39aSCy Schubert /* ------------------------------------------------------------------- 21282b15cb3dSCy Schubert * asprintf replacement... it's not available everywhere... 21292b15cb3dSCy Schubert */ 21302b15cb3dSCy Schubert static int 21312b15cb3dSCy Schubert myasprintf( 21322b15cb3dSCy Schubert char ** spp, 21332b15cb3dSCy Schubert char const * fmt, 21342b15cb3dSCy Schubert ... ) 21352b15cb3dSCy Schubert { 21362b15cb3dSCy Schubert size_t alen, plen; 21372b15cb3dSCy Schubert 21382b15cb3dSCy Schubert alen = 32; 21392b15cb3dSCy Schubert *spp = NULL; 21402b15cb3dSCy Schubert do { 21412b15cb3dSCy Schubert va_list va; 21422b15cb3dSCy Schubert 21432b15cb3dSCy Schubert alen += alen; 21442b15cb3dSCy Schubert free(*spp); 21452b15cb3dSCy Schubert *spp = (char*)malloc(alen); 21462b15cb3dSCy Schubert if (NULL == *spp) 21472b15cb3dSCy Schubert return -1; 21482b15cb3dSCy Schubert 21492b15cb3dSCy Schubert va_start(va, fmt); 21502b15cb3dSCy Schubert plen = (size_t)vsnprintf(*spp, alen, fmt, va); 21512b15cb3dSCy Schubert va_end(va); 21522b15cb3dSCy Schubert } while (plen >= alen); 21532b15cb3dSCy Schubert 21542b15cb3dSCy Schubert return (int)plen; 21552b15cb3dSCy Schubert } 21562b15cb3dSCy Schubert 2157*276da39aSCy Schubert /* ------------------------------------------------------------------- 2158*276da39aSCy Schubert * dump a raw data buffer 2159*276da39aSCy Schubert */ 2160*276da39aSCy Schubert 2161*276da39aSCy Schubert static char * 2162*276da39aSCy Schubert add_string( 2163*276da39aSCy Schubert char *dp, 2164*276da39aSCy Schubert char *ep, 2165*276da39aSCy Schubert const char *sp) 2166*276da39aSCy Schubert { 2167*276da39aSCy Schubert while (dp != ep && *sp) 2168*276da39aSCy Schubert *dp++ = *sp++; 2169*276da39aSCy Schubert return dp; 2170*276da39aSCy Schubert } 2171*276da39aSCy Schubert 2172*276da39aSCy Schubert static void 2173*276da39aSCy Schubert log_data( 2174*276da39aSCy Schubert peerT *peer, 2175*276da39aSCy Schubert const char *what, 2176*276da39aSCy Schubert const char *buf , 2177*276da39aSCy Schubert size_t len ) 2178*276da39aSCy Schubert { 2179*276da39aSCy Schubert /* we're running single threaded with regards to the clocks. */ 2180*276da39aSCy Schubert static char s_lbuf[2048]; 2181*276da39aSCy Schubert 2182*276da39aSCy Schubert clockprocT * const pp = peer->procptr; 2183*276da39aSCy Schubert gpsd_unitT * const up = (gpsd_unitT *)pp->unitptr; 2184*276da39aSCy Schubert 2185*276da39aSCy Schubert if (debug > 1) { 2186*276da39aSCy Schubert const char *sptr = buf; 2187*276da39aSCy Schubert const char *stop = buf + len; 2188*276da39aSCy Schubert char *dptr = s_lbuf; 2189*276da39aSCy Schubert char *dtop = s_lbuf + sizeof(s_lbuf) - 1; /* for NUL */ 2190*276da39aSCy Schubert 2191*276da39aSCy Schubert while (sptr != stop && dptr != dtop) { 2192*276da39aSCy Schubert if (*sptr == '\\') { 2193*276da39aSCy Schubert dptr = add_string(dptr, dtop, "\\\\"); 2194*276da39aSCy Schubert } else if (isprint(*sptr)) { 2195*276da39aSCy Schubert *dptr++ = *sptr; 2196*276da39aSCy Schubert } else { 2197*276da39aSCy Schubert char fbuf[6]; 2198*276da39aSCy Schubert snprintf(fbuf, sizeof(fbuf), "\\%03o", *(const u_char*)sptr); 2199*276da39aSCy Schubert dptr = add_string(dptr, dtop, fbuf); 2200*276da39aSCy Schubert } 2201*276da39aSCy Schubert sptr++; 2202*276da39aSCy Schubert } 2203*276da39aSCy Schubert *dptr = '\0'; 2204*276da39aSCy Schubert mprintf("%s[%s]: '%s'\n", up->logname, what, s_lbuf); 2205*276da39aSCy Schubert } 2206*276da39aSCy Schubert } 2207*276da39aSCy Schubert 22082b15cb3dSCy Schubert #else 22092b15cb3dSCy Schubert NONEMPTY_TRANSLATION_UNIT 22102b15cb3dSCy Schubert #endif /* REFCLOCK && CLOCK_GPSDJSON */ 2211