iter_filter_order(struct iter_env* iter_env, struct module_env* env,
	uint8_t* name, size_t namelen, uint16_t qtype, time_t now,
	struct delegpt* dp, int* selected_rtt, int open_target,
	struct sock_list* blacklist, time_t prefetch)
{
	int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth;
	int alllame = 0;
	size_t num_results;
	struct delegpt_addr* a, *n, *prev=NULL;

	/* fillup sel_rtt and find best rtt in the bunch */
	got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
		&low_rtt, blacklist, &num_results);
	if(got_num == 0)
		return 0;
	if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
		/* If all missing (or not fully resolved) targets are lame,
		 * then use the remaining lame address. */
		((delegpt_count_missing_targets(dp, &alllame) > 0 && !alllame) ||
		open_target > 0)) {
		verbose(VERB_ALGO, "Bad choices, trying to get more choice");
		return 0; /* we want more choice. The best choice is a bad one.
			     return 0 to force the caller to fetch more */
	}

	if(env->cfg->fast_server_permil != 0 && prefetch == 0 &&
		num_results > env->cfg->fast_server_num &&
		ub_random_max(env->rnd, 1000) < env->cfg->fast_server_permil) {
		/* the query is not prefetch, but for a downstream client,
		 * there are more servers available then the fastest N we want
		 * to choose from. Limit our choice to the fastest servers. */
		nth = nth_rtt(dp->result_list, num_results,
			env->cfg->fast_server_num);
		if(nth > 0) {
			rtt_band = nth - low_rtt;
			if(rtt_band > RTT_BAND)
				rtt_band = RTT_BAND;
		}
	}

	got_num = 0;
	a = dp->result_list;
	while(a) {
		/* skip unsuitable targets */
		if(a->sel_rtt == -1) {
			prev = a;
			a = a->next_result;
			continue;
		}
		/* classify the server address and determine what to do */
		swap_to_front = 0;
		if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
			got_num++;
			swap_to_front = 1;
		} else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
			got_num++;
			swap_to_front = 1;
		}
		/* swap to front if necessary, or move to next result */
		if(swap_to_front && prev) {
			n = a->next_result;
			prev->next_result = n;
			a->next_result = dp->result_list;
			dp->result_list = a;
			a = n;
		} else {
			prev = a;
			a = a->next_result;
		}
	}
	*selected_rtt = low_rtt;

	if (env->cfg->prefer_ip6) {
		int got_num6 = 0;
		int low_rtt6 = 0;
		int i;
		int attempt = -1; /* filter to make sure addresses have
		  less attempts on them than the first, to force round
		  robin when all the IPv6 addresses fail */
		int num4ok = 0; /* number ip4 at low attempt count */
		int num4_lowrtt = 0;
		prev = NULL;
		a = dp->result_list;
		for(i = 0; i < got_num; i++) {
			if(!a) break; /* robustness */
			swap_to_front = 0;
			if(a->addr.ss_family != AF_INET6 && attempt == -1) {
				/* if we only have ip4 at low attempt count,
				 * then ip6 is failing, and we need to
				 * select one of the remaining IPv4 addrs */
				attempt = a->attempts;
				num4ok++;
				num4_lowrtt = a->sel_rtt;
			} else if(a->addr.ss_family != AF_INET6 && attempt == a->attempts) {
				num4ok++;
				if(num4_lowrtt == 0 || a->sel_rtt < num4_lowrtt) {
					num4_lowrtt = a->sel_rtt;
				}
			}
			if(a->addr.ss_family == AF_INET6) {
				if(attempt == -1) {
					attempt = a->attempts;
				} else if(a->attempts > attempt) {
					break;
				}
				got_num6++;
				swap_to_front = 1;
				if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) {
					low_rtt6 = a->sel_rtt;
				}
			}
			/* swap to front if IPv6, or move to next result */
			if(swap_to_front && prev) {
				n = a->next_result;
				prev->next_result = n;
				a->next_result = dp->result_list;
				dp->result_list = a;
				a = n;
			} else {
				prev = a;
				a = a->next_result;
			}
		}
		if(got_num6 > 0) {
			got_num = got_num6;
			*selected_rtt = low_rtt6;
		} else if(num4ok > 0) {
			got_num = num4ok;
			*selected_rtt = num4_lowrtt;
		}
	} else if (env->cfg->prefer_ip4) {
		int got_num4 = 0;
		int low_rtt4 = 0;
		int i;
		int attempt = -1; /* filter to make sure addresses have
		  less attempts on them than the first, to force round
		  robin when all the IPv4 addresses fail */
		int num6ok = 0; /* number ip6 at low attempt count */
		int num6_lowrtt = 0;
		prev = NULL;
		a = dp->result_list;
		for(i = 0; i < got_num; i++) {
			if(!a) break; /* robustness */
			swap_to_front = 0;
			if(a->addr.ss_family != AF_INET && attempt == -1) {
				/* if we only have ip6 at low attempt count,
				 * then ip4 is failing, and we need to
				 * select one of the remaining IPv6 addrs */
				attempt = a->attempts;
				num6ok++;
				num6_lowrtt = a->sel_rtt;
			} else if(a->addr.ss_family != AF_INET && attempt == a->attempts) {
				num6ok++;
				if(num6_lowrtt == 0 || a->sel_rtt < num6_lowrtt) {
					num6_lowrtt = a->sel_rtt;
				}
			}
			if(a->addr.ss_family == AF_INET) {
				if(attempt == -1) {
					attempt = a->attempts;
				} else if(a->attempts > attempt) {
					break;
				}
				got_num4++;
				swap_to_front = 1;
				if(low_rtt4 == 0 || a->sel_rtt < low_rtt4) {
					low_rtt4 = a->sel_rtt;
				}
			}
			/* swap to front if IPv4, or move to next result */
			if(swap_to_front && prev) {
				n = a->next_result;
				prev->next_result = n;
				a->next_result = dp->result_list;
				dp->result_list = a;
				a = n;
			} else {
				prev = a;
				a = a->next_result;
			}
		}
		if(got_num4 > 0) {
			got_num = got_num4;
			*selected_rtt = low_rtt4;
		} else if(num6ok > 0) {
			got_num = num6ok;
			*selected_rtt = num6_lowrtt;
		}
	}
	return got_num;
}
iter_filter_order(struct iter_env* iter_env, struct module_env* env,
	uint8_t* name, size_t namelen, uint16_t qtype, time_t now,
	struct delegpt* dp, int* selected_rtt, int open_target,
	struct sock_list* blacklist, time_t prefetch)
{
	int got_num = 0, low_rtt = 0, swap_to_front, rtt_band = RTT_BAND, nth;
	int alllame = 0;
	size_t num_results;
	struct delegpt_addr* a, *n, *prev=NULL;

	 
	got_num = iter_fill_rtt(iter_env, env, name, namelen, qtype, now, dp,
		&low_rtt, blacklist, &num_results);
	if(got_num == 0)
		return 0;
	if(low_rtt >= USEFUL_SERVER_TOP_TIMEOUT &&
		 
		((delegpt_count_missing_targets(dp, &alllame) > 0 && !alllame) ||
		open_target > 0)) {
		verbose(VERB_ALGO, "Bad choices, trying to get more choice");
		return 0;  
	}

	if(env->cfg->fast_server_permil != 0 && prefetch == 0 &&
		num_results > env->cfg->fast_server_num &&
		ub_random_max(env->rnd, 1000) < env->cfg->fast_server_permil) {
		 
		nth = nth_rtt(dp->result_list, num_results,
			env->cfg->fast_server_num);
		if(nth > 0) {
			rtt_band = nth - low_rtt;
			if(rtt_band > RTT_BAND)
				rtt_band = RTT_BAND;
		}
	}

	got_num = 0;
	a = dp->result_list;
	while(a) {
		 
		if(a->sel_rtt == -1) {
			prev = a;
			a = a->next_result;
			continue;
		}
		 
		swap_to_front = 0;
		if(a->sel_rtt >= low_rtt && a->sel_rtt - low_rtt <= rtt_band) {
			got_num++;
			swap_to_front = 1;
		} else if(a->sel_rtt<low_rtt && low_rtt-a->sel_rtt<=rtt_band) {
			got_num++;
			swap_to_front = 1;
		}
		 
		if(swap_to_front && prev) {
			n = a->next_result;
			prev->next_result = n;
			a->next_result = dp->result_list;
			dp->result_list = a;
			a = n;
		} else {
			prev = a;
			a = a->next_result;
		}
	}
	*selected_rtt = low_rtt;

	if (env->cfg->prefer_ip6) {
		int got_num6 = 0;
		int low_rtt6 = 0;
		int i;
		int attempt = -1;  
		int num4ok = 0;  
		int num4_lowrtt = 0;
		prev = NULL;
		a = dp->result_list;
		for(i = 0; i < got_num; i++) {
			if(!a) break;  
			swap_to_front = 0;
			if(a->addr.ss_family != AF_INET6 && attempt == -1) {
				 
				attempt = a->attempts;
				num4ok++;
				num4_lowrtt = a->sel_rtt;
			} else if(a->addr.ss_family != AF_INET6 && attempt == a->attempts) {
				num4ok++;
				if(num4_lowrtt == 0 || a->sel_rtt < num4_lowrtt) {
					num4_lowrtt = a->sel_rtt;
				}
			}
			if(a->addr.ss_family == AF_INET6) {
				if(attempt == -1) {
					attempt = a->attempts;
				} else if(a->attempts > attempt) {
					break;
				}
				got_num6++;
				swap_to_front = 1;
				if(low_rtt6 == 0 || a->sel_rtt < low_rtt6) {
					low_rtt6 = a->sel_rtt;
				}
			}
			 
			if(swap_to_front && prev) {
				n = a->next_result;
				prev->next_result = n;
				a->next_result = dp->result_list;
				dp->result_list = a;
				a = n;
			} else {
				prev = a;
				a = a->next_result;
			}
		}
		if(got_num6 > 0) {
			got_num = got_num6;
			*selected_rtt = low_rtt6;
		} else if(num4ok > 0) {
			got_num = num4ok;
			*selected_rtt = num4_lowrtt;
		}
	} else if (env->cfg->prefer_ip4) {
		int got_num4 = 0;
		int low_rtt4 = 0;
		int i;
		int attempt = -1;  
		int num6ok = 0;  
		int num6_lowrtt = 0;
		prev = NULL;
		a = dp->result_list;
		for(i = 0; i < got_num; i++) {
			if(!a) break;  
			swap_to_front = 0;
			if(a->addr.ss_family != AF_INET && attempt == -1) {
				 
				attempt = a->attempts;
				num6ok++;
				num6_lowrtt = a->sel_rtt;
			} else if(a->addr.ss_family != AF_INET && attempt == a->attempts) {
				num6ok++;
				if(num6_lowrtt == 0 || a->sel_rtt < num6_lowrtt) {
					num6_lowrtt = a->sel_rtt;
				}
			}
			if(a->addr.ss_family == AF_INET) {
				if(attempt == -1) {
					attempt = a->attempts;
				} else if(a->attempts > attempt) {
					break;
				}
				got_num4++;
				swap_to_front = 1;
				if(low_rtt4 == 0 || a->sel_rtt < low_rtt4) {
					low_rtt4 = a->sel_rtt;
				}
			}
			 
			if(swap_to_front && prev) {
				n = a->next_result;
				prev->next_result = n;
				a->next_result = dp->result_list;
				dp->result_list = a;
				a = n;
			} else {
				prev = a;
				a = a->next_result;
			}
		}
		if(got_num4 > 0) {
			got_num = got_num4;
			*selected_rtt = low_rtt4;
		} else if(num6ok > 0) {
			got_num = num6ok;
			*selected_rtt = num6_lowrtt;
		}
	}
	return got_num;
}