mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
	struct mesh_cb* r, struct timeval* start_time)
{
	int secure;
	char* reason = NULL;
	int was_ratelimited = m->s.was_ratelimited;
	/* bogus messages are not made into servfail, sec_status passed
	 * to the callback function */
	if(rep && rep->security == sec_status_secure)
		secure = 1;
	else	secure = 0;
	if(!rep && rcode == LDNS_RCODE_NOERROR)
		rcode = LDNS_RCODE_SERVFAIL;
	if(!rcode && (rep->security == sec_status_bogus ||
		rep->security == sec_status_secure_sentinel_fail)) {
		if(!(reason = errinf_to_str_bogus(&m->s)))
			rcode = LDNS_RCODE_SERVFAIL;
	}
	/* send the reply */
	if(rcode) {
		if(rcode == LDNS_RCODE_SERVFAIL) {
			if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
				rep, rcode, &r->edns, NULL, m->s.region, start_time))
					r->edns.opt_list_inplace_cb_out = NULL;
		} else {
			if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
				&r->edns, NULL, m->s.region, start_time))
					r->edns.opt_list_inplace_cb_out = NULL;
		}
		fptr_ok(fptr_whitelist_mesh_cb(r->cb));
		(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL,
			was_ratelimited);
	} else {
		size_t udp_size = r->edns.udp_size;
		sldns_buffer_clear(r->buf);
		r->edns.edns_version = EDNS_ADVERTISED_VERSION;
		r->edns.udp_size = EDNS_ADVERTISED_SIZE;
		r->edns.ext_rcode = 0;
		r->edns.bits &= EDNS_DO;

		if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
			LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) ||
			!reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 
			r->qflags, r->buf, 0, 1, 
			m->s.env->scratch, udp_size, &r->edns, 
			(int)(r->edns.bits & EDNS_DO), secure)) 
		{
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
				sec_status_unchecked, NULL, 0);
		} else {
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
				rep->security, reason, was_ratelimited);
		}
	}
	free(reason);
	log_assert(m->s.env->mesh->num_reply_addrs > 0);
	m->s.env->mesh->num_reply_addrs--;
}
mesh_do_callback(struct mesh_state* m, int rcode, struct reply_info* rep,
	struct mesh_cb* r, struct timeval* start_time)
{
	int secure;
	char* reason = NULL;
	int was_ratelimited = m->s.was_ratelimited;
	 
	if(rep && rep->security == sec_status_secure)
		secure = 1;
	else	secure = 0;
	if(!rep && rcode == LDNS_RCODE_NOERROR)
		rcode = LDNS_RCODE_SERVFAIL;
	if(!rcode && (rep->security == sec_status_bogus ||
		rep->security == sec_status_secure_sentinel_fail)) {
		if(!(reason = errinf_to_str_bogus(&m->s)))
			rcode = LDNS_RCODE_SERVFAIL;
	}
	 
	if(rcode) {
		if(rcode == LDNS_RCODE_SERVFAIL) {
			if(!inplace_cb_reply_servfail_call(m->s.env, &m->s.qinfo, &m->s,
				rep, rcode, &r->edns, NULL, m->s.region, start_time))
					r->edns.opt_list_inplace_cb_out = NULL;
		} else {
			if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep, rcode,
				&r->edns, NULL, m->s.region, start_time))
					r->edns.opt_list_inplace_cb_out = NULL;
		}
		fptr_ok(fptr_whitelist_mesh_cb(r->cb));
		(*r->cb)(r->cb_arg, rcode, r->buf, sec_status_unchecked, NULL,
			was_ratelimited);
	} else {
		size_t udp_size = r->edns.udp_size;
		sldns_buffer_clear(r->buf);
		r->edns.edns_version = EDNS_ADVERTISED_VERSION;
		r->edns.udp_size = EDNS_ADVERTISED_SIZE;
		r->edns.ext_rcode = 0;
		r->edns.bits &= EDNS_DO;

		if(!inplace_cb_reply_call(m->s.env, &m->s.qinfo, &m->s, rep,
			LDNS_RCODE_NOERROR, &r->edns, NULL, m->s.region, start_time) ||
			!reply_info_answer_encode(&m->s.qinfo, rep, r->qid, 
			r->qflags, r->buf, 0, 1, 
			m->s.env->scratch, udp_size, &r->edns, 
			(int)(r->edns.bits & EDNS_DO), secure)) 
		{
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_SERVFAIL, r->buf,
				sec_status_unchecked, NULL, 0);
		} else {
			fptr_ok(fptr_whitelist_mesh_cb(r->cb));
			(*r->cb)(r->cb_arg, LDNS_RCODE_NOERROR, r->buf,
				rep->security, reason, was_ratelimited);
		}
	}
	free(reason);
	log_assert(m->s.env->mesh->num_reply_addrs > 0);
	m->s.env->mesh->num_reply_addrs--;
}