diff options
-rw-r--r-- | gpsd.h-tail | 3 | ||||
-rw-r--r-- | libgpsd_core.c | 23 | ||||
-rw-r--r-- | netlib.c | 21 | ||||
-rw-r--r-- | serial.c | 3 |
4 files changed, 44 insertions, 6 deletions
diff --git a/gpsd.h-tail b/gpsd.h-tail index a7501306..34ea7a0a 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -272,7 +272,8 @@ typedef enum {source_unknown, source_rs232, source_usb, source_pty, - source_socket} + source_tcp, + source_udp} sourcetype_t; struct gps_device_t { diff --git a/libgpsd_core.c b/libgpsd_core.c index 11c4c79e..95a4370c 100644 --- a/libgpsd_core.c +++ b/libgpsd_core.c @@ -317,7 +317,7 @@ int gpsd_activate(struct gps_device_t *session) if (netgnss_uri_check(session->gpsdata.dev.path)) { session->gpsdata.gps_fd = netgnss_uri_open(session->context, session->gpsdata.dev.path); - session->sourcetype = source_socket; + session->sourcetype = source_tcp; gpsd_report(LOG_SPIN, "netgnss_uri_open(%s) returns socket on fd %d\n", session->gpsdata.dev.path, session->gpsdata.gps_fd); @@ -341,6 +341,27 @@ int gpsd_activate(struct gps_device_t *session) return -1; } session->gpsdata.gps_fd = dsock; + session->sourcetype = source_tcp; + } else if (strncmp(session->gpsdata.dev.path, "udp://", 6) == 0) { + char server[GPS_PATH_MAX], *port; + socket_t dsock; + (void)strlcpy(server, session->gpsdata.dev.path + 6, sizeof(server)); + session->gpsdata.gps_fd = -1; + port = strchr(server, ':'); + if (port == NULL) { + gpsd_report(LOG_ERROR, "Missing colon in UDP feed spec.\n"); + return -1; + } + *port++ = '\0'; + gpsd_report(LOG_INF, "opening UDP feed at %s, port %s.\n", server, + port); + if ((dsock = netlib_connectsock(AF_UNSPEC, server, port, "udp")) < 0) { + gpsd_report(LOG_ERROR, "UDP device open error %s.\n", + netlib_errstr(dsock)); + return -1; + } + session->gpsdata.gps_fd = dsock; + session->sourcetype = source_udp; } /* otherwise, ordinary serial device */ else @@ -51,6 +51,7 @@ socket_t netlib_connectsock(int af, const char *host, const char *service, struct addrinfo *result, *rp; int ret, type, proto, one = 1; socket_t s = -1; + bool bind_me; /*@-type@*/ ppe = getprotobyname(protocol); @@ -63,9 +64,14 @@ socket_t netlib_connectsock(int af, const char *host, const char *service, } /*@+type@*/ + /* we probably ought to pass this in as an explicit flag argument */ + bind_me = (type == SOCK_DGRAM); + memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = af; hints.ai_socktype = type; + if (bind_me) + hints.ai_flags = AI_PASSIVE; hints.ai_protocol = proto; #ifndef S_SPLINT_S if ((ret = getaddrinfo(host, service, &hints, &result))) { @@ -92,9 +98,18 @@ socket_t netlib_connectsock(int af, const char *host, const char *service, (s, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) == -1) ret = NL_NOSOCKOPT; - else if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) { - ret = 0; - break; + else { + if (bind_me) { + if (bind(s, rp->ai_addr, rp->ai_addrlen) == 0) { + ret = 0; + break; + } + } else { + if (connect(s, rp->ai_addr, rp->ai_addrlen) == 0) { + ret = 0; + break; + } + } } if (s > 0) { @@ -37,8 +37,9 @@ static sourcetype_t gpsd_classify(const char *path) return source_unknown; else if (S_ISREG(sb.st_mode)) return source_blockdev; + /* this assumes we won't get UDP from a filesystem socket */ else if (S_ISSOCK(sb.st_mode)) - return source_socket; + return source_tcp; else if (S_ISCHR(sb.st_mode)) { sourcetype_t devtype = source_unknown; #ifdef __linux__ |