Beispiel #1
0
    def create_dconfig_from_params(parameters):
        """
        Create a download configuration based on some given parameters. Possible parameters are:
        - anon_hops: the number of hops for the anonymous download. 0 hops is equivalent to a plain download
        - safe_seeding: whether the seeding of the download should be anonymous or not (0 = off, 1 = on)
        - destination: the destination path of the torrent (where it is saved on disk)
        """
        download_config = DownloadConfig()

        anon_hops = parameters.get('anon_hops', 0)
        safe_seeding = bool(parameters.get('safe_seeding', 0))

        if anon_hops > 0 and not safe_seeding:
            return None, "Cannot set anonymous download without safe seeding enabled"

        if anon_hops > 0:
            download_config.set_hops(anon_hops)

        if safe_seeding:
            download_config.set_safe_seeding(True)

        if parameters.get('destination'):
            dest_dir = parameters['destination']
            download_config.set_dest_dir(dest_dir)

        if 'selected_files' in parameters:
            download_config.set_selected_files(parameters['selected_files'])

        return download_config, None
Beispiel #2
0
async def hidden_seeder_session(seed_config, video_tdef):
    seed_config.set_libtorrent_enabled(False)
    seeder_session = Session(seed_config)
    seeder_session.upgrader_enabled = False
    await seeder_session.start()

    # Also load the tunnel community in the seeder session
    await load_tunnel_community_in_session(seeder_session, start_lt=True)
    seeder_session.tunnel_community.build_tunnels(1)

    dscfg_seed = DownloadConfig()
    dscfg_seed.set_dest_dir(TESTS_DATA_DIR)
    dscfg_seed.set_hops(1)
    upload = seeder_session.dlmgr.start_download(tdef=video_tdef,
                                                 config=dscfg_seed)

    def seeder_state_callback(ds):
        """
        The callback of the seeder download. For now, this only logs the state of the download that's seeder and is
        useful for debugging purposes.
        """
        seeder_session.tunnel_community.monitor_downloads([ds])
        d = ds.get_download()
        print(
            f"seeder: {repr(d.get_def().get_name())} {dlstatus_strings[ds.get_status()]} {ds.get_progress()}"
        )
        return 2

    upload.set_state_callback(seeder_state_callback)

    await upload.wait_for_status(DLSTATUS_SEEDING)
    yield seeder_session
    await seeder_session.shutdown()
Beispiel #3
0
    async def setup_tunnel_seeder(self, hops):
        """
        Setup the seeder.
        """
        from tribler_core.session import Session
        self.seed_config = self.config.copy()
        self.seed_config._state_dir = self.getRootStateDir(2)
        self.seed_config.set_libtorrent_enabled(hops == 0)
        self.seed_config.set_tunnel_community_socks5_listen_ports(
            self.get_ports(5))
        if self.session2 is None:
            self.session2 = Session(self.seed_config)
            self.session2.upgrader_enabled = False
            await self.session2.start()

        tdef = TorrentDef()
        tdef.add_content(TESTS_DATA_DIR / "video.avi")
        tdef.set_tracker("http://localhost/announce")
        torrentfn = self.session2.config.get_state_dir() / "gen.torrent"
        tdef.save(torrent_filepath=torrentfn)
        self.seed_tdef = tdef

        if hops > 0:  # Safe seeding enabled
            self.tunnel_community_seeder = await self.load_tunnel_community_in_session(
                self.session2, start_lt=True)
            self.tunnel_community_seeder.build_tunnels(hops)
        else:
            await self.sanitize_network(self.session2)

        dscfg = DownloadConfig()
        dscfg.set_dest_dir(
            TESTS_DATA_DIR)  # basedir of the file we are seeding
        dscfg.set_hops(hops)
        d = self.session2.dlmgr.start_download(tdef=tdef, config=dscfg)
        d.set_state_callback(self.seeder_state_callback)
Beispiel #4
0
    def check_watch_folder(self):
        if not self.session.config.get_watch_folder_path().is_dir():
            return

        # Make sure that we pass a str to os.walk
        watch_dir = str(self.session.config.get_watch_folder_path())

        for root, _, files in os.walk(watch_dir):
            root = path_util.Path(root)
            for name in files:
                if not name.endswith(".torrent"):
                    continue

                try:
                    tdef = TorrentDef.load(root / name)
                    if not tdef.get_metainfo():
                        self.cleanup_torrent_file(root, name)
                        continue
                except:  # torrent appears to be corrupt
                    self.cleanup_torrent_file(root, name)
                    continue

                infohash = tdef.get_infohash()

                if not self.session.dlmgr.download_exists(infohash):
                    self._logger.info("Starting download from torrent file %s", name)
                    dl_config = DownloadConfig()

                    anon_enabled = self.session.config.get_default_anonymity_enabled()
                    default_num_hops = self.session.config.get_default_number_hops()
                    dl_config.set_hops(default_num_hops if anon_enabled else 0)
                    dl_config.set_safe_seeding(self.session.config.get_default_safeseeding_enabled())
                    dl_config.set_dest_dir(self.session.config.get_default_destination_dir())
                    self.session.dlmgr.start_download(tdef=tdef, config=dl_config)
Beispiel #5
0
def start_anon_download(session, seed_session, tdef, hops=1):
    """
    Start an anonymous download in the main Tribler session.
    """
    session.config.set_libtorrent_dht_readiness_timeout(0)
    dscfg = DownloadConfig()
    dscfg.set_dest_dir(session.config.get_state_dir())
    dscfg.set_hops(hops)
    download = session.dlmgr.start_download(tdef=tdef, config=dscfg)
    session.tunnel_community.bittorrent_peers[download] = [
        ("127.0.0.1", seed_session.config.get_libtorrent_port())
    ]
    return download
Beispiel #6
0
    async def get_metainfo(self, infohash, timeout=30, hops=None, url=None):
        """
        Lookup metainfo for a given infohash. The mechanism works by joining the swarm for the infohash connecting
        to a few peers, and downloading the metadata for the torrent.
        :param infohash: The (binary) infohash to lookup metainfo for.
        :param timeout: A timeout in seconds.
        :param hops: the number of tunnel hops to use for this lookup. If None, use config default.
        :param url: Optional URL. Can contain trackers info, etc.
        :return: The metainfo
        """
        infohash_hex = hexlify(infohash)
        if infohash in self.metainfo_cache:
            self._logger.info('Returning metainfo from cache for %s', infohash_hex)
            return self.metainfo_cache[infohash]['meta_info']

        self._logger.info('Trying to fetch metainfo for %s', infohash_hex)
        if infohash in self.metainfo_requests:
            download = self.metainfo_requests[infohash][0]
            self.metainfo_requests[infohash][1] += 1
        elif infohash in self.downloads:
            download = self.downloads[infohash]
        else:
            tdef = TorrentDefNoMetainfo(infohash, 'metainfo request', url=url)
            dcfg = DownloadConfig()
            dcfg.set_hops(self.tribler_session.config.get_default_number_hops() if hops is None else hops)
            dcfg.set_upload_mode(True)  # Upload mode should prevent libtorrent from creating files
            dcfg.set_dest_dir(self.metadata_tmpdir)
            try:
                download = self.start_download(tdef=tdef, config=dcfg, hidden=True, checkpoint_disabled=True)
            except TypeError:
                return
            self.metainfo_requests[infohash] = [download, 1]

        try:
            metainfo = download.tdef.get_metainfo() or await wait_for(shield(download.future_metainfo), timeout)
            self._logger.info('Successfully retrieved metainfo for %s', infohash_hex)
            self.metainfo_cache[infohash] = {'time': timemod.time(), 'meta_info': metainfo}
        except (CancelledError, asyncio.TimeoutError):
            metainfo = None
            self._logger.info('Failed to retrieve metainfo for %s', infohash_hex)

        if infohash in self.metainfo_requests:
            self.metainfo_requests[infohash][1] -= 1
            if self.metainfo_requests[infohash][1] <= 0:
                await self.remove_download(download, remove_content=True)
                self.metainfo_requests.pop(infohash)

        return metainfo
Beispiel #7
0
    def test_downloadconfig(self):
        dlcfg = DownloadConfig()

        self.assertIsInstance(dlcfg.get_dest_dir(), Path)
        dlcfg.set_dest_dir(self.session_base_dir)
        self.assertEqual(dlcfg.get_dest_dir(), self.session_base_dir)

        dlcfg.set_hops(4)
        self.assertEqual(dlcfg.get_hops(), 4)

        dlcfg.set_safe_seeding(False)
        self.assertFalse(dlcfg.get_safe_seeding())

        dlcfg.set_selected_files([1])
        self.assertEqual(dlcfg.get_selected_files(), [1])

        dlcfg.set_channel_download(True)
        self.assertTrue(dlcfg.get_channel_download())

        dlcfg.set_add_to_channel(True)
        self.assertTrue(dlcfg.get_add_to_channel())

        dlcfg.set_bootstrap_download(True)
        self.assertTrue(dlcfg.get_bootstrap_download())
    async def create_torrent(self, request):
        parameters = await request.json()
        params = {}

        if 'files' in parameters and parameters['files']:
            file_path_list = [
                ensure_unicode(f, 'utf-8') for f in parameters['files']
            ]
        else:
            return RESTResponse({"error": "files parameter missing"},
                                status=HTTP_BAD_REQUEST)

        if 'description' in parameters and parameters['description']:
            params['comment'] = parameters['description']

        if 'trackers' in parameters and parameters['trackers']:
            tracker_url_list = parameters['trackers']
            params['announce'] = tracker_url_list[0]
            params['announce-list'] = tracker_url_list

        name = 'unknown'
        if 'name' in parameters and parameters['name']:
            name = parameters['name']
            params['name'] = name

        export_dir = None
        if 'export_dir' in parameters and parameters['export_dir']:
            export_dir = Path(parameters['export_dir'])

        from tribler_core.version import version_id
        params['created by'] = f"Tribler version: {version_id}"

        params['nodes'] = False
        params['httpseeds'] = False
        params['encoding'] = False
        params['piece length'] = 0  # auto

        try:
            result = await self.session.dlmgr.create_torrent_file(
                file_path_list, recursive_bytes(params))
        except (OSError, UnicodeDecodeError, RuntimeError) as e:
            self._logger.exception(e)
            return return_handled_exception(request, e)

        metainfo_dict = bdecode_compat(result['metainfo'])

        if export_dir and export_dir.exists():
            save_path = export_dir / (f"{name}.torrent")
            with open(save_path, "wb") as fd:
                fd.write(result['metainfo'])

        # Download this torrent if specified
        if 'download' in request.query and request.query[
                'download'] and request.query['download'] == "1":
            download_config = DownloadConfig()
            download_config.set_dest_dir(result['base_path'] if len(
                file_path_list) == 1 else result['base_dir'])
            download_config.set_hops(
                self.session.config.get_default_number_hops())
            try:
                self.session.dlmgr.start_download(
                    tdef=TorrentDef(metainfo_dict), config=download_config)
            except DuplicateDownloadException:
                self._logger.warning(
                    "The created torrent is already being downloaded.")

        return RESTResponse(
            json.dumps({
                "torrent":
                base64.b64encode(result['metainfo']).decode('utf-8')
            }))