gpsd-dev
[Top][All Lists]
Advanced

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

[gpsd-dev] [PATCH 4/8] Windows support for network functions


From: Rob Norris
Subject: [gpsd-dev] [PATCH 4/8] Windows support for network functions
Date: Tue, 19 Apr 2016 21:01:41 +0100

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.

Ensure networking is initialized/shutdown on load/unload in a DLL.

TESTED:
Confirmed compiles under a cross compiler.

Otherwise no effect on current supported systems - 'scons build-all check' - 
passes.
---
 SConstruct    |  8 ++++++-
 libgps_sock.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 netlib.c      | 43 +++++++++++++++++++++++++++++++-----
 test_libgps.c | 19 ++++++++++++++--
 4 files changed, 130 insertions(+), 10 deletions(-)

diff --git a/SConstruct b/SConstruct
index 3ae7424..21e04b3 100644
--- a/SConstruct
+++ b/SConstruct
@@ -729,9 +729,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", "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/libgps_sock.c b/libgps_sock.c
index 9eda2cc..266df55 100644
--- a/libgps_sock.c
+++ b/libgps_sock.c
@@ -17,11 +17,18 @@
 #include <sys/time.h>   /* expected to have a select(2) prototype a la SuS */
 #include <sys/types.h>
 #include <sys/stat.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 */
@@ -44,6 +51,52 @@ struct privdata_t
 #endif /* LIBGPS_DEBUG */
 };
 
+#ifdef HAVE_WINSOCK2_H
+static bool init_dll(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 void shutdown_dll(void)
+/* Shutdown Windows Sockets. */
+{
+  int res = WSACleanup();
+  if (res != 0) {
+    libgps_debug_trace((DEBUG_CALLS, "WSACleanup returns error %d\n", res));
+  }
+}
+
+BOOL WINAPI DllMain(HINSTANCE lib_handle,
+                   DWORD reason,
+                   LPVOID reserved)
+/* Startup/Shutdown events on being loaded/unloaded in a Windows process */
+{
+    (void)lib_handle;
+    (void)reserved;
+    switch(reason) {
+    case DLL_PROCESS_ATTACH:
+      return (BOOL)init_dll();
+      break;
+    case DLL_PROCESS_DETACH:
+      shutdown_dll();
+      return TRUE;
+      break;
+    case DLL_THREAD_ATTACH:
+    case DLL_THREAD_DETACH:
+    default:
+      break;
+    }
+    return TRUE;
+}
+#endif /* HAVE_WINSOCK2_H */
+
 int gps_sock_open(const char *host, const char *port,
                  struct gps_data_t *gpsdata)
 {
@@ -119,7 +172,11 @@ int gps_sock_close(struct gps_data_t *gpsdata)
     int status;
 
     free(PRIVATE(gpsdata));
+#ifdef HAVE_WINSOCK2_H
+    status = closesocket(gpsdata->gps_fd);
+#else
     status = close(gpsdata->gps_fd);
+#endif /* HAVE_WINSOCK2_H */
     gpsdata->gps_fd = -1;
     return status;
 #else
@@ -160,7 +217,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 +234,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 +309,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
        return 0;
     else
        return -1;
diff --git a/netlib.c b/netlib.c
index 4505c37..6fd65b8 100644
--- a/netlib.c
+++ b/netlib.c
@@ -2,23 +2,41 @@
  * This file is Copyright (c) 2010 by the GPSD project
  * 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 "netlib.h"
 #include "sockaddr.h"
 
@@ -97,7 +115,11 @@ socket_t netlib_connectsock(int af, const char *host, const 
char *service,
        }
 
        if (!BAD_SOCKET(s)) {
-           (void)close(s);
+#ifdef HAVE_WINDOWS_H
+         (void)closesocket(s);
+#else
+         (void)close(s);
+#endif
        }
     }
     freeaddrinfo(result);
@@ -126,8 +148,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_WINDOWS_H)
+    u_long one1 = 1;
+    (void)ioctlsocket(s, FIONBIO, &one1);
+#endif
     return s;
 }
 
@@ -155,6 +181,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 +202,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 +233,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/test_libgps.c b/test_libgps.c
index 1102c35..189d974 100644
--- a/test_libgps.c
+++ b/test_libgps.c
@@ -20,6 +20,10 @@
 #include <getopt.h>
 #include <signal.h>
 
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+
 static void onsig(int sig)
 {
     (void)fprintf(stderr, "libgps: died with signal %d\n", sig);
@@ -45,7 +49,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) {
@@ -98,7 +104,16 @@ int main(int argc, char *argv[])
            }
        }
 #endif
-    } else if (gps_open(source.server, source.port, &collect) != 0) {
+    }
+    else {
+#ifdef HAVE_WINSOCK2_H
+       WSADATA wsadata;
+       int res = WSAStartup(MAKEWORD(2, 2), &wsadata);
+       if (res != 0) {
+               libgps_debug_trace((DEBUG_CALLS, "WSAStartup returns error 
%d\n", res));
+       }
+#endif
+    if (gps_open(source.server, source.port, &collect) != 0) {
        (void)fprintf(stderr,
                      "test_libgps: no gpsd running or network error: %d, %s\n",
                      errno, gps_errstr(errno));
@@ -132,7 +147,7 @@ int main(int argc, char *argv[])
        }
        (void)gps_close(&collect);
     }
-
+    }
     return 0;
 }
 
-- 
2.8.0.rc3




reply via email to

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