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_next = NULL;
//g
FIXED_INFO *info;
ULONG buflen = sizeof(*info);
IP_ADDR_STRING *ptr;
IP_ADDR_STRING *ptr = 0;
info = (FIXED_INFO *)malloc(sizeof(FIXED_INFO));
if (info == NULL)
@ -821,7 +820,7 @@ set_os_defaults_windows(struct getdns_context *context)
if (GetNetworkParams(info, &buflen) == NO_ERROR) {
int retval = 0;
ptr = &(info->DnsServerList);
ptr = info->DnsServerList.Next;
*domain = 0;
while (ptr) {
for (size_t i = 0; i < GETDNS_UPSTREAM_TRANSPORTS; i++) {
@ -843,7 +842,6 @@ set_os_defaults_windows(struct getdns_context *context)
free(info);
}
(void)getdns_list_get_length(context->suffix, &length);
if (length == 0 && *domain != 0) {
bindata.data = (uint8_t *)domain;
@ -994,7 +992,7 @@ getdns_context_create_with_extended_memory_functions(
result->fchg_resolvconf = 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
if (set_from_os && (r = set_os_defaults(result)))
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 */
context->tls_ctx = SSL_CTX_new(TLSv1_2_client_method());
if (context->tls_ctx == NULL)
printf("ERROR! Bad TLS context!");
//g return GETDNS_RETURN_BAD_CONTEXT;
#ifndef USE_WINSOCK
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
Unless we later fallback to opportunistic. */
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;
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;
}
#else
if (tls_only_is_in_transports_list(context) == 1)
if (tls_only_is_in_transports_list(context) == 1) {
return GETDNS_RETURN_BAD_CONTEXT;
}
/* A null tls_ctx will make TLS fail and fallback to the other
transports will kick-in.*/
#endif

View File

@ -50,6 +50,7 @@
#define EINPROGRESS 112
#define EWOULDBLOCK 140
typedef u_short sa_family_t;
#include "util/winsock_event.h"
#endif
#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
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;
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);
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)
return STUB_TCP_AGAIN;
else
return STUB_TCP_ERROR;
#endif
} else if (read == 0) {
/* Remote end closed the socket */
/* 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. */
errno == EINPROGRESS)) ||
written < pkt_len + 2) {
#else
#ifdef USE_WINSOCK
written = sendto(fd, netreq->query - 2, pkt_len + 2,
0, (struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len);
#else
written = write(fd, netreq->query - 2, pkt_len + 2);
#endif
if ((written == -1 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) ||
written < pkt_len + 2) {
#else
#ifdef USE_WINSOCK
written = sendto(fd, netreq->query - 2, pkt_len + 2,
0, (struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len);
#else
written = write(fd, netreq->query - 2, pkt_len + 2);
#endif
if ((written == -1 && (errno == EAGAIN ||
errno == EWOULDBLOCK)) ||
written < pkt_len + 2) {
#endif
/* We couldn't write the whole packet.
* We have to return with STUB_TCP_AGAIN.
@ -1359,7 +1374,7 @@ stub_tcp_read_cb(void *userarg)
int q;
switch ((q = stub_tcp_read(netreq->fd, &netreq->tcp,
&dnsreq->context->mf))) {
&dnsreq->context->mf, &netreq->event))) {
case STUB_TCP_AGAIN:
return;
@ -1437,7 +1452,7 @@ upstream_read_cb(void *userarg)
&upstream->upstreams->mf);
else
q = stub_tcp_read(upstream->fd, &upstream->tcp,
&upstream->upstreams->mf);
&upstream->upstreams->mf, &netreq->event);
switch (q) {
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.
* It uses the winsock WSAWaitForMultipleEvents interface on a number of
* sockets.
* Code is originally from the Unbound source for Windows.
*
* Note that windows can only wait for max 64 events at one time.
*
@ -133,92 +134,92 @@
*/
struct _getdns_event_base
{
/** sorted by timeout (absolute), ptr */
_getdns_rbtree_t* times;
/** array (first part in use) of handles to work on */
struct _getdns_event** items;
/** number of items in use in array */
int max;
/** capacity of array, size of array in items */
int cap;
/** array of 0 - maxsig of ptr to event for it */
struct _getdns_event** signals;
/** if we need to exit */
int need_to_exit;
/** where to store time in seconds */
time_t* time_secs;
/** where to store time in microseconds */
struct timeval* time_tv;
/**
* TCP streams have sticky events to them, these are not
* reported by the windows event system anymore, we have to
* keep reporting those events as present until wouldblock() is
* signalled by the handler back to use.
*/
int tcp_stickies;
/**
* should next cycle process reinvigorated stickies,
* these are stickies that have been stored, but due to a new
* event_add a sudden interest in the event has incepted.
*/
int tcp_reinvigorated;
/** The list of events that is currently being processed. */
WSAEVENT waitfor[WSK_MAX_ITEMS];
/** sorted by timeout (absolute), ptr */
_getdns_rbtree_t* times;
/** array (first part in use) of handles to work on */
struct _getdns_event** items;
/** number of items in use in array */
int max;
/** capacity of array, size of array in items */
int cap;
/** array of 0 - maxsig of ptr to event for it */
struct _getdns_event** signals;
/** if we need to exit */
int need_to_exit;
/** where to store time in seconds */
time_t* time_secs;
/** where to store time in microseconds */
struct timeval* time_tv;
/**
* TCP streams have sticky events to them, these are not
* reported by the windows event system anymore, we have to
* keep reporting those events as present until wouldblock() is
* signalled by the handler back to use.
*/
int tcp_stickies;
/**
* should next cycle process reinvigorated stickies,
* these are stickies that have been stored, but due to a new
* event_add a sudden interest in the event has incepted.
*/
int tcp_reinvigorated;
/** The list of events that is currently being processed. */
WSAEVENT waitfor[WSK_MAX_ITEMS];
/* fdset for read write, for fds ready, and added */
fd_set
/** fds for reading */
reads,
/** fds for writing */
writes,
/** fds determined ready for use */
ready,
/** ready plus newly added events. */
content;
/* fdset for read write, for fds ready, and added */
fd_set
/** fds for reading */
reads,
/** fds for writing */
writes,
/** fds determined ready for use */
ready,
/** ready plus newly added events. */
content;
};
/**
* Event structure. Has some of the event elements.
*/
struct _getdns_event {
/** node in timeout rbtree */
_getdns_rbnode_t node;
/** is event already added */
int added;
/** node in timeout rbtree */
_getdns_rbnode_t node;
/** is event already added */
int added;
/** event base it belongs to */
struct _getdns_event_base *ev_base;
/** fd to poll or -1 for timeouts. signal number for sigs. */
int ev_fd;
/** what events this event is interested in, see EV_.. above. */
short ev_events;
/** timeout value */
struct timeval ev_timeout;
/** event base it belongs to */
struct _getdns_event_base *ev_base;
/** fd to poll or -1 for timeouts. signal number for sigs. */
int ev_fd;
/** what events this event is interested in, see EV_.. above. */
short ev_events;
/** timeout value */
struct timeval ev_timeout;
/** callback to call: fd, eventbits, userarg */
void (*ev_callback)(int, short, void *);
/** callback user arg */
void *ev_arg;
/** callback to call: fd, eventbits, userarg */
void (*ev_callback)(int, short, void *);
/** callback user arg */
void *ev_arg;
/* ----- nonpublic part, for winsock_event only ----- */
/** index of this event in the items array (if added) */
int idx;
/** the event handle to wait for new events to become ready */
WSAEVENT hEvent;
/** true if this filedes is a TCP socket and needs special attention */
int is_tcp;
/** remembered EV_ values */
short old_events;
/** should remembered EV_ values be used for TCP streams.
* Reset after WOULDBLOCK is signaled using the function. */
int stick_events;
/* ----- nonpublic part, for winsock_event only ----- */
/** index of this event in the items array (if added) */
int idx;
/** the event handle to wait for new events to become ready */
WSAEVENT hEvent;
/** true if this filedes is a TCP socket and needs special attention */
int is_tcp;
/** remembered EV_ values */
short old_events;
/** should remembered EV_ values be used for TCP streams.
* Reset after WOULDBLOCK is signaled using the function. */
int stick_events;
/** true if this event is a signaling WSAEvent by the user.
* User created and user closed WSAEvent. Only signaled/unsigneled,
* no read/write/distinctions needed. */
int is_signal;
/** used during callbacks to see which events were just checked */
int just_checked;
/** true if this event is a signaling WSAEvent by the user.
* User created and user closed WSAEvent. Only signaled/unsigneled,
* no read/write/distinctions needed. */
int is_signal;
/** used during callbacks to see which events were just checked */
int just_checked;
};
char* wsa_strerror(DWORD err);
@ -267,7 +268,7 @@ int getdns_mini_ev_cmp(const void* a, const void* b);
* retesting the event.
* 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
@ -275,14 +276,14 @@ static void winsock_tcp_wouldblock(struct _getdns_event* ev, int eventbit);
* The callback has to WSAResetEvent to disable the signal.
* @param base: the event base.
* @param ev: the event structure for data storage
* can be passed uninitialised.
* can be passed uninitialised.
* @param wsaevent: the WSAEvent that gets signaled.
* @param cb: callback routine.
* @param arg: user argument to callback routine.
* @return false on error.
*/
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.