gpsd-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gpsd-dev] [PATCH 2/2] Windows libgps support


From: Robert Norris
Subject: [gpsd-dev] [PATCH 2/2] Windows libgps support
Date: Tue, 14 Feb 2017 21:30:25 +0000

Add Windows versions for network functions and disable unused features.

Add detection of various headers and functions that aren't available in
Windows. Note that netlib_localsocket() has no functional implementation
on Windows, but it isn't to be used on that platform and it's not part of
libgps anyway.

Using send() rather than write() seems to work on Windows.

For Windows need to ensure networking is initialised on opening of sockets
(and then correspondingly shutdown upon closing).

Note that within gpsd.h the termios structures and serial related functions
are removed from the Windows build. These are only accessed in serial.c by
gpsd, so since the Windows build is only generating libgps there is
currently no need to modify serial.c.

And for os_compat.h, daemon() is simply disabled under Windows as it's not
used within libgps.

TESTED:
Confirmed compiles under a cross compiler.
Manual build and run of test_libgps on Windows which successfully connects
to a host running GPSD
Manual build DLL version and link with a Windows version of a program
(Viking) that then successfully connects and monitors positions from GPSD

Otherwise no effect on current supported systems.
'scons build-all check' - passes.
---
 SConstruct    |  8 +++++++-
 gpsd.h        | 13 ++++++++++++-
 libgps_sock.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 netlib.c      | 40 +++++++++++++++++++++++++++++++++-----
 os_compat.c   |  5 +++--
 test_libgps.c |  3 ++-
 6 files changed, 119 insertions(+), 12 deletions(-)

diff --git a/SConstruct b/SConstruct
index 1de0fa75..c780bcbb 100644
--- a/SConstruct
+++ b/SConstruct
@@ -750,9 +750,15 @@ else:
             announce("You do not have the endian.h header file. RTCM V2 
support disabled.")
             env["rtcm104v2"] = False
 
+    for hdr in ("sys/un", "sys/socket", "sys/select", "netdb", "netinet/in", 
"netinet/ip", "arpa/inet", "termios", "winsock2"):
+        if config.CheckHeader(hdr + ".h"):
+            confdefs.append("#define HAVE_%s_H 1\n" % 
hdr.replace("/","_").upper())
+        else:
+            confdefs.append("/* #undef HAVE_%s_H */\n" % 
hdr.replace("/","_").upper())
+
     # check function after libraries, because some function require libraries
     # for example clock_gettime() require librt on Linux glibc < 2.17
-    for f in ("daemon", "strlcpy", "strlcat", "clock_gettime", "strptime", 
"gmtime_r" ):
+    for f in ("daemon", "strlcpy", "strlcat", "clock_gettime", "strptime", 
"gmtime_r", "inet_ntop", "fcntl"):
         if config.CheckFunc(f):
             confdefs.append("#define HAVE_%s 1\n" % f.upper())
         else:
diff --git a/gpsd.h b/gpsd.h
index b3dc3c97..50aa759a 100644
--- a/gpsd.h
+++ b/gpsd.h
@@ -17,11 +17,16 @@ extern "C" {
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
+#include "gpsd_config.h"
+#ifdef HAVE_TERMIOS_H
 #include <termios.h>
+#endif
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h> /* for fd_set */
+#endif
 #include <time.h>    /* for time_t */
 
 #include "gps.h"
-#include "gpsd_config.h"
 #include "os_compat.h"
 
 /*
@@ -361,11 +366,13 @@ struct gps_type_t {
     void (*init_query)(struct gps_device_t *session);
     void (*event_hook)(struct gps_device_t *session, event_t event);
 #ifdef RECONFIGURE_ENABLE
+#ifdef HAVE_TERMIOS_H
     bool (*speed_switcher)(struct gps_device_t *session,
                                     speed_t speed, char parity, int stopbits);
     void (*mode_switcher)(struct gps_device_t *session, int mode);
     bool (*rate_switcher)(struct gps_device_t *session, double rate);
     double min_cycle;
+#endif /* HAVE_TERMIOS_H */
 #endif /* RECONFIGURE_ENABLE */
 #ifdef CONTROLSEND_ENABLE
     ssize_t (*control_send)(struct gps_device_t *session, char *buf, size_t 
buflen);
@@ -472,7 +479,9 @@ struct gps_device_t {
     sourcetype_t sourcetype;
     servicetype_t servicetype;
     int mode;
+#ifdef HAVE_TERMIOS_H
     struct termios ttyset, ttyset_old;
+#endif
 #ifndef FIXED_PORT_SPEED
     unsigned int baudindex;
 #endif /* FIXED_PORT_SPEED */
@@ -822,9 +831,11 @@ extern ssize_t gpsd_serial_write(struct gps_device_t *,
                                 const char *, const size_t);
 extern bool gpsd_next_hunt_setting(struct gps_device_t *);
 extern int gpsd_switch_driver(struct gps_device_t *, char *);
+#ifdef HAVE_TERMIOS_H
 extern void gpsd_set_speed(struct gps_device_t *, speed_t, char, unsigned int);
 extern speed_t gpsd_get_speed(const struct gps_device_t *);
 extern speed_t gpsd_get_speed_old(const struct gps_device_t *);
+#endif /* HAVE_TERMIOS_H */
 extern int gpsd_get_stopbits(const struct gps_device_t *);
 extern char gpsd_get_parity(const struct gps_device_t *);
 extern void gpsd_assert_sync(struct gps_device_t *);
diff --git a/libgps_sock.c b/libgps_sock.c
index ea04b8cd..31f73f5c 100644
--- a/libgps_sock.c
+++ b/libgps_sock.c
@@ -16,11 +16,19 @@
 #include <sys/time.h>   /* expected to have a select(2) prototype a la SuS */
 #include <sys/types.h>
 #include <sys/stat.h>
+#include "gpsd_config.h"
+#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
+#endif /* HAVE_SYS_SELECT_H */
 #include <unistd.h>
 
 #ifndef USE_QT
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif /* HAVE_WINSOCK2_H */
 #else
 #include <QTcpSocket>
 #endif /* USE_QT */
@@ -43,6 +51,33 @@ struct privdata_t
 #endif /* LIBGPS_DEBUG */
 };
 
+#ifdef HAVE_WINSOCK2_H
+static bool need_init = TRUE;
+static bool need_finish = TRUE;
+
+static bool windows_init(void)
+/* Ensure socket networking is initialized for Windows. */
+{
+    WSADATA wsadata;
+    /* request access to Windows Sockets API version 2.2 */
+    int res = WSAStartup(MAKEWORD(2, 2), &wsadata);
+    if (res != 0) {
+      libgps_debug_trace((DEBUG_CALLS, "WSAStartup returns error %d\n", res));
+    }
+    return (res == 0);
+}
+
+static bool windows_finish(void)
+/* Shutdown Windows Sockets. */
+{
+  int res = WSACleanup();
+  if (res != 0) {
+    libgps_debug_trace((DEBUG_CALLS, "WSACleanup returns error %d\n", res));
+  }
+  return (res == 0);
+}
+#endif /* HAVE_WINSOCK2_H */
+
 int gps_sock_open(const char *host, const char *port,
                  struct gps_data_t *gpsdata)
 {
@@ -54,6 +89,11 @@ int gps_sock_open(const char *host, const char *port,
     libgps_debug_trace((DEBUG_CALLS, "gps_sock_open(%s, %s)\n", host, port));
 
 #ifndef USE_QT
+#ifdef HAVE_WINSOCK2_H
+       if (need_init) {
+         need_init != windows_init();
+       }
+#endif
        if ((gpsdata->gps_fd =
            netlib_connectsock(AF_UNSPEC, host, port, "tcp")) < 0) {
            errno = gpsdata->gps_fd;
@@ -62,7 +102,7 @@ int gps_sock_open(const char *host, const char *port,
         }
        else
            libgps_debug_trace((DEBUG_CALLS, "netlib_connectsock() returns 
socket on fd %d\n", gpsdata->gps_fd));
-#else
+#else /* HAVE_WINSOCK2_H */
        QTcpSocket *sock = new QTcpSocket();
        gpsdata->gps_fd = sock;
        sock->connectToHost(host, QString(port).toInt());
@@ -119,7 +159,14 @@ int gps_sock_close(struct gps_data_t *gpsdata)
     gpsdata->privdata = NULL;
 #ifndef USE_QT
     int status;
+#ifdef HAVE_WINSOCK2_H
+    status = closesocket(gpsdata->gps_fd);
+    if (need_finish) {
+      need_finish != windows_finish();
+    }
+#else
     status = close(gpsdata->gps_fd);
+#endif /* HAVE_WINSOCK2_H */
     gpsdata->gps_fd = -1;
     return status;
 #else
@@ -160,7 +207,9 @@ int gps_sock_read(struct gps_data_t *gpsdata)
                                                     
sizeof(PRIVATE(gpsdata)->buffer) -
                                                     PRIVATE(gpsdata)->waiting);
 #endif
-
+#ifdef HAVE_WINSOCK2_H
+       int wserr = WSAGetLastError();
+#endif /* HAVE_WINSOCK2_H */
        /* if we just received data from the socket, it's in the buffer */
        if (status > -1)
            PRIVATE(gpsdata)->waiting += status;
@@ -175,9 +224,14 @@ int gps_sock_read(struct gps_data_t *gpsdata)
                return -1;
 #ifndef USE_QT
            /* count transient errors as success, we'll retry later */
+#ifdef HAVE_WINSOCK2_H
+           else if (wserr == WSAEINTR || wserr == WSAEWOULDBLOCK)
+               return 0;
+#else
            else if (errno == EINTR || errno == EAGAIN
                     || errno == EWOULDBLOCK)
                return 0;
+#endif /* HAVE_WINSOCK2_H */
 #endif
            /* hard error return of -1, pass it along */
            else
@@ -245,7 +299,11 @@ int gps_sock_send(struct gps_data_t *gpsdata, const char 
*buf)
 /* send a command to the gpsd instance */
 {
 #ifndef USE_QT
+#ifdef HAVE_WINSOCK2_H
+    if (send(gpsdata->gps_fd, buf, strlen(buf), 0) == (ssize_t) strlen(buf))
+#else
     if (write(gpsdata->gps_fd, buf, strlen(buf)) == (ssize_t) strlen(buf))
+#endif /* HAVE_WINSOCK2_H */
        return 0;
     else
        return -1;
diff --git a/netlib.c b/netlib.c
index c8969382..2939454d 100644
--- a/netlib.c
+++ b/netlib.c
@@ -3,21 +3,38 @@
  * BSD terms apply: see the file COPYING in the distribution root for details.
  */
 
+#include "gpsd_config.h"
 #include <string.h>
 #include <fcntl.h>
+#ifdef HAVE_NETDB_H
 #include <netdb.h>
+#endif /* HAVE_NETDB_H */
 #ifndef AF_UNSPEC
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif /* HAVE_SYS_SOCKET_H */
 #endif /* AF_UNSPEC */
+#ifdef HAVE_SYS_UN_H
 #include <sys/un.h>
+#endif /* HAVE_SYS_UN_H */
 #ifndef INADDR_ANY
+#ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
+#endif /* HAVE_NETINET_IN_H */
 #endif /* INADDR_ANY */
+#ifdef HAVE_ARPA_INET_H
 #include <arpa/inet.h>     /* for htons() and friends */
+#endif /* HAVE_ARPA_INET_H */
 #include <unistd.h>
+#ifdef HAVE_NETINET_IN_H
 #include <netinet/ip.h>
+#endif /* HAVE_NETINET_IN_H */
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#endif
 
 #include "gpsd.h"
 #include "sockaddr.h"
@@ -97,7 +114,11 @@ socket_t netlib_connectsock(int af, const char *host, const 
char *service,
        }
 
        if (!BAD_SOCKET(s)) {
-           (void)close(s);
+#ifdef HAVE_WINSOCK2_H
+         (void)closesocket(s);
+#else
+         (void)close(s);
+#endif
        }
     }
     freeaddrinfo(result);
@@ -126,8 +147,12 @@ socket_t netlib_connectsock(int af, const char *host, 
const char *service,
 #endif
 
     /* set socket to noblocking */
+#ifdef HAVE_FCNTL
     (void)fcntl(s, F_SETFL, fcntl(s, F_GETFL) | O_NONBLOCK);
-
+#elif defined(HAVE_WINSOCK2_H)
+    u_long one1 = 1;
+    (void)ioctlsocket(s, FIONBIO, &one1);
+#endif
     return s;
 }
 
@@ -155,6 +180,7 @@ const char *netlib_errstr(const int err)
 socket_t netlib_localsocket(const char *sockfile, int socktype)
 /* acquire a connection to an existing Unix-domain socket */
 {
+#ifdef HAVE_SYS_UN_H
     int sock;
 
     if ((sock = socket(AF_UNIX, socktype, 0)) < 0) {
@@ -175,16 +201,19 @@ socket_t netlib_localsocket(const char *sockfile, int 
socktype)
 
        return sock;
     }
+#else
+    return -1;
+#endif /* HAVE_SYS_UN_H */
 }
 
 char *netlib_sock2ip(socket_t fd)
 /* retrieve the IP address corresponding to a socket */
 {
+    static char ip[INET6_ADDRSTRLEN];
+    int r = 1;
+#ifdef HAVE_INET_NTOP
     sockaddr_t fsin;
     socklen_t alen = (socklen_t) sizeof(fsin);
-    static char ip[INET6_ADDRSTRLEN];
-    int r;
-
     r = getpeername(fd, &(fsin.sa), &alen);
     if (r == 0) {
        switch (fsin.sa.sa_family) {
@@ -203,6 +232,7 @@ char *netlib_sock2ip(socket_t fd)
            return ip;
        }
     }
+#endif /* HAVE_INET_NTOP */
     if (r != 0) {
        (void)strlcpy(ip, "<unknown>", sizeof(ip));
     }
diff --git a/os_compat.c b/os_compat.c
index b110f4ba..dafbb7a4 100644
--- a/os_compat.c
+++ b/os_compat.c
@@ -45,7 +45,8 @@ int clock_gettime(clockid_t clk_id, struct timespec *ts)
 /* End of clock_gettime section */
 
 #ifndef HAVE_DAEMON
-
+#ifndef HAVE_WINSOCK2_H
+/* No daemon() provided for Windows as not currently needed */
 /* Simulate Linux/BSD daemon() on platforms that don't have it */
 
 #include <stdlib.h>
@@ -90,7 +91,7 @@ int os_daemon(int nochdir, int noclose)
     /* coverity[leaked_handle] Intentional handle duplication */
     return 0;
 }
-
+#endif /* HAVE_WINSOCK2_H */
 #else /* HAVE_DAEMON */
 
 #ifdef __linux__
diff --git a/test_libgps.c b/test_libgps.c
index 91dd65b3..933beba0 100644
--- a/test_libgps.c
+++ b/test_libgps.c
@@ -43,7 +43,9 @@ int main(int argc, char *argv[])
 #endif
 
     (void)signal(SIGSEGV, onsig);
+#ifdef SIGBUS
     (void)signal(SIGBUS, onsig);
+#endif
 
     while ((option = getopt(argc, argv, "bf:hsD:?")) != -1) {
        switch (option) {
@@ -144,7 +146,6 @@ int main(int argc, char *argv[])
        }
        (void)gps_close(&collect);
     }
-
     return 0;
 }
 
-- 
2.11.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]