Bug fix in get_os_defaults, clean up code in winsock_event, add code to handle event handling differences in Winsock2

This commit is contained in:
unknown 2015-12-04 16:12:43 -05:00
parent 2d58ed465c
commit 22a8550caa
4 changed files with 704 additions and 686 deletions

View File

@ -803,10 +803,9 @@ set_os_defaults_windows(struct getdns_context *context)
hints.ai_addr = NULL; hints.ai_addr = NULL;
hints.ai_next = NULL; hints.ai_next = NULL;
//g
FIXED_INFO *info; FIXED_INFO *info;
ULONG buflen = sizeof(*info); ULONG buflen = sizeof(*info);
IP_ADDR_STRING *ptr; IP_ADDR_STRING *ptr = 0;
info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO)); info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO));
if (info == NULL) if (info == NULL)
@ -821,7 +820,7 @@ set_os_defaults_windows(struct getdns_context *context)
if (GetNetworkParams(info, &buflen) == NO_ERROR) { if (GetNetworkParams(info, &buflen) == NO_ERROR) {
int retval = 0; int retval = 0;
ptr = &(info->DnsServerList); ptr = info->DnsServerList.Next;
*domain = 0; *domain = 0;
while (ptr) { while (ptr) {
for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) { for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) {
@ -843,7 +842,6 @@ set_os_defaults_windows(struct getdns_context *context)
free(info); free(info);
} }
(void)getdns_list_get_length(context->suffix, &length); (void)getdns_list_get_length(context->suffix, &length);
if (length == 0 && *domain != 0) { if (length == 0 && *domain != 0) {
bindata.data = (uint8_t *)domain; bindata.data = (uint8_t *)domain;
@ -994,7 +992,7 @@ getdns_context_create_with_extended_memory_functions(
result->fchg_resolvconf = NULL; result->fchg_resolvconf = NULL;
result->fchg_hosts = NULL; result->fchg_hosts = NULL;
//g resolv.conf does not exist on Windows, handle differently // resolv.conf does not exist on Windows, handle differently
#ifndef USE_WINSOCK #ifndef USE_WINSOCK
if (set_from_os && (r = set_os_defaults(result))) if (set_from_os && (r = set_os_defaults(result)))
goto error; goto error;
@ -2358,18 +2356,24 @@ _getdns_context_prepare_for_resolution(struct getdns_context *context,
/* Create client context, use TLS v1.2 only for now */ /* Create client context, use TLS v1.2 only for now */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method()); context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
if (context->tls_ctx == NULL) if (context->tls_ctx == NULL)
printf("ERROR! Bad TLS context!"); #ifndef USE_WINSOCK
//g return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
#else
printf("Warning! Bad TLS context, check openssl version on Windows!\n");;
#endif
/* Be strict and only use the cipher suites recommended in RFC7525 /* Be strict and only use the cipher suites recommended in RFC7525
Unless we later fallback to opportunistic. */ Unless we later fallback to opportunistic. */
const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM"; const char* const PREFERRED_CIPHERS = "EECDH+aRSA+AESGCM:EECDH+aECDSA+AESGCM:EDH+aRSA+AESGCM";
if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS)) if (!SSL_CTX_set_cipher_list(context->tls_ctx, PREFERRED_CIPHERS)) {
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) }
if (!SSL_CTX_set_default_verify_paths(context->tls_ctx)) {
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
#else #else
if (tls_only_is_in_transports_list(context) == 1) if (tls_only_is_in_transports_list(context) == 1) {
return GETDNS_RETURN_BAD_CONTEXT; return GETDNS_RETURN_BAD_CONTEXT;
}
/* A null tls_ctx will make TLS fail and fallback to the other /* A null tls_ctx will make TLS fail and fallback to the other
transports will kick-in.*/ transports will kick-in.*/
#endif #endif

View File

@ -50,6 +50,7 @@
#define EINPROGRESS 112 #define EINPROGRESS 112
#define EWOULDBLOCK 140 #define EWOULDBLOCK 140
typedef u_short sa_family_t; typedef u_short sa_family_t;
#include "util/winsock_event.h"
#endif #endif
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */ #define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
@ -623,7 +624,7 @@ stub_tls_timeout_cb(void *userarg)
/****************************/ /****************************/
static int static int
stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf) stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf, getdns_eventloop_event* event)
{ {
ssize_t read; ssize_t read;
uint8_t *buf; uint8_t *buf;
@ -640,10 +641,24 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
} }
read = recv(fd, tcp->read_pos, tcp->to_read, 0); read = recv(fd, tcp->read_pos, tcp->to_read, 0);
if (read == -1) { if (read == -1) {
#ifdef USE_WINSOCK
printf("read (in tcp ) %s\n",
wsa_strerror(WSAGetLastError()));
if (WSAGetLastError() == WSAECONNRESET)
return STUB_TCP_AGAIN;
if (WSAGetLastError() == WSAEINPROGRESS)
return STUB_TCP_AGAIN;
if (WSAGetLastError() == WSAEWOULDBLOCK) {
winsock_tcp_wouldblock(event, EV_READ);
return STUB_TCP_AGAIN;
}
#else
if (errno == EAGAIN || errno == EWOULDBLOCK) if (errno == EAGAIN || errno == EWOULDBLOCK)
return STUB_TCP_AGAIN; return STUB_TCP_AGAIN;
else else
return STUB_TCP_ERROR; return STUB_TCP_ERROR;
#endif
} else if (read == 0) { } else if (read == 0) {
/* Remote end closed the socket */ /* Remote end closed the socket */
/* TODO: Try to reconnect */ /* TODO: Try to reconnect */
@ -747,19 +762,19 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
upstream). We must let the handshake complete since non-blocking. */ upstream). We must let the handshake complete since non-blocking. */
errno == EINPROGRESS)) || errno == EINPROGRESS)) ||
written < pkt_len + 2) { written < pkt_len + 2) {
#else #else
#ifdef USE_WINSOCK #ifdef USE_WINSOCK
written = sendto(fd, netreq->query - 2, pkt_len + 2, written = sendto(fd, netreq->query - 2, pkt_len + 2,
0, (struct sockaddr *)&(netreq->upstream->addr), 0, (struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len); netreq->upstream->addr_len);
#else #else
written = write(fd, netreq->query - 2, pkt_len + 2); written = write(fd, netreq->query - 2, pkt_len + 2);
#endif #endif
if ((written == -1 && (errno == EAGAIN || if ((written == -1 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) || errno == EWOULDBLOCK)) ||
written < pkt_len + 2) { written < pkt_len + 2) {
#endif #endif
/* We couldn't write the whole packet. /* We couldn't write the whole packet.
* We have to return with STUB_TCP_AGAIN. * We have to return with STUB_TCP_AGAIN.
@ -1359,7 +1374,7 @@ stub_tcp_read_cb(void *userarg)
int q; int q;
switch ((q = stub_tcp_read(netreq->fd, &netreq->tcp, switch ((q = stub_tcp_read(netreq->fd, &netreq->tcp,
&dnsreq->context->mf))) { &dnsreq->context->mf, &netreq->event))) {
case STUB_TCP_AGAIN: case STUB_TCP_AGAIN:
return; return;
@ -1437,7 +1452,7 @@ upstream_read_cb(void *userarg)
&upstream->upstreams->mf); &upstream->upstreams->mf);
else else
q = stub_tcp_read(upstream->fd, &upstream->tcp, q = stub_tcp_read(upstream->fd, &upstream->tcp,
&upstream->upstreams->mf); &upstream->upstreams->mf, &netreq->event);
switch (q) { switch (q) {
case STUB_TCP_AGAIN: case STUB_TCP_AGAIN:

File diff suppressed because it is too large Load Diff

View File

@ -40,6 +40,7 @@
* This file contains interface functions with the WinSock2 API on Windows. * This file contains interface functions with the WinSock2 API on Windows.
* It uses the winsock WSAWaitForMultipleEvents interface on a number of * It uses the winsock WSAWaitForMultipleEvents interface on a number of
* sockets. * sockets.
* Code is originally from the Unbound source for Windows.
* *
* Note that windows can only wait for max 64 events at one time. * Note that windows can only wait for max 64 events at one time.
* *
@ -133,92 +134,92 @@
*/ */
struct _getdns_event_base struct _getdns_event_base
{ {
/** sorted by timeout (absolute), ptr */ /** sorted by timeout (absolute), ptr */
_getdns_rbtree_t* times; _getdns_rbtree_t* times;
/** array (first part in use) of handles to work on */ /** array (first part in use) of handles to work on */
struct _getdns_event** items; struct _getdns_event** items;
/** number of items in use in array */ /** number of items in use in array */
int max; int max;
/** capacity of array, size of array in items */ /** capacity of array, size of array in items */
int cap; int cap;
/** array of 0 - maxsig of ptr to event for it */ /** array of 0 - maxsig of ptr to event for it */
struct _getdns_event** signals; struct _getdns_event** signals;
/** if we need to exit */ /** if we need to exit */
int need_to_exit; int need_to_exit;
/** where to store time in seconds */ /** where to store time in seconds */
time_t* time_secs; time_t* time_secs;
/** where to store time in microseconds */ /** where to store time in microseconds */
struct timeval* time_tv; struct timeval* time_tv;
/** /**
* TCP streams have sticky events to them, these are not * TCP streams have sticky events to them, these are not
* reported by the windows event system anymore, we have to * reported by the windows event system anymore, we have to
* keep reporting those events as present until wouldblock() is * keep reporting those events as present until wouldblock() is
* signalled by the handler back to use. * signalled by the handler back to use.
*/ */
int tcp_stickies; int tcp_stickies;
/** /**
* should next cycle process reinvigorated stickies, * should next cycle process reinvigorated stickies,
* these are stickies that have been stored, but due to a new * these are stickies that have been stored, but due to a new
* event_add a sudden interest in the event has incepted. * event_add a sudden interest in the event has incepted.
*/ */
int tcp_reinvigorated; int tcp_reinvigorated;
/** The list of events that is currently being processed. */ /** The list of events that is currently being processed. */
WSAEVENT waitfor[WSK_MAX_ITEMS]; WSAEVENT waitfor[WSK_MAX_ITEMS];
/* fdset for read write, for fds ready, and added */ /* fdset for read write, for fds ready, and added */
fd_set fd_set
/** fds for reading */ /** fds for reading */
reads, reads,
/** fds for writing */ /** fds for writing */
writes, writes,
/** fds determined ready for use */ /** fds determined ready for use */
ready, ready,
/** ready plus newly added events. */ /** ready plus newly added events. */
content; content;
}; };
/** /**
* Event structure. Has some of the event elements. * Event structure. Has some of the event elements.
*/ */
struct _getdns_event { struct _getdns_event {
/** node in timeout rbtree */ /** node in timeout rbtree */
_getdns_rbnode_t node; _getdns_rbnode_t node;
/** is event already added */ /** is event already added */
int added; int added;
/** event base it belongs to */ /** event base it belongs to */
struct _getdns_event_base *ev_base; struct _getdns_event_base *ev_base;
/** fd to poll or -1 for timeouts. signal number for sigs. */ /** fd to poll or -1 for timeouts. signal number for sigs. */
int ev_fd; int ev_fd;
/** what events this event is interested in, see EV_.. above. */ /** what events this event is interested in, see EV_.. above. */
short ev_events; short ev_events;
/** timeout value */ /** timeout value */
struct timeval ev_timeout; struct timeval ev_timeout;
/** callback to call: fd, eventbits, userarg */ /** callback to call: fd, eventbits, userarg */
void (*ev_callback)(int, short, void *); void (*ev_callback)(int, short, void *);
/** callback user arg */ /** callback user arg */
void *ev_arg; void *ev_arg;
/* ----- nonpublic part, for winsock_event only ----- */ /* ----- nonpublic part, for winsock_event only ----- */
/** index of this event in the items array (if added) */ /** index of this event in the items array (if added) */
int idx; int idx;
/** the event handle to wait for new events to become ready */ /** the event handle to wait for new events to become ready */
WSAEVENT hEvent; WSAEVENT hEvent;
/** true if this filedes is a TCP socket and needs special attention */ /** true if this filedes is a TCP socket and needs special attention */
int is_tcp; int is_tcp;
/** remembered EV_ values */ /** remembered EV_ values */
short old_events; short old_events;
/** should remembered EV_ values be used for TCP streams. /** should remembered EV_ values be used for TCP streams.
* Reset after WOULDBLOCK is signaled using the function. */ * Reset after WOULDBLOCK is signaled using the function. */
int stick_events; int stick_events;
/** true if this event is a signaling WSAEvent by the user. /** true if this event is a signaling WSAEvent by the user.
* User created and user closed WSAEvent. Only signaled/unsigneled, * User created and user closed WSAEvent. Only signaled/unsigneled,
* no read/write/distinctions needed. */ * no read/write/distinctions needed. */
int is_signal; int is_signal;
/** used during callbacks to see which events were just checked */ /** used during callbacks to see which events were just checked */
int just_checked; int just_checked;
}; };
char* wsa_strerror(DWORD err); char* wsa_strerror(DWORD err);
@ -267,7 +268,7 @@ int getdns_mini_ev_cmp(const void* a, const void* b);
* retesting the event. * retesting the event.
* Pass if EV_READ or EV_WRITE gave wouldblock. * Pass if EV_READ or EV_WRITE gave wouldblock.
*/ */
static void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit); void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
/** /**
* Routine for windows only. where you pass a signal WSAEvent that * Routine for windows only. where you pass a signal WSAEvent that
@ -275,14 +276,14 @@ static void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
* The callback has to WSAResetEvent to disable the signal. * The callback has to WSAResetEvent to disable the signal.
* @param base: the event base. * @param base: the event base.
* @param ev: the event structure for data storage * @param ev: the event structure for data storage
* can be passed uninitialised. * can be passed uninitialised.
* @param wsaevent: the WSAEvent that gets signaled. * @param wsaevent: the WSAEvent that gets signaled.
* @param cb: callback routine. * @param cb: callback routine.
* @param arg: user argument to callback routine. * @param arg: user argument to callback routine.
* @return false on error. * @return false on error.
*/ */
static int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev, static int winsock_register_wsaevent(struct _getdns_event_base* base, struct _getdns_event* ev,
WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg); WSAEVENT wsaevent, void (*cb)(int, short, void*), void* arg);
/** /**
* Unregister a wsaevent. User has to close the WSAEVENT itself. * Unregister a wsaevent. User has to close the WSAEVENT itself.