worker->rndstate) != 0;
}
+/** compare outbound entry qstates */
+static int
+outbound_entry_compare(void* a, void* b)
+{
+ struct outbound_entry* e1 = (struct outbound_entry*)a;
+ struct outbound_entry* e2 = (struct outbound_entry*)b;
+ if(e1->qstate == e2->qstate)
+ return 1;
+ return 0;
+}
+
struct outbound_entry*
worker_send_query(uint8_t* qname, size_t qnamelen, uint16_t qtype,
uint16_t qclass, uint16_t flags, int dnssec,
e->qstate = q;
e->qsent = outnet_serviced_query(worker->back, qname,
qnamelen, qtype, qclass, flags, dnssec, addr, addrlen,
- worker_handle_service_reply, e, worker->back->udp_buff);
+ worker_handle_service_reply, e, worker->back->udp_buff,
+ &outbound_entry_compare);
if(!e->qsent) {
free(e);
return NULL;
+18 June 2007: Wouter
+ - same, move subqueries to slumber list when first has resolved.
+ - fixup last fix for duplicate callbacks.
+
15 June 2007: Wouter
- if a query asks to be notified of the same serviced query result
multiple times, this will succeed. Only one callback will happen;
iq->num_current_queries);
return 0;
}
+ /* move other targets to slumber list */
+ if(iq->num_target_queries>0) {
+ (*qstate->env->remove_subqueries)(qstate);
+ }
/* We have a valid target. */
log_nametypeclass(VERB_DETAIL, "sending query:", qstate->qinfo.qname,
/** find callback in list */
static struct service_callback*
-callback_list_find(struct serviced_query* sq, void* cb_arg)
+callback_list_find(struct serviced_query* sq, void* cb_arg,
+ int (*arg_compare)(void*,void*))
{
struct service_callback* p;
for(p = sq->cblist; p; p = p->next) {
- if(p->cb_arg == cb_arg)
+ if(arg_compare(p->cb_arg, cb_arg))
return p;
}
return NULL;
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback,
- void* callback_arg, ldns_buffer* buff)
+ void* callback_arg, ldns_buffer* buff,
+ int (*arg_compare)(void*,void*))
{
struct serviced_query* sq;
struct service_callback* cb;
sq = lookup_serviced(outnet, buff, dnssec, addr, addrlen);
if(sq) {
/* see if it is a duplicate notification request for cb_arg */
- if((cb = callback_list_find(sq, callback_arg))) {
+ if((cb = callback_list_find(sq, callback_arg, arg_compare))) {
return sq;
}
}
* @param addr: to which server to send the query.
* @param addrlen: length of addr.
* @param buff: scratch buffer to create query contents in. Empty on exit.
+ * @param arg_compare: function to compare callback args, return true if
+ * identical. It is given the callback_arg and args that are listed.
* @return 0 on error, or pointer to serviced query that is used to answer
* this serviced query may be shared with other callbacks as well.
*/
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback,
- void* callback_arg, ldns_buffer* buff);
+ void* callback_arg, ldns_buffer* buff,
+ int (*arg_compare)(void*,void*));
/**
* Remove service query callback.
uint8_t* qname, size_t qnamelen, uint16_t qtype, uint16_t qclass,
uint16_t flags, int dnssec, struct sockaddr_storage* addr,
socklen_t addrlen, comm_point_callback_t* callback,
- void* callback_arg, ldns_buffer* ATTR_UNUSED(buff))
+ void* callback_arg, ldns_buffer* ATTR_UNUSED(buff),
+ int (*arg_compare)(void*,void*))
{
struct replay_runtime* runtime = (struct replay_runtime*)outnet->base;
struct fake_pending* pend = (struct fake_pending*)calloc(1,
sizeof(struct fake_pending));
ldns_status status;
+ (void)arg_compare;
log_assert(pend);
/* create packet with EDNS */