Coverage Report

Created: 2026-06-04 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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