From fed6a738de11be79be0215d35023e4435cb14766 Mon Sep 17 00:00:00 2001 From: Wouter Wijngaards Date: Wed, 20 Jun 2007 14:01:58 +0000 Subject: [PATCH] duplicate query callbacks work. git-svn-id: file:///svn/unbound/trunk@408 be551aaa-1e26-0410-a405-d3ace91eadb9 --- daemon/worker.c | 2 ++ doc/Changelog | 1 + services/outside_network.c | 29 +++++++++++++++++++++++++++++ services/outside_network.h | 16 ++++++++++++++++ testcode/fake_event.c | 7 +++++++ 5 files changed, 55 insertions(+) diff --git a/daemon/worker.c b/daemon/worker.c index 8225e3478..2277f65f4 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -833,6 +833,8 @@ worker_init(struct worker* worker, struct config_file *cfg, worker_delete(worker); return 0; } + outside_network_set_secondary_buffer(worker->back, + worker->front->udp_buff); if(worker->thread_num != 0) { /* start listening to commands */ if(!(worker->cmd_com=comm_point_create_local(worker->base, diff --git a/doc/Changelog b/doc/Changelog index 988f7e68f..3a5ee119b 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -7,6 +7,7 @@ - typo in check caused subquery errors to be ignored, fixed. - make lint happy about rlim_t. - freeup of modules after freeup of module-states. + - duplicate replies work, this uses secondary udp buffer in outnet. 19 June 2007: Wouter - nicer layout in stats.c, review 0.3 change. diff --git a/services/outside_network.c b/services/outside_network.c index ffe975a43..85e2f1d28 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -472,6 +472,7 @@ outside_network_create(struct comm_base *base, size_t bufsize, outnet->num_tcp = num_tcp; outnet->infra = infra; outnet->rnd = rnd; + outnet->udp_second = 0; #ifndef INET6 do_ip6 = 0; #endif @@ -532,6 +533,13 @@ outside_network_create(struct comm_base *base, size_t bufsize, return outnet; } +void +outside_network_set_secondary_buffer(struct outside_network* outnet, + ldns_buffer* buf) +{ + outnet->udp_second = buf; +} + /** helper pending delete */ static void pending_node_del(rbnode_t* node, void* arg) @@ -998,6 +1006,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, struct comm_reply* rep) { struct service_callback* p = sq->cblist, *n; + int dobackup = (sq->cblist && sq->cblist->next); /* >1 cb*/ rbnode_t* rem; /* remove from tree, and schedule for deletion, so that callbacks * can safely deregister themselves and even create new serviced @@ -1005,8 +1014,28 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, rem = rbtree_delete(sq->outnet->serviced, sq); log_assert(rem); /* should have been present */ sq->to_be_deleted = 1; + if(dobackup) { + /* make a backup of the query, since the querystate processing + * may send outgoing queries that overwrite the buffer. + * use secondary buffer to store the query. + * This is a data copy, but faster than packet to server */ + log_assert(ldns_buffer_capacity(sq->outnet->udp_second) >= + ldns_buffer_limit(c->buffer)); + ldns_buffer_clear(sq->outnet->udp_second); + ldns_buffer_write(sq->outnet->udp_second, + ldns_buffer_begin(c->buffer), + ldns_buffer_limit(c->buffer)); + ldns_buffer_flip(sq->outnet->udp_second); + } while(p) { n = p->next; + if(dobackup) { + ldns_buffer_clear(c->buffer); + ldns_buffer_write(c->buffer, + ldns_buffer_begin(sq->outnet->udp_second), + ldns_buffer_limit(sq->outnet->udp_second)); + ldns_buffer_flip(c->buffer); + } (void)(*p->cb)(c, p->cb_arg, error, rep); p = n; } diff --git a/services/outside_network.h b/services/outside_network.h index 6fc794e25..0e7e59c33 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -65,6 +65,12 @@ struct outside_network { datagram at any time. */ ldns_buffer* udp_buff; + /** buffer for storage. (buffer for incoming connections, since + * either an event to outside or incoming happens, but not both + * This buffer is used during callbacks, so that the datagram + * that just arrived does not collide with new datagrams sent out. */ + ldns_buffer* udp_second; + /** * Array of udp comm point* that are used to listen to pending events. * Each is on a different port. This is for ip4 ports. @@ -265,6 +271,16 @@ struct outside_network* outside_network_create(struct comm_base* base, */ void outside_network_delete(struct outside_network* outnet); +/** + * Set secondary UDP buffer. Make sure it is not used during outside network + * callbacks. Such as the incoming network UDP buffer. Caller responsible + * for deletion. + * @param outnet: outside network. + * @param buf: buffer to use as secondary buffer. + */ +void outside_network_set_secondary_buffer(struct outside_network* outnet, + ldns_buffer* buf); + /** * Send UDP query, create pending answer. * Changes the ID for the query to be random and unique for that destination. diff --git a/testcode/fake_event.c b/testcode/fake_event.c index ade1e1091..88e6b94d8 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -668,6 +668,13 @@ outside_network_delete(struct outside_network* outnet) free(outnet); } +void +outside_network_set_secondary_buffer(struct outside_network* + ATTR_UNUSED(outnet), ldns_buffer* ATTR_UNUSED(buf)) +{ + /* nothing to do */ +} + struct pending* pending_udp_query(struct outside_network* outnet, ldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, -- 2.47.2