Example #1
0
class Cloud(object):
    """
    Put or get a file from the Cloud.  This class maintains the session, which includes all files that we're serving up to other clients.
    
    This class is reponsible for "put"-ting and "get"-ting files to and from the cloud.
    """
    def __init__(self,
                 torr_dir="c:/torrent",
                 data_dir="c:/torrent/files",
                 tracker_ip="10.0.0.1:8000",
                 callback=lambda: ".",
                 session_dir="c:/torrent",
                 db_name="torrent.db",
                 ext=".torrent"):
        """
        Intialize class.
        
        Parameters
        torr_dir: Location for torrent meta data files
        data_dir: Location for data files
        tracker_ip: IP:PORT string of tracker
        callback: option function which will be called while attempting to seed torrents.
        torr_db: Name of anydbm database where we save what we're serving.
        """

        self.callback = callback
        self.data_dir = data_dir
        self.torr_dir = torr_dir
        self.ext = ext

        self.torr_db = os.path.join(session_dir, db_name)
        self.db = None  # pointer to our torrent DB

        self.my_tracker = Tracker(tracker_ip)
        self.session = Session(session_dir, db_name)
        self.session.register(self.callback)

    def put(self, backup_file):
        """
        Put files to the tracker, given an encrypted ZIP archive, and then serve them.
        
        Parameters
        backup_file: Takes either a full path, or the basename (assumes a directory of self.data_dir in the latter case)
        """

        log.debug(
            "backup_file = %s, data_dir = %s, torr_dir = %s, tracker = %s" %
            (backup_file, self.data_dir, self.torr_dir,
             self.my_tracker.tracker_ip))

        # setup our TorrentMetaInfo object and create a torrent
        ti = TorrentMetaInfo(self.torr_dir, self.data_dir,
                             self.my_tracker.tracker_ip,
                             os.path.basename(backup_file))

        # Make the torrent file and save new TorrentMetaInfo object with torrent name
        if ti.is_valid_create_object():
            t = CreateTorrent(ti)
            ti = t.create(self.my_tracker)
        else:
            raise Exception(
                "TorrentMetaInfo object is not valid for CreateTorrent.")

        # Upload torrent to tracker.  Return false if the upload fails.
        if not self.my_tracker.upload_torrent(ti):
            log.debug("Failed to upload torrent to tracker.")
            return False

        # Serve the torrent
        return self.session.serve(ti)

    def get(self, torr_hash_l):
        """
        Pass a torrent info hash, download files for torrent.
        
        Parameters
        torr_hash_l: Either a string or a list.  Right now, it only takes a single info hash of the torrent to pull down from the tracker.  The
                        data files associated with the torrent are then downloaded from the cloud.
        """

        if self.get_torrents(torr_hash_l):
            self.get_files(torr_hash_l)
            return True
        else:
            return False

    def get_files(self, torr_hash_l):
        """
        Download our files, given a torrent's info hash (string) or a list of torrent info hashes (strings).  Used by the get() function to pull down data
        files from the cloud.
        
        Parameters
        torr_hash_l: string, or list of strings 
        """
        self.session.serve_torrent_by_hash(torr_hash_l, self.torr_dir,
                                           self.data_dir,
                                           self.my_tracker.tracker_ip,
                                           self.ext)

    def serve_torrents(self):
        """
        Serve up all torrents in our torr directory.  Does not take any parameters, simply checks for all torrents
        in our torrent meta data directory, and serves them.
        """
        self.session.serve_all_torrents(self.torr_dir, self.data_dir,
                                        self.my_tracker.tracker_ip, self.ext)

    def get_torrents(self, torr_hash_l):
        """
        Pull a torrent down from the tracker by ID.
        
        Parameter 
        torr_hash_l: list or string of info hashes of torrents to download from the tracker.
        """

        flag = 0

        if hasattr(torr_hash_l, '__iter__'):
            for t in torr_hash_l:
                torr_loc = self.my_tracker.download_torrent(t, self.torr_dir)
                if not torr_loc:
                    log.debug(
                        "Multiple Torr ID's: unable to get torrent location.")
                    flag = 1
        else:
            torr_loc = self.my_tracker.download_torrent(
                torr_hash_l, self.torr_dir)
            if not torr_loc:
                log.debug("Single ID: unable to get torrent location.")
                flag = 1

        if flag:
            return False
        else:
            return True

    # Mark for removal ?
    def get_files_by_torr_name(self, torr_name_l):
        """
        Download files given a torrent file name.  This function will likely be going away as it's not part of our workflow at the moment.
        
        Parameters
        torr_name_l: string or list of torrent info hashes
        """
        # setup our TorrentMetaInfo object and create a torrent

        if hasattr(torr_name_l, '__iter__'):
            for t in torr_name_l:
                ti = TorrentMetaInfo(self.torr_dir,
                                     self.data_dir,
                                     self.my_tracker.tracker_ip,
                                     torr_file=t)
                self.session.serve(ti)
        else:
            ti = TorrentMetaInfo(self.torr_dir,
                                 self.data_dir,
                                 self.my_tracker.tracker_ip,
                                 torr_file=torr_name_l)
            self.session.serve(ti)

    def del_torrent(self, ih):
        """
        Given an info hash, delete a torrent locally
        """

        try:
            self.db = anydbm.open(self.torr_db, 'c')
        except:
            return False

        for info_hash, filename in self.db.iteritems():
            if info_hash == ih:
                self.unstor_torr(ih)
                if self.session.unserve(info_hash=ih):
                    log.debug("Torrent unserved.")
                else:
                    log.debug("Failed to unserve torrent.")
                return True

        self.db.close()
        return False

    ###########################################
    # Start/Stop Cloud
    ###########################################

    # incomplete
    def stop(self):
        """
        Save a session's state
        """

        # loop through our handles and write out fast resume data
        for h in handles:
            if h.is_valid() and h.has_metadata():
                data = lt.bencode(h.write_resume_data())
                open(
                    os.path.join(options.save_path,
                                 h.get_torrent_info().name() + '.fastresume'),
                    'wb').write(data)

        # save session settings here

    def start(self):
        """
        Start the cloud from a saved state
        """

        if self.serving_files():
            log.debug("Cloud already started.")
            return False

        # Open our database, and grind through it.
        try:
            self.db = anydbm.open(self.torr_db, 'c')
        except:
            return False

        flag = 0

        for info_hash, filename in self.db.iteritems():
            log.debug("Loading... %s %s..." % (
                info_hash,
                filename,
            ))
            print os.path.join(self.torr_dir, filename + self.ext)
            ti = TorrentMetaInfo(self.torr_dir, self.data_dir,
                                 self.my_tracker.tracker_ip, filename,
                                 str(filename + self.ext))

            # if we have it, and the tracker has it, serve it
            if not ti.is_valid_torr():
                log.debug("Torrent invalid: %s, %s." % (
                    info_hash,
                    filename,
                ))
                self.unstor_torr(info_hash)
            elif not self.my_tracker.has_torrent(ti):
                log.debug("Torrent does not exist on tracker: %s, %s." % (
                    str(ti.info_hash),
                    filename,
                ))
                self.unstor_torr(info_hash)
            else:
                self.session.serve(ti)
                flag = 1  # serve at least one torrent...

        self.db.close()
        if flag:
            return True
        else:
            log.debug("Nothing in the database to serve.")
            return False

    def serving_files(self):
        """
        Tells us if the cloud is serving any files.
        """
        if len(self.session.handles) > 0:
            return True
        else:
            return False

    ###########################################
    # Database functions
    ###########################################

    def stor_torr(self, info_hash, torr_name):
        """
        Store torrents we're serving in the database.  If it's already in our database, just
        ignore it.  Pairs are stored as key => infohash, value=>torr_name
        
        Parameters
        torr_name: file name of torrent (string)
        info_hash: info hash of torrent (string)
        """
        self.db = anydbm.open(self.torr_db, 'c')
        if not self.db.has_key(info_hash):
            self.db[info_hash] = torr_name
            log.debug("info_hash %s, torr_name: %s" % (
                info_hash,
                torr_name,
            ))
        self.db.close()

    def unstor_torr(self, info_hash):
        """
        Delete a torrent from our database.
        
        Parameters
        info_hash: info hash of torrent to delete
        
        Returns
        True if deleted.
        False if not deleted, or failure.
        """
        try:
            self.db = anydbm.open(self.torr_db, 'w')
        except:
            log.debug("Failed opening database for key removal.")
            return False
        else:
            try:
                del self.db[info_hash]
            except:
                log.debug("Failed removing key.")
                return False
            else:
                return True

    def show_db(self):
        """
        Enumerate all values in our db
        """
        self.db = anydbm.open(self.torr_db, 'c')
        for info_hash, filename in self.db.iteritems():
            print info_hash, " ", filename
        self.db.close()
Example #2
0
class Cloud(object):
    """
    Put or get a file from the Cloud.  This class maintains the session, which includes all files that we're serving up to other clients.
    
    This class is reponsible for "put"-ting and "get"-ting files to and from the cloud.
    """
    
    def __init__(self, torr_dir="c:/torrent", data_dir="c:/torrent/files", tracker_ip="10.0.0.1:8000", callback=lambda: ".", session_dir="c:/torrent", db_name="torrent.db", ext=".torrent"):
        """
        Intialize class.
        
        Parameters
        torr_dir: Location for torrent meta data files
        data_dir: Location for data files
        tracker_ip: IP:PORT string of tracker
        callback: option function which will be called while attempting to seed torrents.
        torr_db: Name of anydbm database where we save what we're serving.
        """        
        
        self.callback = callback
        self.data_dir = data_dir
        self.torr_dir = torr_dir
        self.ext = ext
        
        self.torr_db = os.path.join(session_dir, db_name)
        self.db = None                 # pointer to our torrent DB
        
        self.my_tracker = Tracker(tracker_ip)
        self.session = Session(session_dir, db_name)
        self.session.register(self.callback)
            
    def put(self, backup_file):
        """
        Put files to the tracker, given an encrypted ZIP archive, and then serve them.
        
        Parameters
        backup_file: Takes either a full path, or the basename (assumes a directory of self.data_dir in the latter case)
        """
        
        log.debug("backup_file = %s, data_dir = %s, torr_dir = %s, tracker = %s" % (backup_file, self.data_dir, self.torr_dir, self.my_tracker.tracker_ip))        
        
        # setup our TorrentMetaInfo object and create a torrent
        ti = TorrentMetaInfo(self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, os.path.basename(backup_file))
        
        # Make the torrent file and save new TorrentMetaInfo object with torrent name
        if ti.is_valid_create_object():        
            t=CreateTorrent(ti)
            ti = t.create(self.my_tracker)
        else:
            raise Exception("TorrentMetaInfo object is not valid for CreateTorrent.")
        
        # Upload torrent to tracker.  Return false if the upload fails.
        if not self.my_tracker.upload_torrent(ti):
            log.debug("Failed to upload torrent to tracker.")
            return False

        # Serve the torrent
        return self.session.serve(ti)
    
    def get(self, torr_hash_l):
        """
        Pass a torrent info hash, download files for torrent.
        
        Parameters
        torr_hash_l: Either a string or a list.  Right now, it only takes a single info hash of the torrent to pull down from the tracker.  The
                        data files associated with the torrent are then downloaded from the cloud.
        """
                
        if self.get_torrents(torr_hash_l):
            self.get_files(torr_hash_l)
            return True
        else:
            return False
            
    def get_files(self, torr_hash_l):
        """
        Download our files, given a torrent's info hash (string) or a list of torrent info hashes (strings).  Used by the get() function to pull down data
        files from the cloud.
        
        Parameters
        torr_hash_l: string, or list of strings 
        """
        self.session.serve_torrent_by_hash(torr_hash_l, self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, self.ext)
        
    def serve_torrents(self):
        """
        Serve up all torrents in our torr directory.  Does not take any parameters, simply checks for all torrents
        in our torrent meta data directory, and serves them.
        """
        self.session.serve_all_torrents(self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, self.ext)
               
    def get_torrents(self, torr_hash_l):
        """
        Pull a torrent down from the tracker by ID.
        
        Parameter 
        torr_hash_l: list or string of info hashes of torrents to download from the tracker.
        """
        
        flag = 0
        
        if hasattr(torr_hash_l, '__iter__'):
            for t in torr_hash_l:
                torr_loc = self.my_tracker.download_torrent(t, self.torr_dir)
                if not torr_loc:
                    log.debug("Multiple Torr ID's: unable to get torrent location.")
                    flag = 1
        else:
            torr_loc = self.my_tracker.download_torrent(torr_hash_l, self.torr_dir)
            if not torr_loc:
                log.debug("Single ID: unable to get torrent location.")
                flag = 1
                
        if flag:
            return False
        else:
            return True
    
    # Mark for removal ?
    def get_files_by_torr_name(self, torr_name_l):
        """
        Download files given a torrent file name.  This function will likely be going away as it's not part of our workflow at the moment.
        
        Parameters
        torr_name_l: string or list of torrent info hashes
        """
        # setup our TorrentMetaInfo object and create a torrent
        
        if hasattr(torr_name_l, '__iter__'):
            for t in torr_name_l:  
                ti = TorrentMetaInfo(self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, torr_file=t)
                self.session.serve(ti)
        else:
            ti = TorrentMetaInfo(self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, torr_file=torr_name_l)
            self.session.serve(ti)
    
    def del_torrent(self, ih):
        """
        Given an info hash, delete a torrent locally
        """
        
        try:
            self.db = anydbm.open(self.torr_db, 'c')
        except:
            return False
        
        for info_hash, filename in self.db.iteritems():
            if info_hash == ih:
                self.unstor_torr(ih)
                if self.session.unserve(info_hash=ih):
                    log.debug("Torrent unserved.")
                else:
                    log.debug("Failed to unserve torrent.")
                return True    
                
        self.db.close()
        return False
    
    ###########################################
    # Start/Stop Cloud
    ###########################################    
        
    # incomplete
    def stop(self):
        """
        Save a session's state
        """
        
        # loop through our handles and write out fast resume data
        for h in handles:
            if h.is_valid() and h.has_metadata():
                data = lt.bencode(h.write_resume_data())
                open(os.path.join(options.save_path, h.get_torrent_info().name() + '.fastresume'), 'wb').write(data)
        
        # save session settings here
    
    def start(self):
        """
        Start the cloud from a saved state
        """
        
        if self.serving_files():
            log.debug("Cloud already started.")
            return False
        
        # Open our database, and grind through it.
        try:
            self.db = anydbm.open(self.torr_db, 'c')
        except:
            return False
        
        flag = 0
        
        for info_hash, filename in self.db.iteritems():
            log.debug("Loading... %s %s..." % (info_hash, filename,))
            print os.path.join(self.torr_dir, filename+self.ext)
            ti = TorrentMetaInfo(self.torr_dir, self.data_dir, self.my_tracker.tracker_ip, filename, str(filename+self.ext))
            
            # if we have it, and the tracker has it, serve it
            if not ti.is_valid_torr():
                log.debug("Torrent invalid: %s, %s." % (info_hash, filename, ))
                self.unstor_torr(info_hash)
            elif not self.my_tracker.has_torrent(ti):
                log.debug("Torrent does not exist on tracker: %s, %s." % (str(ti.info_hash), filename, ))
                self.unstor_torr(info_hash)
            else:
                self.session.serve(ti)
                flag = 1                # serve at least one torrent...
                
        self.db.close()
        if flag:
            return True
        else:
            log.debug("Nothing in the database to serve.")
            return False
    
    def serving_files(self):
        """
        Tells us if the cloud is serving any files.
        """
        if len(self.session.handles) > 0:
            return True
        else:
            return False
    
    
    ###########################################
    # Database functions
    ###########################################        
    
    def stor_torr(self, info_hash, torr_name):
        """
        Store torrents we're serving in the database.  If it's already in our database, just
        ignore it.  Pairs are stored as key => infohash, value=>torr_name
        
        Parameters
        torr_name: file name of torrent (string)
        info_hash: info hash of torrent (string)
        """
        self.db = anydbm.open(self.torr_db, 'c')
        if not self.db.has_key(info_hash):
            self.db[info_hash] = torr_name
            log.debug("info_hash %s, torr_name: %s" % (info_hash, torr_name,))
        self.db.close()
        
    def unstor_torr(self, info_hash):
        """
        Delete a torrent from our database.
        
        Parameters
        info_hash: info hash of torrent to delete
        
        Returns
        True if deleted.
        False if not deleted, or failure.
        """
        try:
            self.db = anydbm.open(self.torr_db, 'w')
        except:
            log.debug("Failed opening database for key removal.")
            return False
        else:
            try:
                del self.db[info_hash]
            except:
                log.debug("Failed removing key.")
                return False
            else:
                return True

    def show_db(self):
        """
        Enumerate all values in our db
        """
        self.db = anydbm.open(self.torr_db, 'c')
        for info_hash, filename in self.db.iteritems():
            print info_hash, " ", filename
        self.db.close()