def send_metadata_request(self, permid, infohash, selversion=-1, caller="BC"):
        if DEBUG:
            print >> sys.stderr,"metadata: Connect to send GET_METADATA to",show_permid_short(permid)
        if not isValidInfohash(infohash):
            return False
        
        filename,metadata = self.torrent_exists(infohash)
        if filename is not None:    # torrent already exists on disk
            if DEBUG:
                print >> sys.stderr,"metadata: send_meta_req: Already on disk??!"
            self.notify_torrent_is_in(infohash, metadata, filename)
            return True
        
        if caller == "dlhelp":
            self.requested_torrents.add(infohash)
        
        if self.min_free_space != 0 and (self.free_space - self.avg_torrent_size < self.min_free_space):   # no space to collect
            self.free_space = self.get_free_space()
            if self.free_space - self.avg_torrent_size < self.min_free_space:
                self.warn_disk_full()
                return True

        try:
            # Optimization: don't connect if we're connected, although it won't 
            # do any harm.
            if selversion == -1: # not currently connected
                self.overlay_bridge.connect(permid,lambda e,d,p,s:self.get_metadata_connect_callback(e,d,p,s,infohash))
            else:
                self.get_metadata_connect_callback(None,None,permid,selversion,infohash)
            
        except:
            print_exc()
            return False
        return True
Ejemplo n.º 2
0
 def getSubtileInfosForInfohash(self, infohash):
     '''
     Retrieve available information about subtitles for the given infohash.
     
     Given the infohash of a .torrent, retrieves every
     information about subtitles published for that .torrent that is
     currently available in the DB. 
     
     @param infohash: a .torrent infohash (binary)
     @return: a dictionary. The dictionary looks like this::
             { 
               channel_id1 : {langCode : L{SubtitleInfo}, ...} ,
               channel_id2 : {langCode : L{SubtitleInfo}, ... },
               ...
             } 
         Each entry in the dictionary has the following semantics:
             - channel_id is the permid identifiying the channel (binary).
             - langCode is an ISO 693-2 three characters language code
     '''
     assert utilities.isValidInfohash(infohash)
     assert self._registered, "Instance is not registered"
     
     returnDictionary = dict()
     
     #a metadataDTO corrisponds to all metadata for a pair channel, infohash
     metadataDTOs = self.richMetadata_db.getAllMetadataForInfohash(infohash)
     
     for metadataDTO in metadataDTOs:
         channel = metadataDTO.channel
         subtitles = metadataDTO.getAllSubtitles()
         if len(subtitles) > 0 :
             returnDictionary[channel] = subtitles
     
     return returnDictionary
Ejemplo n.º 3
0
   def publishSubtitle(self, infohash, lang, pathToSrtSubtitle):
       '''
       Allows an user to publish an srt subtitle file in his channel.
       
       Called by a channel owner this method inserts a new subtitle for
       a torrent published in his channel. 
       The method assumes that the torrent identified by the infohash
       parameter is already in the channel, and that the parameter 
       pathToSrtSubtitle points to an existing srt file on the local
       filesystem.
       If a subtitle for the same language was already associated to the 
       specified infohash and channel, it will be overwritten.
       After calling this method the newly inserted subtitle will be 
       disseminated via Channelcast.
       
       @param infohash: the infohash of the torrent to associate the subtitle
                        with, binary
       @param lang: a 3 characters code for the language of the subtitle as
                    specified in ISO 639-2. Currently just 32 language codes
                    will be supported.
       @param pathToSrtSubtitle: a path in the local filesystem to a subtitle
                                 in srt format.
       
       @raise RichMetadataException: if something "general" goes wrong while
                                     adding new metadata
       @raise IOError: if disk related problems occur
       '''
       assert utilities.isValidInfohash(infohash), "Invalid Infohash"
       assert lang is not None and self.langUtility.isLangCodeSupported(lang)
       assert self._registered, "Instance is not registered"
 
       channelid = bin2str(self.my_permid)
       base64infohash = bin2str(infohash)
       # consisnstency check: I want to assure that this method is called
       # for an item that is actually in my channel
       consinstent = self.channelcast_db.isItemInChannel(channelid,base64infohash)
       
       if not consinstent:
           msg = "Infohash %s not found in my channel. Rejecting subtitle" \
                   % base64infohash
           if DEBUG:
               print >> sys.stderr, time.asctime(),'-', msg
           raise RichMetadataException(msg)
       
       try:
       
           filepath = \
               self.subtitlesHandler.copyToSubtitlesFolder(pathToSrtSubtitle,
                                                           self.my_permid,infohash,
                                                           lang)   
       except Exception,e:
           if DEBUG:
               print >> sys.stderr, time.asctime(),'-', "Failed to read and copy subtitle to appropriate folder: %s" % str(e)
Ejemplo n.º 4
0
 def __init__(self, publisher,infohash,timestamp = None,
              description=u"", subtitles=None,signature=None):
     """
     Create a MetataDTO instance.
     
     publisher and infohash are mandatory to be not null
     @param publisher: the permid  of the owner of the 
                       channel this instance refers to
     @param infohash: the infohash of the item in the channel this instance
                      refers to 
     @param timestamp: the timestamp of the creation of this metadata
                       instance. This can be later reset with 
                       resetTimestamp()
     @param description: an optional utf-8 string description for the item. 
                         Defaults to an empty string
     @param subtitles: a dictionary of type {langCode : SubtitleInfo}
     @param signature: signature of the packed version of this metadataDTO.
                       Defaults to None. It can be later signed with sign()
     """
     
     assert publisher is not None
     assert infohash is not None
     assert isValidPermid(publisher)
     assert isValidInfohash(infohash)
     
     #stringified permid of the owner of the channel
     self.channel = publisher
     
     #stringified infohash (bin2str) of the torrent
     self.infohash = infohash
     if timestamp is not None:
         timestring = int(floor(timestamp))
     else:
         timestring = int(floor(time.time()))
     
     #integer timestamp of the creation of this content
     #(the content, not the MetadataDTO instance)
     self.timestamp = timestring
     
     #utf-8 string description
     if isinstance(description, str):
         description = unicode(description, "utf-8")
         
     self.description = description
     
     if subtitles is None:
         subtitles = {}
     self._subtitles = subtitles
     self.signature = signature
Ejemplo n.º 5
0
    def send_metadata_request(self,
                              permid,
                              infohash,
                              selversion=-1,
                              caller="BC"):
        if DEBUG:
            print >> sys.stderr, "metadata: Connect to send GET_METADATA to", show_permid_short(
                permid)
        if not isValidInfohash(infohash):
            return False

        filename, metadata = self.torrent_exists(infohash)
        if filename is not None:  # torrent already exists on disk
            if DEBUG:
                print >> sys.stderr, "metadata: send_meta_req: Already on disk??!"
            self.notify_torrent_is_in(infohash, metadata, filename)
            return True

        if caller == "dlhelp":
            self.requested_torrents.add(infohash)

        if self.min_free_space != 0 and (
                self.free_space - self.avg_torrent_size <
                self.min_free_space):  # no space to collect
            self.free_space = self.get_free_space()
            if self.free_space - self.avg_torrent_size < self.min_free_space:
                self.warn_disk_full()
                return True

        try:
            # Optimization: don't connect if we're connected, although it won't
            # do any harm.
            if selversion == -1:  # not currently connected
                self.overlay_bridge.connect(
                    permid,
                    lambda e, d, p, s: self.get_metadata_connect_callback(
                        e, d, p, s, infohash))
            else:
                self.get_metadata_connect_callback(None, None, permid,
                                                   selversion, infohash)

        except:
            print_exc()
            return False
        return True
Ejemplo n.º 6
0
    def send_metadata(self, permid, message, selversion):
        try:
            infohash = bdecode(message[1:])
        except:
            print_exc()
            if DEBUG:
                print >> sys.stderr, "metadata: GET_METADATA: error becoding"
            return False
        if not isValidInfohash(infohash):
            if DEBUG:
                print >> sys.stderr, "metadata: GET_METADATA: invalid hash"
            return False

        # TODO:
        res = self.torrent_db.getOne(('torrent_file_name', 'status_id'),
                                     infohash=bin2str(infohash))
        if not res:
            if DEBUG:
                print >> sys.stderr, "metadata: GET_METADATA: not in database", infohash
            return True  # don't close connection because I don't have the torrent
        torrent_file_name, status_id = res
        if status_id == self.torrent_db._getStatusID('dead'):
            if DEBUG:
                print >> sys.stderr, "metadata: GET_METADATA: Torrent was dead"
            return True
        if not torrent_file_name:
            return True
        torrent_path = os.path.join(self.torrent_dir, torrent_file_name)
        if not os.path.isfile(torrent_path):
            if DEBUG:
                print >> sys.stderr, "metadata: GET_METADATA: not existing", res, torrent_path
            return True

        task = {
            'permid': permid,
            'infohash': infohash,
            'torrent_path': torrent_path,
            'selversion': selversion
        }
        self.upload_queue.append(task)
        if int(time()) >= self.next_upload_time:
            self.checking_upload_queue()

        return True
Ejemplo n.º 7
0
    def send_metadata(self, permid, message, selversion):
        try:
            infohash = bdecode(message[1:])
        except:
            print_exc()
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: error becoding"
            return False
        if not isValidInfohash(infohash):
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: invalid hash"
            return False

        # TODO:
        res = self.torrent_db.getOne(('torrent_file_name', 'status_id'), infohash=bin2str(infohash))
        if not res:
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: not in database", infohash
            return True    # don't close connection because I don't have the torrent
        torrent_file_name, status_id = res
        if status_id == self.torrent_db._getStatusID('dead'):
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: Torrent was dead"
            return True
        if not torrent_file_name:
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: no torrent file name"
            return True
        torrent_path = os.path.join(self.torrent_dir, torrent_file_name)
        if not os.path.isfile(torrent_path):
            if DEBUG:
                print >> sys.stderr,time.asctime(),'-', "metadata: GET_METADATA: not existing", res, torrent_path
            return True
        
        task = {'permid':permid, 'infohash':infohash, 'torrent_path':torrent_path, 'selversion':selversion}
        self.upload_queue.append(task)
        if int(time()) >= self.next_upload_time:
            self.checking_upload_queue()
        
        return True
Ejemplo n.º 8
0
    def sendSubtitleRequest(self, permid, channel_id, infohash, languages, callback=None, selversion=-1):
        """
        Send a request for subtitle files. Only called by the OLThread
        
        Send a GET_SUBS request to the peer indentified by permid.
        The request asks for several subtitles file, for a given channel_id
        and torrent infohash. The subtitles file to request are specified
        by the languages parameter that is a list of 3 characters language
        codes.
        
        The contents of a GET_SUBS request are:
            - channel_id: the identifier of the channel for which the subtitles
              were added. (a permid). Binary.
            - infohash: the infohash of the torrent, the subtitles refer to.
              Binary.
            - bitmask:  a 32 bit bitmask (an integer) which specifies the 
              languages requested
                      
        
        
        @param permid: the destination of the request (binary)
        @param channel_id: the identifier of the channel for which the subtitle
                           was added (binary)
        @param infohash: the infohash of a torrent the subtitles refers to (binary).
        @param languages: a list of 3-characters language codes. It must be
                          on of the supported language codes (see Languages)
        @param callback: a function that will be called WHENEVER some of the
                         requested subtitles are received. It must have exactly
                         one parameter that will be bound to a list of 
                         the languages that were received
        @param selversion: the protocol version of the peer whe are sending 
                            the request to
        
        @raise SubtitleMsgHandlerException: if the message failed its attempt to be sent.
                                      Notice that also if the method returns without
                                      raising any exception it doesn't mean
                                      that the message has been sent.
        """

        assert utilities.isValidInfohash(infohash), SUBS_LOG_PREFIX + "Invalid infohash %s" % infohash
        assert utilities.isValidPermid(permid), SUBS_LOG_PREFIX + "Invlaid destination permid %s" % permid

        assert self.languagesUtility.isLangListSupported(languages), (
            SUBS_LOG_PREFIX + "Some of the languages where not supported"
        )

        if DEBUG:
            print >>sys.stderr, SUBS_LOG_PREFIX + "preparing to send GET_SUBS to " + utilities.show_permid_short(permid)

        # Better to leave up to the caller the responsibility to check
        # if the subtitle is already available and as correct checsum and so on..
        #        onDisk = []
        #        for langCode in languages:
        #
        #            filename = self.diskManager.isFilenOnDisk(self.subs_dir,
        #                    getSubtitleFileRelativeName(channel_id, infohash, langCode))
        #
        #
        #            # should I skip this part and just send the request anyway?
        #            # (thus leaving to the caller the responsibility to avoid useless
        #            # requests)
        #            if filename:
        #                log.debug(SUBS_LOG_PREFIX + langCode +
        #                          " subtitle already on disk. Skipping it"\
        #                          " in the request")
        #                onDisk.append(langCode)
        #                self._notify_sub_is_in(channel_id, infohash, langCode, filename)
        #
        #        for deleteme in onDisk:
        #            languages.remove(deleteme)

        if len(languages) == 0:
            if DEBUG:
                print >>sys.stderr, SUBS_LOG_PREFIX + " no subtitles to request."
            return

        if not self.diskManager.tryReserveSpace(self.subs_dir, len(languages) * self.avg_subtitle_size):
            self._warn_disk_full()
            return False

        requestDetails = dict()
        requestDetails["channel_id"] = channel_id
        requestDetails["infohash"] = infohash
        requestDetails["languages"] = languages

        self._subsMsgHndlr.sendSubtitleRequest(
            permid, requestDetails, lambda e, d, c, i, b: self._subsRequestSent(e, d, c, i, b), callback, selversion
        )
    def got_metadata(self, permid, message, selversion):    
        """ receive torrent file from others """
        
        # Arno, 2007-06-20: Disabled the following code. What's this? Somebody sends 
        # us something and we refuse? Also doesn't take into account download help 
        #and remote-query extension.
        
        #if self.upload_rate <= 0:    # if no upload, no download, that's the game
        #    return True    # don't close connection
        
        try:
            message = bdecode(message[1:])
        except:
            print_exc()
            return False
        if not isinstance(message, dict):
            return False
        try:
            infohash = message['torrent_hash']
            if not isValidInfohash(infohash):
                return False

            if not infohash in self.requested_torrents:    # got a torrent which was not requested
                return True
            if self.torrent_db.hasMetaData(infohash):
                return True

            # P2PURL
            goturl = False
            if selversion >= OLPROTO_VER_ELEVENTH:
                if 'metatype' in message and message['metatype'] == URL_MIME_TYPE:
                    try:
                        tdef = TorrentDef.load_from_url(metadata['metadata'])
                        # Internal storage format is still .torrent file
                        metainfo = tdef.get_metainfo()
                        metadata = bencode(metainfo)
                        goturl = True
                    except:
                        print_exc()
                        return False
                else:
                    metadata = message['metadata']
            else:
                metadata = message['metadata']
                    
            if not self.valid_metadata(infohash, metadata):
                return False
            
            if DEBUG:
                torrent_size = len(metadata)
                if goturl:
                    mdt = "URL"
                else:
                    mdt = "torrent" 
                print >> sys.stderr,"metadata: Recvd",mdt,`infohash`,sha(infohash).hexdigest(), torrent_size
            
            extra_info = {}
            if selversion >= OLPROTO_VER_FOURTH:
                try:
                    extra_info = {'leecher': message.get('leecher', -1),
                              'seeder': message.get('seeder', -1),
                              'last_check_time': message.get('last_check_time', -1),
                              'status':message.get('status', 'unknown')}
                except Exception, msg:
                    print_exc()
                    print >> sys.stderr, "metadata: wrong extra info in msg - ", message
                    extra_info = {}
                
            filename = self.save_torrent(infohash, metadata, extra_info=extra_info)
            self.requested_torrents.remove(infohash)
            
            #if DEBUG:
            #    print >>sys.stderr,"metadata: Was I asked to dlhelp someone",self.dlhelper

            if filename is not None:
                self.notify_torrent_is_in(infohash,metadata,filename)
            
            
            # BarterCast: add bytes of torrent to BarterCastDB
            # Save exchanged KBs in BarterCastDB
            if permid is not None and BARTERCAST_TORRENTS:
                self.overlay_bridge.add_task(lambda:self.olthread_bartercast_torrentexchange(permid, 'downloaded'), 0)
Ejemplo n.º 10
0
    def got_metadata(self, permid, message, selversion):
        """ receive torrent file from others """

        # Arno, 2007-06-20: Disabled the following code. What's this? Somebody sends
        # us something and we refuse? Also doesn't take into account download help
        #and remote-query extension.

        #if self.upload_rate <= 0:    # if no upload, no download, that's the game
        #    return True    # don't close connection

        try:
            message = bdecode(message[1:])
        except:
            print_exc()
            return False
        if not isinstance(message, dict):
            return False
        try:
            infohash = message['torrent_hash']
            if not isValidInfohash(infohash):
                return False

            if not infohash in self.requested_torrents:  # got a torrent which was not requested
                return True
            if self.torrent_db.hasMetaData(infohash):
                return True

            # P2PURL
            goturl = False
            if selversion >= OLPROTO_VER_ELEVENTH:
                if 'metatype' in message and message[
                        'metatype'] == URL_MIME_TYPE:
                    try:
                        tdef = TorrentDef.load_from_url(metadata['metadata'])
                        # Internal storage format is still .torrent file
                        metainfo = tdef.get_metainfo()
                        metadata = bencode(metainfo)
                        goturl = True
                    except:
                        print_exc()
                        return False
                else:
                    metadata = message['metadata']
            else:
                metadata = message['metadata']

            if not self.valid_metadata(infohash, metadata):
                return False

            if DEBUG:
                torrent_size = len(metadata)
                if goturl:
                    mdt = "URL"
                else:
                    mdt = "torrent"
                print >> sys.stderr, "metadata: Recvd", mdt, ` infohash `, sha(
                    infohash).hexdigest(), torrent_size

            extra_info = {}
            if selversion >= OLPROTO_VER_FOURTH:
                try:
                    extra_info = {
                        'leecher': message.get('leecher', -1),
                        'seeder': message.get('seeder', -1),
                        'last_check_time': message.get('last_check_time', -1),
                        'status': message.get('status', 'unknown')
                    }
                except Exception, msg:
                    print_exc()
                    print >> sys.stderr, "metadata: wrong extra info in msg - ", message
                    extra_info = {}

            filename = self.save_torrent(infohash,
                                         metadata,
                                         extra_info=extra_info)
            self.requested_torrents.remove(infohash)

            #if DEBUG:
            #    print >>sys.stderr,"metadata: Was I asked to dlhelp someone",self.dlhelper

            if filename is not None:
                self.notify_torrent_is_in(infohash, metadata, filename)

            # BarterCast: add bytes of torrent to BarterCastDB
            # Save exchanged KBs in BarterCastDB
            if permid is not None and BARTERCAST_TORRENTS:
                self.overlay_bridge.add_task(
                    lambda: self.olthread_bartercast_torrentexchange(
                        permid, 'downloaded'), 0)