Beispiel #1
0
    def add_torrent(self, torrentdl, atp):
        # If we are collecting the torrent for this infohash, abort this first.
        with self.metainfo_lock:
            ltsession = self.get_session(atp.pop('hops', 0))

            if 'ti' in atp:
                infohash = str(atp['ti'].info_hash())
            elif 'url' in atp:
                infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1])
            else:
                raise ValueError('No ti or url key in add_torrent_params')

            # Check if we added this torrent before
            known = [str(h.info_hash()) for h in ltsession.get_torrents()]
            if infohash in known:
                self.torrents[infohash] = (torrentdl, ltsession)
                infohash_bin = binascii.unhexlify(infohash)
                return ltsession.find_torrent(lt.big_number(infohash_bin))

            # Otherwise, add it anew
            torrent_handle = ltsession.add_torrent(encode_atp(atp))
            infohash = str(torrent_handle.info_hash())
            if infohash in self.torrents:
                raise DuplicateDownloadException(
                    "This download already exists.")
            self.torrents[infohash] = (torrentdl, ltsession)

            self._logger.debug("added torrent %s", infohash)

            return torrent_handle
Beispiel #2
0
    def start_download(self,
                       torrentfilename=None,
                       infohash=None,
                       tdef=None,
                       dconfig=None):
        self._logger.debug(u"starting download: filename: %s, torrent def: %s",
                           torrentfilename, tdef)

        if infohash is not None:
            assert isinstance(infohash,
                              str), "infohash type: %s" % type(infohash)
            assert len(infohash) == 20, "infohash length is not 20: %s, %s" % (
                len(infohash), infohash)

        # the priority of the parameters is: (1) tdef, (2) infohash, (3) torrent_file.
        # so if we have tdef, infohash and torrent_file will be ignored, and so on.
        if tdef is None:
            if infohash is not None:
                # try to get the torrent from torrent_store if the infohash is provided
                torrent_data = self.trsession.get_collected_torrent(infohash)
                if torrent_data is not None:
                    # use this torrent data for downloading
                    tdef = TorrentDef.load_from_memory(torrent_data)

            if tdef is None:
                assert torrentfilename is not None, "torrent file must be provided if tdef and infohash are not given"
                # try to get the torrent from the given torrent file
                torrent_data = fix_torrent(torrentfilename)
                if torrent_data is None:
                    raise TorrentFileException(
                        "error while decoding torrent file")

                tdef = TorrentDef.load_from_memory(torrent_data)

        assert tdef is not None, "tdef MUST not be None after loading torrent"

        d = self.trsession.get_download(tdef.get_infohash())
        if d:
            new_trackers = list(
                set(tdef.get_trackers_as_single_tuple()) -
                set(d.get_def().get_trackers_as_single_tuple()))
            if not new_trackers:
                raise DuplicateDownloadException(
                    "This download already exists.")

            else:
                self.trsession.update_trackers(tdef.get_infohash(),
                                               new_trackers)
            return

        default_dl_config = DefaultDownloadStartupConfig.getInstance()
        dscfg = default_dl_config.copy()

        if dconfig is not None:
            dscfg = dconfig

        self._logger.info('start_download: Starting in VOD mode')
        result = self.trsession.start_download_from_tdef(tdef, dscfg)

        return result
Beispiel #3
0
    def add_torrent(self, torrentdl, atp):
        # If we are collecting the torrent for this infohash, abort this first.
        with self.metainfo_lock:

            if atp.has_key('ti'):
                infohash = str(atp['ti'].info_hash())
            elif atp.has_key('url'):
                infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1])
            else:
                infohash = str(atp["info_hash"])

            if infohash in self.metainfo_requests:
                print >> sys.stderr, "LibtorrentMgr: killing get_metainfo request for", infohash
                handle, _ = self.metainfo_requests.pop(infohash)
                if handle:
                    self.ltsession.remove_torrent(handle, 0)

            handle = self.ltsession.add_torrent(atp)
            infohash = str(handle.info_hash())
            with self.torlock:
                if infohash in self.torrents:
                    raise DuplicateDownloadException()
                self.torrents[infohash] = torrentdl

            if DEBUG:
                print >> sys.stderr, "LibtorrentMgr: added torrent", infohash

            return handle
Beispiel #4
0
    def add_torrent(self, torrentdl, atp):
        # If we are collecting the torrent for this infohash, abort this first.
        with self.metainfo_lock:
            ltsession = self.get_session(atp.pop('hops', 0))

            if 'ti' in atp:
                infohash = str(atp['ti'].info_hash())
            elif 'url' in atp:
                infohash = binascii.hexlify(parse_magnetlink(atp['url'])[1])
            else:
                raise ValueError('No ti or url key in add_torrent_params')

            if infohash in self.metainfo_requests:
                self._logger.info("killing get_metainfo request for %s", infohash)
                request_handle = self.metainfo_requests.pop(infohash)['handle']
                if request_handle:
                    ltsession.remove_torrent(request_handle, 0)

            torrent_handle = ltsession.add_torrent(encode_atp(atp))
            infohash = str(torrent_handle.info_hash())
            if infohash in self.torrents:
                raise DuplicateDownloadException("This download already exists.")
            self.torrents[infohash] = (torrentdl, ltsession)

            self._logger.debug("added torrent %s", infohash)

            return torrent_handle
Beispiel #5
0
    def add(self, tdef, dscfg, pstate=None, setupDelay=0, hidden=False,
            share_mode=False, checkpoint_disabled=False):
        """ Called by any thread """
        d = None
        with self.session_lock:
            if not isinstance(tdef, TorrentDefNoMetainfo) and not tdef.is_finalized():
                raise ValueError("TorrentDef not finalized")

            infohash = tdef.get_infohash()

            # Create the destination directory if it does not exist yet
            try:
                if not os.path.isdir(dscfg.get_dest_dir()):
                    os.makedirs(dscfg.get_dest_dir())
            except OSError:
                self._logger.error("Unable to create the download destination directory.")

            if dscfg.get_time_added() == 0:
                dscfg.set_time_added(int(timemod.time()))

            # Check if running or saved on disk
            if infohash in self.downloads:
                raise DuplicateDownloadException("This download already exists.")

            from Tribler.Core.Libtorrent.LibtorrentDownloadImpl import LibtorrentDownloadImpl
            d = LibtorrentDownloadImpl(self.session, tdef)

            if pstate is None:  # not already resuming
                pstate = self.load_download_pstate_noexc(infohash)
                if pstate is not None:
                    self._logger.debug("tlm: add: pstate is %s %s",
                                       pstate.get('dlstate', 'status'), pstate.get('dlstate', 'progress'))

            # Store in list of Downloads, always.
            self.downloads[infohash] = d
            setup_deferred = d.setup(dscfg, pstate, wrapperDelay=setupDelay,
                                     share_mode=share_mode, checkpoint_disabled=checkpoint_disabled)
            setup_deferred.addCallback(self.on_download_handle_created)

        if d and not hidden and self.session.config.get_megacache_enabled():
            @forceDBThread
            def write_my_pref():
                torrent_id = self.torrent_db.getTorrentID(infohash)
                data = {'destination_path': d.get_dest_dir()}
                self.mypref_db.addMyPreference(torrent_id, data)

            if isinstance(tdef, TorrentDefNoMetainfo):
                self.torrent_db.addOrGetTorrentID(tdef.get_infohash())
                self.torrent_db.updateTorrent(tdef.get_infohash(), name=tdef.get_name_as_unicode())
                write_my_pref()
            elif self.rtorrent_handler:
                self.rtorrent_handler.save_torrent(tdef, write_my_pref)
            else:
                self.torrent_db.addExternalTorrent(tdef, extra_info={'status': 'good'})
                write_my_pref()

        return d
Beispiel #6
0
 def add_torrent(self, torrentdl, atp):
     handle = self.ltsession.add_torrent(atp)
     infohash = str(handle.info_hash())
     with self.torlock:
         if infohash in self.torrents:
             raise DuplicateDownloadException()
         self.torrents[infohash] = torrentdl
     if DEBUG:
         print >> sys.stderr, "LibtorrentMgr: added torrent", infohash
     return handle
Beispiel #7
0
    def startDownload(self,
                      torrentfilename=None,
                      destdir=None,
                      infohash=None,
                      tdef=None,
                      cmdline=False,
                      vodmode=False,
                      hops=0,
                      selectedFiles=None,
                      hidden=False):
        self._logger.debug(u"startDownload: %s %s %s %s %s", torrentfilename,
                           destdir, tdef, vodmode, selectedFiles)

        # TODO(lipu): remove the assertions after it becomes stable
        if infohash is not None:
            assert isinstance(infohash,
                              str), "infohash type: %s" % type(infohash)
            assert len(infohash) == 20, "infohash length is not 20: %s, %s" % (
                len(infohash), infohash)

        # the priority of the parameters is: (1) tdef, (2) infohash, (3) torrent_file.
        # so if we have tdef, infohash and torrent_file will be ignored, and so on.
        if tdef is None:
            if infohash is not None:
                # try to get the torrent from torrent_store if the infohash is provided
                torrent_data = self.utility.session.get_collected_torrent(
                    infohash)
                if torrent_data is not None:
                    # use this torrent data for downloading
                    tdef = TorrentDef.load_from_memory(torrent_data)

            if tdef is None:
                assert torrentfilename is not None, "torrent file must be provided if tdef and infohash are not given"
                # try to get the torrent from the given torrent file
                torrent_data = fix_torrent(torrentfilename)
                if torrent_data is None:
                    # show error message: could not open torrent file
                    dlg = wx.MessageBox(
                        self,
                        "Could not open torrent file %s" % torrentfilename,
                        "Error", wx.OK | wx.ICON_ERROR)
                    dlg.ShowModal()
                    dlg.Destroy()
                    return

                tdef = TorrentDef.load_from_memory(torrent_data)

        assert tdef is not None, "tdef MUST not be None after loading torrent"

        try:
            d = self.utility.session.get_download(tdef.get_infohash())
            if d:
                new_trackers = list(
                    set(tdef.get_trackers_as_single_tuple()) -
                    set(d.get_def().get_trackers_as_single_tuple()))
                if not new_trackers:
                    raise DuplicateDownloadException()

                else:

                    @forceWxThread
                    def do_gui():
                        # Show update tracker dialog
                        dialog = wx.MessageDialog(
                            None,
                            'This torrent is already being downloaded. Do you wish to load the trackers from it?',
                            'Tribler',
                            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
                        if dialog.ShowModal() == wx.ID_YES:
                            # Update trackers
                            self.utility.session.update_trackers(
                                tdef.get_infohash(), new_trackers)
                        dialog.Destroy()

                    do_gui()
                return

            defaultDLConfig = DefaultDownloadStartupConfig.getInstance()
            dscfg = defaultDLConfig.copy()

            cancelDownload = False
            useDefault = not self.utility.read_config('showsaveas')
            safe_seeding = self.utility.read_config(
                'default_safeseeding_enabled')
            if not useDefault and not destdir:
                defaultname = tdef.get_name_as_unicode(
                ) if tdef.is_multifile_torrent() else None

                if wx.Thread_IsMain():
                    dlg = SaveAs(None, tdef, dscfg.get_dest_dir(), defaultname,
                                 selectedFiles)
                    dlg.CenterOnParent()

                    if isinstance(tdef, TorrentDefNoMetainfo):
                        # Correct for the smaller size of the dialog if there is no metainfo
                        center_pos = dlg.GetPosition()
                        center_pos[1] -= 150
                        dlg.SetPosition(center_pos)

                    if dlg.ShowModal() == wx.ID_OK:
                        # If the dialog has collected a torrent, use the new tdef
                        tdef = dlg.GetCollected() or tdef

                        if tdef and tdef.is_multifile_torrent():
                            selectedFiles = dlg.GetSelectedFiles()
                        destdir = dlg.GetPath()

                        # Anonymity over exit nodes or hidden services
                        safe_seeding = dlg.UseSafeSeeding()
                        if dlg.UseTunnels():
                            hops = self.utility.read_config(
                                'default_number_hops')

                    else:
                        cancelDownload = True
                    dlg.Destroy()
                else:
                    raise Exception("cannot create dialog, not on wx thread")

            # use default setup
            else:
                if useDefault:
                    if self.utility.read_config('default_anonymity_enabled'):
                        # only load default anonymous level if we use default settings
                        hops = self.utility.read_config('default_number_hops')
                    else:
                        hops = 0

            if hops > 0:
                if not tdef:
                    raise Exception(
                        'Currently only torrents can be downloaded in anonymous mode'
                    )

            dscfg.set_hops(hops)
            dscfg.set_safe_seeding(safe_seeding)

            if not cancelDownload:
                if destdir is not None:
                    dscfg.set_dest_dir(destdir)

                if selectedFiles and len(selectedFiles) == 1:
                    # we should filter files to see if they are all playable
                    videofiles = selectedFiles

                elif tdef and not selectedFiles:
                    videofiles = tdef.get_files(exts=videoextdefaults)

                else:
                    videofiles = []

                # disable vodmode if no videofiles, unless we still need to collect the torrent
                if vodmode and len(videofiles) == 0 and (
                        not tdef
                        or not isinstance(tdef, TorrentDefNoMetainfo)):
                    vodmode = False

                if vodmode:
                    self._logger.info(
                        'MainFrame: startDownload: Starting in VOD mode')
                    result = self.utility.session.start_download_from_tdef(
                        tdef, dscfg)
                    self.guiUtility.library_manager.playTorrent(
                        tdef.get_infohash(),
                        videofiles[0] if len(videofiles) == 1 else None)

                else:
                    if selectedFiles:
                        dscfg.set_selected_files(selectedFiles)

                    self._logger.debug(
                        'MainFrame: startDownload: Starting in DL mode')
                    result = self.utility.session.start_download_from_tdef(
                        tdef, dscfg, hidden=hidden)

                if result and not hidden:
                    self.show_saved(tdef)

                return result

        except DuplicateDownloadException as e:
            # If there is something on the cmdline, all other torrents start
            # in STOPPED state. Restart
            if cmdline:
                dlist = self.utility.session.get_downloads()
                for d in dlist:
                    if d.get_def().get_infohash() == tdef.get_infohash():
                        d.restart()
                        break

            if wx.Thread_IsMain():
                # show nice warning dialog
                dlg = wx.MessageDialog(
                    None,
                    "You are already downloading this torrent, see the Downloads section.",
                    "Duplicate download", wx.OK | wx.ICON_ERROR)
                result = dlg.ShowModal()
                dlg.Destroy()

            else:
                print_exc()
                self.onWarning(e)

        except Exception as e:
            print_exc()
            self.onWarning(e)

        return None
Beispiel #8
0
 def test_duplicate_download_exception(self):
     raise DuplicateDownloadException("DuplicateDownloadException")
Beispiel #9
0
    def add(self,
            tdef,
            dscfg,
            pstate=None,
            initialdlstatus=None,
            setupDelay=0,
            hidden=False):
        """ Called by any thread """
        d = None
        self.sesslock.acquire()
        try:
            if not isinstance(
                    tdef, TorrentDefNoMetainfo) and not tdef.is_finalized():
                raise ValueError("TorrentDef not finalized")

            infohash = tdef.get_infohash()

            # Check if running or saved on disk
            if infohash in self.downloads:
                raise DuplicateDownloadException()

            from Tribler.Core.Libtorrent.LibtorrentDownloadImpl import LibtorrentDownloadImpl
            d = LibtorrentDownloadImpl(self.session, tdef)

            if pstate is None:  # not already resuming
                pstate = self.load_download_pstate_noexc(infohash)
                if pstate is not None:
                    self._logger.debug("tlm: add: pstate is %s %s",
                                       pstate.get('dlstate', 'status'),
                                       pstate.get('dlstate', 'progress'))

            # Store in list of Downloads, always.
            self.downloads[infohash] = d
            d.setup(dscfg,
                    pstate,
                    initialdlstatus,
                    self.network_engine_wrapper_created_callback,
                    wrapperDelay=setupDelay)

        finally:
            self.sesslock.release()

        if d and not hidden and self.session.get_megacache():

            @forceDBThread
            def write_my_pref():
                torrent_id = self.torrent_db.getTorrentID(infohash)
                data = {'destination_path': d.get_dest_dir()}
                self.mypref_db.addMyPreference(torrent_id, data)

            if isinstance(tdef, TorrentDefNoMetainfo):
                self.torrent_db.addOrGetTorrentID(tdef.get_infohash())
                self.torrent_db.updateTorrent(tdef.get_infohash(),
                                              name=tdef.get_name_as_unicode())
                write_my_pref()
            elif self.rtorrent_handler:
                self.rtorrent_handler.save_torrent(tdef, write_my_pref)
            else:
                self.torrent_db.addExternalTorrent(
                    tdef, extra_info={'status': 'good'})
                write_my_pref()

        return d