Merge pull request #353 from getdnsapi/devel/errno_handling

Handle more harmless I/O error cases +
This commit is contained in:
wtoorop 2017-11-03 20:00:40 +01:00 committed by GitHub
commit 168d83ac19
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 275 additions and 74 deletions

View File

@ -1199,10 +1199,10 @@ static void tas_read_cb(void *userarg)
return;
}
}
} else if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
} else if (_getdns_socketerror_wants_retry())
return;
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, strerror(errno));
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, _getdns_errnostr());
GETDNS_CLEAR_EVENT(a->loop, &a->event);
tas_next(context, a);
}
@ -1249,10 +1249,10 @@ static void tas_write_cb(void *userarg)
tas_read_cb, NULL, tas_timeout_cb));
return;
} else if (_getdns_socketerror() == _getdns_EWOULDBLOCK || _getdns_socketerror() == _getdns_EINPROGRESS)
} else if (_getdns_socketerror_wants_retry())
return;
DEBUG_ANCHOR("Write error: %s\n", strerror(errno));
DEBUG_ANCHOR("Write error: %s\n", _getdns_errnostr());
GETDNS_CLEAR_EVENT(a->loop, &a->event);
tas_next(context, a);
}
@ -1316,7 +1316,8 @@ static void tas_connect(getdns_context *context, tas_connection *a)
if ((a->fd = socket(( a->req->request_type == GETDNS_RRTYPE_A
? AF_INET : AF_INET6), SOCK_STREAM, IPPROTO_TCP)) == -1) {
DEBUG_ANCHOR("Error creating socket: %s\n", strerror(errno));
DEBUG_ANCHOR("Error creating socket: %s\n",
_getdns_errnostr());
tas_next(context, a);
return;
}
@ -1426,7 +1427,7 @@ static void tas_connect(getdns_context *context, tas_connection *a)
DEBUG_ANCHOR("Scheduled write with event\n");
return;
} else
DEBUG_ANCHOR("Connect error: %s\n", strerror(errno));
DEBUG_ANCHOR("Connect error: %s\n", _getdns_errnostr());
error:
tas_next(context, a);

View File

@ -408,8 +408,12 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking)
} else
#endif
if (_getdns_poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
_getdns_perror("poll() failed");
exit(EXIT_FAILURE);
if (_getdns_socketerror() == _getdns_EAGAIN ||
_getdns_socketerror() == _getdns_EINTR )
return;
DEBUG_SCHED("I/O error with poll(): %s\n", _getdns_errnostr());
return;
}
now = get_now_plus(0);

View File

@ -245,8 +245,11 @@ select_eventloop_run_once(getdns_eventloop *loop, int blocking)
#endif
if (select(max_fd + 1, &readfds, &writefds, NULL,
(timeout == TIMEOUT_FOREVER ? NULL : &tv)) < 0) {
_getdns_perror("select() failed");
exit(EXIT_FAILURE);
if (_getdns_socketerror_wants_retry())
return;
DEBUG_SCHED("I/O error with select(): %s\n", _getdns_errnostr());
return;
}
#ifdef USE_WINSOCK
}

View File

@ -59,6 +59,113 @@ void _getdns_perror(const char *str)
fputs(msg, stderr);
}
const char *_getdns_strerror(DWORD errnum)
{
static char unknown[32];
switch(errnum) {
case WSA_INVALID_HANDLE: return "Specified event object handle is invalid.";
case WSA_NOT_ENOUGH_MEMORY: return "Insufficient memory available.";
case WSA_INVALID_PARAMETER: return "One or more parameters are invalid.";
case WSA_OPERATION_ABORTED: return "Overlapped operation aborted.";
case WSA_IO_INCOMPLETE: return "Overlapped I/O event object not in signaled state.";
case WSA_IO_PENDING: return "Overlapped operations will complete later.";
case WSAEINTR: return "Interrupted function call.";
case WSAEBADF: return "File handle is not valid.";
case WSAEACCES: return "Permission denied.";
case WSAEFAULT: return "Bad address.";
case WSAEINVAL: return "Invalid argument.";
case WSAEMFILE: return "Too many open files.";
case WSAEWOULDBLOCK: return "Resource temporarily unavailable.";
case WSAEINPROGRESS: return "Operation now in progress.";
case WSAEALREADY: return "Operation already in progress.";
case WSAENOTSOCK: return "Socket operation on nonsocket.";
case WSAEDESTADDRREQ: return "Destination address required.";
case WSAEMSGSIZE: return "Message too long.";
case WSAEPROTOTYPE: return "Protocol wrong type for socket.";
case WSAENOPROTOOPT: return "Bad protocol option.";
case WSAEPROTONOSUPPORT: return "Protocol not supported.";
case WSAESOCKTNOSUPPORT: return "Socket type not supported.";
case WSAEOPNOTSUPP: return "Operation not supported.";
case WSAEPFNOSUPPORT: return "Protocol family not supported.";
case WSAEAFNOSUPPORT: return "Address family not supported by protocol family.";
case WSAEADDRINUSE: return "Address already in use.";
case WSAEADDRNOTAVAIL: return "Cannot assign requested address.";
case WSAENETDOWN: return "Network is down.";
case WSAENETUNREACH: return "Network is unreachable.";
case WSAENETRESET: return "Network dropped connection on reset.";
case WSAECONNABORTED: return "Software caused connection abort.";
case WSAECONNRESET: return "Connection reset by peer.";
case WSAENOBUFS: return "No buffer space available.";
case WSAEISCONN: return "Socket is already connected.";
case WSAENOTCONN: return "Socket is not connected.";
case WSAESHUTDOWN: return "Cannot send after socket shutdown.";
case WSAETOOMANYREFS: return "Too many references.";
case WSAETIMEDOUT: return "Connection timed out.";
case WSAECONNREFUSED: return "Connection refused.";
case WSAELOOP: return "Cannot translate name.";
case WSAENAMETOOLONG: return "Name too long.";
case WSAEHOSTDOWN: return "Host is down.";
case WSAEHOSTUNREACH: return "No route to host.";
case WSAENOTEMPTY: return "Directory not empty.";
case WSAEPROCLIM: return "Too many processes.";
case WSAEUSERS: return "User quota exceeded.";
case WSAEDQUOT: return "Disk quota exceeded.";
case WSAESTALE: return "Stale file handle reference.";
case WSAEREMOTE: return "Item is remote.";
case WSASYSNOTREADY: return "Network subsystem is unavailable.";
case WSAVERNOTSUPPORTED: return "Winsock.dll version out of range.";
case WSANOTINITIALISED: return "Successful WSAStartup not yet performed.";
case WSAEDISCON: return "Graceful shutdown in progress.";
case WSAENOMORE: return "No more results.";
case WSAECANCELLED: return "Call has been canceled.";
case WSAEINVALIDPROCTABLE: return "Procedure call table is invalid.";
case WSAEINVALIDPROVIDER: return "Service provider is invalid.";
case WSAEPROVIDERFAILEDINIT: return "Service provider failed to initialize.";
case WSASYSCALLFAILURE: return "System call failure.";
case WSASERVICE_NOT_FOUND: return "Service not found.";
case WSATYPE_NOT_FOUND: return "Class type not found.";
case WSA_E_NO_MORE: return "No more results.";
case WSA_E_CANCELLED: return "Call was canceled.";
case WSAEREFUSED: return "Database query was refused.";
case WSAHOST_NOT_FOUND: return "Host not found.";
case WSATRY_AGAIN: return "Nonauthoritative host not found.";
case WSANO_RECOVERY: return "This is a nonrecoverable error.";
case WSANO_DATA: return "Valid name, no data record of requested type.";
case WSA_QOS_RECEIVERS: return "QOS receivers.";
case WSA_QOS_SENDERS: return "QOS senders.";
case WSA_QOS_NO_SENDERS: return "No QOS senders.";
case WSA_QOS_NO_RECEIVERS: return "QOS no receivers.";
case WSA_QOS_REQUEST_CONFIRMED: return "QOS request confirmed.";
case WSA_QOS_ADMISSION_FAILURE: return "QOS admission error.";
case WSA_QOS_POLICY_FAILURE: return "QOS policy failure.";
case WSA_QOS_BAD_STYLE: return "QOS bad style.";
case WSA_QOS_BAD_OBJECT: return "QOS bad object.";
case WSA_QOS_TRAFFIC_CTRL_ERROR: return "QOS traffic control error.";
case WSA_QOS_GENERIC_ERROR: return "QOS generic error.";
case WSA_QOS_ESERVICETYPE: return "QOS service type error.";
case WSA_QOS_EFLOWSPEC: return "QOS flowspec error.";
case WSA_QOS_EPROVSPECBUF: return "Invalid QOS provider buffer.";
case WSA_QOS_EFILTERSTYLE: return "Invalid QOS filter style.";
case WSA_QOS_EFILTERTYPE: return "Invalid QOS filter type.";
case WSA_QOS_EFILTERCOUNT: return "Incorrect QOS filter count.";
case WSA_QOS_EOBJLENGTH: return "Invalid QOS object length.";
case WSA_QOS_EFLOWCOUNT: return "Incorrect QOS flow count.";
/*case WSA_QOS_EUNKOWNPSOBJ: return "Unrecognized QOS object.";*/
case WSA_QOS_EPOLICYOBJ: return "Invalid QOS policy object.";
case WSA_QOS_EFLOWDESC: return "Invalid QOS flow descriptor.";
case WSA_QOS_EPSFLOWSPEC: return "Invalid QOS provider-specific flowspec.";
case WSA_QOS_EPSFILTERSPEC: return "Invalid QOS provider-specific filterspec.";
case WSA_QOS_ESDMODEOBJ: return "Invalid QOS shape discard mode object.";
case WSA_QOS_ESHAPERATEOBJ: return "Invalid QOS shaping rate object.";
case WSA_QOS_RESERVED_PETYPE: return "Reserved policy QOS element type.";
default:
snprintf(unknown, sizeof(unknown),
"unknown WSA error code %d", (int)errnum);
return unknown;
}
}
#else
void _getdns_perror(const char *str)
@ -66,4 +173,8 @@ void _getdns_perror(const char *str)
perror(str);
}
const char *_getdns_strerror(int errnum)
{
return strerror(errnum);
}
#endif

View File

@ -39,16 +39,27 @@
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EINTR (WSAEINTR)
#define _getdns_EAGAIN (WSATRY_AGAIN)
#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAEINPROGRESS)
#define _getdns_ENOBUFS (WSAENOBUFS)
#define _getdns_EPROTO (0)
#define _getdns_EMFILE (WSAEMFILE)
#ifdef WSAENFILE
# define _getdns_ENFILE (WSAENFILE)
#else
# define _getdns_ENFILE (0)
#endif
#define _getdns_ECONNRESET (WSAECONNRESET)
#define _getdns_ECONNABORTED (0)
#define _getdns_EISCONN (WSAEISCONN)
#define _getdns_closesocket(fd) closesocket(fd)
#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer)
#define _getdns_socketerror() (WSAGetLastError())
const char *_getdns_strerror(DWORD errnum);
#else /* USE_WINSOCK */
#ifdef HAVE_SYS_POLL_H
@ -57,11 +68,53 @@ typedef u_short sa_family_t;
# include <poll.h>
#endif
#define _getdns_EINTR (EINTR)
#define _getdns_EAGAIN (EAGAIN)
#ifdef EWOULDBLOCK
#define _getdns_EWOULDBLOCK (EWOULDBLOCK)
#define _getdns_EINPROGRESS (EINPROGRESS)
#define _getdns_EMFILE (EMFILE)
#define _getdns_ECONNRESET (ECONNRESET)
#else
#define _getdns_EWOULDBLOCK (0)
#endif
#ifdef EINPROGRESS
# define _getdns_EINPROGRESS (EINPROGRESS)
#else
# define _getdns_EINPROGRESS (0)
#endif
#ifdef ENOBUFS
# define _getdns_ENOBUFS (ENOBUFS)
#else
# define _getdns_ENOBUFS (0)
#endif
#ifdef EPROTO
# define _getdns_EPROTO (EPROTO)
#else
# define _getdns_EPROTO (0)
#endif
#ifdef EMFILE
# define _getdns_EMFILE (EMFILE)
#else
# define _getdns_EMFILE (0)
#endif
#ifdef ENFILE
# define _getdns_ENFILE (ENFILE)
#else
# define _getdns_ENFILE (0)
#endif
#ifdef ECONNRESET
# define _getdns_ECONNRESET (ECONNRESET)
#else
# define _getdns_ECONNRESET (0)
#endif
#ifdef ECONNABORTED
# define _getdns_ECONNABORTED (ECONNABORTED)
#else
# define _getdns_ECONNABORTED (0)
#endif
#ifdef EISCONN
# define _getdns_EISCONN (EISCONN)
#else
# define _getdns_EISCONN (0)
#endif
#define SOCKADDR struct sockaddr
#define SOCKADDR_IN struct sockaddr_in
@ -77,8 +130,22 @@ typedef u_short sa_family_t;
#define _getdns_closesocket(fd) close(fd)
#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer)
#define _getdns_socketerror() (errno)
const char *_getdns_strerror(int errnum);
#endif
void _getdns_perror(const char *str);
#define _getdns_errnostr() (_getdns_strerror(_getdns_socketerror()))
#define _getdns_error_wants_retry(X) ( (X) != 0 \
&& ( (X) == _getdns_EINTR \
|| (X) == _getdns_EAGAIN \
|| (X) == _getdns_EWOULDBLOCK \
|| (X) == _getdns_EINPROGRESS \
|| (X) == _getdns_ENOBUFS ))
#define _getdns_socketerror_wants_retry() (_getdns_error_wants_retry(_getdns_socketerror()))
#define _getdns_resource_depletion() ( _getdns_socketerror() != 0 \
&& ( _getdns_socketerror() == _getdns_ENFILE \
|| _getdns_socketerror() == _getdns_EMFILE ))
#endif

View File

@ -191,6 +191,12 @@ static void tcp_write_cb(void *userarg)
(const void *)&to_write->write_buf[to_write->written],
to_write->write_buf_len - to_write->written, 0)) == -1) {
if (_getdns_socketerror_wants_retry())
return;
DEBUG_SERVER("I/O error from send(): %s\n",
_getdns_errnostr());
/* IO error, close connection */
conn->event.read_cb = conn->event.write_cb =
conn->event.timeout_cb = NULL;
@ -281,10 +287,11 @@ getdns_reply(
if (conn->l->fd >= 0 && sendto(conn->l->fd, (void *)buf, len, 0,
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event);
_getdns_closesocket(conn->l->fd);
conn->l->fd = -1;
/* TODO: handle _getdns_socketerror_wants_retry() */
/* IO error, never cleanup a listener because of I/O error */
DEBUG_SERVER("I/O error from sendto(): %s\n",
_getdns_errnostr());
}
/* Unlink this connection */
(void) _getdns_rbtree_delete(
@ -364,10 +371,13 @@ static void tcp_read_cb(void *userarg)
if ((bytes_read = recv(conn->fd,
(void *)conn->read_pos, conn->to_read, 0)) < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK)
if (_getdns_socketerror_wants_retry())
return; /* Come back to do the read later */
/* IO error, close connection */
DEBUG_SERVER("I/O error from recv(): %s\n",
_getdns_errnostr());
tcp_connection_destroy(conn);
return;
}
@ -475,10 +485,19 @@ static void tcp_accept_cb(void *userarg)
conn->super.addrlen = sizeof(conn->super.remote_in);
if ((conn->fd = accept(l->fd, (struct sockaddr *)
&conn->super.remote_in, &conn->super.addrlen)) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event);
_getdns_closesocket(l->fd);
l->fd = -1;
if (_getdns_socketerror_wants_retry() ||
_getdns_socketerror() == _getdns_ECONNRESET)
; /* pass */
else if (_getdns_resource_depletion())
; /* TODO: Stop listening for a little while? */
else
DEBUG_SERVER("I/O error during accept: %s\n",
_getdns_errnostr());
/* Never cleanup a listener because of I/O errors! */
GETDNS_FREE(*mf, conn);
return;
}
@ -545,18 +564,17 @@ static void udp_read_cb(void *userarg)
conn->addrlen = sizeof(conn->remote_in);
if ((len = recvfrom(l->fd, (void *)buf, sizeof(buf), 0,
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
if (_getdns_socketerror() == _getdns_ECONNRESET) {
if ( _getdns_socketerror_wants_retry() &&
_getdns_socketerror() != _getdns_ECONNRESET) {
/*
* WINSOCK gives ECONNRESET on ICMP Port Unreachable
* being received. Ignore it.
* */
GETDNS_FREE(*mf, conn);
return;
*/
DEBUG_SERVER("I/O error from recvfrom: %s\n",
_getdns_errnostr());
}
/* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event);
_getdns_closesocket(l->fd);
l->fd = -1;
/* Never cleanup a listener because of an I/O error! */
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
} else {

View File

@ -57,16 +57,17 @@
#include "pubkey-pinning.h"
/* WSA TODO:
* STUB_TCP_WOULDBLOCK added to deal with edge triggered event loops (versus
* STUB_TCP_RETRY added to deal with edge triggered event loops (versus
* level triggered). See also lines containing WSA TODO below...
*/
#define STUB_TRY_AGAIN_LATER -24 /* EMFILE, i.e. Out of OS resources */
#define STUB_NO_AUTH -8 /* Existing TLS connection is not authenticated */
#define STUB_CONN_GONE -7 /* Connection has failed, clear queue*/
#define STUB_TCP_WOULDBLOCK -6
#define STUB_TCP_RETRY -6
#define STUB_OUT_OF_OPTIONS -5 /* upstream options exceeded MAXIMUM_UPSTREAM_OPTION_SPACE */
#define STUB_SETUP_ERROR -4
#define STUB_TCP_AGAIN -3
#define STUB_TCP_MORE_TO_READ -3
#define STUB_TCP_MORE_TO_WRITE -3
#define STUB_TCP_ERROR -2
/* Don't currently have access to the context whilst doing handshake */
@ -407,9 +408,9 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
NULL, 0, NULL, NULL) == 0) {
return fd;
}
if (errno == EINPROGRESS) {
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
return fd;
}
#else
(void)transport;
#endif
@ -429,10 +430,8 @@ tcp_connected(getdns_upstream *upstream) {
int error = 0;
socklen_t len = (socklen_t)sizeof(error);
getsockopt(upstream->fd, SOL_SOCKET, SO_ERROR, (void*)&error, &len);
if (error == _getdns_EINPROGRESS)
return STUB_TCP_AGAIN;
else if (error == _getdns_EWOULDBLOCK || error == _getdns_EAGAIN)
return STUB_TCP_WOULDBLOCK;
if (_getdns_error_wants_retry(error))
return STUB_TCP_RETRY;
else if (error != 0) {
return STUB_SETUP_ERROR;
}
@ -639,8 +638,8 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
}
read = recv(fd, (void *)tcp->read_pos, tcp->to_read, 0);
if (read < 0) {
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
if (_getdns_socketerror_wants_retry())
return STUB_TCP_RETRY;
else
return STUB_TCP_ERROR;
} else if (read == 0) {
@ -654,7 +653,7 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
tcp->read_pos += read;
if (tcp->to_read > 0)
return STUB_TCP_AGAIN;
return STUB_TCP_MORE_TO_READ;
read = tcp->read_pos - tcp->read_buf;
if (read == 2) {
@ -679,14 +678,14 @@ stub_tcp_read(int fd, getdns_tcp_state *tcp, struct mem_funcs *mf)
}
/* Ready to start reading the packet */
tcp->read_pos = tcp->read_buf;
return STUB_TCP_AGAIN;
return STUB_TCP_MORE_TO_READ;
}
return GLDNS_ID_WIRE(tcp->read_buf);
}
/* stub_tcp_write(fd, tcp, netreq)
* will return STUB_TCP_AGAIN when we need to come back again,
* STUB_TCP_ERROR on error and a query_id on successful sent.
* will return STUB_TCP_RETRY or STUB_TCP_MORE_TO_WRITE when we need to come
* back again, STUB_TCP_ERROR on error and a query_id on successful sent.
*/
static int
stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
@ -749,7 +748,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
netreq->upstream->addr_len);
/* If pipelining we will find that the connection is already up so
just fall back to a 'normal' write. */
if (written == -1 && errno == EISCONN)
if (written == -1 && _getdns_socketerror() == _getdns_EISCONN)
written = write(fd, netreq->query - 2, pkt_len + 2);
#else
written = sendto(fd, (const char *)(netreq->query - 2),
@ -757,27 +756,24 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
(struct sockaddr *)&(netreq->upstream->addr),
netreq->upstream->addr_len);
#endif
if ((written < 0 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
/* Add the error case where the connection is in progress which is when
a cookie is not available (e.g. when doing the first request to an
upstream). We must let the handshake complete since non-blocking. */
_getdns_socketerror() == _getdns_EINPROGRESS)) ||
(size_t)written < pkt_len + 2) {
if ((written == -1 && _getdns_socketerror_wants_retry()) ||
(size_t)written < pkt_len + 2) {
/* We couldn't write the whole packet.
* We have to return with STUB_TCP_AGAIN.
* Setup tcp to track the state.
*/
tcp->write_buf = netreq->query - 2;
tcp->write_buf_len = pkt_len + 2;
tcp->written = written >= 0 ? written : 0;
return STUB_TCP_WOULDBLOCK;
return written == -1
? STUB_TCP_RETRY
: STUB_TCP_MORE_TO_WRITE;
} else if (written == -1) {
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
, strerror(errno));
, _getdns_errnostr());
return STUB_TCP_ERROR;
}
@ -792,12 +788,12 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
written = send(fd, (void *)(tcp->write_buf + tcp->written),
tcp->write_buf_len - tcp->written, 0);
if (written == -1) {
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
if (_getdns_socketerror_wants_retry())
return STUB_TCP_RETRY;
else {
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
" %s\n", STUB_DEBUG_WRITE, __FUNC__, (void*)netreq
, strerror(errno));
, _getdns_errnostr());
return STUB_TCP_ERROR;
}
@ -805,7 +801,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
tcp->written += written;
if (tcp->written < tcp->write_buf_len)
/* Still more to send */
return STUB_TCP_AGAIN;
return STUB_TCP_MORE_TO_WRITE;
query_id = (int)GLDNS_ID_WIRE(tcp->write_buf + 2);
/* Done. Start reading */
@ -1029,7 +1025,7 @@ tls_do_handshake(getdns_upstream *upstream)
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, TIMEOUT_TLS, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_READ;
return STUB_TCP_AGAIN;
return STUB_TCP_RETRY;
case SSL_ERROR_WANT_WRITE:
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
upstream->event.read_cb = NULL;
@ -1037,7 +1033,7 @@ tls_do_handshake(getdns_upstream *upstream)
GETDNS_SCHEDULE_EVENT(upstream->loop,
upstream->fd, TIMEOUT_TLS, &upstream->event);
upstream->tls_hs_state = GETDNS_HS_WRITE;
return STUB_TCP_AGAIN;
return STUB_TCP_RETRY;
default:
DEBUG_STUB("%s %-35s: FD: %d Handshake failed %d\n",
STUB_DEBUG_SETUP_TLS, __FUNC__, upstream->fd,
@ -1121,7 +1117,7 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
renegotiation. Need to keep handshake state to do that.*/
int want = SSL_get_error(tls_obj, read);
if (want == SSL_ERROR_WANT_READ) {
return STUB_TCP_AGAIN; /* read more later */
return STUB_TCP_RETRY; /* Come back later */
} else
return STUB_TCP_ERROR;
}
@ -1129,7 +1125,7 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
tcp->read_pos += read;
if ((int)tcp->to_read > 0)
return STUB_TCP_AGAIN;
return STUB_TCP_MORE_TO_READ;
read = tcp->read_pos - tcp->read_buf;
if (read == 2) {
@ -1161,14 +1157,14 @@ stub_tls_read(getdns_upstream *upstream, getdns_tcp_state *tcp,
renegotiation. Need to keep handshake state to do that.*/
int want = SSL_get_error(tls_obj, read);
if (want == SSL_ERROR_WANT_READ) {
return STUB_TCP_AGAIN; /* read more later */
return STUB_TCP_RETRY; /* read more later */
} else
return STUB_TCP_ERROR;
}
tcp->to_read -= read;
tcp->read_pos += read;
if ((int)tcp->to_read > 0)
return STUB_TCP_AGAIN;
return STUB_TCP_MORE_TO_READ;
}
return GLDNS_ID_WIRE(tcp->read_buf);
}
@ -1285,7 +1281,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
switch (SSL_get_error(tls_obj, written)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
return STUB_TCP_AGAIN;
return STUB_TCP_RETRY;
default:
return STUB_TCP_ERROR;
}
@ -1335,14 +1331,14 @@ stub_udp_read_cb(void *userarg)
* i.e. overflow
*/
0, NULL, NULL);
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
if (read == -1 && (_getdns_socketerror_wants_retry() ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; /* Try again later */
if (read == -1) {
DEBUG_STUB("%s %-35s: MSG: %p error while reading from socket:"
" %s\n", STUB_DEBUG_READ, __FUNC__, (void*)netreq
, strerror(errno));
, _getdns_errnostr());
stub_cleanup(netreq);
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
@ -1451,7 +1447,7 @@ stub_udp_write_cb(void *userarg)
if (written == -1)
DEBUG_STUB( "%s %-35s: MSG: %p error: %s\n"
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
, strerror(errno));
, _getdns_errnostr());
else
DEBUG_STUB( "%s %-35s: MSG: %p returned: %d, expeced: %d\n"
, STUB_DEBUG_WRITE, __FUNC__, (void *)netreq
@ -1517,10 +1513,10 @@ upstream_read_cb(void *userarg)
&upstream->upstreams->mf);
switch (q) {
case STUB_TCP_AGAIN:
case STUB_TCP_MORE_TO_READ:
/* WSA TODO: if callback is still upstream_read_cb, do it again
*/
case STUB_TCP_WOULDBLOCK:
case STUB_TCP_RETRY:
return;
case STUB_SETUP_ERROR: /* Can happen for TLS HS*/
case STUB_TCP_ERROR:
@ -1648,10 +1644,10 @@ upstream_write_cb(void *userarg)
q = stub_tcp_write(upstream->fd, &upstream->tcp, netreq);
switch (q) {
case STUB_TCP_AGAIN:
case STUB_TCP_MORE_TO_WRITE:
/* WSA TODO: if callback is still upstream_write_cb, do it again
*/
case STUB_TCP_WOULDBLOCK:
case STUB_TCP_RETRY:
return;
case STUB_OUT_OF_OPTIONS:
case STUB_TCP_ERROR:
@ -2064,7 +2060,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
continue;
if (fd == -1) {
if (_getdns_socketerror() == _getdns_EMFILE)
if (_getdns_resource_depletion())
return STUB_TRY_AGAIN_LATER;
return -1;
}

View File

@ -217,6 +217,7 @@ void assert_address_in_answer(struct extracted_response *ex_response, int a, int
case GETDNS_RRTYPE_A:
if(a && type == GETDNS_RRTYPE_A)
address_records++;
/* fallthrough */
case GETDNS_RRTYPE_AAAA:
if(aaaa && type == GETDNS_RRTYPE_AAAA)
address_records++;