[tor-commits] [tor/master] Write extra-info bridge-ip-transports lines.

nickm at torproject.org nickm at torproject.org
Thu Aug 15 16:16:46 UTC 2013


commit 05306ad74f48deef8903e281544d672efcfdebd1
Author: George Kadianakis <desnacked at riseup.net>
Date:   Mon Feb 11 20:52:28 2013 +0100

    Write extra-info bridge-ip-transports lines.
---
 src/or/geoip.c |  125 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/or/geoip.h |    1 +
 2 files changed, 123 insertions(+), 3 deletions(-)

diff --git a/src/or/geoip.c b/src/or/geoip.c
index b1efefd..dbb7ddd 100644
--- a/src/or/geoip.c
+++ b/src/or/geoip.c
@@ -782,6 +782,107 @@ geoip_change_dirreq_state(uint64_t dirreq_id, dirreq_type_t type,
   }
 }
 
+/** Return the bridge-ip-transports string that should be inserted in
+ *  our extra-info descriptor. Return NULL if the bridge-ip-transports
+ *  line should be empty.  */
+char *
+geoip_get_transport_history(void)
+{
+  unsigned granularity = IP_GRANULARITY;
+  /** String hash table <name of transport> -> <number of users>. */
+  strmap_t *transport_counts = strmap_new();
+  void *ptr;
+  intptr_t val;
+
+  /** Smartlist that contains copies of the names of the transports
+      that have been used. */
+  smartlist_t *transports_used = smartlist_new();
+
+  /* Special string to signify that no transport was used for this
+     connection. Pluggable transport names can't have symbols in their
+     names, so this string will never collide with a real transport. */
+  static const char* no_transport_str = "<OR>";
+
+  clientmap_entry_t **ent;
+  const char *transport_name = NULL;
+  smartlist_t *string_chunks = smartlist_new();
+  char *the_string = NULL;
+  int i = 0;
+
+  /* If we haven't seen any clients yet, return NULL. */
+  if (HT_EMPTY(&client_history))
+    goto done;
+
+  /** We do the following steps to form the transport history string:
+   *  a) Foreach client that uses a pluggable transport, we increase the
+   *  times that transport was used by one. If the client did not use
+   *  a transport, we increase the number of times someone connected
+   *  without obfuscation.
+   *  b) Foreach transport we observed, we write its transport history
+   *  string and push it to string_chunks. So, for example, if we've
+   *  seen 665 obfs2 clients, we write "obfs2=665".
+   *  c) We concatenate string_chunks to form the final string.
+   */
+
+  log_debug(LD_GENERAL,"Starting iteration for transport history. %d clients.",
+            HT_SIZE(&client_history));
+
+  /* Loop through all clients. */
+  HT_FOREACH(ent, clientmap, &client_history) {
+    transport_name = (*ent)->transport_name;
+    if (!transport_name)
+      transport_name = no_transport_str;
+
+    /* Increase the count for this transport name. */
+    ptr = strmap_get(transport_counts, transport_name);
+    val = (intptr_t)ptr;
+    val++;
+    ptr = (void*)val;
+    strmap_set(transport_counts, transport_name, ptr);
+
+    /* If it's the first time we see this transport, note it. */
+    if (!smartlist_contains_string(transports_used, transport_name))
+      smartlist_add(transports_used, tor_strdup(transport_name));
+
+    log_debug(LD_GENERAL, "Client from '%s' with transport '%s'. "
+              "I've now seen %d clients.",
+              safe_str_client(fmt_addr(&(*ent)->addr)),
+              transport_name ? transport_name : "<no transport>",
+              (int)val);
+  }
+
+  /* Sort the transport names (helps with unit testing). */
+  smartlist_sort_strings(transports_used);
+
+  /* Loop through all seen transports. */
+  SMARTLIST_FOREACH_BEGIN(transports_used, const char *, transport_name) {
+    void *transport_count_ptr = strmap_get(transport_counts, transport_name);
+    unsigned int transport_count = (uintptr_t) transport_count_ptr;
+    i++; /* counter so that we don't add a comma if it's the last transport. */
+
+    log_debug(LD_GENERAL, "We got %u clients with transport '%s'.",
+              transport_count, transport_name);
+
+    smartlist_add_asprintf(string_chunks, "%s=%u%s",
+                           transport_name,
+                           round_to_next_multiple_of(transport_count, granularity),
+                           i != smartlist_len(transports_used) ? "," : "");
+  } SMARTLIST_FOREACH_END(transport_name);
+
+  the_string = smartlist_join_strings(string_chunks, "", 0, NULL);
+
+  log_debug(LD_GENERAL, "Final bridge-ip-transports string: '%s'", the_string);
+
+ done:
+  strmap_free(transport_counts, NULL);
+  SMARTLIST_FOREACH(transports_used, char *, s, tor_free(s));
+  smartlist_free(transports_used);
+  SMARTLIST_FOREACH(string_chunks, char *, s, tor_free(s));
+  smartlist_free(string_chunks);
+
+  return the_string;
+}
+
 /** Return a newly allocated comma-separated string containing statistics
  * on network status downloads. The string contains the number of completed
  * requests, timeouts, and still running requests as well as the download
@@ -1202,6 +1303,8 @@ validate_bridge_stats(const char *stats_str, time_t now)
   const char *BRIDGE_STATS_END = "bridge-stats-end ";
   const char *BRIDGE_IPS = "bridge-ips ";
   const char *BRIDGE_IPS_EMPTY_LINE = "bridge-ips\n";
+  const char *BRIDGE_TRANSPORTS = "bridge-ip-transports ";
+  const char *BRIDGE_TRANSPORTS_EMPTY_LINE = "bridge-ip-transports\n";
   const char *tmp;
   time_t stats_end_time;
   int seconds;
@@ -1236,6 +1339,16 @@ validate_bridge_stats(const char *stats_str, time_t now)
       return 0;
   }
 
+  /* Parse: "bridge-ip-transports PT=N,PT=N,..." */
+  tmp = find_str_at_start_of_line(stats_str, BRIDGE_TRANSPORTS);
+  if (!tmp) {
+    /* Look if there is an empty "bridge-ip-transports" line */
+    tmp = find_str_at_start_of_line(stats_str, BRIDGE_TRANSPORTS_EMPTY_LINE);
+    if (!tmp)
+      return 0;
+  }
+
+
   return 1;
 }
 
@@ -1249,7 +1362,8 @@ static char *bridge_stats_extrainfo = NULL;
 char *
 geoip_format_bridge_stats(time_t now)
 {
-  char *out = NULL, *country_data = NULL, *ipver_data = NULL;
+  char *out = NULL;
+  char *country_data = NULL, *ipver_data = NULL, *transport_data = NULL;
   long duration = now - start_of_bridge_stats_interval;
   char written[ISO_TIME_LEN+1];
 
@@ -1260,16 +1374,20 @@ geoip_format_bridge_stats(time_t now)
 
   format_iso_time(written, now);
   geoip_get_client_history(GEOIP_CLIENT_CONNECT, &country_data, &ipver_data);
+  transport_data = geoip_get_transport_history();
 
   tor_asprintf(&out,
                "bridge-stats-end %s (%ld s)\n"
                "bridge-ips %s\n"
-               "bridge-ip-versions %s\n",
+               "bridge-ip-versions %s\n"
+               "bridge-ip-transports %s\n",
                written, duration,
                country_data ? country_data : "",
-               ipver_data ? ipver_data : "");
+               ipver_data ? ipver_data : "",
+               transport_data ? transport_data : "");
   tor_free(country_data);
   tor_free(ipver_data);
+  tor_free(transport_data);
 
   return out;
 }
@@ -1544,5 +1662,6 @@ geoip_free_all(void)
   }
 
   clear_geoip_db();
+  tor_free(bridge_stats_extrainfo);
 }
 
diff --git a/src/or/geoip.h b/src/or/geoip.h
index 19855c9..b9b53c3 100644
--- a/src/or/geoip.h
+++ b/src/or/geoip.h
@@ -34,6 +34,7 @@ void geoip_note_client_seen(geoip_client_action_t action,
 void geoip_remove_old_clients(time_t cutoff);
 
 void geoip_note_ns_response(geoip_ns_response_t response);
+char *geoip_get_transport_history(void);
 int geoip_get_client_history(geoip_client_action_t action,
                              char **country_str, char **ipver_str);
 char *geoip_get_request_history(void);





More information about the tor-commits mailing list