/src/gpsd/gpsd-3.27.6~dev/gpsd/net_dgpsip.c
Line | Count | Source |
1 | | /* net_dgpsip.c -- gather and dispatch DGPS data from DGPSIP servers |
2 | | * |
3 | | * This file is Copyright by the GPSD project |
4 | | * SPDX-License-Identifier: BSD-2-clause |
5 | | */ |
6 | | |
7 | | #include "../include/gpsd_config.h" // must be before all includes |
8 | | |
9 | | #include <errno.h> // for errno |
10 | | #include <fcntl.h> |
11 | | #include <netdb.h> |
12 | | #include <stdbool.h> |
13 | | #include <stdio.h> |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | #include <sys/socket.h> |
17 | | #include <sys/types.h> |
18 | | #include <unistd.h> |
19 | | |
20 | | #include "../include/gpsd.h" |
21 | | |
22 | | /* open a connection to a DGPSIP server |
23 | | * Return: socket on success |
24 | | * less than zero on failure |
25 | | */ |
26 | | socket_t dgpsip_open(struct gps_device_t *device, const char *dgpsserver) |
27 | 0 | { |
28 | 0 | char *colon; |
29 | 0 | const char *dgpsport = "rtcm-sc104"; |
30 | 0 | int opts; |
31 | 0 | char hn[256], buf[BUFSIZ]; |
32 | 0 | socket_t dsock; |
33 | 0 | ssize_t blen; |
34 | 0 | char server[GPS_PATH_MAX]; |
35 | |
|
36 | 0 | device->servicetype = SERVICE_DGPSIP; |
37 | 0 | device->dgpsip.reported = false; |
38 | 0 | strlcpy(server, dgpsserver, sizeof(server)); |
39 | 0 | if (NULL != (colon = strchr(server, ':'))) { |
40 | 0 | dgpsport = colon + 1; |
41 | 0 | *colon = '\0'; |
42 | 0 | } |
43 | 0 | if (!getservbyname(dgpsport, "tcp")) { |
44 | 0 | dgpsport = DEFAULT_RTCM_PORT; |
45 | 0 | } |
46 | |
|
47 | 0 | dsock = netlib_connectsock(AF_UNSPEC, server, dgpsport, "tcp"); |
48 | 0 | if (0 > dsock) { |
49 | | // cast for 32-bit ints |
50 | 0 | GPSD_LOG(LOG_ERROR, &device->context->errout, |
51 | 0 | "DGPS: can't connect to DGPS server %s, " |
52 | 0 | "netlib error %s(%ld).\n", |
53 | 0 | dgpsserver, netlib_errstr(dsock), (long)dsock); |
54 | 0 | device->gpsdata.gps_fd = PLACEHOLDING_FD; |
55 | 0 | return dsock; |
56 | 0 | } |
57 | | // cast for 32-bit ints |
58 | 0 | GPSD_LOG(LOG_PROG, &device->context->errout, |
59 | 0 | "DGPS: connection to DGPS server %s established. fd=%ld\n", |
60 | 0 | dgpsserver, (long)dsock); |
61 | 0 | device->gpsdata.gps_fd = (gps_fd_t)dsock; |
62 | 0 | (void)gethostname(hn, sizeof(hn)); |
63 | | // greeting required by some RTCM104 servers; others will ignore it |
64 | 0 | blen = snprintf(buf, sizeof(buf), "HELO %s gpsd %s\r\nR\r\n", hn, |
65 | 0 | VERSION); |
66 | 0 | if (1 > blen || |
67 | 0 | write(device->gpsdata.gps_fd, buf, blen) != blen) { |
68 | 0 | GPSD_LOG(LOG_ERROR, &device->context->errout, |
69 | 0 | "DGPS: hello to DGPS server %s failed\n", |
70 | 0 | dgpsserver); |
71 | 0 | } |
72 | 0 | opts = fcntl(device->gpsdata.gps_fd, F_GETFL); |
73 | |
|
74 | 0 | if (0 <= opts) { |
75 | 0 | (void)fcntl(device->gpsdata.gps_fd, F_SETFL, opts | O_NONBLOCK); |
76 | 0 | } else { |
77 | 0 | GPSD_LOG(LOG_ERROR, &device->context->errout, |
78 | 0 | "DGPS: fcntl %s failed. %s(%d)\n", |
79 | 0 | dgpsserver, strerror(errno), errno); |
80 | 0 | } |
81 | 0 | return (socket_t)device->gpsdata.gps_fd; |
82 | 0 | } |
83 | | |
84 | | // may be time to ship a usage report to the DGPSIP server |
85 | | void dgpsip_report(struct gps_context_t *context, |
86 | | struct gps_device_t *gps, |
87 | | struct gps_device_t *dgpsip) |
88 | 0 | { |
89 | | /* |
90 | | * 10 is an arbitrary number, the point is to have gotten several good |
91 | | * fixes before reporting usage to our DGPSIP server. |
92 | | */ |
93 | 0 | if (10 < context->fixcnt && |
94 | 0 | !dgpsip->dgpsip.reported) { |
95 | 0 | dgpsip->dgpsip.reported = true; |
96 | 0 | if (-1 < dgpsip->gpsdata.gps_fd) { |
97 | 0 | char buf[BUFSIZ]; |
98 | 0 | ssize_t blen; |
99 | |
|
100 | 0 | blen = snprintf(buf, sizeof(buf), "R %0.8f %0.8f %0.2f\r\n", |
101 | 0 | gps->gpsdata.fix.latitude, |
102 | 0 | gps->gpsdata.fix.longitude, |
103 | 0 | gps->gpsdata.fix.altMSL); |
104 | 0 | if (1 > blen || |
105 | 0 | write(dgpsip->gpsdata.gps_fd, buf,blen) != blen) { |
106 | 0 | GPSD_LOG(LOG_WARN, &context->errout, |
107 | 0 | "DGPS: write to dgps FAILED\n"); |
108 | 0 | } else { |
109 | 0 | GPSD_LOG(LOG_IO, &context->errout, "DGPS: => dgps %s\n", buf); |
110 | 0 | } |
111 | 0 | } |
112 | 0 | } |
113 | 0 | } |
114 | | |
115 | | // vim: set expandtab shiftwidth=4 |