Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Support srv weight properly
Baptiste Daroussin committed 12 years ago
commit 7319cf6cd03bffc2275a033ac24a7c1257ce1954
parent 549f2df
2 files changed +64 -13
modified libpkg/dns_utils.c
@@ -41,7 +41,7 @@ typedef union {
} query_t;

static int
-
srv_cmp_priotity(const void *a, const void *b)
+
srv_cmp_priority(const void *a, const void *b)
{
	struct dns_srvinfo *da = *(struct dns_srvinfo **)a;
	struct dns_srvinfo *db = *(struct dns_srvinfo **)b;
@@ -49,6 +49,50 @@ srv_cmp_priotity(const void *a, const void *b)
	return ((da->priority > db->priority) - (da->priority < db->priority));
}

+
static int
+
srv_final_cmp(const void *a, const void *b)
+
{
+
	struct dns_srvinfo *da = *(struct dns_srvinfo **)a;
+
	struct dns_srvinfo *db = *(struct dns_srvinfo **)b;
+
	int res;
+

+
	res = ((da->priority > db->priority) - (da->priority < db->priority));
+
	if (res == 0)
+
		res = ((db->finalweight > da->finalweight) - (db->finalweight < da->finalweight));
+

+
	return (res);
+
}
+

+
static void
+
compute_weight(struct dns_srvinfo **d, int first, int last)
+
{
+
	int i, j;
+
	int totalweight = 0;
+
	int *chosen = malloc(sizeof(int) * last - first + 1);
+

+
	for (i = 0; i <= last; i++)
+
		totalweight += d[i]->weight;
+

+
	if (totalweight == 0)
+
		return;
+

+
	for (i = 0; i <= last; i++) {
+
		for (;;) {
+
			chosen[i] = random() % (d[i]->weight * 100 / totalweight);
+
			for (j = 0; j < i; j++) {
+
				if (chosen[i] == chosen[j])
+
					break;
+
			}
+
			if (j == i) {
+
				d[i]->finalweight = chosen[i];
+
				break;
+
			}
+
		}
+
	}
+

+
	free(chosen);
+
}
+

struct dns_srvinfo *
dns_getsrvinfo(const char *zone)
{
@@ -57,7 +101,8 @@ dns_getsrvinfo(const char *zone)
	int len, qdcount, ancount, n, i;
	struct dns_srvinfo **res, *first;
	unsigned char *end, *p;
-
	unsigned int type, class, ttl, priority, weight, port, totalweight;
+
	unsigned int type, class, ttl, priority, weight, port;
+
	int f, l;

	if ((len = res_query(zone, C_IN, T_SRV, q.buf, sizeof(q.buf))) == -1 ||
	    len < (int)sizeof(HEADER))
@@ -83,7 +128,6 @@ dns_getsrvinfo(const char *zone)
	n = 0;
	while (ancount > 0 && p < end) {
		ancount--;
-
		totalweight = 0;
		len = dn_expand(q.buf, end, p, host, MAXHOSTNAMELEN);
		if (len < 0) {
			for (i = 0; i < n; i++)
@@ -132,20 +176,27 @@ dns_getsrvinfo(const char *zone)
		res[n]->next = NULL;
		strlcpy(res[n]->host, host, MAXHOSTNAMELEN);

-
		for (i = 0; i < n -1; i++) {
-
			if (res[i]->priority == priority) {
-
				if (totalweight == 0)
-
					totalweight = res[i]->totalweight + weight;
-
				res[i]->totalweight = totalweight;
-
			}
-
		}
-

		p += len;
		n++;
	}

	/* order by priority */
-
	qsort(res, n, sizeof(res[0]), srv_cmp_priotity);
+
	qsort(res, n, sizeof(res[0]), srv_cmp_priority);
+

+
	priority = 0;
+
	f = 0;
+
	l = 0;
+
	for (i = 0; i < n; i++) {
+
		if (res[i]->priority != priority) {
+
			if (f != l)
+
				compute_weight(res, f, l);
+
			f = i;
+
			priority = res[i]->priority;
+
		}
+
		l = i;
+
	}
+

+
	qsort(res, n, sizeof(res[0]), srv_final_cmp);

	for (i = 0; i < n - 1; i++)
		res[i]->next = res[i + 1];
modified libpkg/private/utils.h
@@ -61,7 +61,7 @@ struct dns_srvinfo {
	unsigned int priority;
	unsigned int weight;
	unsigned int port;
-
	unsigned int totalweight;
+
	unsigned int finalweight;
	char host[MAXHOSTNAMELEN];
	struct dns_srvinfo *next;
};