Adjust Unix socket/Winsock handling.

Centralise it into util-internal.h, remove duplicate definitions from mdns, and add new pseudo-functions _getdns_closesocket(), _getdns_poll() and _getdns_socketerror(). Convert error values to simple values and convert error checking to use _getdns_socketerror() and the simple values. The simple values can also be used with the result from getsockopt() with SO_ERROR in stub.c.
This commit is contained in:
Jim Hague 2017-10-04 17:31:33 +01:00
parent 4acce42720
commit a0c313412d
8 changed files with 81 additions and 185 deletions

View File

@ -1198,7 +1198,7 @@ static void tas_read_cb(void *userarg)
return;
}
}
} else if (_getdns_EWOULDBLOCK)
} else if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return;
DEBUG_ANCHOR("Read error: %d %s\n", (int)n, strerror(errno));
@ -1248,7 +1248,7 @@ static void tas_write_cb(void *userarg)
tas_read_cb, NULL, tas_timeout_cb));
return;
} else if (_getdns_EWOULDBLOCK || _getdns_EINPROGRESS)
} else if (_getdns_socketerror() == _getdns_EWOULDBLOCK || _getdns_socketerror() == _getdns_EINPROGRESS)
return;
DEBUG_ANCHOR("Write error: %s\n", strerror(errno));
@ -1348,8 +1348,8 @@ static void tas_connect(getdns_context *context, tas_connection *a)
addr.sin6_scope_id = 0;
r = connect(a->fd, (struct sockaddr *)&addr, sizeof(addr));
}
if (r == 0 || (r == -1 && (_getdns_EINPROGRESS ||
_getdns_EWOULDBLOCK))) {
if (r == 0 || (r == -1 && (_getdns_socketerror() == _getdns_EINPROGRESS ||
_getdns_socketerror() == _getdns_EWOULDBLOCK))) {
char tas_hostname[256];
const char *path = "", *fmt;
getdns_return_t R;

View File

@ -704,11 +704,7 @@ _getdns_upstreams_dereference(getdns_upstreams *upstreams)
}
if (upstream->fd != -1)
{
#ifdef USE_WINSOCK
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
_getdns_closesocket(upstream->fd);
}
while (pin) {
sha256_pin_t *nextpin = pin->next;
@ -809,11 +805,7 @@ _getdns_upstream_reset(getdns_upstream *upstream)
upstream->tls_obj = NULL;
}
if (upstream->fd != -1) {
#ifdef USE_WINSOCK
closesocket(upstream->fd);
#else
close(upstream->fd);
#endif
_getdns_closesocket(upstream->fd);
upstream->fd = -1;
}
/* Set connection ready for use again*/

View File

@ -27,13 +27,7 @@
#include "config.h"
#ifdef HAVE_SYS_POLL_H
#include <sys/poll.h>
#else
#ifndef USE_WINSOCK
#include <poll.h>
#endif
#endif
#include "util-internal.h"
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
@ -411,10 +405,8 @@ poll_eventloop_run_once(getdns_eventloop *loop, int blocking)
{
Sleep(poll_timeout);
} else
if (WSAPoll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
#else
if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
#endif
if (poll(poll_loop->pfds, poll_loop->fd_events_free, poll_timeout) < 0) {
perror("poll() failed");
exit(EXIT_FAILURE);
}

View File

@ -30,24 +30,6 @@
#ifdef HAVE_MDNS_SUPPORT
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
WSAGetLastError() == WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
#else
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
#define SOCKADDR struct sockaddr
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR_IN6 struct sockaddr_in6
#define SOCKET int
#define IP_MREQ struct ip_mreq
#define IPV6_MREQ struct ipv6_mreq
#define BOOL int
#define TRUE 1
#endif
/* Define IPV6_ADD_MEMBERSHIP for FreeBSD and Mac OS X */
#ifndef IPV6_ADD_MEMBERSHIP
#define IPV6_ADD_MEMBERSHIP IPV6_JOIN_GROUP
@ -1148,7 +1130,8 @@ mdns_udp_multicast_read_cb(void *userarg)
sizeof(cnx->response), 0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK)
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET)
return; /* TODO: this will stop the receive loop! */
if (read >= GLDNS_HEADER_SIZE)
@ -1353,11 +1336,7 @@ static int mdns_open_ipv4_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
if (ret != 0 && fd4 != -1)
{
#ifdef USE_WINSOCK
closesocket(fd4);
#else
close(fd4);
#endif
_getdns_closesocket(fd4);
fd4 = -1;
}
@ -1428,11 +1407,7 @@ static int mdns_open_ipv6_multicast(SOCKADDR_STORAGE* mcast_dest, int* mcast_des
if (ret != 0 && fd6 != -1)
{
#ifdef USE_WINSOCK
closesocket(fd6);
#else
close(fd6);
#endif
_getdns_closesocket(fd6);
fd6 = -1;
}
@ -1514,11 +1489,7 @@ static getdns_return_t mdns_delayed_network_init(struct getdns_context *context)
GETDNS_CLEAR_EVENT(context->extension
, &context->mdns_connection[i].event);
#ifdef USE_WINSOCK
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
_getdns_closesocket(context->mdns_connection[i].fd);
}
}
@ -1657,11 +1628,7 @@ void _getdns_mdns_context_destroy(struct getdns_context *context)
/* suppress the receive event */
GETDNS_CLEAR_EVENT(context->extension, &context->mdns_connection[i].event);
/* close the socket */
#ifdef USE_WINSOCK
closesocket(context->mdns_connection[i].fd);
#else
close(context->mdns_connection[i].fd);
#endif
_getdns_closesocket(context->mdns_connection[i].fd);
}
GETDNS_FREE(context->mf, context->mdns_connection);
@ -1686,11 +1653,7 @@ _getdns_cancel_mdns_request(getdns_network_req *netreq)
{
mdns_cleanup(netreq);
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
}
}
@ -1706,11 +1669,7 @@ mdns_timeout_cb(void *userarg)
/* Check the required cleanup */
mdns_cleanup(netreq);
if (netreq->fd >= 0)
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
if (netreq->owner->user_callback) {
netreq->debug_end_time = _getdns_get_time_as_uintt64();
@ -1745,7 +1704,8 @@ mdns_udp_read_cb(void *userarg)
* i.e. overflow
*/
0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK)
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET)
return;
if (read < GLDNS_HEADER_SIZE)
@ -1759,11 +1719,7 @@ mdns_udp_read_cb(void *userarg)
// TODO: check that the source address originates from the local network.
// TODO: check TTL = 255
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
/*
* TODO: how to handle an MDNS response with TC bit set?
* Ignore it for now, as we do not support any kind of TCP fallback
@ -1814,11 +1770,7 @@ mdns_udp_write_cb(void *userarg)
netreq->fd, (const void *)netreq->query, pkt_len, 0,
(struct sockaddr *)&mdns_mcast_v4,
sizeof(mdns_mcast_v4))) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
return;
}
GETDNS_SCHEDULE_EVENT(

View File

@ -24,13 +24,10 @@
#ifdef HAVE_MDNS_SUPPORT
#include "getdns/getdns.h"
#include "types-internal.h"
#include "util-internal.h"
#include "util/lruhash.h"
#include "config.h"
#ifndef USE_WINSOCK
#define SOCKADDR_STORAGE struct sockaddr_storage
#endif
getdns_return_t
_getdns_submit_mdns_request(getdns_network_req *netreq);

View File

@ -39,6 +39,7 @@
#include "types-internal.h"
#include "debug.h"
#include "util/rbtree.h"
#include "util-internal.h"
#include "server.h"
#define DNS_REQUEST_SZ 4096
@ -135,11 +136,7 @@ static void tcp_connection_destroy(tcp_connection *conn)
loop->vmt->clear(loop, &conn->event);
if (conn->fd >= 0)
#ifdef USE_WINSOCK
(void) closesocket(conn->fd);
#else
(void) close(conn->fd);
#endif
(void) _getdns_closesocket(conn->fd);
GETDNS_FREE(*mf, conn->read_buf);
for (cur = conn->to_write; cur; cur = next) {
@ -285,11 +282,7 @@ getdns_reply(
(struct sockaddr *)&conn->remote_in, conn->addrlen) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &conn->l->event);
#ifdef USE_WINSOCK
closesocket(conn->l->fd);
#else
close(conn->l->fd);
#endif
_getdns_closesocket(conn->l->fd);
conn->l->fd = -1;
}
/* Unlink this connection */
@ -483,11 +476,7 @@ static void tcp_accept_cb(void *userarg)
&conn->super.remote_in, &conn->super.addrlen)) == -1) {
/* IO error, cleanup this listener */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
GETDNS_FREE(*mf, conn);
return;
@ -557,11 +546,7 @@ static void udp_read_cb(void *userarg)
(struct sockaddr *)&conn->remote_in, &conn->addrlen)) == -1) {
/* IO error, cleanup this listener. */
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
#if 0 && defined(SERVER_DEBUG) && SERVER_DEBUG
@ -710,11 +695,7 @@ static void remove_listeners(listen_set *set)
continue;
loop->vmt->clear(loop, &l->event);
#ifdef USE_WINSOCK
closesocket(l->fd);
#else
close(l->fd);
#endif
_getdns_closesocket(l->fd);
l->fd = -1;
if (l->transport != GETDNS_TRANSPORT_TCP)

View File

@ -38,17 +38,6 @@
*/
#define INTERCEPT_COM_DS 0
#ifdef USE_POLL_DEFAULT_EVENTLOOP
# ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
# else
#ifdef USE_WINSOCK
#define poll(fdarray, nbsockets, timer) WSAPoll(fdarray, nbsockets, timer)
#else
# include <poll.h>
#endif
# endif
#endif
#include "debug.h"
#include <openssl/err.h>
#include <openssl/conf.h>
@ -426,13 +415,10 @@ tcp_connect(getdns_upstream *upstream, getdns_transport_list_t transport)
#endif
if (connect(fd, (struct sockaddr *)&upstream->addr,
upstream->addr_len) == -1) {
if (_getdns_EINPROGRESS || _getdns_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EINPROGRESS ||
_getdns_socketerror() == _getdns_EWOULDBLOCK)
return fd;
#ifdef USE_WINSOCK
closesocket(fd);
#else
close(fd);
#endif
_getdns_closesocket(fd);
return -1;
}
return fd;
@ -443,22 +429,13 @@ 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);
#ifdef USE_WINSOCK
if (error == WSAEINPROGRESS)
if (error == _getdns_EINPROGRESS)
return STUB_TCP_AGAIN;
else if (error == WSAEWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
else if (error != 0)
return STUB_SETUP_ERROR;
#else
if (error == EINPROGRESS)
return STUB_TCP_AGAIN;
else if (error == EWOULDBLOCK || error == EAGAIN)
else if (error == _getdns_EWOULDBLOCK || error == _getdns_EAGAIN)
return STUB_TCP_WOULDBLOCK;
else if (error != 0) {
return STUB_SETUP_ERROR;
}
#endif
if (upstream->transport == GETDNS_TRANSPORT_TCP &&
upstream->queries_sent == 0) {
upstream->conn_state = GETDNS_CONN_OPEN;
@ -570,11 +547,7 @@ _getdns_cancel_stub_request(getdns_network_req *netreq)
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
stub_cleanup(netreq);
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
}
}
@ -589,11 +562,7 @@ stub_timeout_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_TIMED_OUT);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
netreq->upstream->udp_timeouts++;
if (netreq->upstream->udp_timeouts % 100 == 0)
@ -650,7 +619,7 @@ upstream_setup_timeout_cb(void *userarg)
#ifdef USE_POLL_DEFAULT_EVENTLOOP
fds.fd = upstream->fd;
fds.events = POLLOUT;
ret = poll(&fds, 1, 0);
ret = _getdns_poll(&fds, 1, 0);
#else
FD_ZERO(&fds);
FD_SET((int)(upstream->fd), &fds);
@ -690,7 +659,7 @@ 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_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
else
return STUB_TCP_ERROR;
@ -807,11 +776,11 @@ 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_EWOULDBLOCK ||
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_EINPROGRESS)) ||
_getdns_socketerror() == _getdns_EINPROGRESS)) ||
(size_t)written < pkt_len + 2) {
/* We couldn't write the whole packet.
@ -847,7 +816,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
tcp->write_buf_len - tcp->written);
#endif
if (written == -1) {
if (_getdns_EWOULDBLOCK)
if (_getdns_socketerror() == _getdns_EWOULDBLOCK)
return STUB_TCP_WOULDBLOCK;
else {
DEBUG_STUB("%s %-35s: MSG: %p error while writing to TCP socket:"
@ -1386,7 +1355,8 @@ stub_udp_read_cb(void *userarg)
* i.e. overflow
*/
0, NULL, NULL);
if (read == -1 && _getdns_EWOULDBLOCK)
if (read == -1 && (_getdns_socketerror() == _getdns_EWOULDBLOCK ||
_getdns_socketerror() == _getdns_ECONNRESET))
return; /* Try again later */
if (read == -1) {
@ -1398,11 +1368,7 @@ stub_udp_read_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
stub_next_upstream(netreq);
}
@ -1422,11 +1388,7 @@ stub_udp_read_cb(void *userarg)
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
while (GLDNS_TC_WIRE(netreq->response)) {
DEBUG_STUB("%s %-35s: MSG: %p TC bit set in response \n", STUB_DEBUG_READ,
@ -1519,11 +1481,7 @@ stub_udp_write_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
/* Handle upstream*/
if (netreq->fd >= 0) {
#ifdef USE_WINSOCK
closesocket(netreq->fd);
#else
close(netreq->fd);
#endif
_getdns_closesocket(netreq->fd);
netreq->fd = -1;
stub_next_upstream(netreq);
}
@ -2055,11 +2013,7 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
if (upstream->tls_obj == NULL) {
upstream_failed(upstream, 1);
_getdns_upstream_reset(upstream);
#ifdef USE_WINSOCK
closesocket(fd);
#else
close(fd);
#endif
_getdns_closesocket(fd);
return -1;
}
upstream->tls_hs_state = GETDNS_HS_WRITE;
@ -2128,7 +2082,7 @@ upstream_find_for_netreq(getdns_network_req *netreq)
continue;
if (fd == -1) {
if (_getdns_EMFILE)
if (_getdns_socketerror() == _getdns_EMFILE)
return STUB_TRY_AGAIN_LATER;
return -1;
}

View File

@ -221,14 +221,42 @@ INLINE uint64_t _getdns_ms_until_expiry2(uint64_t expires, uint64_t *now_ms)
#ifdef USE_WINSOCK
typedef u_short sa_family_t;
#define _getdns_EWOULDBLOCK (WSAGetLastError() == WSATRY_AGAIN ||\
WSAGetLastError() == WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAGetLastError() == WSAEINPROGRESS)
#define _getdns_EMFILE (WSAGetLastError() == WSAEMFILE)
#define _getdns_EAGAIN (WSATRY_AGAIN)
#define _getdns_EWOULDBLOCK (WSAEWOULDBLOCK)
#define _getdns_EINPROGRESS (WSAEINPROGRESS)
#define _getdns_EMFILE (WSAEMFILE)
#define _getdns_ECONNRESET (WSAECONNRESET)
#define _getdns_closesocket(fd) closesocket(fd)
#define _getdns_poll(fdarray, nsockets, timer) WSAPoll(fdarray, nsockets, timer)
#define _getdns_socketerror() (WSAGetLastError())
#else
#define _getdns_EWOULDBLOCK (errno == EAGAIN || errno == EWOULDBLOCK)
#define _getdns_EINPROGRESS (errno == EINPROGRESS)
#define _getdns_EMFILE (errno == EMFILE)
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#else
# include <poll.h>
#endif
#define _getdns_EAGAIN (EAGAIN)
#define _getdns_EWOULDBLOCK (EWOULDBLOCK)
#define _getdns_EINPROGRESS (EINPROGRESS)
#define _getdns_EMFILE (EMFILE)
#define _getdns_ECONNRESET (ECONNRESET)
#define SOCKADDR struct sockaddr
#define SOCKADDR_IN struct sockaddr_in
#define SOCKADDR_IN6 struct sockaddr_in6
#define SOCKADDR_STORAGE struct sockaddr_storage
#define SOCKET int
#define IP_MREQ struct ip_mreq
#define IPV6_MREQ struct ipv6_mreq
#define BOOL int
#define TRUE 1
#define _getdns_closesocket(fd) close(fd)
#define _getdns_poll(fdarray, nsockets, timer) poll(fdarray, nsockets, timer)
#define _getdns_socketerror() (errno)
#endif
#endif