mirror of https://github.com/getdnsapi/getdns.git
Decrease assumptions based on network_by_query_id
This commit is contained in:
parent
ee4feb0cc6
commit
f83c8e217e
|
@ -107,6 +107,12 @@ network_req_cleanup(getdns_network_req *net_req)
|
||||||
{
|
{
|
||||||
assert(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 ||
|
if (net_req->response && (net_req->response < net_req->wire_data ||
|
||||||
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
|
net_req->response > net_req->wire_data+ net_req->wire_data_sz))
|
||||||
GETDNS_FREE(net_req->owner->my_mf, net_req->response);
|
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;
|
net_req->unbound_id = -1;
|
||||||
_getdns_netreq_change_state(net_req, NET_REQ_NOT_SENT);
|
_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->dnssec_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||||
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
|
net_req->tsig_status = GETDNS_DNSSEC_INDETERMINATE;
|
||||||
net_req->response_len = 0;
|
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!
|
/* Scheduling, touch only via _getdns_netreq_change_state!
|
||||||
*/
|
*/
|
||||||
net_req->state = NET_REQ_NOT_SENT;
|
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) {
|
if (max_query_sz == 0) {
|
||||||
net_req->query = NULL;
|
net_req->query = NULL;
|
||||||
|
|
119
src/stub.c
119
src/stub.c
|
@ -83,8 +83,7 @@ static void upstream_write_cb(void *userarg);
|
||||||
static void upstream_idle_timeout_cb(void *userarg);
|
static void upstream_idle_timeout_cb(void *userarg);
|
||||||
static void upstream_schedule_netreq(getdns_upstream *upstream,
|
static void upstream_schedule_netreq(getdns_upstream *upstream,
|
||||||
getdns_network_req *netreq);
|
getdns_network_req *netreq);
|
||||||
static void upstream_reschedule_events(getdns_upstream *upstream,
|
static void upstream_reschedule_events(getdns_upstream *upstream);
|
||||||
uint64_t idle_timeout);
|
|
||||||
static int upstream_working_ok(getdns_upstream *upstream);
|
static int upstream_working_ok(getdns_upstream *upstream);
|
||||||
static int upstream_auth_status_ok(getdns_upstream *upstream,
|
static int upstream_auth_status_ok(getdns_upstream *upstream,
|
||||||
getdns_network_req *netreq);
|
getdns_network_req *netreq);
|
||||||
|
@ -498,20 +497,20 @@ stub_cleanup(getdns_network_req *netreq)
|
||||||
DEBUG_STUB("%s %-35s: MSG: %p\n",
|
DEBUG_STUB("%s %-35s: MSG: %p\n",
|
||||||
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
|
STUB_DEBUG_CLEANUP, __FUNC__, (void*)netreq);
|
||||||
getdns_dns_req *dnsreq = netreq->owner;
|
getdns_dns_req *dnsreq = netreq->owner;
|
||||||
getdns_upstream *upstream;
|
|
||||||
|
|
||||||
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
GETDNS_CLEAR_EVENT(dnsreq->loop, &netreq->event);
|
||||||
|
|
||||||
/* Nothing globally scheduled? Then nothing queued */
|
if (netreq->query_id_registered) {
|
||||||
if (!netreq->upstream || !(upstream = netreq->upstream)->event.ev)
|
(void) _getdns_rbtree_delete(
|
||||||
return;
|
netreq->query_id_registered, netreq->node.key);
|
||||||
|
netreq->query_id_registered = NULL;
|
||||||
/* Delete from upstream->netreq_by_query_id (if present) */
|
netreq->node.key = NULL;
|
||||||
(void) _getdns_rbtree_delete(&upstream->netreq_by_query_id,
|
}
|
||||||
(void *)(intptr_t)GLDNS_ID_WIRE(netreq->query));
|
if (netreq->upstream) {
|
||||||
|
remove_from_write_queue(netreq->upstream, netreq);
|
||||||
remove_from_write_queue(upstream, netreq);
|
if (netreq->upstream->event.ev)
|
||||||
upstream_reschedule_events(upstream, upstream->keepalive_timeout);
|
upstream_reschedule_events(netreq->upstream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -528,14 +527,6 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
||||||
if (during_setup) {
|
if (during_setup) {
|
||||||
/* Reset timeout on setup failure to trigger fallback handling.*/
|
/* Reset timeout on setup failure to trigger fallback handling.*/
|
||||||
GETDNS_CLEAR_EVENT(upstream->loop, &upstream->event);
|
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
|
/* Special case if failure was due to authentication issues since this
|
||||||
upstream could be used oppotunistically with no problem.*/
|
upstream could be used oppotunistically with no problem.*/
|
||||||
if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
|
if (!(upstream->transport == GETDNS_TRANSPORT_TLS &&
|
||||||
|
@ -545,6 +536,14 @@ upstream_failed(getdns_upstream *upstream, int during_setup)
|
||||||
upstream->conn_shutdowns++;
|
upstream->conn_shutdowns++;
|
||||||
/* [TLS1]TODO: Re-try these queries if possible.*/
|
/* [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) {
|
while (upstream->netreq_by_query_id.count) {
|
||||||
netreq = (getdns_network_req *)
|
netreq = (getdns_network_req *)
|
||||||
_getdns_rbtree_first(&upstream->netreq_by_query_id);
|
_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_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||||
_getdns_check_dns_req_complete(netreq->owner);
|
_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
|
void
|
||||||
|
@ -613,42 +618,12 @@ upstream_idle_timeout_cb(void *userarg)
|
||||||
static void
|
static void
|
||||||
upstream_setup_timeout_cb(void *userarg)
|
upstream_setup_timeout_cb(void *userarg)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
getdns_upstream *upstream = (getdns_upstream *)userarg;
|
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",
|
DEBUG_STUB("%s %-35s: FD: %d\n",
|
||||||
STUB_DEBUG_CLEANUP, __FUNC__, upstream->fd);
|
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
|
upstream_failed(upstream, 1);
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -748,6 +723,7 @@ stub_tcp_write(int fd, getdns_tcp_state *tcp, getdns_network_req *netreq)
|
||||||
|
|
||||||
} while (!_getdns_rbtree_insert(
|
} while (!_getdns_rbtree_insert(
|
||||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
&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);
|
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(
|
} while (!_getdns_rbtree_insert(
|
||||||
&netreq->upstream->netreq_by_query_id, &netreq->node));
|
&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);
|
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_SETUP_ERROR: /* Can happen for TLS HS*/
|
||||||
case STUB_TCP_ERROR:
|
case STUB_TCP_ERROR:
|
||||||
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1) );
|
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1) );
|
||||||
if (!upstream->write_queue)
|
|
||||||
_getdns_upstream_shutdown(upstream);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Lookup netreq */
|
/* Lookup netreq */
|
||||||
query_id = (uint16_t) q;
|
query_id = (uint16_t) q;
|
||||||
query_id_intptr = (intptr_t) query_id;
|
query_id_intptr = (intptr_t) query_id;
|
||||||
|
@ -1572,7 +1546,16 @@ upstream_read_cb(void *userarg)
|
||||||
upstream->tcp.to_read = 2;
|
upstream->tcp.to_read = 2;
|
||||||
return;
|
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",
|
DEBUG_STUB("%s %-35s: MSG: %p (read)\n",
|
||||||
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
|
STUB_DEBUG_READ, __FUNC__, (void*)netreq);
|
||||||
_getdns_netreq_change_state(netreq, NET_REQ_FINISHED);
|
_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.*/
|
/* Could not complete the set up. Need to fallback.*/
|
||||||
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
|
DEBUG_STUB("%s %-35s: Upstream: %p ERROR = %d\n", STUB_DEBUG_WRITE,
|
||||||
__FUNC__, (void*)userarg, q);
|
__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));
|
upstream_failed(upstream, (q == STUB_TCP_ERROR ? 0:1));
|
||||||
/* Fall through */
|
return;
|
||||||
case STUB_CONN_GONE:
|
case STUB_CONN_GONE:
|
||||||
case STUB_NO_AUTH:
|
case STUB_NO_AUTH:
|
||||||
/* Cleaning up after connection or auth check failure. Need to fallback. */
|
/* 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_netreq_change_state(netreq, NET_REQ_ERRORED);
|
||||||
_getdns_check_dns_req_complete(netreq->owner);
|
_getdns_check_dns_req_complete(netreq->owner);
|
||||||
}
|
}
|
||||||
if (!upstream->write_queue)
|
|
||||||
_getdns_upstream_shutdown(upstream);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
/* Unqueue the netreq from the write_queue */
|
||||||
|
remove_from_write_queue(upstream, netreq);
|
||||||
|
|
||||||
if (netreq->owner->return_call_reporting &&
|
if (netreq->owner->return_call_reporting &&
|
||||||
netreq->upstream->tls_obj &&
|
netreq->upstream->tls_obj &&
|
||||||
netreq->debug_tls_peer_cert.data == NULL &&
|
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;
|
netreq->debug_tls_auth_status = netreq->upstream->tls_auth_state;
|
||||||
upstream->queries_sent++;
|
upstream->queries_sent++;
|
||||||
|
|
||||||
/* Unqueue the netreq from the write_queue */
|
|
||||||
remove_from_write_queue(upstream, netreq);
|
|
||||||
|
|
||||||
/* Empty write_queue?, then deschedule upstream write_cb */
|
/* Empty write_queue?, then deschedule upstream write_cb */
|
||||||
if (upstream->write_queue == NULL) {
|
if (upstream->write_queue == NULL) {
|
||||||
assert(upstream->write_queue_last == 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);
|
fd = tcp_connect(upstream, transport);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
upstream_failed(upstream, 1);
|
upstream_failed(upstream, 1);
|
||||||
_getdns_upstream_reset(upstream);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
upstream->loop = dnsreq->loop;
|
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);
|
upstream->tls_obj = tls_create_object(dnsreq, fd, upstream);
|
||||||
if (upstream->tls_obj == NULL) {
|
if (upstream->tls_obj == NULL) {
|
||||||
upstream_failed(upstream, 1);
|
upstream_failed(upstream, 1);
|
||||||
_getdns_upstream_reset(upstream);
|
|
||||||
_getdns_closesocket(fd);
|
_getdns_closesocket(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -2137,7 +2114,7 @@ fallback_on_write(getdns_network_req *netreq)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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,
|
DEBUG_STUB("%s %-35s: FD: %d \n", STUB_DEBUG_SCHEDULE,
|
||||||
__FUNC__, upstream->fd);
|
__FUNC__, upstream->fd);
|
||||||
|
@ -2159,7 +2136,8 @@ upstream_reschedule_events(getdns_upstream *upstream, uint64_t idle_timeout) {
|
||||||
upstream->fd, TIMEOUT_FOREVER, &upstream->event);
|
upstream->fd, TIMEOUT_FOREVER, &upstream->event);
|
||||||
else {
|
else {
|
||||||
DEBUG_STUB("%s %-35s: FD: %d Connection idle - timeout is %d\n",
|
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,
|
/* TODO: Schedule a read also anyway,
|
||||||
* to digest timed out answers.
|
* to digest timed out answers.
|
||||||
* Dont forget to schedule with upstream->fd then!
|
* 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.read_cb = upstream_read_cb;
|
||||||
*/
|
*/
|
||||||
upstream->event.timeout_cb = upstream_idle_timeout_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,
|
GETDNS_SCHEDULE_EVENT(upstream->loop, -1,
|
||||||
idle_timeout, &upstream->event);
|
( upstream->conn_state == GETDNS_CONN_OPEN
|
||||||
|
? upstream->keepalive_timeout : 0), &upstream->event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,9 @@ typedef struct getdns_tcp_state {
|
||||||
typedef struct getdns_network_req
|
typedef struct getdns_network_req
|
||||||
{
|
{
|
||||||
/* For storage in upstream->netreq_by_query_id */
|
/* 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
|
#ifdef HAVE_MDNS_SUPPORT
|
||||||
/*
|
/*
|
||||||
* for storage of continuous query context in hash table of cached results.
|
* for storage of continuous query context in hash table of cached results.
|
||||||
|
|
Loading…
Reference in New Issue