summaryrefslogtreecommitdiff
path: root/libgps_sock.c
diff options
context:
space:
mode:
authorRobert Norris <rw_norris@hotmail.com>2017-02-14 21:30:25 +0000
committerFred Wright <fw@fwright.net>2017-02-17 14:46:05 -0800
commit92e30abaa3f7fb298d05ebe207c16f7096d0c15a (patch)
treed55dc7876efef57847e635afb80efd0274cfa3fb /libgps_sock.c
parentb8890ecae932892fd8e6fc45a3f003c937d3f82f (diff)
downloadgpsd-92e30abaa3f7fb298d05ebe207c16f7096d0c15a.tar.gz
Windows libgps support
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. Signed-off-by: Fred Wright <fw@fwright.net>
Diffstat (limited to 'libgps_sock.c')
-rw-r--r--libgps_sock.c62
1 files changed, 60 insertions, 2 deletions
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;