Decrease assumptions based on network_by_query_id

This commit is contained in:
Willem Toorop 2017-10-17 13:47:29 +02:00
parent ee4feb0cc6
commit f83c8e217e
3 changed files with 68 additions and 72 deletions

View File

@ -107,6 +107,12 @@ network_req_cleanup(getdns_network_req *net_req)
{
assert(net_req);
if (net_req->query_id_registered) {
(void) _getdns_rbtree_delete(
net_req->query_id_registered, net_req->node.key);
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
}
if (net_req->response && (net_req->response < net_req->wire_data ||
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
@ -123,6 +129,12 @@ netreq_reset(getdns_network_req *net_req)
*/
net_req->unbound_id = -1;
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
if (net_req->query_id_registered) {
(void) _getdns_rbtree_delete(net_req->query_id_registered,
(void *)(intptr_t)GLDNS_ID_WIRE(net_req->query));
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
}
net_req->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
net_req->response_len = 0;
@ -196,6 +208,11 @@ network_req_init(getdns_network_req *net_req, getdns_dns_req *owner,
/* Scheduling, touch only via _getdns_netreq_change_state!
*/
net_req->state = NET_REQ_NOT_SENT;
/* A registered netreq (on a statefull transport)
* Deregister on reset and cleanup.
*/
net_req->query_id_registered = NULL;
net_req->node.key = NULL;
if (max_query_sz == 0) {
net_req->query = NULL;

View File

@ -83,8 +83,7 @@ static void upstream_write_cb(void *userarg);
static void upstream_idle_timeout_cb(void *userarg);
static void upstream_schedule_netreq(getdns_upstream *upstream,
getdns_network_req *netreq);
static void upstream_reschedule_events(getdns_upstream *upstream,
uint64_t idle_timeout);
static void upstream_reschedule_events(getdns_upstream *upstream);
static int upstream_working_ok(getdns_upstream *upstream);
static int upstream_auth_status_ok(getdns_upstream *upstream,
getdns_network_req *netreq);
@ -498,20 +497,20 @@ stub_cleanup(getdns_network_req *netreq)
DEBUG_STUB("%s %-35s: MSG: %p\n",
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
getdns_dns_req *dnsreq = netreq->owner;
getdns_upstream *upstream;
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
/* Nothing globally scheduled? Then nothing queued */
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev)
return;
/* Delete from upstream->netreq_by_query_id (if present) */
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
remove_from_write_queue(upstream, netreq);
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
if (netreq->query_id_registered) {
(void) _getdns_rbtree_delete(
netreq->query_id_registered, netreq->node.key);
netreq->query_id_registered = NULL;
netreq->node.key = NULL;
}
if (netreq->upstream) {
remove_from_write_queue(netreq->upstream, netreq);
if (netreq->upstream->event.ev)
upstream_reschedule_events(netreq->upstream);
}
}
static void
@ -528,14 +527,6 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
if (during_setup) {
/* Reset timeout on setup failure to trigger fallback handling.*/
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
/* Need this check because if the setup failed because the interface is
not up we get -1 and then a seg fault. Found when using IPv6 address
but IPv6 interface not enabled.*/
if (upstream->fd != -1) {
GETDNS_SCHEDULE_EVENT(upstream->loop, upstream->fd, TIMEOUT_FOREVER,
getdns_eventloop_event_init(&upstream->event, upstream,
NULL, upstream_write_cb, NULL));
}
/* Special case if failure was due to authentication issues since this
upstream could be used oppotunistically with no problem.*/
if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
@ -545,6 +536,14 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
upstream->conn_shutdowns++;
/* [TLS1]TODO: Re-try these queries if possible.*/
}
upstream->conn_state = GETDNS_CONN_TEARDOWN;
if (upstream->write_queue) {
if (!during_setup)
during_setup = -1;
while (upstream->write_queue)
upstream_write_cb(upstream);
}
while (upstream->netreq_by_query_id.count) {
netreq = (getdns_network_req *)
_getdns_rbtree_first(&upstream->netreq_by_query_id);
@ -552,7 +551,13 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner);
}
upstream->conn_state = GETDNS_CONN_TEARDOWN;
if (during_setup == 0)
return;
else if (during_setup > 0)
_getdns_upstream_reset(upstream);
else
_getdns_upstream_shutdown(upstream);
}
void
@ -613,42 +618,12 @@ upstream_idle_timeout_cb(void *userarg)
static void
upstream_setup_timeout_cb(void *userarg)
{
int ret;
getdns_upstream *upstream = (getdns_upstream *)userarg;
#ifdef USE_POLL_DEFAULT_EVENTLOOP
struct pollfd fds;
#else
fd_set fds;
struct timeval tval;
#endif
DEBUG_STUB("%s %-35s: FD: %d\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
/* Clean up and trigger a write to let the fallback code to its job */
upstream_failed(upstream, 1);
/* Need to handle the case where the far end doesn't respond to a
* TCP SYN and doesn't do a reset (as is the case with e.g. 8.8.8.8@853).
* For that case the socket never becomes writable so doesn't trigger any
* callbacks. If so then clear out the queue in one go.*/
#ifdef USE_POLL_DEFAULT_EVENTLOOP
fds.fd = upstream->fd;
fds.events = POLLOUT;
ret = _getdns_poll(&fds, 1, 0);
#else
FD_ZERO(&fds);
FD_SET((int)(upstream->fd), &fds);
tval.tv_sec = 0;
tval.tv_usec = 0;
ret = select(upstream->fd+1, NULL, &fds, NULL, &tval);
#endif
if (ret == 0) {
DEBUG_STUB("%s %-35s: FD: %d Cleaning up dangling queue\n",
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
while (upstream->write_queue)
upstream_write_cb(upstream);
}
_getdns_upstream_reset(upstream);
upstream_failed(upstream, 1);
}
@ -748,6 +723,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
} while (!_getdns_rbtree_insert(
&netreq->upstream->netreq_by_query_id, &netreq->node));
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
GLDNS_ID_SET(netreq->query, query_id);
@ -1241,6 +1217,7 @@ stub_tls_write(getdns_upstream *upstream, getdns_tcp_state *tcp,
} while (!_getdns_rbtree_insert(
&netreq->upstream->netreq_by_query_id, &netreq->node));
netreq->query_id_registered = &netreq->upstream->netreq_by_query_id;
GLDNS_ID_SET(netreq->query, query_id);
@ -1555,12 +1532,9 @@ upstream_read_cb(void *userarg)
case STUB_SETUP_ERROR: /* Can happen for TLS HS*/
case STUB_TCP_ERROR:
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1) );
if (!upstream->write_queue)
_getdns_upstream_shutdown(upstream);
return;
default:
/* Lookup netreq */
query_id = (uint16_t) q;
query_id_intptr = (intptr_t) query_id;
@ -1572,7 +1546,16 @@ upstream_read_cb(void *userarg)
upstream->tcp.to_read = 2;
return;
}
if (netreq->query_id_registered == &upstream->netreq_by_query_id) {
netreq->query_id_registered = NULL;
netreq->node.key = NULL;
} else if (netreq->query_id_registered) {
(void) _getdns_rbtree_delete(
netreq->query_id_registered, netreq->node.key);
netreq->query_id_registered = NULL;
netreq->node.key = NULL;
}
DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
@ -1685,10 +1668,8 @@ upstream_write_cb(void *userarg)
/* Could not complete the set up. Need to fallback.*/
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
__FUNC__, (void*)userarg, q);
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1));
/* Fall through */
return;
case STUB_CONN_GONE:
case STUB_NO_AUTH:
/* Cleaning up after connection or auth check failure. Need to fallback. */
@ -1702,11 +1683,12 @@ upstream_write_cb(void *userarg)
_getdns_netreq_change_state(netreq, NET_REQ_ERRORED);
_getdns_check_dns_req_complete(netreq->owner);
}
if (!upstream->write_queue)
_getdns_upstream_shutdown(upstream);
return;
default:
/* Unqueue the netreq from the write_queue */
remove_from_write_queue(upstream, netreq);
if (netreq->owner->return_call_reporting &&
netreq->upstream->tls_obj &&
netreq->debug_tls_peer_cert.data == NULL &&
@ -1719,9 +1701,6 @@ upstream_write_cb(void *userarg)
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
upstream->queries_sent++;
/* Unqueue the netreq from the write_queue */
remove_from_write_queue(upstream, netreq);
/* Empty write_queue?, then deschedule upstream write_cb */
if (upstream->write_queue == NULL) {
assert(upstream->write_queue_last == NULL);
@ -2015,7 +1994,6 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
fd = tcp_connect(upstream, transport);
if (fd == -1) {
upstream_failed(upstream, 1);
_getdns_upstream_reset(upstream);
return -1;
}
upstream->loop = dnsreq->loop;
@ -2025,7 +2003,6 @@ upstream_connect(getdns_upstream *upstream, getdns_transport_list_t transport,
upstream->tls_obj = tls_create_object(dnsreq, fd, upstream);
if (upstream->tls_obj == NULL) {
upstream_failed(upstream, 1);
_getdns_upstream_reset(upstream);
_getdns_closesocket(fd);
return -1;
}
@ -2137,7 +2114,7 @@ fallback_on_write(getdns_network_req *netreq)
}
static void
upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
upstream_reschedule_events(getdns_upstream *upstream) {
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE,
__FUNC__, upstream->fd);
@ -2159,7 +2136,8 @@ upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
upstream->fd, TIMEOUT_FOREVER, &upstream->event);
else {
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd, (int)idle_timeout);
STUB_DEBUG_SCHEDULE, __FUNC__, upstream->fd,
(int)upstream->keepalive_timeout);
/* TODO: Schedule a read also anyway,
* to digest timed out answers.
* Dont forget to schedule with upstream->fd then!
@ -2167,10 +2145,9 @@ upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
* upstream->event.read_cb = upstream_read_cb;
*/
upstream->event.timeout_cb = upstream_idle_timeout_cb;
if (upstream->conn_state != GETDNS_CONN_OPEN)
idle_timeout = 0;
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
idle_timeout, &upstream->event);
( upstream->conn_state == GETDNS_CONN_OPEN
? upstream->keepalive_timeout : 0), &upstream->event);
}
}

View File

@ -188,7 +188,9 @@ typedef struct getdns_tcp_state {
typedef struct getdns_network_req
{
/* For storage in upstream->netreq_by_query_id */
_getdns_rbnode_t node;
_getdns_rbnode_t node;
/* The netreq_by_query_id tree in which this netreq was registered */
_getdns_rbtree_t *query_id_registered;
#ifdef HAVE_MDNS_SUPPORT
/*
* for storage of continuous query context in hash table of cached results.