mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-28 14:23:30 +01:00
Write extra-info bridge-ip-transports lines.
This commit is contained in:
parent
e765d6ed84
commit
05306ad74f
125
src/or/geoip.c
125
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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user