From c809bb9ece278a3a685fa4982a4f71aa5d279ef8 Mon Sep 17 00:00:00 2001 From: "W.C.A. Wijngaards" Date: Tue, 23 Jun 2020 15:29:40 +0200 Subject: [PATCH] tcp reuse timeout event cleanup and callbacks. --- services/outside_network.c | 97 ++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 14 deletions(-) diff --git a/services/outside_network.c b/services/outside_network.c index 99b969026..7e58b1c99 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -1449,26 +1449,95 @@ pending_udp_query(struct serviced_query* sq, struct sldns_buffer* packet, return pend; } +/** perform failure callbacks for waiting queries in reuse write list */ +static void reuse_cb_writewait_for_failure(struct pending_tcp* pend, int err) +{ + struct waiting_tcp* w; + w = pend->reuse.write_wait_first; + while(w) { + comm_point_callback_type* cb = w->cb; + void* cb_arg = w->cb_arg; + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, err, NULL); + w = w->write_wait_next; + } +} + +/** perform failure callbacks for waiting queries in reuse read rbtree */ +static void reuse_cb_readwait_for_failure(struct pending_tcp* pend, int err) +{ + rbnode_type* node; + node = rbtree_first(&pend->reuse.tree_by_id); + while(node && node != RBTREE_NULL) { + struct waiting_tcp* w = (struct waiting_tcp*)node->key; + comm_point_callback_type* cb = w->cb; + void* cb_arg = w->cb_arg; + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, err, NULL); + node = rbtree_next(node); + } +} + +/** perform failure callbacks for current written query in reuse struct */ +static void reuse_cb_curquery_for_failure(struct pending_tcp* pend, int err) +{ + struct waiting_tcp* w = pend->query; + if(w) { + comm_point_callback_type* cb = w->cb; + void* cb_arg = w->cb_arg; + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, err, NULL); + } +} + +/** helper function that deletes and element from the tree of readwait + * elements in tcp reuse structure */ +static void reuse_del_readwait_elem(rbnode_type* node, void* ATTR_UNUSED(arg)) +{ + struct waiting_tcp* w = (struct waiting_tcp*)node->key; + waiting_tcp_delete(w); +} + +/** delete readwait waiting_tcp elements, deletes the elements in the list */ +static void reuse_del_readwait(struct pending_tcp* pend) +{ + traverse_postorder(&pend->reuse.tree_by_id, &reuse_del_readwait_elem, + NULL); +} + +/** delete writewait waiting_tcp elements, deletes the elements in the list */ +static void reuse_del_writewait(struct pending_tcp* pend) +{ + struct waiting_tcp* w, *n; + w = pend->reuse.write_wait_first; + while(w) { + n = w->write_wait_next; + waiting_tcp_delete(w); + w = n; + } +} + void outnet_tcptimer(void* arg) { struct waiting_tcp* w = (struct waiting_tcp*)arg; struct outside_network* outnet = w->outnet; - int do_callback = 1; verbose(5, "outnet_tcptimer"); if(w->on_tcp_waiting_list) { /* it is on the waiting list */ + comm_point_callback_type* cb = w->cb; + void* cb_arg = w->cb_arg; waiting_list_remove(outnet, w); + waiting_tcp_delete(w); + fptr_ok(fptr_whitelist_pending_tcp(cb)); + (void)(*cb)(NULL, cb_arg, NETEVENT_TIMEOUT, NULL); } else { /* it was in use */ struct pending_tcp* pend=(struct pending_tcp*)w->next_waiting; /* see if it needs unlink from reuse tree */ if(pend->reuse.pending) { reuse_tcp_remove_tree_list(outnet, &pend->reuse); - do_callback = 0; } - /* do failure callbacks for all the queries in the - * wait for write list and in the id-tree TODO */ if(pend->c->ssl) { #ifdef HAVE_SSL SSL_shutdown(pend->c->ssl); @@ -1477,20 +1546,20 @@ outnet_tcptimer(void* arg) #endif } comm_point_close(pend->c); + /* do failure callbacks for all the queries in the + * wait for write list and in the id-tree */ + /* callback for 'w' arg already in list of curquery, + * readwait list, writewait list */ + reuse_cb_curquery_for_failure(pend, NETEVENT_TIMEOUT); + reuse_cb_readwait_for_failure(pend, NETEVENT_TIMEOUT); + reuse_cb_writewait_for_failure(pend, NETEVENT_TIMEOUT); + waiting_tcp_delete(pend->query); /* del curquery */ + reuse_del_readwait(pend); + reuse_del_writewait(pend); pend->query = NULL; pend->next_free = outnet->tcp_free; outnet->tcp_free = pend; } - if(do_callback) { - comm_point_callback_type* cb = w->cb; - void* cb_arg = w->cb_arg; - waiting_tcp_delete(w); - fptr_ok(fptr_whitelist_pending_tcp(cb)); - (void)(*cb)(NULL, cb_arg, NETEVENT_TIMEOUT, NULL); - } else { - /* waiting_tcp_delete(w); -- should be deleted if entire - * stream with reuse elements is gone. TODO remove this? */ - } use_free_buffer(outnet); }