static int ntrip_stream_probe(const char *caster, const char *port, const char *stream, struct ntrip_stream_t *keep) { int ret; socket_t dsock; char buf[BUFSIZ]; if ((dsock = netlib_connectsock(AF_UNSPEC, caster, port, "tcp")) == -1) { printf("ntrip stream connect error %d\n", dsock); return -1; } (void)snprintf(buf, sizeof(buf), "GET / HTTP/1.1\r\n" "User-Agent: NTRIP gpsd/%s\r\n" "Connection: close\r\n" "\r\n", VERSION); if (write(dsock, buf, strlen(buf)) != (ssize_t) strlen(buf)) { printf("ntrip stream write error %d\n", dsock); return -1; } ret = ntrip_sourcetable_parse(dsock, buf, (ssize_t) sizeof(buf), stream, keep); (void)close(dsock); return ret; }
int ntrip_open(struct gps_device_t *device, char *caster) /* open a connection to a Ntrip broadcaster */ { char *amp, *colon, *slash; char *auth = NULL; char *port = NULL; char *stream = NULL; char *url = NULL; int ret = -1; char t[strlen(caster) + 1]; char *tmp = t; switch (device->ntrip.conn_state) { case ntrip_conn_init: /* this has to be done here, because it is needed for multi-stage connection */ device->servicetype = service_ntrip; device->ntrip.works = false; device->ntrip.sourcetable_parse = false; device->ntrip.stream.set = false; (void)strlcpy(tmp, caster, sizeof(t)); if ((amp = strchr(tmp, '@')) != NULL) { if (((colon = strchr(tmp, ':')) != NULL) && colon < amp) { auth = tmp; *amp = '\0'; tmp = amp + 1; url = tmp; } else { gpsd_log(&device->context->errout, LOG_ERROR, "can't extract user-ID and password from %s\n", caster); device->ntrip.conn_state = ntrip_conn_err; return -1; } } if ((slash = strchr(tmp, '/')) != NULL) { *slash = '\0'; stream = slash + 1; } else { /* todo: add autoconnect like in dgpsip.c */ gpsd_log(&device->context->errout, LOG_ERROR, "can't extract Ntrip stream from %s\n", caster); device->ntrip.conn_state = ntrip_conn_err; return -1; } if ((colon = strchr(tmp, ':')) != NULL) { port = colon + 1; *colon = '\0'; } if (!port) { port = "rtcm-sc104"; if (!getservbyname(port, "tcp")) port = DEFAULT_RTCM_PORT; } (void)strlcpy(device->ntrip.stream.mountpoint, stream, sizeof(device->ntrip.stream.mountpoint)); if (auth != NULL) (void)strlcpy(device->ntrip.stream.credentials, auth, sizeof(device->ntrip.stream.credentials)); /* * Semantically url and port ought to be non-NULL by now, * but just in case...this code appeases Coverity. */ if (url != NULL) (void)strlcpy(device->ntrip.stream.url, url, sizeof(device->ntrip.stream.url)); if (port != NULL) (void)strlcpy(device->ntrip.stream.port, port, sizeof(device->ntrip.stream.port)); ret = ntrip_stream_req_probe(&device->ntrip.stream, &device->context->errout); if (ret == -1) { device->ntrip.conn_state = ntrip_conn_err; return -1; } device->gpsdata.gps_fd = ret; device->ntrip.conn_state = ntrip_conn_sent_probe; return ret; case ntrip_conn_sent_probe: ret = ntrip_sourcetable_parse(device); if (ret == -1) { device->ntrip.conn_state = ntrip_conn_err; return -1; } if (ret == 0 && device->ntrip.stream.set == false) { return ret; } (void)close(device->gpsdata.gps_fd); if (ntrip_auth_encode(&device->ntrip.stream, device->ntrip.stream.credentials, device->ntrip.stream.authStr, sizeof(device->ntrip.stream.authStr)) != 0) { device->ntrip.conn_state = ntrip_conn_err; return -1; } ret = ntrip_stream_get_req(&device->ntrip.stream, &device->context->errout); if (ret == -1) { device->ntrip.conn_state = ntrip_conn_err; return -1; } device->gpsdata.gps_fd = ret; device->ntrip.conn_state = ntrip_conn_sent_get; break; case ntrip_conn_sent_get: ret = ntrip_stream_get_parse(&device->ntrip.stream, device->gpsdata.gps_fd, &device->context->errout); if (ret == -1) { device->ntrip.conn_state = ntrip_conn_err; return -1; } device->ntrip.conn_state = ntrip_conn_established; device->ntrip.works = true; // we know, this worked. break; case ntrip_conn_established: case ntrip_conn_err: return -1; } return ret; }