[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] r12863: Sort GeoIP results in descending order of IP counts. (in tor/trunk: . src/or)



Author: nickm
Date: 2007-12-18 18:45:19 -0500 (Tue, 18 Dec 2007)
New Revision: 12863

Modified:
   tor/trunk/
   tor/trunk/src/or/geoip.c
   tor/trunk/src/or/test.c
Log:
 r17239@catbus:  nickm | 2007-12-18 16:57:02 -0500
 Sort GeoIP results in descending order of IP counts.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r17239] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/or/geoip.c
===================================================================
--- tor/trunk/src/or/geoip.c	2007-12-18 23:04:49 UTC (rev 12862)
+++ tor/trunk/src/or/geoip.c	2007-12-18 23:45:19 UTC (rev 12863)
@@ -294,6 +294,27 @@
   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 @@
   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 @@
       ++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 @@
       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;
 }

Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c	2007-12-18 23:04:49 UTC (rev 12862)
+++ tor/trunk/src/or/test.c	2007-12-18 23:45:19 UTC (rev 12863)
@@ -3414,7 +3414,7 @@
     geoip_note_client_seen(i, now-7200);
   s = geoip_get_client_history(now+5*24*60*60);
   test_assert(s);
-  test_streq("ab=8,zz=16", s);
+  test_streq("zz=16,ab=8", s);
   tor_free(s);
 
   /* Now clear out all the zz observations. */