diff options
author | Nick Mathewson <nickm@torproject.org> | 2007-12-18 23:45:19 +0000 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2007-12-18 23:45:19 +0000 |
commit | 076097281dde078149ed789cf3df0ef6ecce815d (patch) | |
tree | 5cbcb59faf2391139c370e916559399f9e8555a1 /src/or/geoip.c | |
parent | 74d05f4b2cf31d6bbda1a60b9a4d589cf62c9a51 (diff) | |
download | tor-076097281dde078149ed789cf3df0ef6ecce815d.tar.gz tor-076097281dde078149ed789cf3df0ef6ecce815d.zip |
r17239@catbus: nickm | 2007-12-18 16:57:02 -0500
Sort GeoIP results in descending order of IP counts.
svn:r12863
Diffstat (limited to 'src/or/geoip.c')
-rw-r--r-- | src/or/geoip.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/src/or/geoip.c b/src/or/geoip.c index 5ca9f9c2a4..0c82e97ea5 100644 --- a/src/or/geoip.c +++ b/src/or/geoip.c @@ -294,6 +294,27 @@ geoip_get_history_start(void) return client_history_starts; } +/* Helper type: used to sort results by value. */ +typedef struct c_hist_t { + char country[3]; + unsigned total; +} c_hist_t; + +/** Sorting helper: return -1, 1, or 0 based on comparison of two + * geoip_entry_t. Sort in descending order of total, and then by country + * code. */ +static int +_c_hist_compare(const void **_a, const void **_b) +{ + const c_hist_t *a = *_a, *b = *_b; + if (a->total > b->total) + return -1; + else if (a->total < b->total) + return 1; + else + return strcmp(a->country, b->country); +} + /** Return a newly allocated comma-separated string containing entries for all * the countries from which we've seen enough clients connect. The entry * format is cc=num where num is the number of IPs we've seen connecting from @@ -308,6 +329,7 @@ geoip_get_client_history(time_t now) if (client_history_starts < (now - 12*60*60)) { char buf[32]; smartlist_t *chunks = NULL; + smartlist_t *entries = NULL; int n_countries = geoip_get_n_countries(); int i; clientmap_entry_t **ent; @@ -321,19 +343,35 @@ geoip_get_client_history(time_t now) ++counts[country]; ++total; } + /* Don't record anything if we haven't seen enough IPs. */ if (total < MIN_IPS_TO_NOTE_ANYTHING) goto done; - chunks = smartlist_create(); + /* Make a list of c_hist_t */ + entries = smartlist_create(); for (i = 0; i < n_countries; ++i) { unsigned c = counts[i]; const char *countrycode; + c_hist_t *ent; + /* Only report a country if it has a minimum number of IPs. */ if (c >= MIN_IPS_TO_NOTE_COUNTRY) { c -= c % IP_GRANULARITY; countrycode = geoip_get_country_name(i); - tor_snprintf(buf, sizeof(buf), "%s=%u", countrycode, c); - smartlist_add(chunks, tor_strdup(buf)); + ent = tor_malloc(sizeof(c_hist_t)); + strlcpy(ent->country, countrycode, sizeof(ent->country)); + ent->total = c; + smartlist_add(entries, ent); } } + /* Sort entries. Note that we must do this _AFTER_ rounding, or else + * the sort order could leak info. */ + smartlist_sort(entries, _c_hist_compare); + + /* Build the result. */ + chunks = smartlist_create(); + SMARTLIST_FOREACH(entries, c_hist_t *, ch, { + tor_snprintf(buf, sizeof(buf), "%s=%u", ch->country, ch->total); + smartlist_add(chunks, tor_strdup(buf)); + }); result = smartlist_join_strings(chunks, ",", 0, NULL); done: tor_free(counts); @@ -341,6 +379,10 @@ geoip_get_client_history(time_t now) SMARTLIST_FOREACH(chunks, char *, c, tor_free(c)); smartlist_free(chunks); } + if (entries) { + SMARTLIST_FOREACH(entries, c_hist_t *, c, tor_free(c)); + smartlist_free(entries); + } } return result; } |