From dee33f53b65e03dd3d31da781863867e9d03bb7a Mon Sep 17 00:00:00 2001 From: Christian Huitema Date: Mon, 5 Dec 2016 11:38:59 -0800 Subject: [PATCH] Reminder of changes required by the Windows port. This solves the issues 228, 229, 230 and 232. --- src/compat/arc4random.c | 11 +++++ src/compat/gettimeofday.c | 73 +++++++++++++++++++++++++++++++ src/extension/default_eventloop.c | 16 +++---- src/stub.c | 41 +++++++++++++++-- 4 files changed, 129 insertions(+), 12 deletions(-) create mode 100644 src/compat/gettimeofday.c diff --git a/src/compat/arc4random.c b/src/compat/arc4random.c index 2c78818f..bd5f6e3a 100644 --- a/src/compat/arc4random.c +++ b/src/compat/arc4random.c @@ -38,6 +38,9 @@ #ifndef GETDNS_ON_WINDOWS #include #endif +#if defined(GETDNS_ON_WINDOWS) && !defined(MAP_INHERIT_ZERO) +#define explicit_bzero(rnd, rnd_size) memset(rnd, 0, rnd_size) +#endif #define KEYSTREAM_ONLY #include "chacha_private.h" @@ -136,7 +139,15 @@ _rs_stir_if_needed(size_t len) { #ifndef MAP_INHERIT_ZERO static pid_t _rs_pid = 0; +#ifdef GETDNS_ON_WINDOWS + /* + * TODO: if compiling for the Windows Runtime, use GetCurrentProcessId(), + * but this requires linking with kernel32.lib + */ + pid_t pid = _getpid(); +#else pid_t pid = getpid(); +#endif /* If a system lacks MAP_INHERIT_ZERO, resort to getpid() */ if (_rs_pid == 0 || _rs_pid != pid) { diff --git a/src/compat/gettimeofday.c b/src/compat/gettimeofday.c new file mode 100644 index 00000000..d8fe91bc --- /dev/null +++ b/src/compat/gettimeofday.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016 Christian Huitema + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + /* + * Numerous places in the code make reference to the Unix/Linux + * "gettimeofday()" function, which is not available in the standard + * windows libraries. This code provides a compatible implementation. + */ +#include "config.h" + +#ifdef GETDNS_ON_WINDOWS +int gettimeofday(struct timeval* tv, struct timezone* tz) +{ + FILETIME ft; + uint64_t now = 0; + + /* + * The GetSystemTimeAsFileTime API returns the number + * of 100-nanosecond intervals since January 1, 1601 (UTC), + * in FILETIME format. + */ + GetSystemTimeAsFileTime(&ft); + + /* + * Convert to plain 64 bit format, without making + * assumptions about the FILETIME structure alignment. + */ + now |= ft.dwHighDateTime; + now <<= 32; + now |= ft.dwLowDateTime; + /* + * Convert units from 100ns to 1us + */ + now /= 10; + /* + * Account for microseconds elapsed between 1601 and 1970. + */ + now -= 11644473600000000ULL; + + if (tv != NULL) + { + uint64_t sec = now / 1000000; + uint64_t usec = now % 1000000; + + tv->tv_sec = (long)sec; + tv->tv_usec = (long)usec; + } + + if (tz != NULL) + { + /* + * TODO: implement a timezone retrieval function. + * Not urgent, since the GetDNS code always set this parameter to NULL. + */ + return -1; + } + + return 0; +} +#endif /* GETDNS_ON_WINDOWS */ \ No newline at end of file diff --git a/src/extension/default_eventloop.c b/src/extension/default_eventloop.c index 10efff59..2f9856dd 100644 --- a/src/extension/default_eventloop.c +++ b/src/extension/default_eventloop.c @@ -25,6 +25,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "Config.h" + #include "extension/default_eventloop.h" #include "debug.h" @@ -32,7 +34,7 @@ static uint64_t get_now_plus(uint64_t amount) { struct timeval tv; uint64_t now; - + if (gettimeofday(&tv, NULL)) { perror("gettimeofday() failed"); exit(EXIT_FAILURE); @@ -81,8 +83,7 @@ default_eventloop_schedule(getdns_eventloop *loop, #endif default_loop->fd_events[fd] = event; default_loop->fd_timeout_times[fd] = get_now_plus(timeout); - event->ev = (void *) (intptr_t) fd + 1; - + event->ev = (void *)(intptr_t)(fd + 1); DEBUG_SCHED( "scheduled read/write at %d\n", fd); return GETDNS_RETURN_GOOD; } @@ -101,9 +102,8 @@ default_eventloop_schedule(getdns_eventloop *loop, for (i = 0; i < MAX_TIMEOUTS; i++) { if (default_loop->timeout_events[i] == NULL) { default_loop->timeout_events[i] = event; - default_loop->timeout_times[i] = get_now_plus(timeout); - event->ev = (void *) (intptr_t) i + 1; - + default_loop->timeout_times[i] = get_now_plus(timeout); + event->ev = (void *)(intptr_t)(i + 1); DEBUG_SCHED( "scheduled timeout at %d\n", (int)i); return GETDNS_RETURN_GOOD; } @@ -219,8 +219,8 @@ default_eventloop_run_once(getdns_eventloop *loop, int blocking) tv.tv_sec = 0; tv.tv_usec = 0; } else { - tv.tv_sec = (timeout - now) / 1000000; - tv.tv_usec = (timeout - now) % 1000000; + tv.tv_sec = (long)((timeout - now) / 1000000); + tv.tv_usec = (long)((timeout - now) % 1000000); } if (select(max_fd + 1, &readfds, &writefds, NULL, (timeout == ((uint64_t)-1) ? NULL : &tv)) < 0) { diff --git a/src/stub.c b/src/stub.c index 4aa14dae..8232e288 100644 --- a/src/stub.c +++ b/src/stub.c @@ -399,7 +399,11 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport) upstream->addr_len) == -1) { if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK) return fd; +#ifdef USE_WINSOCK + closesocket(fd); +#else close(fd); +#endif return -1; } return fd; @@ -541,7 +545,13 @@ void _getdns_cancel_stub_request(getdns_network_req *netreq) { stub_cleanup(netreq); - if (netreq->fd >= 0) close(netreq->fd); + if (netreq->fd >= 0) { +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else + close(netreq->fd); +#endif + } } /* May be needed in future for better UDP error handling?*/ @@ -564,7 +574,12 @@ stub_timeout_cb(void *userarg) STUB_DEBUG_CLEANUP, __FUNCTION__, netreq); stub_next_upstream(netreq); stub_cleanup(netreq); - if (netreq->fd >= 0) close(netreq->fd); + if (netreq->fd >= 0) +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else + close(netreq->fd); +#endif netreq->state = NET_REQ_TIMED_OUT; if (netreq->owner->user_callback) { netreq->debug_end_time = _getdns_get_time_as_uintt64(); @@ -807,8 +822,13 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq) /* Coming back from an earlier unfinished write or handshake. * Try to send remaining data */ +#ifdef USE_WINSOCK + written = send(fd, tcp->write_buf + tcp->written, + tcp->write_buf_len - tcp->written, 0); +#else written = write(fd, tcp->write_buf + tcp->written, tcp->write_buf_len - tcp->written); +#endif if (written == -1) { if (_getdns_EWOULDBLOCK) return STUB_TCP_WOULDBLOCK; @@ -1257,10 +1277,10 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp, static uint64_t _getdns_get_time_as_uintt64() { - + struct timeval tv; uint64_t now; - + if (gettimeofday(&tv, NULL)) { return 0; } @@ -1268,6 +1288,7 @@ _getdns_get_time_as_uintt64() { return now; } + /**************************/ /* UDP callback functions */ /**************************/ @@ -1305,7 +1326,11 @@ stub_udp_read_cb(void *userarg) upstream, netreq->response, read)) return; /* Client cookie didn't match? */ +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else close(netreq->fd); +#endif while (GLDNS_TC_WIRE(netreq->response)) { DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ, __FUNCTION__, netreq); @@ -1369,7 +1394,11 @@ stub_udp_write_cb(void *userarg) netreq->fd, (const void *)netreq->query, pkt_len, 0, (struct sockaddr *)&netreq->upstream->addr, netreq->upstream->addr_len)) { +#ifdef USE_WINSOCK + closesocket(netreq->fd); +#else close(netreq->fd); +#endif return; } GETDNS_SCHEDULE_EVENT( @@ -1706,7 +1735,11 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport, if (fd == -1) return -1; upstream->tls_obj = tls_create_object(dnsreq, fd, upstream); if (upstream->tls_obj == NULL) { +#ifdef USE_WINSOCK + closesocket(fd); +#else close(fd); +#endif return -1; }