static int ntrip_sourcetable_parse(struct gps_device_t *device) { struct ntrip_stream_t hold; ssize_t llen, len = 0; char *line; bool sourcetable = false; bool match = false; char buf[BUFSIZ]; size_t blen = sizeof(buf); int fd = device->gpsdata.gps_fd; for (;;) { char *eol; ssize_t rlen; memset(&buf[len], 0, (size_t) (blen - len)); rlen = read(fd, &buf[len], (size_t) (blen - 1 - len)); if (rlen == -1) { if (errno == EINTR) { continue; } if (sourcetable && !match && errno == EAGAIN) { // we have not yet found a match, but there currently is no more data return 0; } if (match) { return 1; } gpsd_log(&device->context->errout, LOG_ERROR, "ntrip stream read error %d on fd %d\n", errno, fd); return -1; } else if (rlen == 0) { // server closed the connection gpsd_log(&device->context->errout, LOG_ERROR, "ntrip stream unexpected close %d on fd %d during sourcetable read\n", errno, fd); return -1; } line = buf; rlen = len += rlen; gpsd_log(&device->context->errout, LOG_RAW, "Ntrip source table buffer %s\n", buf); sourcetable = device->ntrip.sourcetable_parse; if (!sourcetable) { /* parse SOURCETABLE */ if (str_starts_with(line, NTRIP_SOURCETABLE)) { sourcetable = true; device->ntrip.sourcetable_parse = true; llen = (ssize_t) strlen(NTRIP_SOURCETABLE); line += llen; len -= llen; } else { gpsd_log(&device->context->errout, LOG_WARN, "Received unexpexted Ntrip reply %s.\n", buf); return -1; } } while (len > 0) { /* parse ENDSOURCETABLE */ if (str_starts_with(line, NTRIP_ENDSOURCETABLE)) goto done; /* coverity[string_null] - nul-terminated by previous memset */ if (!(eol = strstr(line, NTRIP_BR))) break; gpsd_log(&device->context->errout, LOG_DATA, "next Ntrip source table line %s\n", line); *eol = '\0'; llen = (ssize_t) (eol - line); /* todo: parse headers */ /* parse STR */ if (str_starts_with(line, NTRIP_STR)) { ntrip_str_parse(line + strlen(NTRIP_STR), (size_t) (llen - strlen(NTRIP_STR)), &hold, &device->context->errout); if (strcmp(device->ntrip.stream.mountpoint, hold.mountpoint) == 0) { /* todo: support for RTCM 3.0, SBAS (WAAS, EGNOS), ... */ if (hold.format == fmt_unknown) { gpsd_log(&device->context->errout, LOG_ERROR, "Ntrip stream %s format not supported\n", line); return -1; } /* todo: support encryption and compression algorithms */ if (hold.compr_encryp != cmp_enc_none) { gpsd_log(&device->context->errout, LOG_ERROR, "Ntrip stream %s compression/encryption algorithm not supported\n", line); return -1; } /* todo: support digest authentication */ if (hold.authentication != auth_none && hold.authentication != auth_basic) { gpsd_log(&device->context->errout, LOG_ERROR, "Ntrip stream %s authentication method not supported\n", line); return -1; } /* no memcpy, so we can keep the other infos */ device->ntrip.stream.format = hold.format; device->ntrip.stream.carrier = hold.carrier; device->ntrip.stream.latitude = hold.latitude; device->ntrip.stream.longitude = hold.longitude; device->ntrip.stream.nmea = hold.nmea; device->ntrip.stream.compr_encryp = hold.compr_encryp; device->ntrip.stream.authentication = hold.authentication; device->ntrip.stream.fee = hold.fee; device->ntrip.stream.bitrate = hold.bitrate; device->ntrip.stream.set = true; match = true; } /* todo: compare stream location to own location to * find nearest stream if user hasn't provided one */ } /* todo: parse CAS */ /* else if (str_starts_with(line, NTRIP_CAS)); */ /* todo: parse NET */ /* else if (str_starts_with(line, NTRIP_NET)); */ llen += strlen(NTRIP_BR); line += llen; len -= llen; gpsd_log(&device->context->errout, LOG_RAW, "Remaining Ntrip source table buffer %zd %s\n", len, line); } /* message too big to fit into buffer */ if ((size_t)len == blen - 1) return -1; if (len > 0) memmove(buf, &buf[rlen - len], (size_t) len); } done: return match ? 1 : -1; }
static int ntrip_sourcetable_parse(int fd, char *buf, ssize_t blen, const char *stream, struct ntrip_stream_t *keep) { struct ntrip_stream_t hold; ssize_t llen, len = 0; char *line; bool srctbl = false; bool match = false; for (;;) { char *eol; ssize_t rlen; memset(&buf[len], 0, (size_t) (blen - len)); if ((rlen = recv(fd, &buf[len], (size_t) (blen - 1 - len), 0)) == -1) { if (errno == EINTR) continue; return -1; } if (rlen == 0) continue; line = buf; rlen = len += rlen; gpsd_report(LOG_RAW, "Ntrip source table buffer %s\n", buf); if (!srctbl) { /* parse SOURCETABLE */ if (strncmp(line, NTRIP_SOURCETABLE, strlen(NTRIP_SOURCETABLE)) == 0) { srctbl = true; llen = (ssize_t) strlen(NTRIP_SOURCETABLE); line += llen; len -= llen; } else { gpsd_report(LOG_WARN, "Received unexpexted Ntrip reply %s.\n", buf); return -1; } } if (!srctbl) return -1; while (len > 0) { /* parse ENDSOURCETABLE */ if (strncmp (line, NTRIP_ENDSOURCETABLE, strlen(NTRIP_ENDSOURCETABLE)) == 0) goto done; if (!(eol = strstr(line, NTRIP_BR))) break; gpsd_report(LOG_IO, "next Ntrip source table line %s\n", line); *eol = '\0'; llen = (ssize_t) (eol - line); /* todo: parse headers */ /* parse STR */ if (strncmp(line, NTRIP_STR, strlen(NTRIP_STR)) == 0) { ntrip_str_parse(line + strlen(NTRIP_STR), (size_t) (llen - strlen(NTRIP_STR)), &hold); if (stream != NULL && strcmp(stream, hold.mountpoint) == 0) { /* todo: support for RTCM 3.0, SBAS (WAAS, EGNOS), ... */ if (hold.format == fmt_unknown) { gpsd_report(LOG_ERROR, "Ntrip stream %s format not supported\n", line); return -1; } /* todo: support encryption and compression algorithms */ if (hold.compr_encryp != cmp_enc_none) { gpsd_report(LOG_ERROR, "Ntrip stream %s compression/encryption algorithm not supported\n", line); return -1; } /* todo: support digest authentication */ if (hold.authentication != auth_none && hold.authentication != auth_basic) { gpsd_report(LOG_ERROR, "Ntrip stream %s authentication method not supported\n", line); return -1; } memcpy(keep, &hold, sizeof(hold)); match = true; } /* todo: compare stream location to own location to * find nearest stream if user hasn't provided one */ } /* todo: parse CAS */ /* else if (strncmp(line, NTRIP_CAS, strlen(NTRIP_CAS))==0); */ /* todo: parse NET */ /* else if (strncmp(line, NTRIP_NET, strlen(NTRIP_NET))==0); */ llen += strlen(NTRIP_BR); line += llen; len -= llen; gpsd_report(LOG_RAW, "Remaining Ntrip source table buffer %zd %s\n", len, line); } /* message too big to fit into buffer */ if (len == blen - 1) return -1; if (len > 0) memcpy(buf, &buf[rlen - len], (size_t) len); } done: return match ? 0 : -1; }