def start_tor_filter_nodes_with_timer(reactor, config, control_port, tor_binary, data_dir, bridges, timeout): """ Start bootstrapping a Tor process wrapped with an instance of the class decorator :func:`ooni.utils.timer.deferred_timeout` and complete callbacks to either :func:`setup_done` or :func:`setup_fail`. Then, filter our list of bridges to remove known public relays by calling back to :func:`remove_public_relays`. Return a fully-setup :class:`ooni.lib.txtorcon.TorState`. Then search for our bridges to test in the list of known public relays, :ivar:`ooni.lib.txtorcon.TorState.routers`, and remove any bridges which are listed as known public relays. :param reactor: The :class:`twisted.internet.reactor`. :param config: An instance of :class:`ooni.lib.txtorcon.TorConfig`. :param control_port: The port to use for Tor's ControlPort. If already configured in the TorConfig instance, this can be given as TorConfig.config.ControlPort. :param tor_binary: The full path to the Tor binary to execute. :param data_dir: The full path to the directory to use as Tor's DataDirectory. :param bridges: A dictionary which has a key 'all' which is a list of bridges to test connecting to, e.g.: bridges['all'] = ['1.1.1.1:443', '22.22.22.22:9001'] :param timeout: The number of seconds to attempt to bootstrap the Tor process before raising a :class:`ooni.utils.timer.TimeoutError`. :return: If the timeout limit is not exceeded, return a fully initialized :class:`ooni.lib.txtorcon.TorState`, else return None. """ error_msg = "Bootstrapping has exceeded the timeout limit..." with_timeout = deferred_timeout(timeout, e=error_msg)(start_tor_filter_nodes) try: state = yield with_timeout(reactor, config, control_port, tor_binary, data_dir, bridges) except TimeoutError, te: log.err(te) defer.returnValue(None)
def __start_tor_with_timer__(reactor, config, control_port, tor_binary, data_dir, bridges=None, relays=None, timeout=None, retry=None): """ A wrapper for :func:`start_tor` which wraps the bootstrapping of a Tor process and its connection to a reactor with a :class:`twisted.internet.defer.Deferred` class decorator utility, :func:`ooni.utils.timer.deferred_timeout`, and a mechanism for resets. ## XXX fill me in """ raise NotImplementedError class RetryException(Exception): pass import sys from ooni.utils.timer import deferred_timeout, TimeoutError def __make_var__(old, default, _type): if old is not None: assert isinstance(old, _type) new = old else: new = default return new reactor = reactor timeout = __make_var__(timeout, 120, int) retry = __make_var__(retry, 1, int) with_timeout = deferred_timeout(timeout)(start_tor) @defer.inlineCallbacks def __start_tor__(rc=reactor, cf=config, cp=control_port, tb=tor_binary, dd=data_dir, br=bridges, rl=relays, cb=setup_done, eb=setup_fail, af=remove_public_relays, retry=retry): try: setup = yield with_timeout(rc,cf,cp,tb,dd) except TimeoutError: retry -= 1 defer.returnValue(retry) else: if setup.callback: setup = yield cb(setup) elif setup.errback: setup = yield eb(setup) else: setup = setup if br is not None: state = af(setup,br) else: state = setup defer.returnValue(state) @defer.inlineCallbacks def __try_until__(tries): result = yield __start_tor__() try: assert isinstance(result, int) except AssertionError: defer.returnValue(result) else: if result >= 0: tried = yield __try_until__(result) defer.returnValue(tried) else: raise RetryException try: tried = yield __try_until__(retry) except RetryException: log.msg("All retry attempts to bootstrap Tor have timed out.") log.msg("Exiting ...") defer.returnValue(sys.exit()) else: defer.returnValue(tried)