mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2025-02-25 07:07:52 +01:00
Merge remote-tracking branch 'origin/maint-0.2.2'
This commit is contained in:
commit
07ab483e62
4 changed files with 101 additions and 81 deletions
4
changes/feature2711
Normal file
4
changes/feature2711
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
o Minor features
|
||||||
|
- Export GeoIP information on usage to bridge controller even if we have
|
||||||
|
not yet been running for 24 hours.
|
||||||
|
|
|
@ -1851,12 +1851,12 @@ getinfo_helper_events(control_connection_t *control_conn,
|
||||||
"information", question);
|
"information", question);
|
||||||
}
|
}
|
||||||
} else if (!strcmp(question, "status/clients-seen")) {
|
} else if (!strcmp(question, "status/clients-seen")) {
|
||||||
const char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL));
|
char *bridge_stats = geoip_get_bridge_stats_controller(time(NULL));
|
||||||
if (!bridge_stats) {
|
if (!bridge_stats) {
|
||||||
*errmsg = "No bridge-client stats available";
|
*errmsg = "No bridge-client stats available";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
*answer = tor_strdup(bridge_stats);
|
*answer = bridge_stats;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
172
src/or/geoip.c
172
src/or/geoip.c
|
@ -1103,14 +1103,14 @@ geoip_bridge_stats_term(void)
|
||||||
start_of_bridge_stats_interval = 0;
|
start_of_bridge_stats_interval = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Parse the bridge statistics as they are written to extra-info
|
/** Validate a bridge statistics string as it would be written to a
|
||||||
* descriptors for being returned to controller clients. Return the
|
* current extra-info descriptor. Return 1 if the string is valid and
|
||||||
* controller string if successful, or NULL otherwise. */
|
* recent enough, or 0 otherwise. */
|
||||||
static char *
|
static int
|
||||||
parse_bridge_stats_controller(const char *stats_str, time_t now)
|
validate_bridge_stats(const char *stats_str, time_t now)
|
||||||
{
|
{
|
||||||
char stats_end_str[ISO_TIME_LEN+1], stats_start_str[ISO_TIME_LEN+1],
|
char stats_end_str[ISO_TIME_LEN+1], stats_start_str[ISO_TIME_LEN+1],
|
||||||
*controller_str, *eos, *eol, *summary;
|
*eos;
|
||||||
|
|
||||||
const char *BRIDGE_STATS_END = "bridge-stats-end ";
|
const char *BRIDGE_STATS_END = "bridge-stats-end ";
|
||||||
const char *BRIDGE_IPS = "bridge-ips ";
|
const char *BRIDGE_IPS = "bridge-ips ";
|
||||||
|
@ -1124,63 +1124,90 @@ parse_bridge_stats_controller(const char *stats_str, time_t now)
|
||||||
"bridge-stats-end YYYY-MM-DD HH:MM:SS (N s)" */
|
"bridge-stats-end YYYY-MM-DD HH:MM:SS (N s)" */
|
||||||
tmp = find_str_at_start_of_line(stats_str, BRIDGE_STATS_END);
|
tmp = find_str_at_start_of_line(stats_str, BRIDGE_STATS_END);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return 0;
|
||||||
tmp += strlen(BRIDGE_STATS_END);
|
tmp += strlen(BRIDGE_STATS_END);
|
||||||
|
|
||||||
if (strlen(tmp) < ISO_TIME_LEN + 6)
|
if (strlen(tmp) < ISO_TIME_LEN + 6)
|
||||||
return NULL;
|
return 0;
|
||||||
strlcpy(stats_end_str, tmp, sizeof(stats_end_str));
|
strlcpy(stats_end_str, tmp, sizeof(stats_end_str));
|
||||||
if (parse_iso_time(stats_end_str, &stats_end_time) < 0)
|
if (parse_iso_time(stats_end_str, &stats_end_time) < 0)
|
||||||
return NULL;
|
return 0;
|
||||||
if (stats_end_time < now - (25*60*60) ||
|
if (stats_end_time < now - (25*60*60) ||
|
||||||
stats_end_time > now + (1*60*60))
|
stats_end_time > now + (1*60*60))
|
||||||
return NULL;
|
return 0;
|
||||||
seconds = (int)strtol(tmp + ISO_TIME_LEN + 2, &eos, 10);
|
seconds = (int)strtol(tmp + ISO_TIME_LEN + 2, &eos, 10);
|
||||||
if (!eos || seconds < 23*60*60)
|
if (!eos || seconds < 23*60*60)
|
||||||
return NULL;
|
return 0;
|
||||||
format_iso_time(stats_start_str, stats_end_time - seconds);
|
format_iso_time(stats_start_str, stats_end_time - seconds);
|
||||||
|
|
||||||
/* Parse: "bridge-ips CC=N,CC=N,..." */
|
/* Parse: "bridge-ips CC=N,CC=N,..." */
|
||||||
tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS);
|
tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS);
|
||||||
if (tmp) {
|
if (!tmp) {
|
||||||
tmp += strlen(BRIDGE_IPS);
|
|
||||||
tmp = eat_whitespace_no_nl(tmp);
|
|
||||||
eol = strchr(tmp, '\n');
|
|
||||||
if (eol)
|
|
||||||
summary = tor_strndup(tmp, eol-tmp);
|
|
||||||
else
|
|
||||||
summary = tor_strdup(tmp);
|
|
||||||
} else {
|
|
||||||
/* Look if there is an empty "bridge-ips" line */
|
/* Look if there is an empty "bridge-ips" line */
|
||||||
tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS_EMPTY_LINE);
|
tmp = find_str_at_start_of_line(stats_str, BRIDGE_IPS_EMPTY_LINE);
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return 0;
|
||||||
summary = tor_strdup("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tor_asprintf(&controller_str,
|
return 1;
|
||||||
"TimeStarted=\"%s\" CountrySummary=%s",
|
|
||||||
stats_start_str, summary);
|
|
||||||
tor_free(summary);
|
|
||||||
return controller_str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Most recent bridge statistics formatted to be written to extra-info
|
/** Most recent bridge statistics formatted to be written to extra-info
|
||||||
* descriptors. */
|
* descriptors. */
|
||||||
static char *bridge_stats_extrainfo = NULL;
|
static char *bridge_stats_extrainfo = NULL;
|
||||||
|
|
||||||
/** Most recent bridge statistics formatted to be returned to controller
|
/** Return a newly allocated string holding our bridge usage stats by country
|
||||||
* clients. */
|
* in a format suitable for inclusion in an extrainfo document. Return NULL on
|
||||||
static char *bridge_stats_controller = NULL;
|
* failure. */
|
||||||
|
static char *
|
||||||
|
format_bridge_stats_extrainfo(time_t now)
|
||||||
|
{
|
||||||
|
char *out = NULL, *data = NULL;
|
||||||
|
long duration = now - start_of_bridge_stats_interval;
|
||||||
|
char written[ISO_TIME_LEN+1];
|
||||||
|
|
||||||
|
if (duration < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
format_iso_time(written, now);
|
||||||
|
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
|
||||||
|
|
||||||
|
tor_asprintf(&out,
|
||||||
|
"bridge-stats-end %s (%ld s)\n"
|
||||||
|
"bridge-ips %s\n",
|
||||||
|
written, duration,
|
||||||
|
data ? data : "");
|
||||||
|
tor_free(data);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return a newly allocated string holding our bridge usage stats by country
|
||||||
|
* in a format suitable for the answer to a controller request. Return NULL on
|
||||||
|
* failure. */
|
||||||
|
static char *
|
||||||
|
format_bridge_stats_controller(time_t now)
|
||||||
|
{
|
||||||
|
char *out = NULL, *data = NULL;
|
||||||
|
char started[ISO_TIME_LEN+1];
|
||||||
|
(void) now;
|
||||||
|
|
||||||
|
format_iso_time(started, start_of_bridge_stats_interval);
|
||||||
|
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
|
||||||
|
|
||||||
|
tor_asprintf(&out,
|
||||||
|
"TimeStarted=\"%s\" CountrySummary=%s",
|
||||||
|
started, data ? data : "");
|
||||||
|
tor_free(data);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
/** Write bridge statistics to $DATADIR/stats/bridge-stats and return
|
/** Write bridge statistics to $DATADIR/stats/bridge-stats and return
|
||||||
* when we should next try to write statistics. */
|
* when we should next try to write statistics. */
|
||||||
time_t
|
time_t
|
||||||
geoip_bridge_stats_write(time_t now)
|
geoip_bridge_stats_write(time_t now)
|
||||||
{
|
{
|
||||||
char *statsdir = NULL, *filename = NULL, *data = NULL,
|
char *filename = NULL, *val = NULL, *statsdir = NULL;
|
||||||
written[ISO_TIME_LEN+1], *out = NULL, *controller_str;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
/* Check if 24 hours have passed since starting measurements. */
|
/* Check if 24 hours have passed since starting measurements. */
|
||||||
if (now < start_of_bridge_stats_interval + WRITE_STATS_INTERVAL)
|
if (now < start_of_bridge_stats_interval + WRITE_STATS_INTERVAL)
|
||||||
|
@ -1189,64 +1216,54 @@ geoip_bridge_stats_write(time_t now)
|
||||||
/* Discard all items in the client history that are too old. */
|
/* Discard all items in the client history that are too old. */
|
||||||
geoip_remove_old_clients(start_of_bridge_stats_interval);
|
geoip_remove_old_clients(start_of_bridge_stats_interval);
|
||||||
|
|
||||||
|
/* Generate formatted string */
|
||||||
|
val = format_bridge_stats_extrainfo(now);
|
||||||
|
if (val == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Update the stored value. */
|
||||||
|
tor_free(bridge_stats_extrainfo);
|
||||||
|
bridge_stats_extrainfo = val;
|
||||||
|
start_of_bridge_stats_interval = now;
|
||||||
|
|
||||||
|
/* Write it to disk. */
|
||||||
statsdir = get_datadir_fname("stats");
|
statsdir = get_datadir_fname("stats");
|
||||||
if (check_private_dir(statsdir, CPD_CREATE) < 0)
|
if (check_private_dir(statsdir, CPD_CREATE) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
filename = get_datadir_fname2("stats", "bridge-stats");
|
filename = get_datadir_fname2("stats", "bridge-stats");
|
||||||
data = geoip_get_client_history(GEOIP_CLIENT_CONNECT);
|
|
||||||
format_iso_time(written, now);
|
write_str_to_file(filename, bridge_stats_extrainfo, 0);
|
||||||
len = strlen("bridge-stats-end (999999 s)\nbridge-ips \n") +
|
|
||||||
ISO_TIME_LEN + (data ? strlen(data) : 0) + 42;
|
/* Tell the controller, "hey, there are clients!" */
|
||||||
out = tor_malloc(len);
|
{
|
||||||
if (tor_snprintf(out, len, "bridge-stats-end %s (%u s)\nbridge-ips %s\n",
|
char *controller_str = format_bridge_stats_controller(now);
|
||||||
written, (unsigned) (now - start_of_bridge_stats_interval),
|
if (controller_str)
|
||||||
data ? data : "") < 0)
|
control_event_clients_seen(controller_str);
|
||||||
goto done;
|
tor_free(controller_str);
|
||||||
write_str_to_file(filename, out, 0);
|
}
|
||||||
controller_str = parse_bridge_stats_controller(out, now);
|
|
||||||
if (!controller_str)
|
|
||||||
goto done;
|
|
||||||
start_of_bridge_stats_interval = now;
|
|
||||||
tor_free(bridge_stats_extrainfo);
|
|
||||||
tor_free(bridge_stats_controller);
|
|
||||||
bridge_stats_extrainfo = out;
|
|
||||||
out = NULL;
|
|
||||||
bridge_stats_controller = controller_str;
|
|
||||||
control_event_clients_seen(controller_str);
|
|
||||||
done:
|
done:
|
||||||
tor_free(filename);
|
tor_free(filename);
|
||||||
tor_free(statsdir);
|
tor_free(statsdir);
|
||||||
tor_free(data);
|
|
||||||
tor_free(out);
|
return start_of_bridge_stats_interval + WRITE_STATS_INTERVAL;
|
||||||
return start_of_bridge_stats_interval +
|
|
||||||
WRITE_STATS_INTERVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Try to load the most recent bridge statistics from disk, unless we
|
/** Try to load the most recent bridge statistics from disk, unless we
|
||||||
* have finished a measurement interval lately. */
|
* have finished a measurement interval lately, and check whether they
|
||||||
|
* are still recent enough. */
|
||||||
static void
|
static void
|
||||||
load_bridge_stats(time_t now)
|
load_bridge_stats(time_t now)
|
||||||
{
|
{
|
||||||
char *statsdir, *fname=NULL, *contents, *controller_str;
|
char *fname, *contents;
|
||||||
if (bridge_stats_extrainfo)
|
if (bridge_stats_extrainfo)
|
||||||
return;
|
return;
|
||||||
statsdir = get_datadir_fname("stats");
|
|
||||||
if (check_private_dir(statsdir, CPD_CREATE) < 0)
|
|
||||||
goto done;
|
|
||||||
fname = get_datadir_fname2("stats", "bridge-stats");
|
fname = get_datadir_fname2("stats", "bridge-stats");
|
||||||
contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
|
contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
|
||||||
if (contents) {
|
if (contents && validate_bridge_stats(contents, now))
|
||||||
controller_str = parse_bridge_stats_controller(contents, now);
|
bridge_stats_extrainfo = contents;
|
||||||
if (controller_str) {
|
|
||||||
bridge_stats_extrainfo = contents;
|
|
||||||
bridge_stats_controller = controller_str;
|
|
||||||
} else {
|
|
||||||
tor_free(contents);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
done:
|
|
||||||
tor_free(fname);
|
tor_free(fname);
|
||||||
tor_free(statsdir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return most recent bridge statistics for inclusion in extra-info
|
/** Return most recent bridge statistics for inclusion in extra-info
|
||||||
|
@ -1258,13 +1275,12 @@ geoip_get_bridge_stats_extrainfo(time_t now)
|
||||||
return bridge_stats_extrainfo;
|
return bridge_stats_extrainfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return most recent bridge statistics to be returned to controller
|
/** Return a new string containing the recent bridge statistics to be returned
|
||||||
* clients, or NULL if we don't have recent bridge statistics. */
|
* to controller clients, or NULL if we don't have any bridge statistics. */
|
||||||
const char *
|
char *
|
||||||
geoip_get_bridge_stats_controller(time_t now)
|
geoip_get_bridge_stats_controller(time_t now)
|
||||||
{
|
{
|
||||||
load_bridge_stats(now);
|
return format_bridge_stats_controller(now);
|
||||||
return bridge_stats_controller;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Start time of entry stats or 0 if we're not collecting entry
|
/** Start time of entry stats or 0 if we're not collecting entry
|
||||||
|
|
|
@ -52,7 +52,7 @@ void geoip_bridge_stats_init(time_t now);
|
||||||
time_t geoip_bridge_stats_write(time_t now);
|
time_t geoip_bridge_stats_write(time_t now);
|
||||||
void geoip_bridge_stats_term(void);
|
void geoip_bridge_stats_term(void);
|
||||||
const char *geoip_get_bridge_stats_extrainfo(time_t);
|
const char *geoip_get_bridge_stats_extrainfo(time_t);
|
||||||
const char *geoip_get_bridge_stats_controller(time_t);
|
char *geoip_get_bridge_stats_controller(time_t);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue