diff options
author | Gary E. Miller <gem@rellim.com> | 2018-07-24 15:54:42 -0700 |
---|---|---|
committer | Gary E. Miller <gem@rellim.com> | 2018-07-24 15:54:42 -0700 |
commit | bdb327c9e3d6ff90a73058ff0579491e6beedcff (patch) | |
tree | 6b8198549f4a43f7ce642385a1f3896afbca954f /gpsd.c | |
parent | 03c1110012730a2a72e43756580f03709684a04a (diff) | |
download | gpsd-bdb327c9e3d6ff90a73058ff0579491e6beedcff.tar.gz |
gpsd.c: fix gpsd master/slave mode
The gpsd command parser was splitting the ? from commands (WATCH, POLL,
etc.), and then sending the ? to the gpsd master in a separate packet.
But the gpsd is not buffering network data, so failing to recognize
The two packets of ? and WATCH as one complete command. Adding full
buffering to the gpsd master looks a lot harder than just sending
the ?WATCH in one packet. Also leading to some code simplification
in the gpsd slave. Been broken since 2013 at least.
Many thanks to Virgin Orbit for the support finding and fixing this.
Diffstat (limited to 'gpsd.c')
-rw-r--r-- | gpsd.c | 37 |
1 files changed, 19 insertions, 18 deletions
@@ -920,6 +920,7 @@ static void handle_control(int sfd, char *buf) } else if (buf[0] == '&') { /* split line after & into dev=hexdata, send unpacked hexdata to dev */ char *eq; + (void)snarfline(buf + 1, &stash); eq = strchr(stash, '='); if (eq == NULL) { @@ -1117,15 +1118,13 @@ static void handle_request(struct subscriber_t *sub, struct gps_device_t *devp; const char *end = NULL; - if (buf[0] == '?') - ++buf; - if (str_starts_with(buf, "DEVICES;")) { - buf += 8; + if (str_starts_with(buf, "?DEVICES;")) { + buf += 9; json_devicelist_dump(reply, replylen); - } else if (str_starts_with(buf, "WATCH") - && (buf[5] == ';' || buf[5] == '=')) { + } else if (str_starts_with(buf, "?WATCH") + && (buf[6] == ';' || buf[6] == '=')) { const char *start = buf; - buf += 5; + buf += 6; if (*buf == ';') { ++buf; } else { @@ -1152,8 +1151,9 @@ static void handle_request(struct subscriber_t *sub, if (allocated_device(devp)) { (void)awaken(devp); if (devp->sourcetype == source_gpsd) { - (void)gpsd_write(devp, "?", 1); - (void)gpsd_write(devp, start, (size_t)(end-start)); + /* forward to master gpsd */ + (void)gpsd_write(devp, start, + (size_t)(end-start)); } } } else { @@ -1167,7 +1167,6 @@ static void handle_request(struct subscriber_t *sub, goto bailout; } else if (awaken(devp)) { if (devp->sourcetype == source_gpsd) { - (void)gpsd_write(devp, "?", 1); (void)gpsd_write(devp, start, (size_t)(end-start)); } } else { @@ -1185,10 +1184,10 @@ static void handle_request(struct subscriber_t *sub, json_devicelist_dump(reply + strlen(reply), replylen - strlen(reply)); json_watch_dump(&sub->policy, reply + strlen(reply), replylen - strlen(reply)); - } else if (str_starts_with(buf, "DEVICE") - && (buf[6] == ';' || buf[6] == '=')) { + } else if (str_starts_with(buf, "?DEVICE") + && (buf[7] == ';' || buf[7] == '=')) { struct devconfig_t devconf; - buf += 6; + buf += 7; devconf.path[0] = '\0'; /* initially, no device selection */ if (*buf == ';') { ++buf; @@ -1314,10 +1313,10 @@ static void handle_request(struct subscriber_t *sub, reply + strlen(reply), replylen - strlen(reply)); } - } else if (str_starts_with(buf, "POLL;")) { + } else if (str_starts_with(buf, "?POLL;")) { char tbuf[JSON_DATE_MAX+1]; int active = 0; - buf += 5; + buf += 6; for (devp = devices; devp < devices + MAX_DEVICES; devp++) if (allocated_device(devp) && subscribed(sub, devp)) if ((devp->observed & GPS_TYPEMASK) != 0) @@ -1364,8 +1363,8 @@ static void handle_request(struct subscriber_t *sub, } str_rstrip_char(reply, ','); (void)strlcat(reply, "]}\r\n", replylen); - } else if (str_starts_with(buf, "VERSION;")) { - buf += 8; + } else if (str_starts_with(buf, "?VERSION;")) { + buf += 9; json_version_dump(reply, replylen); } else { const char *errend; @@ -1698,8 +1697,10 @@ static void all_reports(struct gps_device_t *device, gps_mask_t changed) } #ifdef SOCKET_EXPORT_ENABLE +/* Execute GPSD requests (?POLL, ?WATCH, etc.) from a buffer. + * The entire request must be in the buffer. + */ static int handle_gpsd_request(struct subscriber_t *sub, const char *buf) -/* execute GPSD requests from a buffer */ { char reply[GPS_JSON_RESPONSE_MAX + 1]; |