+static void iplist_filter_async(rbl_result_t *result, void *arg)
+{
+ filter_context_t *context = arg;
+ const filter_t *filter = context->current_filter;
+ const iplist_filter_t *data = filter->data;
+ iplist_async_data_t *async = context->contexts[filter_type];
+
+
+ if (*result != RBL_ERROR) {
+ async->error = false;
+ }
+ --async->awaited;
+
+ debug("got asynchronous request result for filter %s, rbl %d, still awaiting %d answers",
+ filter->name, (int)(result - array_ptr(async->results, 0)), async->awaited);
+
+ if (async->awaited == 0) {
+ filter_result_t res = HTK_FAIL;
+ if (async->error) {
+ res = HTK_ERROR;
+ } else {
+ for (uint32_t i = 0 ; i < array_len(data->host_offsets) ; ++i) {
+ int weight = array_elt(data->host_weights, i);
+
+ switch (array_elt(async->results, i)) {
+ case RBL_ASYNC:
+ crit("no more awaited answer but result is ASYNC");
+ abort();
+ case RBL_FOUND:
+ async->sum += weight;
+ break;
+ default:
+ break;
+ }
+ }
+ if (async->sum >= (uint32_t)data->hard_threshold) {
+ res = HTK_HARD_MATCH;
+ } else if (async->sum >= (uint32_t)data->soft_threshold) {
+ res = HTK_SOFT_MATCH;
+ }
+ }
+ debug("answering to filter %s", filter->name);
+ filter_post_async_result(context, res);
+ }
+}
+
+static filter_result_t iplist_filter(const filter_t *filter, const query_t *query,
+ filter_context_t *context)