summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2006-02-06 05:04:27 +0000
committerNick Mathewson <nickm@torproject.org>2006-02-06 05:04:27 +0000
commite5a574ce2e80e4fc202f2ea35b5bb6c986aab025 (patch)
tree2481609cd213a93b887cf80599f74b353045fff0
parent2bb4fd24de054685ba005177e7359ad1eb087804 (diff)
downloadtor-e5a574ce2e80e4fc202f2ea35b5bb6c986aab025.tar.gz
tor-e5a574ce2e80e4fc202f2ea35b5bb6c986aab025.zip
Move "sort list of versions" logic into routerparse.c; make version-checking code say which versions it would have accepted. (not tested.)
svn:r5927
-rw-r--r--src/or/dirserv.c26
-rw-r--r--src/or/or.h1
-rw-r--r--src/or/routerlist.c79
-rw-r--r--src/or/routerparse.c31
4 files changed, 106 insertions, 31 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 6fffe6c257..a9c542a7b4 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -761,30 +761,6 @@ list_server_status(smartlist_t *routers, char **router_status_out)
return 0;
}
-/** Helper: Given pointers to two strings describing tor versions, return -1
- * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
- * Used to sort a list of versions. */
-static int
-_compare_tor_version_str_ptr(const void **_a, const void **_b)
-{
- const char *a = *_a, *b = *_b;
- int ca, cb;
- tor_version_t va, vb;
- ca = tor_version_parse(a, &va);
- cb = tor_version_parse(b, &vb);
- /* If they both parse, compare them. */
- if (!ca && !cb)
- return tor_version_compare(&va,&vb);
- /* If one parses, it comes first. */
- if (!ca && cb)
- return -1;
- if (ca && !cb)
- return 1;
- /* If neither parses, compare strings. Also, the directory server admin
- ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
- return strcmp(a,b);
-}
-
/* Given a (possibly empty) list of config_line_t, each line of which contains
* a list of comma-separated version numbers surrounded by optional space,
* allocate and return a new string containing the version numbers, in order,
@@ -800,7 +776,7 @@ format_versions_list(config_line_t *ln)
smartlist_split_string(versions, ln->value, ",",
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
}
- smartlist_sort(versions, _compare_tor_version_str_ptr);
+ sort_version_list(versions);
result = smartlist_join_strings(versions,",",0,NULL);
SMARTLIST_FOREACH(versions,char *,s,tor_free(s));
smartlist_free(versions);
diff --git a/src/or/or.h b/src/or/or.h
index f48507fc66..75642a0639 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2391,6 +2391,7 @@ version_status_t version_status_join(version_status_t a, version_status_t b);
int tor_version_parse(const char *s, tor_version_t *out);
int tor_version_as_new_as(const char *platform, const char *cutoff);
int tor_version_compare(tor_version_t *a, tor_version_t *b);
+void sort_version_list(smartlist_t *lst);
void assert_addr_policy_ok(addr_policy_t *t);
networkstatus_t *networkstatus_parse_from_string(const char *s);
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 935dc91b13..61ff58f871 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -2662,6 +2662,69 @@ networkstatus_get_by_digest(const char *digest)
return NULL;
}
+/** We believe networkstatuses more recent than this when they tell us that
+ * our server is broken, invalid, obsolete, etc. */
+#define SELF_OPINION_INTERVAL 90*60
+
+/** Return a string naming the versions of Tor recommended by
+ * at least n_needed versioning networkstatuses */
+static char *
+compute_recommended_versions(time_t now, int client)
+{
+ int n_seen;
+ char *current;
+ smartlist_t *combined, *recommended;
+ int n_recent;
+ char *result;
+
+ if (!networkstatus_list)
+ return tor_strdup("<none>");
+
+ combined = smartlist_create();
+ n_recent = 0;
+ SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
+ {
+ const char *vers;
+ if (! ns->recommends_versions)
+ continue;
+ if (ns->received_on + SELF_OPINION_INTERVAL < now)
+ continue;
+ n_recent++;
+ vers = client ? ns->client_versions : ns->server_versions;
+ if (!vers)
+ continue;
+ smartlist_split_string(combined, vers, ",",
+ SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
+ });
+
+ sort_version_list(combined);
+
+ current = NULL;
+ n_seen = 0;
+ recommended = smartlist_create();
+ SMARTLIST_FOREACH(combined, char *, cp,
+ {
+ if (current && !strcmp(cp, current)) {
+ ++n_seen;
+ } else {
+ if (n_seen >= n_recent/2 && current)
+ smartlist_add(recommended, current);
+ n_seen = 0;
+ current = cp;
+ }
+ });
+ if (n_seen >= n_recent/2 && current)
+ smartlist_add(recommended, current);
+
+ result = smartlist_join_strings(recommended, ", ", 0, NULL);
+
+ SMARTLIST_FOREACH(combined, char *, cp, tor_free(cp));
+ smartlist_free(combined);
+ smartlist_free(recommended);
+
+ return result;
+}
+
/** If the network-status list has changed since the last time we called this
* function, update the status of every routerinfo from the network-status
* list.
@@ -2669,7 +2732,6 @@ networkstatus_get_by_digest(const char *digest)
void
routers_update_all_from_networkstatus(void)
{
-#define SELF_OPINION_INTERVAL 90*60
routerinfo_t *me;
time_t now;
if (!routerlist || !networkstatus_list ||
@@ -2747,22 +2809,27 @@ routers_update_all_from_networkstatus(void)
if (n_recent > 2 && n_recommended < n_recent/2) {
if (consensus == VS_NEW || consensus == VS_NEW_IN_SERIES) {
if (!have_warned_about_new_version) {
+ char *rec = compute_recommended_versions(now, !is_server);
notice(LD_GENERAL, "This version of Tor (%s) is newer than any "
"recommended version%s, according to %d/%d recent network "
- "statuses.",
+ "statuses. Versions recommended by at least %d recent "
+ "authorities are: %s",
VERSION,
consensus == VS_NEW_IN_SERIES ? " in its series" : "",
- n_recent-n_recommended, n_recent);
+ n_recent-n_recommended, n_recent, n_recent/2, rec);
have_warned_about_new_version = 1;
+ tor_free(rec);
}
} else {
+ char *rec = compute_recommended_versions(now, !is_server);
warn(LD_GENERAL, "Please upgrade! "
"This version of Tor (%s) is %s, according to "
- "%d/%d recent network statuses.",
+ "%d/%d recent network statuses. Versions recommended by "
+ "at least %d recent authorities are: %s",
VERSION, consensus == VS_OLD ? "obsolete" : "not recommended",
- n_recent-n_recommended, n_recent);
- /* XXX011 we need to tell them what versions *are* recommended! */
+ n_recent-n_recommended, n_recent, n_recent/2, rec);
have_warned_about_old_version = 1;
+ tor_free(rec);
}
} else {
info(LD_GENERAL, "%d/%d recent directories think my version is ok.",
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 99fb7defb5..61de43fcae 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -1835,3 +1835,34 @@ tor_version_same_series(tor_version_t *a, tor_version_t *b)
(a->micro == b->micro));
}
+/** Helper: Given pointers to two strings describing tor versions, return -1
+ * if _a precedes _b, 1 if _b preceeds _a, and 0 if they are equivalent.
+ * Used to sort a list of versions. */
+static int
+_compare_tor_version_str_ptr(const void **_a, const void **_b)
+{
+ const char *a = *_a, *b = *_b;
+ int ca, cb;
+ tor_version_t va, vb;
+ ca = tor_version_parse(a, &va);
+ cb = tor_version_parse(b, &vb);
+ /* If they both parse, compare them. */
+ if (!ca && !cb)
+ return tor_version_compare(&va,&vb);
+ /* If one parses, it comes first. */
+ if (!ca && cb)
+ return -1;
+ if (ca && !cb)
+ return 1;
+ /* If neither parses, compare strings. Also, the directory server admin
+ ** needs to be smacked upside the head. But Tor is tolerant and gentle. */
+ return strcmp(a,b);
+}
+
+/** Sort a list of string-representations of versions in ascending order. */
+void
+sort_version_list(smartlist_t *versions)
+{
+ smartlist_sort(versions, _compare_tor_version_str_ptr);
+}
+