GitLab is used only for code review, issue tracking and project management. Canonical locations for source code are still and

Verified Commit a66516f8 authored by Georg Koppen's avatar Georg Koppen
Browse files

Merge remote-tracking branch 'gitlab/merge-requests/39' into maint-1.1

parents 378f1792 cb97fe8c
from stem import CircuitExtensionFailed, InvalidRequest, ProtocolError, Timeout
from stem import InvalidArguments, ControllerError, SocketClosed
import random
from .relaylist import Relay
import logging
log = logging.getLogger(__name__)
......@@ -25,24 +23,14 @@ class CircuitBuilder:
them, but CircuitBuilder will keep track of existing circuits and close
them when it is deleted.
def __init__(self, args, conf, controller, relay_list,
# XXX: In new major version, remove args and conf, they are not used.
def __init__(self, args, conf, controller, relay_list=None,
self.controller = controller
self.rng = random.SystemRandom()
self.relay_list = relay_list
self.built_circuits = set()
self.close_circuits_on_exit = close_circuits_on_exit
self.circuit_timeout = conf.getint('general', 'circuit_timeout')
def relays(self):
return self.relay_list.relays
def build_circuit(self, *a, **kw):
''' Implementations of this method should build the circuit and return
its (str) ID. If it cannot be built, it should return None. '''
raise NotImplementedError()
def close_circuit(self, circ_id):
......@@ -91,62 +79,16 @@ class CircuitBuilder:
# build the circuit, the relays are not just choosen as random as this class
# does.
class GapsCircuitBuilder(CircuitBuilder):
''' The build_circuit member function takes a list. Falsey values in the
list will be replaced with relays chosen uniformally at random; Truthy
values will be assumed to be relays. '''
"""Same as ``CircuitBuilder`` but implements build_circuit."""
def __init__(self, *a, **kw):
super().__init__(*a, **kw)
def _normalize_path(self, path):
''' Change fingerprints/nicks to relay descriptor and change Falsey
values to None. Return the new path, or None if error '''
new_path = []
for fp in path:
if not fp:
relay = Relay(fp, self.controller)
if not relay.fingerprint:
log.debug('Tor seems to no longer think %s is a relay', fp)
return None
return new_path
def _random_sample_relays(self, number, blacklist):
''' Get <number> random relays from self.relays that are not in the
blacklist. Return None if it cannot be done because too many are
blacklisted. Otherwise return a list of relays. '''
all_fps = [r.fingerprint for r in self.relays]
black_fps = [r.fingerprint for r in blacklist]
if len(black_fps) + number > len(all_fps):
return None
chosen_fps = []
while len(chosen_fps) < number:
choice = self.rng.choice(all_fps)
if choice in black_fps:
return [Relay(fp, self.controller) for fp in chosen_fps]
def build_circuit(self, path):
''' <path> is a list of relays and Falsey values. Relays can be
specified by fingerprint or nickname, and fingerprint is highly
recommended. Falsey values (like None) will be replaced with relays
chosen uniformally at random. A relay will not be in a circuit twice.
if not valid_circuit_length(path):
return None, "Can not build a circuit, invalid path."
path = self._normalize_path(path)
if path is None:
return None, "Can not build a circuit, no path."
num_missing = len(['foo' for r in path if not r])
insert_relays = self._random_sample_relays(
num_missing, [r for r in path if r is not None])
if insert_relays is None:
path = ','.join([r.nickname if r else str(None) for r in path])
return None, "Can not build a circuit with the current relays."
assert len(insert_relays) == num_missing
path = [r.fingerprint if r else insert_relays.pop().fingerprint
for r in path]
"""Return parent class build circuit method.
Since sbws is only building 2 hop paths, there is no need to add random
relays to the path, or convert back and forth between fingerprint and
``Relay`` objects.
return self._build_circuit_impl(path)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment