|
@@ -26,11 +26,17 @@ import dateutil.parser
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+from stem.descriptor.remote import DescriptorDownloader
|
|
|
|
+
|
|
import logging
|
|
import logging
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
logging.basicConfig(level=logging.DEBUG)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+PERFORM_IPV6_DIRPORT_CHECKS = False
|
|
|
|
+
|
|
|
|
|
|
OUTPUT_CANDIDATES = False
|
|
OUTPUT_CANDIDATES = False
|
|
|
|
|
|
@@ -84,6 +90,16 @@ CUTOFF_GUARD = .95
|
|
|
|
|
|
PERMITTED_BADEXIT = .00
|
|
PERMITTED_BADEXIT = .00
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+CONSENSUS_DOWNLOAD_SPEED_MAX = 15.0
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+CONSENSUS_DOWNLOAD_RETRY = True
|
|
|
|
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -802,7 +818,57 @@ class Candidate(object):
|
|
def original_fallback_weight_fraction(self, total_weight):
|
|
def original_fallback_weight_fraction(self, total_weight):
|
|
return float(self.original_consensus_weight()) / total_weight
|
|
return float(self.original_consensus_weight()) / total_weight
|
|
|
|
|
|
- def fallbackdir_line(self, total_weight, original_total_weight):
|
|
+ @staticmethod
|
|
|
|
+ def fallback_consensus_dl_speed(dirip, dirport, nickname, max_time):
|
|
|
|
+ downloader = DescriptorDownloader()
|
|
|
|
+ start = datetime.datetime.utcnow()
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ downloader.get_consensus(endpoints = [(dirip, dirport)]).run()
|
|
|
|
+ elapsed = (datetime.datetime.utcnow() - start).total_seconds()
|
|
|
|
+ if elapsed > max_time:
|
|
|
|
+ status = 'too slow'
|
|
|
|
+ else:
|
|
|
|
+ status = 'ok'
|
|
|
|
+ logging.debug(('Consensus download: %0.2fs %s from %s (%s:%d), '
|
|
|
|
+ + 'max download time %0.2fs.') % (elapsed, status,
|
|
|
|
+ nickname, dirip, dirport,
|
|
|
|
+ max_time))
|
|
|
|
+ return elapsed
|
|
|
|
+
|
|
|
|
+ def fallback_consensus_dl_check(self):
|
|
|
|
+ ipv4_speed = Candidate.fallback_consensus_dl_speed(self.dirip,
|
|
|
|
+ self.dirport,
|
|
|
|
+ self._data['nickname'],
|
|
|
|
+ CONSENSUS_DOWNLOAD_SPEED_MAX)
|
|
|
|
+ if self.ipv6addr is not None and PERFORM_IPV6_DIRPORT_CHECKS:
|
|
|
|
+
|
|
|
|
+ ipv6_speed = Candidate.fallback_consensus_dl_speed(self.ipv6addr,
|
|
|
|
+ self.dirport,
|
|
|
|
+ self._data['nickname'],
|
|
|
|
+ CONSENSUS_DOWNLOAD_SPEED_MAX)
|
|
|
|
+ else:
|
|
|
|
+ ipv6_speed = None
|
|
|
|
+
|
|
|
|
+ if (ipv4_speed > CONSENSUS_DOWNLOAD_SPEED_MAX
|
|
|
|
+ and CONSENSUS_DOWNLOAD_RETRY):
|
|
|
|
+ ipv4_speed = Candidate.fallback_consensus_dl_speed(self.dirip,
|
|
|
|
+ self.dirport,
|
|
|
|
+ self._data['nickname'],
|
|
|
|
+ CONSENSUS_DOWNLOAD_SPEED_MAX)
|
|
|
|
+ if (self.ipv6addr is not None and PERFORM_IPV6_DIRPORT_CHECKS
|
|
|
|
+ and ipv6_speed > CONSENSUS_DOWNLOAD_SPEED_MAX
|
|
|
|
+ and CONSENSUS_DOWNLOAD_RETRY):
|
|
|
|
+ ipv6_speed = Candidate.fallback_consensus_dl_speed(self.ipv6addr,
|
|
|
|
+ self.dirport,
|
|
|
|
+ self._data['nickname'],
|
|
|
|
+ CONSENSUS_DOWNLOAD_SPEED_MAX)
|
|
|
|
+
|
|
|
|
+ return (ipv4_speed <= CONSENSUS_DOWNLOAD_SPEED_MAX
|
|
|
|
+ and (not PERFORM_IPV6_DIRPORT_CHECKS
|
|
|
|
+ or ipv6_speed <= CONSENSUS_DOWNLOAD_SPEED_MAX))
|
|
|
|
+
|
|
|
|
+ def fallbackdir_line(self, total_weight, original_total_weight, dl_speed_ok):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -813,6 +879,7 @@ class Candidate(object):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
|
s = '/*'
|
|
s = '/*'
|
|
s += '\n'
|
|
s += '\n'
|
|
@@ -839,6 +906,10 @@ class Candidate(object):
|
|
s += '\n'
|
|
s += '\n'
|
|
s += '*/'
|
|
s += '*/'
|
|
s += '\n'
|
|
s += '\n'
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if not dl_speed_ok:
|
|
|
|
+ s += '/* Consensus download failed or was too slow:\n'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -852,6 +923,9 @@ class Candidate(object):
|
|
cleanse_c_string(self.ipv6addr), cleanse_c_string(self.ipv6orport))
|
|
cleanse_c_string(self.ipv6addr), cleanse_c_string(self.ipv6orport))
|
|
s += '\n'
|
|
s += '\n'
|
|
s += '" weight=%d",'%(weight)
|
|
s += '" weight=%d",'%(weight)
|
|
|
|
+ if not dl_speed_ok:
|
|
|
|
+ s += '\n'
|
|
|
|
+ s += '*/'
|
|
return s
|
|
return s
|
|
|
|
|
|
|
|
|
|
@@ -1249,7 +1323,8 @@ def list_fallbacks():
|
|
print describe_fetch_source(s)
|
|
print describe_fetch_source(s)
|
|
|
|
|
|
for x in candidates.fallbacks[:max_count]:
|
|
for x in candidates.fallbacks[:max_count]:
|
|
- print x.fallbackdir_line(total_weight, pre_clamp_total_weight)
|
|
+ dl_speed_ok = x.fallback_consensus_dl_check()
|
|
|
|
+ print x.fallbackdir_line(total_weight, pre_clamp_total_weight, dl_speed_ok)
|
|
|
|
|
|
|
|
|
|
|
|
|