class TunnelHelperService(TaskManager): def __init__(self): super(TunnelHelperService, self).__init__() self._stopping = False self.log_circuits = False self.session = None self.community = None def on_circuit_reject(self, reject_time, balance): with open( os.path.join(self.session.config.get_state_dir(), "circuit_rejects.log"), 'a') as out_file: time_millis = int(round(reject_time * 1000)) out_file.write("%d,%d\n" % (time_millis, balance)) def tribler_started(self): async def signal_handler(sig): print("Received shut down signal %s" % sig) if not self._stopping: self._stopping = True await self.session.shutdown() get_event_loop().stop() signal.signal(signal.SIGINT, lambda sig, _: ensure_future(signal_handler(sig))) signal.signal(signal.SIGTERM, lambda sig, _: ensure_future(signal_handler(sig))) self.register_task("bootstrap", self.session.tunnel_community.bootstrap, interval=30) # Remove all logging handlers root_logger = logging.getLogger() handlers = root_logger.handlers for handler in handlers: root_logger.removeHandler(handler) logging.getLogger().setLevel(logging.ERROR) new_strategies = [] with self.session.ipv8.overlay_lock: for strategy, target_peers in self.session.ipv8.strategies: if strategy.overlay == self.session.tunnel_community: new_strategies.append((strategy, -1)) else: new_strategies.append((strategy, target_peers)) self.session.ipv8.strategies = new_strategies def circuit_removed(self, circuit, additional_info): self.session.ipv8.network.remove_by_address(circuit.peer.address) if self.log_circuits: with open( os.path.join(self.session.config.get_state_dir(), "circuits.log"), 'a') as out_file: duration = time.time() - circuit.creation_time out_file.write("%d,%f,%d,%d,%s\n" % (circuit.circuit_id, duration, circuit.bytes_up, circuit.bytes_down, additional_info)) async def start(self, options): # Determine ipv8 port ipv8_port = options.ipv8_port if ipv8_port == -1 and "HELPER_INDEX" in os.environ and "HELPER_BASE" in os.environ: base_port = int(os.environ["HELPER_BASE"]) ipv8_port = base_port + int(os.environ["HELPER_INDEX"]) * 5 statedir = Path( os.path.join(get_root_state_directory(), "tunnel-%d") % ipv8_port) config = TriblerConfig(statedir, config_file=statedir / 'triblerd.conf') config.set_tunnel_community_socks5_listen_ports([]) config.set_tunnel_community_random_slots(options.random_slots) config.set_tunnel_community_competing_slots(options.competing_slots) config.set_torrent_checking_enabled(False) config.set_ipv8_enabled(True) config.set_libtorrent_enabled(False) config.set_ipv8_port(ipv8_port) config.set_ipv8_address(options.ipv8_address) config.set_trustchain_enabled(True) config.set_market_community_enabled(False) config.set_dht_enabled(True) config.set_tunnel_community_exitnode_enabled(bool(options.exit)) config.set_popularity_community_enabled(False) config.set_testnet(bool(options.testnet)) config.set_chant_enabled(False) config.set_bootstrap_enabled(False) if not options.no_rest_api: config.set_http_api_enabled(True) api_port = options.restapi if "HELPER_INDEX" in os.environ and "HELPER_BASE" in os.environ: api_port = int(os.environ["HELPER_BASE"]) + 10000 + int( os.environ["HELPER_INDEX"]) config.set_http_api_port(api_port) if options.ipv8_bootstrap_override is not None: config.set_ipv8_bootstrap_override(options.ipv8_bootstrap_override) self.session = Session(config) self.log_circuits = options.log_circuits self.session.notifier.add_observer(NTFY.TUNNEL_REMOVE, self.circuit_removed) await self.session.start() if options.log_rejects: # We set this after Tribler has started since the tunnel_community won't be available otherwise self.session.tunnel_community.reject_callback = self.on_circuit_reject # Tunnel helpers store more TrustChain blocks self.session.trustchain_community.settings.max_db_blocks = 5000000 self.tribler_started() async def stop(self): await self.shutdown_task_manager() if self.session: return self.session.shutdown()
class TinyTriblerService: """Lightweight tribler service, that used for experiments. All overlays are disabled by default. """ def __init__(self, config, timeout_in_sec=None, working_dir=Path('/tmp/tribler'), config_path=Path('tribler.conf')): self.logger = logging.getLogger(self.__class__.__name__) self.session = None self.process_checker = None self.working_dir = working_dir self.config_path = config_path self.config = config self.timeout_in_sec = timeout_in_sec async def on_tribler_started(self): """Function will calls after the Tribler session is started It is good place to add a custom code. """ async def start_tribler(self): self.logger.info(f'Starting tribler instance in directory: {self.working_dir}') self._check_already_running() await self._start_session() if self.timeout_in_sec: asyncio.create_task(self._terminate_by_timeout()) self._enable_graceful_shutdown() await self.on_tribler_started() @staticmethod def create_default_config(working_dir, config_path): config = TriblerConfig(working_dir, config_path) config.set_tunnel_community_enabled(False) config.set_popularity_community_enabled(False) config.set_bootstrap_enabled(False) config.set_torrent_checking_enabled(True) config.set_ipv8_enabled(False) config.set_libtorrent_enabled(False) config.set_dht_enabled(False) config.set_chant_enabled(False) return config async def _start_session(self): self.logger.info(f"Starting Tribler session with config: {self.config}") self.session = Session(self.config) await self.session.start() self.logger.info("Tribler session started") def _check_already_running(self): self.logger.info(f'Check if we are already running a Tribler instance in: {self.working_dir}') self.process_checker = ProcessChecker() if self.process_checker.already_running: self.logger.error(f"Another Tribler instance is already using directory: {self.working_dir}") asyncio.get_running_loop().stop() def _enable_graceful_shutdown(self): self.logger.info("Enabling graceful shutdown") def signal_handler(signum, frame): self.logger.info(f"Received shut down signal {signum} in frame {frame}") self._graceful_shutdown() signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) def _graceful_shutdown(self): self.logger.info("Shutdown gracefully") if not self.session.shutdownstarttime: task = asyncio.create_task(self.session.shutdown()) task.add_done_callback(lambda result: asyncio.get_running_loop().stop()) async def _terminate_by_timeout(self): self.logger.info(f"Scheduling terminating by timeout {self.timeout_in_sec}s from now") await asyncio.sleep(self.timeout_in_sec) self.logger.info("Terminating by timeout") self._graceful_shutdown()