예제 #1
0
파일: utility.py 프로젝트: zzmjohn/tribler
def getMetainfo(src, openoptions='rb', style="file"):
    if src is None:
        return None

    metainfo = None
    try:
        metainfo_file = None
        # We're getting a url
        if style == "rawdata":
            return bdecode(src)
        # We're getting a file that exists
        elif os.access(src, os.R_OK):
            metainfo_file = open(src, openoptions)

        if metainfo_file is not None:
            metainfo = bdecode(metainfo_file.read())
            metainfo_file.close()
    except:
        print_exc()
        if metainfo_file is not None:
            try:
                metainfo_file.close()
            except:
                pass
        metainfo = None
    return metainfo
예제 #2
0
파일: olconn.py 프로젝트: duy/tribler
    def __init__(self,my_keypair,hostname,port,opensock=None,mylistenport=481,myoversion=None):
        """ If opensock is not None, we assume this is a connection we
            accepted, and he initiates the Challenge/Response
        """

        self.my_keypair = my_keypair
        self.b = BTConnection(hostname,port,opensock,mylistenport=mylistenport,myoversion=myoversion)
        if opensock:
            self.b.read_handshake_medium_rare()
            # Read challenge
            msg = self.b.recv()
            assert(msg[0] == CHALLENGE)
            randomB = bdecode(msg[1:])
            [randomA,resp1_data] = self.create_good_response1(randomB,self.b.get_his_id())
            self.b.send(resp1_data)
            # Read response2
            msg = self.b.recv()
            assert(msg[0] == RESPONSE2)
        else:
            self.b.read_handshake()
            [rB,chal_data] = self.create_good_challenge()
            self.b.send(chal_data)
            resp1_data = self.b.recv()
            if DEBUG:
                print >>sys.stderr,"olconn: recv",len(resp1_data),"bytes"
            resp1_dict = bdecode(resp1_data[1:])
            resp2_data = self.create_good_response2(rB,resp1_dict,self.b.get_his_id())
            self.b.send(resp2_data)
            if DEBUG:
                print >>sys.stderr,"olconn: sent",len(resp2_data),"bytes"
예제 #3
0
    def subtest_channelcast(self):
        print >> sys.stderr, "test: channelcast----------------------"
        s = OLConnection(self.my_keypair, 'localhost', self.hisport)
        chcast = ChannelCastCore(None,
                                 s,
                                 self.session,
                                 None,
                                 log='',
                                 dnsindb=None)

        #Send Empty ChannelCast message
        chdata = {}
        print >> sys.stderr, "Test Good ChannelCast", ` chdata `
        msg = CHANNELCAST + bencode(chdata)
        s.send(msg)
        resp = s.recv()
        if len(resp) > 0:
            print >> sys.stderr, "test: channelcast: got", getMessageName(
                resp[0])
        self.assert_(resp[0] == CHANNELCAST)
        print >> sys.stderr, "test: channelcast: got msg", ` bdecode(
            resp[1:]) `
        chdata_rcvd = bdecode(resp[1:])
        self.assert_(validChannelCastMsg(chdata_rcvd) == True)
        s.close()

        #Now, send a bad ChannelCast message.
        # The other side should close the connection
        # Create bad message by manipulating a good one
        #bad infohash
        chdata = deepcopy(chdata_rcvd)
        for k, v in chdata.items():
            v['infohash'] = 234
        self.subtest_bad_channelcast(chdata)

        #bad torrentname
        chdata = deepcopy(chdata_rcvd)
        for k, v in chdata.items():
            v['torrentname'] = 1231
        self.subtest_bad_channelcast(chdata)

        #bad signature.. temporarily disabled.
        # Got to enable when signature validation in validChannelCastMsg are enabled
        #        chdata = deepcopy(chdata_rcvd)
        #        value_list = chdata.values()
        #        if len(value_list)>0:
        #            chdata['sdfg234sadf'] = value_list[0]
        #            self.subtest_bad_channelcast(chdata)

        #Bad message format
        chdata = {'2343ww34': ''}
        self.subtest_bad_channelcast(chdata)

        #Bad
        print >> sys.stderr, "End of channelcast test---------------------------"
예제 #4
0
    def subtest_channelcast(self):
        print >> sys.stderr, "test: channelcast----------------------"
        s = OLConnection(self.my_keypair, "localhost", self.hisport)
        chcast = ChannelCastCore(None, s, self.session, None, log="", dnsindb=None)

        # Send Empty ChannelCast message
        chdata = {}
        print >> sys.stderr, "Test Good ChannelCast", ` chdata `
        msg = CHANNELCAST + bencode(chdata)
        s.send(msg)
        resp = s.recv()
        if len(resp) > 0:
            print >> sys.stderr, "test: channelcast: got", getMessageName(resp[0])
        self.assert_(resp[0] == CHANNELCAST)
        print >> sys.stderr, "test: channelcast: got msg", ` bdecode(resp[1:]) `
        chdata_rcvd = bdecode(resp[1:])
        self.assert_(validChannelCastMsg(chdata_rcvd) == True)
        s.close()

        # Now, send a bad ChannelCast message.
        # The other side should close the connection
        # Create bad message by manipulating a good one
        # bad infohash
        chdata = deepcopy(chdata_rcvd)
        for k, v in chdata.items():
            v["infohash"] = 234
        self.subtest_bad_channelcast(chdata)

        # bad torrentname
        chdata = deepcopy(chdata_rcvd)
        for k, v in chdata.items():
            v["torrentname"] = 1231
        self.subtest_bad_channelcast(chdata)

        # bad signature.. temporarily disabled.
        # Got to enable when signature validation in validChannelCastMsg are enabled
        #        chdata = deepcopy(chdata_rcvd)
        #        value_list = chdata.values()
        #        if len(value_list)>0:
        #            chdata['sdfg234sadf'] = value_list[0]
        #            self.subtest_bad_channelcast(chdata)

        # Bad message format
        chdata = {"2343ww34": ""}
        self.subtest_bad_channelcast(chdata)

        # Bad
        print >> sys.stderr, "End of channelcast test---------------------------"
예제 #5
0
def getStatus(announce, url, info_hash, info_hashes):
    returndict = {info_hash: (0, 0)}
    try:
        resp = timeouturlopen.urlOpenTimeout(url, timeout=HTTP_TIMEOUT)
        response = resp.read()

        response_dict = bdecode(response)
        for cur_infohash, status in response_dict["files"].iteritems():
            seeder = max(0, status["complete"])
            leecher = max(0, status["incomplete"])

            returndict[cur_infohash] = (seeder, leecher)

        registerSuccess(announce)
        return returndict

    except IOError:
        registerIOError(announce)
        return {info_hash: (-1, -1)}

    except KeyError:
        try:
            if "flags" in response_dict:  # may be interval problem
                if "min_request_interval" in response_dict["flags"]:
                    return {info_hash: (-3, -3)}
        except:
            pass
    except:
        pass
    return None
    def check_get_metadata(self, data):
        infohash = bdecode(data)
        self.check_infohash(infohash)

        # Extra check: he can only ask us for metadata for an infohash we
        # gave him.
        self.assert_(infohash in self.myprefs)
 def test_createSingleResponseMessage(self):
     langUtil = LanguagesProvider.getLanguagesInstance()
     data = {
             'permid' : testDestPermId,
             'channel_id' : testChannelId,
             'infohash' : testInfohash,
             'subtitles' : {"eng" : "This is content 1", "nld": "This is content  2",
                            "ita" : "This is content 3"},
             'selversion' : OLPROTO_VER_FOURTEENTH
             }
     langs = data['subtitles'].keys()
     
     bitmask = langUtil.langCodesToMask(langs)
     binaryBitmask = pack("!L", bitmask)
     expextedMessage = SUBS + \
                         bencode((
                                 data['channel_id'],
                                 data['infohash'],
                                 binaryBitmask,
                                 [data['subtitles']['eng'], data['subtitles']['ita'],
                                  data['subtitles']['nld']]
                                  ))
     msg = self.underTest._createSingleResponseMessage(data)
     decoded = bdecode(msg[1:])
     
     self.assertEquals(expextedMessage, msg)
    def check_rquery_reply(self,querytype,data,goodtorrents):
        d = bdecode(data)

        print >>sys.stderr,"test: Got reply",`d`

        self.assert_(type(d) == DictType)
        self.assert_(d.has_key('a'))
        self.check_adict(d['a'])
        self.assert_(d.has_key('id'))
        id = d['id']
        self.assert_(type(id) == StringType)

        k = d['a'].keys()
        self.assert_(len(k) == 2)
        var1 = k[0] == goodtorrents.keys()[0] and k[1] == goodtorrents.keys()[1]
        var2 = k[0] == goodtorrents.keys()[1] and k[1] == goodtorrents.keys()[0]
        self.assert_(var1 or var2)

        # OLPROTO_VER_NINETH must contain torrent_size
        for infohash, torrent in d['a'].iteritems():
            self.assert_(torrent['torrent_size'], goodtorrents[infohash])

        if querytype.startswith("SIMPLE+METADATA"):
            for infohash, torrent in d['a'].iteritems():
                self.assert_('metadata' in torrent)
                bmetainfo = torrent['metadata']
                self.assert_(bmetainfo == goodtorrents[infohash])
예제 #9
0
    def check_rquery_reply(self,querytype,data,goodtorrents):
        d = bdecode(data)
        
        print >>sys.stderr,"test: Got reply",`d`
        
        self.assert_(type(d) == DictType)
        self.assert_(d.has_key('a'))
        self.check_adict(d['a'])
        self.assert_(d.has_key('id'))
        id = d['id']
        self.assert_(type(id) == StringType)

        k = d['a'].keys()
        self.assert_(len(k) == 2)
        var1 = k[0] == goodtorrents.keys()[0] and k[1] == goodtorrents.keys()[1]
        var2 = k[0] == goodtorrents.keys()[1] and k[1] == goodtorrents.keys()[0]
        self.assert_(var1 or var2)

        # OLPROTO_VER_NINETH must contain torrent_size
        for infohash, torrent in d['a'].iteritems():
            self.assert_(torrent['torrent_size'], goodtorrents[infohash])
            
        if querytype.startswith("SIMPLE+METADATA"):
            for infohash, torrent in d['a'].iteritems():
                self.assert_('metadata' in torrent)
                bmetainfo = torrent['metadata']
                self.assert_(bmetainfo == goodtorrents[infohash])
예제 #10
0
    def subtest_valid_nat_check(self):
        """
        Send a CRAWLER_NATCHECK message to the Tribler instance. A
        reply containing a nat type should be returned.
        """
        print >>sys.stderr, "-"*80, "\ntest: subtest_valid_nat_check"

        # make sure that the OLConnection IS in the crawler_db
        crawler_db = CrawlerDBHandler.getInstance()
        crawler_db.temporarilyAddCrawler(self.my_permid)

        s = OLConnection(self.my_keypair, "localhost", self.hisport, mylistenport=self.listen_port)
        self.send_crawler_request(s, CRAWLER_NATCHECK, 42, 0, "")
        s.close()

        if DEBUG: print >>sys.stderr, "test_natcheck: the nat-check code allows for a 10 minute delay in reporting the nat stats"
        self.listen_socket.settimeout(11 * 60)

        # wait for reply
        try:
            conn, addr = self.listen_socket.accept()
        except socket.timeout:
            if DEBUG: print >> sys.stderr,"test_natcheck: timeout, bad, peer didn't connect to send the crawler reply"
            assert False, "test_natcheck: timeout, bad, peer didn't connect to send the crawler reply"
        s = OLConnection(self.my_keypair, "", 0, conn, mylistenport=self.listen_port)

        # read reply
        error, payload = self.receive_crawler_reply(s, CRAWLER_NATCHECK, 42)
        assert error == 0
        if DEBUG: print >>sys.stderr, "test_natcheck:", bdecode(payload)

        time.sleep(1)
예제 #11
0
    def readTorrent(self, torrent):
        try:
            torrent_path = torrent['torrent_path']

            if not path.isfile(torrent_path):
                # torrent not found, try filename + current torrent collection directory
                _, torrent_filename = path.split(torrent_path)
                torrent_path = path.join(self.torrent_collection_dir, torrent_filename)

            if path.isfile(torrent_path):
                f = open(torrent_path, 'rb')
                _data = f.read()
                f.close()

                data = bdecode(_data)

                assert 'info' in data
                del data['info']

                torrent['info'] = data

        except Exception:
            # print_exc()
            pass

        return torrent
예제 #12
0
 def _test_response1(self, ss, gen_resp1, good):
     print >> sys.stderr, "test: myserver running:", gen_resp1
     conn, addr = ss.accept()
     s = BTConnection('', 0, conn)
     s.read_handshake_medium_rare()
     # Read challenge
     msg = s.recv()
     self.testcase.assert_(msg[0] == CHALLENGE)
     randomB = bdecode(msg[1:])
     self.testcase.assert_(type(randomB) == StringType)
     self.testcase.assert_(len(randomB) == random_size)
     [randomA, resp1_data] = gen_resp1(randomB, s.get_his_id())
     s.send(resp1_data)
     if good:
         # Read response2
         msg = s.recv()
         self.testcase.assert_(msg[0] == RESPONSE2)
         self.check_response2(msg[1:], randomA, randomB, s.get_my_id())
         # the connection should be intact, so this should not throw an
         # exception:
         time.sleep(5)
         s.send('bla')
         s.close()
     else:
         time.sleep(5)
         # the other side should not our bad RESPONSE1 this and close the
         # connection
         msg = s.recv()
         self.testcase.assert_(len(msg) == 0)
         s.close()
예제 #13
0
 def _test_response1(self,ss,gen_resp1,good):
     print >>sys.stderr,"test: myserver running:",gen_resp1
     conn, addr = ss.accept()
     s = BTConnection('',0,conn)
     s.read_handshake_medium_rare()
     # Read challenge
     msg = s.recv()
     self.testcase.assert_(msg[0] == CHALLENGE)
     randomB = bdecode(msg[1:])
     self.testcase.assert_(type(randomB) == StringType)
     self.testcase.assert_(len(randomB) == random_size)
     [randomA,resp1_data] = gen_resp1(randomB,s.get_his_id())
     s.send(resp1_data)
     if good:
         # Read response2
         msg = s.recv()
         self.testcase.assert_(msg[0] == RESPONSE2)
         self.check_response2(msg[1:],randomA,randomB,s.get_my_id())
         # the connection should be intact, so this should not throw an
         # exception:
         time.sleep(5)
         s.send('bla')
         s.close()
     else:
         time.sleep(5)
         # the other side should not our bad RESPONSE1 this and close the 
         # connection
         msg = s.recv()
         self.testcase.assert_(len(msg)==0)
         s.close()
예제 #14
0
    def subtest_good_friendship_stats(self):
        """
        Send a valid message-id from a registered crawler peer
        """
        print >>sys.stderr, "-"*80, "\ntest: good friendship stats"

        s = OLConnection(self.my_keypair, "localhost", self.hisport)

        t = time.time() - 100.0
        msg_dict = {'current time':int(t)}
        payload = bencode(msg_dict)
        self.send_crawler_request(s, CRAWLER_FRIENDSHIP_STATS, 0, 0, payload)

        error, payload = self.receive_crawler_reply(s, CRAWLER_FRIENDSHIP_STATS, 0)
        assert error == 0
        
        d = bdecode(payload)
        if DEBUG:
            print >>sys.stderr, "test: Got FRIENDSHIPSTATISTICS",`d`
        stats = d['stats']
        self.assert_(len(stats) == 1)
        record = d['stats'][0]
        self.assert_(record[0] == bin2str(self.his_permid))  # source_permid
        self.assert_(record[1] == bin2str(self.some_permid)) # target_permid
        self.assert_(record[2] == 0) # isForwarder

        time.sleep(1)
        s.close()
예제 #15
0
    def setUpPostSession(self):
        """ override TestAsServer """
        TestAsServer.setUpPostSession(self)

        self.mypermid = str(self.my_keypair.pub().get_der())
        self.hispermid = str(self.his_keypair.pub().get_der())  
        
        # Calculating the infohash for proxyservice.test.torrent
        self.torrentfile = os.path.join('extend_hs_dir','proxyservice.test.torrent')
        
        # Read torrentfile to calculate the infohash
        torrentfile_content = open(self.torrentfile, "rb")
        # Decode all the file
        metainfo = bdecode(torrentfile_content.read())
        # Re-encode only the info section
        self.infohash = hashlib.sha1(bencode(metainfo['info'])).digest()
        # Close the torrentfile
        torrentfile_content.close()
        
        # Add us as friend, so he will accept the ASK_FOR_HELP
        if False:  # TEMP
            friendsdb = FriendDBHandler.getInstance()
            friendsdb.addFriend(self.mypermid)
        else:
            self.session.set_overlay_request_policy(AllowAllRequestPolicy())
          
        self.session.set_download_states_callback(self.states_callback)
예제 #16
0
    def check_friendship(self,
                         data,
                         mtype,
                         fwd,
                         resp,
                         dobdecode=True,
                         source=None,
                         dest=None):
        if dobdecode:
            d = bdecode(data)
        else:
            d = data

        print >> sys.stderr, "test: Got FRIENDSHIP", ` d `, type(d)

        self.assert_(type(d) == DictType)
        self.assert_('msg type' in d)
        self.assert_(type(d['msg type']) == StringType)
        self.assert_(d['msg type'] == mtype)

        if mtype == RESP:
            self.assert_('response' in d)
            self.assert_(type(d['response']) == IntType)

            print >> sys.stderr, "test: COMPARE", ` d['response'] `, ` resp `

            self.assert_(d['response'] == resp)
        elif mtype == FWD:
            self.assert_('source' in d)
            self.check_peer(d['source'], permid=source)
            self.assert_('dest' in d)
            self.check_peer(d['dest'], permid=dest)
            self.assert_('msg' in d)
            self.check_friendship(d['msg'], fwd, None, resp, dobdecode=False)
예제 #17
0
    def subtest_good_friendship_req_fromhim(self, mtype, fwd=None, mresp=None):
        print >> sys.stderr, "test: good FRIENDSHIP req from him", mtype, fwd

        # He should try to forward the request to us, his friend
        try:
            self.destss.settimeout(330.0)
            conn, addr = self.destss.accept()
            s = OLConnection(self.dest_keypair, '', 0, conn, self.destport)
            while True:
                resp = s.recv()
                self.assert_(len(resp) > 0)
                print >> sys.stderr, "test: good FRIENDSHIP fwd: Dest got reply", getMessageName(
                    resp[0])
                if resp[0] == FRIENDSHIP:
                    break
                elif resp[0] == SOCIAL_OVERLAP:
                    d = bdecode(resp[1:])
                    print >> sys.stderr, "test: SOCIAL OVERLAP", ` d `
                    pass
                else:
                    self.assert_(False)
        except socket.timeout:
            print >> sys.stderr, "test: Timeout, bad, peer didn't connect to FWD dest"
            self.assert_(False)

        self.check_friendship(resp[1:],
                              mtype,
                              fwd,
                              mresp,
                              source=self.hispermid,
                              dest=self.mypermid)
    def get_thumbstreaminfo(self, infohash, hit):

        if DEBUG:
            print >> sys.stderr, "hitmap: get_thumbstreaminfo", infohash2urlpath(
                infohash)

        torrent_db = self.session.open_dbhandler(NTFY_TORRENTS)
        try:
            if hit['hittype'] == "localdb":
                dbhit = torrent_db.getTorrent(infohash, include_mypref=False)

                colltorrdir = self.session.get_torrent_collecting_dir()
                filepath = os.path.join(colltorrdir,
                                        dbhit['torrent_file_name'])
                tdef = TorrentDef.load(filepath)
                (thumbtype, thumbdata) = tdef.get_thumbnail()
                return self.create_thumbstreaminfo(thumbtype, thumbdata)

            else:
                if hit['metatype'] == URL_MIME_TYPE:
                    # Shouldn't happen, not thumb in P2PURL
                    return streaminfo404()
                else:
                    if DEBUG:
                        print >> sys.stderr, "hitmap: get_thumbstreaminfo: looking for thumb in remote hit"

                    metainfo = bdecode(hit['metadata'])
                    tdef = TorrentDef.load_from_dict(metainfo)
                    (thumbtype, thumbdata) = tdef.get_thumbnail()
                    return self.create_thumbstreaminfo(thumbtype, thumbdata)
        finally:
            self.session.close_dbhandler(torrent_db)
    def StringToValue(self, value, type):
        # Assume that the value is already in the proper form
        # if it's not a string
        # (the case for some defaults)
        if value is not None:
            if not isinstance(value, unicode) and not isinstance(value, str):
                return value

        try:
            if type == "boolean":
                if value == "1":
                    value = True
                else:
                    value = False
            elif type == "int":
                value = int(value)
            elif type == "float":
                value = float(value)
            elif type == "color":
                red = int(value[0:3])
                green = int(value[3:6])
                blue = int(value[6:9])
                value = wx.Colour(red, green, blue)
            elif type.startswith("bencode"):
                value = bdecode(value)
        except:
            value = None

        if value is None:
            value = self.defaultvalues[type]

        return value
예제 #20
0
    def setUpPostSession(self):
        """ override TestAsServer """
        TestAsServer.setUpPostSession(self)

        self.mypermid = str(self.my_keypair.pub().get_der())
        self.hispermid = str(self.his_keypair.pub().get_der())

        # Calculating the infohash for proxyservice.test.torrent
        self.torrentfile = os.path.join('extend_hs_dir',
                                        'proxyservice.test.torrent')

        # Read torrentfile to calculate the infohash
        torrentfile_content = open(self.torrentfile, "rb")
        # Decode all the file
        metainfo = bdecode(torrentfile_content.read())
        # Re-encode only the info section
        self.infohash = hashlib.sha1(bencode(metainfo['info'])).digest()
        # Close the torrentfile
        torrentfile_content.close()

        # Add us as friend, so he will accept the ASK_FOR_HELP
        if False:  # TEMP
            friendsdb = FriendDBHandler.getInstance()
            friendsdb.addFriend(self.mypermid)
        else:
            self.session.set_overlay_request_policy(AllowAllRequestPolicy())

        self.session.set_download_states_callback(self.states_callback)
def getStatus(announce, url, info_hash, info_hashes):
    returndict = {}
    try:
        resp = timeouturlopen.urlOpenTimeout(url, timeout=HTTP_TIMEOUT)
        response = resp.read()

        response_dict = bdecode(response)
        for cur_infohash, status in response_dict["files"].iteritems():
            seeder = max(0, status["complete"])
            leecher = max(0, status["incomplete"])

            returndict[cur_infohash] = (seeder, leecher)

        registerSuccess(announce)
        return returndict

    except IOError:
        registerIOError(announce)
        return {info_hash: (-1, -1)}

    except KeyError:
        try:
            if response_dict.has_key("flags"):  # may be interval problem
                if response_dict["flags"].has_key("min_request_interval"):
                    return {info_hash: (-3, -3)}
        except:
            pass
    except:
        pass
    return None
    def check_buddycast(self, data, oversion):
        d = bdecode(data)

        print >> sys.stderr, "test: Got BUDDYCAST", d.keys()
        #print >>sys.stderr,"test: Got CONTENT",`d`

        self.assert_(type(d) == DictType)
        self.assert_('ip' in d)
        self.assert_(type(d['ip']) == StringType)
        self.assert_('port' in d)
        self.assert_(type(d['port']) == IntType)
        self.assert_('name' in d)
        self.assert_(type(d['name']) == StringType)
        self.assert_('preferences' in d)
        self.check_preferences(d['preferences'], oversion)
        self.assert_('taste buddies' in d)
        self.check_taste_buddies(d['taste buddies'], oversion)
        self.assert_('random peers' in d)
        self.check_random_peers(d['random peers'], oversion)
        if oversion >= 3:
            self.assert_('connectable' in d)
            #print >>sys.stderr,"CONNECTABLE TYPE",type(d['connectable'])
            self.assert_(type(d['connectable']) == IntType)
        if oversion >= 4:
            self.assert_('collected torrents' in d)
            self.check_collected_torrents(d['collected torrents'], oversion)
        if oversion >= 6:
            self.assert_('npeers' in d)
            self.assert_(type(d['npeers']) == IntType)
            self.assert_('nfiles' in d)
            self.assert_(type(d['nfiles']) == IntType)
            self.assert_('ndls' in d)
            self.assert_(type(d['ndls']) == IntType)
예제 #23
0
 def check_response1(self,resp1_data,rB,myid):
     resp1 = bdecode(resp1_data)
     self.assert_(type(resp1) == DictType)
     self.assert_(resp1.has_key('certA'))
     self.assert_(resp1.has_key('rA'))
     self.assert_(resp1.has_key('B'))
     self.assert_(resp1.has_key('SA'))
     # show throw exception when key no good
     pubA = EC.pub_key_from_der(resp1['certA'])
     rA = resp1['rA']
     self.assert_(type(rA) == StringType)
     self.assert_(len(rA) == random_size)
     B = resp1['B']
     self.assert_(type(B) == StringType)
     self.assert_(B,myid)
     SA = resp1['SA']
     self.assert_(type(SA) == StringType)
     # verify signature
     sig_list = [rA,rB,myid]
     sig_data = bencode(sig_list)
     sig_hash = sha(sig_data).digest()
     self.assert_(pubA.verify_dsa_asn1(sig_hash,SA))
     # Cannot resign the data with his keypair to double check. Signing
     # appears to yield different, supposedly valid sigs each time.
     return resp1
예제 #24
0
파일: Search.py 프로젝트: Devristo/tribler
    def get_thumbstreaminfo(self,infohash,hit):

        if DEBUG:
            print >>sys.stderr,"hitmap: get_thumbstreaminfo",infohash2urlpath(infohash)

        torrent_db = self.session.open_dbhandler(NTFY_TORRENTS)
        try:
            if hit['hittype'] == "localdb":
                dbhit = torrent_db.getTorrent(infohash,include_mypref=False)

                colltorrdir = self.session.get_torrent_collecting_dir()
                filepath = os.path.join(colltorrdir,dbhit['torrent_file_name'])
                tdef = TorrentDef.load(filepath)
                (thumbtype,thumbdata) = tdef.get_thumbnail()
                return self.create_thumbstreaminfo(thumbtype,thumbdata)

            else:
                if hit['metatype'] == URL_MIME_TYPE:
                    # Shouldn't happen, not thumb in P2PURL
                    return streaminfo404()
                else:
                    if DEBUG:
                        print >>sys.stderr,"hitmap: get_thumbstreaminfo: looking for thumb in remote hit"

                    metainfo = bdecode(hit['metadata'])
                    tdef = TorrentDef.load_from_dict(metainfo)
                    (thumbtype,thumbdata) = tdef.get_thumbnail()
                    return self.create_thumbstreaminfo(thumbtype,thumbdata)
        finally:
            self.session.close_dbhandler(torrent_db)
    def test_createSingleResponseMessage(self):
        langUtil = LanguagesProvider.getLanguagesInstance()
        data = {
                'permid' : testDestPermId,
                'channel_id' : testChannelId,
                'infohash' : testInfohash,
                'subtitles' : {"eng" : "This is content 1", "nld": "This is content  2",
                               "ita" : "This is content 3"},
                'selversion' : OLPROTO_VER_FOURTEENTH
                }
        langs = data['subtitles'].keys()

        bitmask = langUtil.langCodesToMask(langs)
        binaryBitmask = pack("!L", bitmask)
        expextedMessage = SUBS + \
                            bencode((
                                    data['channel_id'],
                                    data['infohash'],
                                    binaryBitmask,
                                    [data['subtitles']['eng'], data['subtitles']['ita'],
                                     data['subtitles']['nld']]
                                     ))
        msg = self.underTest._createSingleResponseMessage(data)
        decoded = bdecode(msg[1:])

        self.assertEquals(expextedMessage, msg)
예제 #26
0
    def subtest_good_friendship_req_fromhim(self,mtype,fwd=None,mresp=None):
        print >>sys.stderr,"test: good FRIENDSHIP req from him",mtype,fwd

        # He should try to forward the request to us, his friend
        try:
            self.destss.settimeout(330.0)
            conn, addr = self.destss.accept()
            s = OLConnection(self.dest_keypair,'',0,conn,self.destport)
            while True:
                resp = s.recv()
                self.assert_(len(resp) > 0)
                print >>sys.stderr,"test: good FRIENDSHIP fwd: Dest got reply",getMessageName(resp[0])
                if resp[0] == FRIENDSHIP:
                    break
                elif resp[0] == SOCIAL_OVERLAP:
                    d = bdecode(resp[1:])
                    print >>sys.stderr,"test: SOCIAL OVERLAP",`d`
                    pass
                else:
                    self.assert_(False)
        except socket.timeout:
            print >> sys.stderr,"test: Timeout, bad, peer didn't connect to FWD dest"
            self.assert_(False)

        self.check_friendship(resp[1:],mtype,fwd,mresp,source=self.hispermid,dest=self.mypermid)
예제 #27
0
 def check_friendship(self,data,mtype,fwd,resp,dobdecode=True,source=None,dest=None):
     if dobdecode:
         d = bdecode(data)
     else:
         d = data
     
     print >>sys.stderr,"test: Got FRIENDSHIP",`d`,type(d)
     
     self.assert_(type(d) == DictType)
     self.assert_('msg type' in d)
     self.assert_(type(d['msg type']) == StringType)
     self.assert_(d['msg type'] == mtype)
     
     if mtype == RESP:
         self.assert_('response' in d)
         self.assert_(type(d['response']) == IntType)
         
         print >>sys.stderr,"test: COMPARE",`d['response']`,`resp`
         
         self.assert_(d['response'] == resp)
     elif mtype == FWD:
         self.assert_('source' in d)
         self.check_peer(d['source'],permid=source)
         self.assert_('dest' in d)
         self.check_peer(d['dest'],permid=dest)
         self.assert_('msg' in d)
         self.check_friendship(d['msg'],fwd,None,resp,dobdecode=False)
 def check_response1(self, resp1_data, rB, myid):
     resp1 = bdecode(resp1_data)
     self.assert_(type(resp1) == DictType)
     self.assert_(resp1.has_key('certA'))
     self.assert_(resp1.has_key('rA'))
     self.assert_(resp1.has_key('B'))
     self.assert_(resp1.has_key('SA'))
     # show throw exception when key no good
     pubA = EC.pub_key_from_der(resp1['certA'])
     rA = resp1['rA']
     self.assert_(type(rA) == StringType)
     self.assert_(len(rA) == random_size)
     B = resp1['B']
     self.assert_(type(B) == StringType)
     self.assert_(B, myid)
     SA = resp1['SA']
     self.assert_(type(SA) == StringType)
     # verify signature
     sig_list = [rA, rB, myid]
     sig_data = bencode(sig_list)
     sig_hash = sha(sig_data).digest()
     self.assert_(pubA.verify_dsa_asn1(sig_hash, SA))
     # Cannot resign the data with his keypair to double check. Signing
     # appears to yield different, supposedly valid sigs each time.
     return resp1
예제 #29
0
파일: configreader.py 프로젝트: duy/tribler
    def StringToValue(self, value, type):
        # Assume that the value is already in the proper form
        # if it's not a string
        # (the case for some defaults)
        if value is not None:
            if not isinstance(value, unicode) and not isinstance(value, str):
                return value

        try:
            if type == "boolean":
                if value == "1":
                    value = True
                else:
                    value = False
            elif type == "int":
                value = int(value)
            elif type == "float":
                value = float(value)
            elif type == "color":
                red = int(value[0:3])
                green = int(value[3:6])
                blue = int(value[6:9])
                value = wx.Colour(red, green, blue)
            elif type.startswith("bencode"):
                value = bdecode(value)
        except:           
            value = None
            
        if value is None:
            value = self.defaultvalues[type]
        
        return value
예제 #30
0
    def check_get_metadata(self,data):
        infohash = bdecode(data)
        self.check_infohash(infohash)

        # Extra check: he can only ask us for metadata for an infohash we
        # gave him.
        self.assert_(infohash in self.myprefs)
예제 #31
0
    def check_buddycast(self,data,oversion):
        d = bdecode(data)

        print >>sys.stderr,"test: Got BUDDYCAST",d.keys()
        #print >>sys.stderr,"test: Got CONTENT",`d`

        self.assert_(type(d) == DictType)
        self.assert_('ip' in d)
        self.assert_(type(d['ip']) == StringType)
        self.assert_('port' in d)
        self.assert_(type(d['port']) == IntType)
        self.assert_('name' in d)
        self.assert_(type(d['name']) == StringType)
        self.assert_('preferences' in d)
        self.check_preferences(d['preferences'],oversion)
        self.assert_('taste buddies' in d)
        self.check_taste_buddies(d['taste buddies'],oversion)
        self.assert_('random peers' in d)
        self.check_random_peers(d['random peers'],oversion
                                )
        if oversion >= 3:
            self.assert_('connectable' in d)
            #print >>sys.stderr,"CONNECTABLE TYPE",type(d['connectable'])
            self.assert_(type(d['connectable']) == IntType)
        if oversion >= 4:
            self.assert_('collected torrents' in d)
            self.check_collected_torrents(d['collected torrents'],oversion)
        if oversion >= 6:
            self.assert_('npeers' in d)
            self.assert_(type(d['npeers']) == IntType)
            self.assert_('nfiles' in d)
            self.assert_(type(d['nfiles']) == IntType)
            self.assert_('ndls' in d)
            self.assert_(type(d['ndls']) == IntType)
예제 #32
0
 def subtest_channel_keyword_query(self, nickname):
     print >> sys.stderr, "test: chquery keyword-----------------------------"
     s = OLConnection(self.my_keypair, 'localhost', self.hisport)
     data = {}
     uq = u'CHANNEL k ' + nickname
     data['q'] = uq.encode("UTF-8")
     data['id'] = 'b' * 20
     msg = QUERY + bencode(data)
     s.send(msg)
     resp = s.recv()
     #print >> sys.stderr, "printing resp", resp
     if len(resp) > 0:
         print >> sys.stderr, "test: chquery: got", getMessageName(resp[0])
     self.assert_(resp[0] == QUERY_REPLY)
     self.check_chquery_reply(resp[1:], nickname)
     print >> sys.stderr, "test:", ` bdecode(resp[1:]) `
     s.close()
예제 #33
0
 def subtest_channel_keyword_query(self, nickname):
     print >> sys.stderr, "test: chquery keyword-----------------------------"
     s = OLConnection(self.my_keypair, "localhost", self.hisport)
     data = {}
     uq = u"CHANNEL k " + nickname
     data["q"] = uq.encode("UTF-8")
     data["id"] = "b" * 20
     msg = QUERY + bencode(data)
     s.send(msg)
     resp = s.recv()
     # print >> sys.stderr, "printing resp", resp
     if len(resp) > 0:
         print >> sys.stderr, "test: chquery: got", getMessageName(resp[0])
     self.assert_(resp[0] == QUERY_REPLY)
     self.check_chquery_reply(resp[1:], nickname)
     print >> sys.stderr, "test:", ` bdecode(resp[1:]) `
     s.close()
예제 #34
0
    def check_metadata(self,bdata,tdef):
        data = bdecode(bdata)
        # selversion >= OLPROTO_VER_ELEVENTH:
        for key in ['torrent_hash','metatype','metadata','last_check_time','status','leecher','seeder']:
            self.assert_(key in data)

        self.assertEqual(data['metatype'],URL_MIME_TYPE)
        self.assertEqual(data['torrent_hash'],tdef.get_infohash())

        url = data['metadata']
        cidx = url.find(':')
        self.assert_(cidx != -1)
        scheme = url[0:cidx]
        if url[cidx+1] == '/':
            # hierarchical URL
            qidx = url.find('?')
            self.assert_(qidx != -1)
            tracker = "http"+url[cidx:qidx]
        else:
            # Not yet supported by TorrentDef
            tracker = None
            qidx = cidx+1

        query = url[qidx+1:]
        kvs = query.split('&')
        pt = {}
        for kv in kvs:
            if not '=' in kv:
                k = 'n'
                v = kv
            else:
                (k,v) = kv.split('=')
                if k == 'l': #length
                    v = p2purl_decode_nnumber(v)
                elif k == 's': # piece size
                    v = p2purl_decode_piecelength(v)
                elif k == 'r': # root hash
                    v = p2purl_decode_base64url(v)
                elif k == 'k': # live key
                    v = p2purl_decode_base64url(v)
                elif k == 'a': # live auth method
                    pass
                elif k == 'b': # bitrate
                    v = p2purl_decode_nnumber(v)
            pt[k] = v

        # Compare:
        self.assertEqual(P2PURL_SCHEME,scheme)
        self.assertEqual(tdef.get_tracker(),tracker)
        self.assertEqual(tdef.get_name(),pt['n'])
        self.assertEqual(tdef.get_length(),pt['l'])
        self.assertEqual(tdef.get_piece_length(),pt['s'])
        if 'r' in pt:
            self.assertEqual(tdef.get_infohash(),pt['r'])
        else:
            self.assertEqual(tdef.get_live_pubkey(),pt['k'])
            self.assertEqual(tdef.get_live_authmethod(),pt['a'])
        self.assertEqual(tdef.get_bitrate(),pt['b'])
예제 #35
0
    def _refresh(self):
        channel_url = None
        try:
            self.key_url_lock.acquire()
            channel_url = deepcopy(self.key_url)
        finally:
            self.key_url_lock.release()

        if channel_url:
            for key, urls in channel_url.iteritems():
                if key in self.key_callbacks:
                    for url in urls:
                        if DEBUG:
                            print >> sys.stderr, "RssParser: getting rss", url, len(urls)

                        historyfile = self.gethistfilename(url, key)
                        urls_already_seen = URLHistory(historyfile)
                        urls_already_seen.read()

                        newItems = self.readUrl(url, urls_already_seen)
                        for title, new_urls, description, thumbnail in newItems:
                            for new_url in new_urls:
                                urls_already_seen.add(new_url)
                                urls_already_seen.write()

                                try:
                                    if DEBUG:
                                        print >> sys.stderr, "RssParser: trying", new_url

                                    referer = urlparse(new_url)
                                    referer = referer.scheme + "://" + referer.netloc + "/"
                                    stream = urlOpenTimeout(new_url, referer=referer)
                                    bdata = stream.read()
                                    stream.close()

                                    bddata = bdecode(bdata, 1)
                                    torrent = TorrentDef._create(bddata)

                                    def processCallbacks(key):
                                        for callback in self.key_callbacks[key]:
                                            try:
                                                callback(key, torrent, extraInfo={'title': title, 'description': description, 'thumbnail': thumbnail})
                                            except:
                                                print_exc()

                                    if self.remote_th.is_registered():
                                        callback = lambda key = key: processCallbacks(key)
                                        self.remote_th.save_torrent(torrent, callback)
                                    else:
                                        processCallbacks(key)

                                except:
                                    if DEBUG:
                                        print >> sys.stderr, "RssParser: could not download", new_url
                                    pass

                                time.sleep(RSS_CHECK_FREQUENCY)
    def check_bartercast(self, data):
        d = bdecode(data)

        print "Received data:"
        print d

        self.assert_(type(d) == DictType)
        self.assert_(d.has_key('data'))
        self.check_bartercast_data(d['data'])
예제 #37
0
 def _read(stream):
     """ Internal class method that reads a torrent file from stream,
     checks it for correctness and sets self.input and self.metainfo
     accordingly. """
     bdata = stream.read()
     stream.close()
     data = bdecode(bdata)
     #print >>sys.stderr,data
     return TorrentDef._create(data)
예제 #38
0
 def _read(stream):
     """ Internal class method that reads a torrent file from stream,
     checks it for correctness and sets self.input and self.metainfo
     accordingly. """
     bdata = stream.read()
     stream.close()
     data = bdecode(bdata)
     #print >>sys.stderr,data
     return TorrentDef._create(data)
예제 #39
0
def check_challenge(cdata):
    try:
        randomB = bdecode(cdata)
    except:
        return None
    if len(randomB) != num_random_bits / 8:
        return None
    else:
        return randomB
예제 #40
0
 def check_bartercast(self,data):
     d = bdecode(data)
     
     print "Received data:"
     print d
     
     self.assert_(type(d) == DictType)
     self.assert_(d.has_key('data'))
     self.check_bartercast_data(d['data'])
예제 #41
0
파일: permid.py 프로젝트: Devristo/tribler
def check_challenge(cdata):
    try:
        randomB = bdecode(cdata)
    except:
        return None
    if len(randomB) != num_random_bits/8:
        return None
    else:
        return randomB
예제 #42
0
    def __init__(self,
                 my_keypair,
                 hostname,
                 port,
                 opensock=None,
                 mylistenport=481,
                 myoversion=None):
        """ If opensock is not None, we assume this is a connection we
            accepted, and he initiates the Challenge/Response
        """

        self.my_keypair = my_keypair
        self.b = BTConnection(hostname,
                              port,
                              opensock,
                              mylistenport=mylistenport,
                              myoversion=myoversion)
        if opensock:
            self.b.read_handshake_medium_rare()
            # Read challenge
            msg = self.b.recv()
            assert (msg[0] == CHALLENGE)
            randomB = bdecode(msg[1:])
            [randomA,
             resp1_data] = self.create_good_response1(randomB,
                                                      self.b.get_his_id())
            self.b.send(resp1_data)
            # Read response2
            msg = self.b.recv()
            assert (msg[0] == RESPONSE2)
        else:
            self.b.read_handshake()
            [rB, chal_data] = self.create_good_challenge()
            self.b.send(chal_data)
            resp1_data = self.b.recv()
            if DEBUG:
                print >> sys.stderr, "olconn: recv", len(resp1_data), "bytes"
            resp1_dict = bdecode(resp1_data[1:])
            resp2_data = self.create_good_response2(rB, resp1_dict,
                                                    self.b.get_his_id())
            self.b.send(resp2_data)
            if DEBUG:
                print >> sys.stderr, "olconn: sent", len(resp2_data), "bytes"
    def check_reserve_pieces(self, data):
        # torrent_hash + 1-byte all_or_nothing + bencode([piece num,...])
        self.assert_(len(data) > 21)
        infohash = data[0:20]
        allflag = data[20]
        plist = bdecode(data[21:])

        self.assert_(infohash == self.infohash)
        self.assert_(type(plist) == ListType)
        return plist
예제 #44
0
파일: test_dlhelp.py 프로젝트: duy/tribler
 def check_reserve_pieces(self,data):
     # torrent_hash + 1-byte all_or_nothing + bencode([piece num,...])
     self.assert_(len(data) > 21)
     infohash = data[0:20]
     allflag = data[20]
     plist = bdecode(data[21:])
     
     self.assert_(infohash == self.infohash)
     self.assert_(type(plist) == ListType)
     return plist
예제 #45
0
 def check_tribler_extend_hs(self, data):
     self.assert_(data[0] == chr(0))
     d = bdecode(data[1:])
     self.assert_(isinstance(d, DictType))
     self.assert_('m' in d.keys())
     m = d['m']
     self.assert_(isinstance(m, DictType))
     self.assert_('Tr_hashpiece' in m.keys())
     val = m['Tr_hashpiece']
     self.assert_(isinstance(val, IntType))
     self.assert_(val == 250)
예제 #46
0
 def check_tribler_extend_hs(self,data):
     self.assert_(data[0] == chr(0))
     d = bdecode(data[1:])
     self.assert_(type(d) == DictType)
     self.assert_('m' in d.keys())
     m = d['m']
     self.assert_(type(m) == DictType)
     self.assert_('Tr_OVERLAYSWARM' in m.keys())
     val = m['Tr_OVERLAYSWARM']
     self.assert_(type(val) == IntType)
     self.assert_(val == 253)
예제 #47
0
 def check_tribler_extend_hs(self, data):
     self.assert_(data[0] == chr(0))
     d = bdecode(data[1:])
     self.assert_(isinstance(d, DictType))
     self.assert_("m" in d.keys())
     m = d["m"]
     self.assert_(isinstance(m, DictType))
     self.assert_("Tr_hashpiece" in m.keys())
     val = m["Tr_hashpiece"]
     self.assert_(isinstance(val, IntType))
     self.assert_(val == 250)
예제 #48
0
 def metadata_id_from_extend_handshake(self, data):
     assert data[0] == chr(0)
     d = bdecode(data[1:])
     assert isinstance(d, dict)
     assert 'm' in d.keys()
     m = d['m']
     assert isinstance(m, dict)
     assert "ut_metadata" in m.keys()
     val = m["ut_metadata"]
     assert isinstance(val, int)
     return val
예제 #49
0
 def metadata_id_from_extend_handshake(self, data):
     assert data[0] == chr(0)
     d = bdecode(data[1:])
     assert isinstance(d, dict)
     assert 'm' in d.keys()
     m = d['m']
     assert isinstance(m, dict)
     assert "ut_metadata" in m.keys()
     val = m["ut_metadata"]
     assert isinstance(val, int)
     return val
 def check_tribler_extend_hs(self, data):
     self.assert_(data[0] == chr(0))
     d = bdecode(data[1:])
     self.assert_(type(d) == DictType)
     self.assert_('m' in d.keys())
     m = d['m']
     self.assert_(type(m) == DictType)
     self.assert_('Tr_OVERLAYSWARM' in m.keys())
     val = m['Tr_OVERLAYSWARM']
     self.assert_(type(val) == IntType)
     self.assert_(val == 253)
예제 #51
0
    def subtest_votecast(self):
        print >> sys.stderr, "test: votecast-----------------------------"
        s = OLConnection(self.my_keypair, 'localhost', self.hisport)
        vcast = VoteCastCore(None, s, self.session, None, log='', dnsindb=None)

        #Send Good VoteCast message
        vdata = {self.hispermid: {'vote': -1, 'time_stamp': 12345345}}
        print >> sys.stderr, "Test Good VoteCast", ` vdata `
        msg = VOTECAST + bencode(vdata)
        s.send(msg)
        resp = s.recv()
        #print >> sys.stderr, "printing resp", resp
        if len(resp) > 0:
            print >> sys.stderr, "test: votecast: got", getMessageName(resp[0])
        self.assert_(resp[0] == VOTECAST)
        print >> sys.stderr, "test: votecast: got msg", ` bdecode(resp[1:]) `
        vdata_rcvd = bdecode(resp[1:])
        self.assert_(validVoteCastMsg(vdata_rcvd) == True)
        s.close()

        #Now, send a bad ChannelCast messages
        # The other side should close the connection

        #Bad time_stamp: it can only int
        vdata = {bin2str(self.hispermid): {'vote': -1, 'time_stamp': 'halo'}}
        self.subtest_bad_votecast(vdata)

        #Bad Vote: Vote can only -1 or 2
        vdata = {
            bin2str(self.hispermid): {
                'vote': -15,
                'time_stamp': 12345345
            }
        }
        self.subtest_bad_votecast(vdata)

        # Bad Message format ... Correct format is 'time_stamp'
        vdata = {bin2str(self.hispermid): {'vote': -15, 'timestamp': 12345345}}
        self.subtest_bad_votecast(vdata)

        print >> sys.stderr, "End of votecast test"
예제 #52
0
    def check_g2g_v2(self,data,g2g_id):
        self.assert_(data[0] == chr(g2g_id))
        d = bdecode(data[1:])

        print >>sys.stderr,"test: l is",`d`

        self.assert_(type(d) == DictType)
        for k,v in d.iteritems():
            self.assert_(type(k) == StringType)
            self.assert_(type(v) == StringType)
            self.assert_(ord(k) > 0)
            self.assert_(ord(v) <= 100)
예제 #53
0
 def check_chquery_reply(self, data, nickname):
     d = bdecode(data)
     self.assert_(type(d) == DictType)
     self.assert_(d.has_key('a'))
     self.assert_(d.has_key('id'))
     id = d['id']
     self.assert_(type(id) == StringType)
     self.assert_(validChannelCastMsg(d['a']) == True)
     self.assert_(len(d['a']) > 0)
     for key, val in d['a'].iteritems():
         self.assert_(val['publisher_name'] == nickname.encode("UTF-8"))
         self.assert_(val['publisher_id'] == self.hispermid)
    def check_rquery(self,data):
        d = bdecode(data)
        self.assert_(type(d) == DictType)
        self.assert_(d.has_key('q'))
        q = d['q']
        self.assert_(type(q) == StringType)
        self.assert_(d.has_key('id'))
        id = d['id']
        self.assert_(type(id) == StringType)

        self.assert_(q == self.query.encode("UTF-8"))
        return d['id']
예제 #55
0
    def check_g2g_v2(self, data, g2g_id):
        self.assert_(data[0] == chr(g2g_id))
        d = bdecode(data[1:])

        print >> sys.stderr, "test: l is", ` d `

        self.assert_(type(d) == DictType)
        for k, v in d.iteritems():
            self.assert_(type(k) == StringType)
            self.assert_(type(v) == StringType)
            self.assert_(ord(k) > 0)
            self.assert_(ord(v) <= 100)
예제 #56
0
    def check_rquery(self,data):
        d = bdecode(data)
        self.assert_(type(d) == DictType)
        self.assert_(d.has_key('q'))
        q = d['q']
        self.assert_(type(q) == StringType)
        self.assert_(d.has_key('id'))
        id = d['id']
        self.assert_(type(id) == StringType)

        self.assert_(q == self.query.encode("UTF-8"))
        return d['id']
    def add_metadata_piece(self, piece, data):
        """
        A metadata piece was received
        """
        if not self._closed:

            for index, block_tuple in zip(xrange(len(self._metadata_blocks)), self._metadata_blocks):
                if block_tuple[1] == piece:
                    block_tuple[0] = max(0, block_tuple[0] - 1)
                    block_tuple[2] = data
                    self._metadata_blocks.sort()
                    break

#            def p(s):
#                if s is None: return 0
#                return len(s)
#            if DEBUG: print >> sys.stderr, "Progress:", [p(t[2]) for t in self._metadata_blocks]
            progress = sum([1 if t[2] else 0 for t in self._metadata_blocks])/float(len(self._metadata_blocks))
            self._notifier.notify(NTFY_TORRENTS, NTFY_MAGNET_PROGRESS, self._info_hash, progress)

            # see if we are done
            for requested, piece, data in self._metadata_blocks:
                if data is None:
                    break

            else:
                # _metadata_blocks is sorted by requested count.  we need to sort it by piece-id
                metadata_blocks = [(piece, data) for _, piece, data in self._metadata_blocks]
                metadata_blocks.sort()

                metadata = "".join([data for _, data in metadata_blocks])
                info_hash = sha(metadata).digest()

                if info_hash == self._info_hash:
                    if DEBUG: print >> sys.stderr, "MiniBitTorrent.add_metadata_piece() Done!"

                    # get nice list with recent BitTorrent peers, sorted
                    # by most recently connected
                    peers = [(timestamp, address) for address, timestamp in self._good_peers.iteritems()]
                    peers.sort(reverse=True)
                    peers = [address for _, address in peers]

                    self._callback(bdecode(metadata), peers)

                else:
                    # for piece, data in metadata_blocks:
                    #     open("failed-hash-{0}.data".format(piece), "w+").write(data)

                    # todo: hash failed... now what?
                    # quick solution... remove everything and try again
                    if DEBUG: print >> sys.stderr, "MiniBitTorrent.add_metadata_piece() Failed hashcheck! Restarting all over again :("
                    self._metadata_blocks = [[requested, piece, None] for requested, piece, data in self._metadata_blocks]
    def subtest_receptionOfSUBSTwoRequestsOneAvailable(self):
        """
        Asking for two subtitles while the recipent of the request has only one.
        The response should contain only the one available subtitle content,
        plus a bitmask that reflects the contents of the response.
        """

        print >> sys.stderr, "test: test_subtitles_msgs_2_1 -----------------------"
        ol_conn = OLConnection(self.my_keypair, 'localhost', self.hisport)

        bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(
            ['nld', 'eng'])
        binmask = utilities.uintToBinaryString(bitmask, length=4)

        request = GET_SUBS + \
                      bencode((
                              self.anotherpermid,
                              self.testInfohash,
                              binmask
                              ))

        subshandler = SubtitlesHandler()
        subshandler.register(ol_conn, self.richMetadata_db, self.session)

        ol_conn.send(request)
        subs_data = ol_conn.recv()
        self.assertEquals(SUBS, subs_data[0])
        data = bdecode(subs_data[1:])
        print >> sys.stderr, "test: subtitles_messages : received SUBS repsonse: ", data

        #check on the format of the response
        self.assertTrue(isinstance(data, list))
        self.assertEquals(4, len(data))  # for fields
        self.assertEquals(self.mdto.channel, data[0])
        self.assertEquals(self.mdto.infohash, data[1])

        #the receiver had only one of the two requested subtitles
        # so I expect a different bitmask
        bitmask = LanguagesProvider.getLanguagesInstance().langCodesToMask(
            ['nld'])
        expectedBinarymask = utilities.uintToBinaryString(bitmask, length=4)

        self.assertEquals(expectedBinarymask, data[2])
        self.assertTrue(isinstance(data[3], list))
        self.assertEquals(1, len(data[3]))
        with codecs.open(self.sub1, "rb", "utf-8") as sub:
            expectedContents = sub.read()
        self.assertEquals(expectedContents, data[3][0])

        ol_conn.close()
        print >> sys.stderr, "test: subtitles_messages: received content is valid."
        print >> sys.stderr, "End of test_subtitles_msgs_2_1 test --------------------"