Example #1
0
    def got_proxy_unhave(self, permid, selversion, aggregated_string):
        """ Take the list of pieces the proxy sent and combine it with the numhaves in the piece picker
        
        @param permid: The permid of the node sending the message
        @param selversion: selected Overlay protocol version
        @param aggregated_string: a bitstring of available pieces built by the proxy based on UNHAVE messages it received
        """
        if DEBUG:
            print >> sys.stderr, "doe: received a PROXY_UNHAVE message from", show_permid_short(
                permid)

        # TODO: make this test using a different approach
#        if len(aggregated_string) != self.num_pieces:
#            print >> sys.stderr, "doe: got_proxy_have: invalid payload in received PROXY_HAVE message. self.num_pieces=", self.num_pieces, "len(aggregated_string)=", len(aggregated_string)

# Search for the SingleDownload object that has the connection with this peer
        if DEBUG:
            debug_found_connection = False

        for single_dl in self.proxydownloader.downloads:
            if permid == single_dl.proxy_permid:
                # If the connection is found, add the piece_list information to the d.have information
                single_dl.proxy_have = Bitfield(
                    length=self.btdownloader.numpieces,
                    bitstring=aggregated_string)
                if DEBUG:
                    debug_found_connection = True
                break

        if DEBUG:
            if debug_found_connection:
                print >> sys.stderr, "doe: got_proxy_unhave: found a data connection for the received PROXY_UNHAVE"
            else:
                print >> sys.stderr, "doe: got_proxy_unhave: no data connection for the received PROXY_UNHAVE has been found"
Example #2
0
    def __init__(self, downloader, connection):
        self.downloader = downloader
        self.connection = connection
        self.choked = True
        self.interested = False
        self.active_requests = []
        self.measure = Measure(downloader.max_rate_period)
        self.peermeasure = Measure(downloader.max_rate_period)
        self.have = Bitfield(downloader.numpieces)
        self.last = -1000
        self.last2 = -1000
        self.example_interest = None
        self.backlog = 2
        self.ip = connection.get_ip()
        self.guard = BadDataGuard(self)

        # boudewijn: VOD needs a download measurement that is not
        # averaged over a 'long' period. downloader.max_rate_period is
        # (by default) 20 seconds because this matches the unchoke
        # policy.
        self.short_term_measure = Measure(5)

        # boudewijn: each download maintains a counter for the number
        # of high priority piece requests that did not get any
        # responce within x seconds.
        self.bad_performance_counter = 0
Example #3
0
    def live_invalidate_ranges(self, toinvalidateranges, toinvalidateset):
        """ STBPEED: Faster version of live_invalidate that copies have arrays
        rather than iterate over them for clearing
        """
        if len(toinvalidateranges) == 1:
            (s, e) = toinvalidateranges[0]
            emptyrange = [False for piece in xrange(s, e + 1)]
            assert len(emptyrange) == e + 1 - s

            for d in self.downloads:
                newhave = d.have[0:s] + emptyrange + d.have[e + 1:]

                #oldhave = d.have
                d.have = Bitfield(length=len(newhave), fromarray=newhave)
                #assert oldhave.tostring() == d.have.tostring()
                """
                for piece in toinvalidateset:
                    d.have[piece] = False
                print >>sys.stderr,"d len",len(d.have)
                print >>sys.stderr,"new len",len(newhave)
                    
                for i in xrange(0,len(newhave)):
                    if d.have[i] != newhave[i]:
                        print >>sys.stderr,"newhave diff",i
                        assert False
                """

        else:
            (s1, e1) = toinvalidateranges[0]
            (s2, e2) = toinvalidateranges[1]
            emptyrange1 = [False for piece in xrange(s1, e1 + 1)]
            emptyrange2 = [False for piece in xrange(s2, e2 + 1)]

            assert len(emptyrange1) == e1 + 1 - s1
            assert len(emptyrange2) == e2 + 1 - s2

            for d in self.downloads:
                newhave = emptyrange1 + d.have[e1 + 1:s2] + emptyrange2

                #oldhave = d.have
                d.have = Bitfield(length=len(newhave), fromarray=newhave)
                #assert oldhave.tostring() == d.have.tostring()
                """
Example #4
0
    def subtest_connect2downloader(self):

        print >> sys.stderr, "test: verifier: Connecting to seeder to check bitfield"

        infohash = self.tdef.get_infohash()
        s = BTConnection('localhost',
                         self.mylistenport,
                         user_infohash=infohash)
        s.read_handshake_medium_rare()

        try:
            s.s.settimeout(10.0)
            resp = s.recv()
            self.assert_(len(resp) > 0)
            print >> sys.stderr, "test: verifier: Got message", getMessageName(
                resp[0])
            self.assert_(resp[0] == EXTEND)
            resp = s.recv()
            self.assert_(len(resp) > 0)
            print >> sys.stderr, "test: verifier: Got 2nd message", getMessageName(
                resp[0])
            self.assert_(resp[0] == BITFIELD)
            b = Bitfield(self.npieces, resp[1:])
            print >> sys.stderr, "test: verifier: Bitfield is", ` b.toboollist(
            ) `

            b2 = Bitfield(self.npieces)
            b2[0] = True
            msg = BITFIELD + b2.tostring()
            s.send(msg)

            time.sleep(5)

        except socket.timeout:
            print >> sys.stderr, "test: verifier: Timeout, peer didn't reply"
            self.assert_(False)
        s.close()
Example #5
0
    def __init__(self, proxydownloader, proxy_permid):
        self.downloader = proxydownloader
        self.proxy_permid = proxy_permid

        self.connection = None

        self.measure = Measure(self.downloader.max_rate_period)
        self.active_requests = {
        }  # dictionary with all  indexes currently being downloaded. Key: index, value: timestamp (the moment when the piece was requested)
        self.piece_size = self.downloader.storage._piecelen(0)
        self.total_len = self.downloader.storage.total_length
        self.requests = {
        }  # dictionary of lists: requests[index] contains a list of all reserved chunks
        self.request_size = {}  # dictionary of piece sizes
        self.received_data = {}  # a dictionary of piece data
        self.endflag = False
        self.error = None
        self.retry_period = 0  #30
        self._retry_period = None
        self.errorcount = 0
        self.active = False
        self.cancelled = False
        self.numpieces = self.downloader.numpieces

        self.proxy_have = Bitfield(self.downloader.numpieces)

        self.first_piece_request = True

        # boudewijn: VOD needs a download measurement that is not
        # averaged over a 'long' period. downloader.max_rate_period is
        # (by default) 20 seconds because this matches the unchoke
        # policy.
        self.short_term_measure = Measure(SHORT_TERM_MEASURE_INTERVAL)

        # boudewijn: each download maintains a counter for the number
        # of high priority piece requests that did not get any
        # responce within x seconds.
        self.bad_performance_counter = 0

        # HTTP Video Support
        self.request_lock = Lock()
        self.video_support_policy = False  # TODO : get from constructor parameters
        self.video_support_enabled = False  # Don't start immediately with support
        self.video_support_speed = 0.0  # Start with the faster rescheduling speed
        self.video_support_slow_start = False  # If enabled delay the first request (give chance to peers to give bandwidth)
        # Arno, 2010-04-07: Wait 1 second before using HTTP seed. TODO good policy
        # If Video Support policy is not eneabled then use Http seed normaly
        if not self.video_support_policy:
            self.resched(1)
Example #6
0
 def __init__(self, downloader, connection):
     # 2fastbt_
     SingleDownloadHelperInterface.__init__(self)
     # _2fastbt
     self.downloader = downloader
     self.connection = connection
     self.choked = True
     self.interested = False
     self.active_requests = []
     self.measure = Measure(downloader.max_rate_period)
     self.peermeasure = Measure(downloader.max_rate_period)
     self.have = Bitfield(downloader.numpieces)
     self.last = -1000
     self.last2 = -1000
     self.example_interest = None
     self.backlog = 2
     self.ip = connection.get_ip()
     self.guard = BadDataGuard(self)
     # 2fastbt_
     self.helper = downloader.picker.helper
Example #7
0
    def got_have_bitfield(self, have):

        if self.downloader.picker.am_I_complete() and have.complete():
            # Arno: If we're both seeds
            if self.downloader.super_seeding:
                self.connection.send_bitfield(
                    have.tostring())  # be nice, show you're a seed too
            self.connection.close()
            self.downloader.add_disconnected_seed(
                self.connection.get_readable_id())
            return

        #print >>sys.stderr,"Downloader: got_have_bitfield: VVV#############################################################################################VVVVVVVVVVVVVVVVVVVVVVVVV valid",self.downloader.picker.get_valid_range_iterator(),"len",self.downloader.numpieces
        #print >>sys.stderr,"Downloader: got_have_bitfield: input",`have.toboollist()`
        if have.complete():
            # Arno: He is seed
            self.downloader.picker.got_seed()
        else:
            # Arno: LIVEWRAP: filter out valid pieces
            # TODO: may be slow with 32K pieces.
            validhave = Bitfield(self.downloader.numpieces)
            for i in self.downloader.picker.get_valid_range_iterator():
                if have[i]:
                    validhave[i] = True
                    self.downloader.picker.got_have(i, self.connection)
            have = validhave
        # Store filtered bitfield
        self.have = have

        #print >>sys.stderr,"Downloader: got_have_bitfield: valid",`have.toboollist()`

        if self.downloader.endgamemode and not self.downloader.paused:
            for piece, begin, length in self.downloader.all_requests:
                if self.have[piece]:
                    self.send_interested()
                    break
            return
        self._check_interests()
Example #8
0
    def aggregate_and_send_haves(self):
        """ Aggregates the information from the haves bitfields for all the active connections,
        then calls the proxy class to send the aggregated information as a PROXY_HAVE message 
        """
        DEBUG = False
        if self.proxydownloader:
            proxyservice_role = self.proxydownloader.dlinstance.get_proxyservice_role(
            )
            if proxyservice_role == PROXYSERVICE_ROLE_PROXY:
                # The current node is a proxy
                if DEBUG:
                    print >> sys.stderr, "Downloader: aggregate_and_send_haves"

                # haves_vector is a matrix, having on each line a Bitfield
                # len(self.downloads) = the number of connections to swarm peers
                # +1 = me (the pieces i have locally)
                haves_vector = [None] * (len(self.downloads) + 1)
                for i in range(0, len(self.downloads)):
                    haves_vector[i] = self.downloads[i].have

                haves_vector[len(
                    self.downloads)] = self.storage.get_have_copy()

                #Calculate the aggregated haves
                aggregated_haves = Bitfield(self.numpieces)
                for piece in range(0, self.numpieces):
                    aggregated_value = False
                    # For every column in the haves_vector matrix
                    for d in range(0, len(self.downloads) + 1):
                        # For every active connection
                        aggregated_value = aggregated_value or haves_vector[d][
                            piece]  # Logical OR operation
                    aggregated_haves[piece] = aggregated_value

                if DEBUG:
                    print >> sys.stderr, "Downloader: aggregate_and_send_haves"  #, len(self.downloads), aggregated_haves.toboollist()
                self.proxydownloader.proxy.send_proxy_have(aggregated_haves)
    def setUpPostSession(self):
        """ override TestAsServer """
        TestAsServer.setUpPostSession(self)

        # Let Tribler start downloading an non-functioning torrent, so
        # we can talk to a normal download engine.
        self.tdef = TorrentDef()
        self.sourcefn = os.path.join(os.getcwd(), "API", "file2.wmv")
        self.tdef.add_content(self.sourcefn)
        self.tdef.set_create_merkle_torrent(True)
        self.tdef.set_tracker("http://127.0.0.1:12/announce")
        self.tdef.finalize()

        self.torrentfn = os.path.join(self.session.get_state_dir(),
                                      "gen.torrent")
        self.tdef.save(self.torrentfn)

        dscfg = self.setUpDownloadConfig()

        self.session.start_download(self.tdef, dscfg)

        self.infohash = self.tdef.get_infohash()
        self.mylistenport = 4810

        self.numpieces = (self.tdef.get_length() +
                          self.tdef.get_piece_length() -
                          1) / self.tdef.get_piece_length()
        b = Bitfield(self.numpieces)
        for i in range(self.numpieces):
            b[i] = True
        self.assert_(b.complete())
        self.seederbitfieldstr = b.tostring()

        #piece_hashes = ['\x01\x02\x03\x04\x05\x06\x07\x08\x07\x06\x05\x04\x03\x02\x01\x00\x01\x02\x03\x04' ] * npieces
        # Construct Merkle tree
        tdef2 = TorrentDef()
        tdef2.add_content(self.sourcefn)
        tdef2.set_create_merkle_torrent(False)
        tdef2.set_tracker("http://127.0.0.1:12/announce")
        tdef2.set_piece_length(self.tdef.get_piece_length())
        tdef2.finalize()
        metainfo = tdef2.get_metainfo()

        piecesstr = metainfo['info']['pieces']
        print >> sys.stderr, "test: pieces has len", len(piecesstr)
        piece_hashes = []
        for i in range(0, len(piecesstr), 20):
            hash = piecesstr[i:i + 20]
            print >> sys.stderr, "test: piece", i / 20, "hash", ` hash `
            piece_hashes.append(hash)

        print >> sys.stderr, "test: Putting", len(
            piece_hashes), "into MerkleTree, size", self.tdef.get_piece_length(
            ), tdef2.get_piece_length()

        self.tree = MerkleTree(self.tdef.get_piece_length(),
                               self.tdef.get_length(), None, piece_hashes)

        f = open(self.sourcefn, "rb")
        piece1 = f.read(2**18)
        piece2 = f.read(2**18)
        print >> sys.stderr, "read piece1", len(piece1)
        print >> sys.stderr, "read piece2", len(piece2)
        f.close()
        hash1 = sha(piece1).digest()
        hash2 = sha(piece2).digest()
        print >> sys.stderr, "hash piece1", ` hash1 `
        print >> sys.stderr, "hash piece2", ` hash2 `
        f2 = open("piece1.bin", "wb")
        f2.write(piece2)
        f2.close()
Example #10
0
    def _test_proxy(self, genresdict):
        """ Send messages to the helper instance and test it.

            Testing ASK_FOR_HELP, STOP_HELPING, REQUEST_PIECES, CANCEL_PIECE and METADATA
        """
        # 1. Establish overlay connection to Tribler
        ol_connection = OLConnection(self.my_keypair,
                                     'localhost',
                                     self.hisport,
                                     mylistenport=self.mylistenport2)

        # 2. Send the ASK_FOR_HELP message
        (generate_data, sent_good_values) = genresdict[ASK_FOR_HELP]
        msg = generate_data()
        ol_connection.send(msg)
        if sent_good_values:
            # Read the helper's response
            resp = ol_connection.recv()
            # Check the helper's response
            # 3. At this point, the helper does not have the .torrent file, so it requests it with a METADATA message
            self.assert_(resp[0] == GET_METADATA)
            self.check_get_metadata(resp[1:])
            print >> sys.stderr, "test: Got GET_METADATA for torrent, good"
        else:
            # Read the helper's response
            resp = ol_connection.recv()
            # Check the helper's response
            self.assert_(len(resp) == 0)
            ol_connection.close()
            return

        # 4. Send METADATA
        (generate_data, sent_good_values) = genresdict[METADATA]
        msg = generate_data()
        ol_connection.send(msg)
        if sent_good_values:
            # 5. At this point the helper is confirming his availability to help
            # Read the helper's response
            resp = ol_connection.recv()
            # Check the helper's response
            self.assert_(resp[0] == JOIN_HELPERS)
            self.check_ask_for_help(resp)
            print >> sys.stderr, "test: Got JOIN_HELPERS for torrent, good"

            # 6. At this point, the helper will contact the tracker and then wait for REQUEST_PIECES messages
            # So we send a request pieces message
            (generate_data, sent_good_values) = genresdict[REQUEST_PIECES]
            msg = generate_data()
            ol_connection.send(msg)

            # At this point the helper will contact the seeders in the swarm to download the requested piece
            # There is only one seeder in the swarm, the coordinator's twin
            # 8. Our tracker says there is another peer (also us) on port 4810
            # Now accept a connection on that port and pretend we're a seeder
            self.myss.settimeout(10.0)
            conn, addr = self.myss.accept()
            options = '\x00\x00\x00\x00\x00\x00\x00\x00'
            s2 = BTConnection('',
                              0,
                              conn,
                              user_option_pattern=options,
                              user_infohash=self.infohash,
                              myid=self.myid)
            s2.read_handshake_medium_rare()

            # Send a bitfield message to the helper (pretending we are a regular seeder)
            b = Bitfield(self.numpieces)
            for i in range(self.numpieces):
                b[i] = True
            self.assert_(b.complete())
            msg = BITFIELD + b.tostring()
            s2.send(msg)
            msg = UNCHOKE
            s2.send(msg)
            print >> sys.stderr, "test: Got BT connection to us, as fake seeder, good"
        else:
            resp = ol_connection.recv()
            self.assert_(len(resp) == 0)
            ol_connection.close()
            return

        # 7. Accept the data connection the helper wants to establish with us, the coordinator.
        # The helper will send via this connection the pieces we request it to download.
        self.myss2.settimeout(10.0)
        conn, addr = self.myss2.accept()
        s3 = BTConnection('',
                          0,
                          conn,
                          user_infohash=self.infohash,
                          myid=self.myid2)
        s3.read_handshake_medium_rare()

        msg = UNCHOKE
        s3.send(msg)
        print >> sys.stderr, "test: Got data connection to us, as coordinator, good"

        # 9. At this point the helper should sent a PROXY_HAVE message on the overlay connection
        #        resp = ol_connection.recv()
        #        self.assert_(resp[0] == PROXY_HAVE)
        #        print >>sys.stderr,"test: Got PROXY)HAVE, good"

        # 10. Await REQUEST on fake seeder
        try:
            while True:
                s2.s.settimeout(10.0)
                resp = s2.recv()
                self.assert_(len(resp) > 0)
                print "test: Fake seeder got message", getMessageName(resp[0])
                if resp[0] == REQUEST:
                    self.check_request(resp[1:])
                    print >> sys.stderr, "test: Fake seeder got REQUEST for reserved piece, good"
                    break

        except socket.timeout:
            print >> sys.stderr, "test: Timeout, bad, fake seeder didn't reply with message"
            self.assert_(False)

        # 11. Sent the helper a STOP_HELPING message
        (generate_data, sent_good_values) = genresdict[STOP_HELPING]
        msg = generate_data()
        ol_connection.send(msg)
        # The other side should close the connection, whether the msg was good or bad
        resp = ol_connection.recv()
        self.assert_(len(resp) == 0)
        ol_connection.close()
Example #11
0
    def got_message(self, connection, message):
        # connection: Encrypter.Connection; c: Connecter.Connection
        c = self.connections[connection]
        t = message[0]
        # EXTEND handshake will be sent just after BT handshake,
        # before BITFIELD even

        st = time.time()

        if DEBUG_NORMAL_MSGS:
            print >> sys.stderr, "connecter: Got", getMessageName(
                t), connection.get_ip()

        if t == EXTEND:
            self.got_extend_message(connection, c, message,
                                    self.ut_pex_enabled)
            return
        if t == BITFIELD and c.got_anything:
            if DEBUG:
                print >> sys.stderr, "Close on BITFIELD"
            connection.close()
            return
        c.got_anything = True
        if (t in [CHOKE, UNCHOKE, INTERESTED, NOT_INTERESTED]
                and len(message) != 1):
            if DEBUG:
                print >> sys.stderr, "Close on bad (UN)CHOKE/(NOT_)INTERESTED", t
            connection.close()
            return
        if t == CHOKE:
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got CHOKE from", connection.get_ip(
                )
            c.download.got_choke()
        elif t == UNCHOKE:
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got UNCHOKE from", connection.get_ip(
                )
            c.download.got_unchoke()
        elif t == INTERESTED:
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got INTERESTED from", connection.get_ip(
                )
            if c.upload is not None:
                c.upload.got_interested()
        elif t == NOT_INTERESTED:
            c.upload.got_not_interested()
        elif t == HAVE:
            if len(message) != 5:
                if DEBUG:
                    print >> sys.stderr, "Close on bad HAVE: msg len"
                connection.close()
                return
            i = toint(message[1:])
            if i >= self.numpieces:
                if DEBUG:
                    print >> sys.stderr, "Close on bad HAVE: index out of range"
                connection.close()
                return
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got HAVE(", i, ") from", connection.get_ip(
                )
            c.download.got_have(i)
        elif t == BITFIELD:
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got BITFIELD from", connection.get_ip(
                )
            try:
                b = Bitfield(self.numpieces, message[1:])
            except ValueError:
                if DEBUG:
                    print >> sys.stderr, "Close on bad BITFIELD"
                connection.close()
                return
            if c.download is not None:
                c.download.got_have_bitfield(b)
        elif t == REQUEST:
            #print >>sys.stderr, "MOJO message: PoPOPOPO...Poker Face"
            #print >>sys.stderr,"connecter: Got REQUEST(",toint(message[1:5]),") from",connection.get_ip()
            if len(message) != 13:
                if DEBUG:
                    print >> sys.stderr, "Close on bad REQUEST: msg len"
                connection.close()
                return
            i = toint(message[1:5])
            if i >= self.numpieces:
                if DEBUG:
                    print >> sys.stderr, "Close on bad REQUEST: index out of range"
                connection.close()
                return
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got REQUEST(", i, ") from", connection.get_ip(
                )
            c.got_request(i, toint(message[5:9]), toint(message[9:]))
        elif t == CANCEL:
            if len(message) != 13:
                if DEBUG:
                    print >> sys.stderr, "Close on bad CANCEL: msg len"
                connection.close()
                return
            i = toint(message[1:5])
            if i >= self.numpieces:
                if DEBUG:
                    print >> sys.stderr, "Close on bad CANCEL: index out of range"
                connection.close()
                return
            c.upload.got_cancel(i, toint(message[5:9]), toint(message[9:]))
        elif t == PIECE:
            x.update("RCVCOUNT", float(x.data["RCVCOUNT"][0]) + 1)
            if len(message) <= 9:
                if DEBUG:
                    print >> sys.stderr, "Close on bad PIECE: msg len"
                connection.close()
                return
            i = toint(message[1:5])
            if i >= self.numpieces:
                if DEBUG:
                    print >> sys.stderr, "Close on bad PIECE: msg len"
                connection.close()
                return
            if DEBUG_NORMAL_MSGS:
                print >> sys.stderr, "connecter: Got PIECE(", i, ") from", connection.get_ip(
                )

            try:
                if c.download.got_piece(i, toint(message[5:9]), [],
                                        message[9:]):
                    self.got_piece(i)
            except Exception, e:
                if DEBUG:
                    print >> sys.stderr, "Close on bad PIECE: exception", str(
                        e)
                    traceback.print_exc()
                connection.close()
                return
    def _test_2fast(self, genresdict):
        """
            test ASK_FOR_HELP, METADATA, PIECES_RESERVED and STOP_DOWNLOAD_HELP sequence
        """
        # 1. Establish overlay connection to Tribler
        s = OLConnection(self.my_keypair,
                         'localhost',
                         self.hisport,
                         mylistenport=self.mylistenport2)

        (func, good) = genresdict[ASK_FOR_HELP]
        msg = func()
        s.send(msg)
        if good:
            resp = s.recv()
            self.assert_(resp[0] == GET_METADATA)
            self.check_get_metadata(resp[1:])
            print >> sys.stderr, "test: Got GET_METADATA for torrent, good"
        else:
            resp = s.recv()
            self.assert_(len(resp) == 0)
            s.close()
            return

        (func, good) = genresdict[METADATA]
        msg = func()
        s.send(msg)

        if good:
            # 2. Accept the data connection Tribler wants to establish with us, the coordinator
            self.myss2.settimeout(10.0)
            conn, addr = self.myss2.accept()
            s3 = BTConnection('',
                              0,
                              conn,
                              user_infohash=self.infohash,
                              myid=self.myid2)
            s3.read_handshake_medium_rare()

            msg = UNCHOKE
            s3.send(msg)
            print >> sys.stderr, "test: Got data connection to us, as coordinator, good"
        else:
            resp = s.recv()
            self.assert_(len(resp) == 0)
            s.close()
            return

        # 3. Our tracker says there is another peer (also us) on port 4810
        # Now accept a connection on that port and pretend we're a seeder
        self.myss.settimeout(10.0)
        conn, addr = self.myss.accept()
        options = '\x00\x00\x00\x00\x00\x00\x00\x00'
        s2 = BTConnection('',
                          0,
                          conn,
                          user_option_pattern=options,
                          user_infohash=self.infohash,
                          myid=self.myid)
        s2.read_handshake_medium_rare()

        numpieces = 10  # must correspond to the torrent in test/extend_hs_dir
        b = Bitfield(numpieces)
        for i in range(numpieces):
            b[i] = True
        self.assert_(b.complete())
        msg = BITFIELD + b.tostring()
        s2.send(msg)
        msg = UNCHOKE
        s2.send(msg)
        print >> sys.stderr, "test: Got BT connection to us, as fake seeder, good"

        # 4. Await a RESERVE_PIECES message on the overlay connection
        resp = s.recv()
        self.assert_(resp[0] == RESERVE_PIECES)
        pieces = self.check_reserve_pieces(resp[1:])
        print >> sys.stderr, "test: Got RESERVE_PIECES, good"

        (func, good) = genresdict[PIECES_RESERVED]

        # 5. Reply with PIECES_RESERVED
        msg = func(pieces)
        s.send(msg)

        if good:
            # 6. Await REQUEST on fake seeder
            try:
                while True:
                    s2.s.settimeout(10.0)
                    resp = s2.recv()
                    self.assert_(len(resp) > 0)
                    print "test: Fake seeder got message", getMessageName(
                        resp[0])
                    if resp[0] == REQUEST:
                        self.check_request(resp[1:], pieces)
                        print >> sys.stderr, "test: Fake seeder got REQUEST for reserved piece, good"
                        break

            except socket.timeout:
                print >> sys.stderr, "test: Timeout, bad, fake seeder didn't reply with message"
                self.assert_(False)
        else:
            resp = s.recv()
            self.assert_(len(resp) == 0)
            s.close()
            return

        (func, good) = genresdict[STOP_DOWNLOAD_HELP]
        # 5. Reply with STOP_DOWNLOAD_HELP
        msg = func()
        s.send(msg)

        # the other side should close the connection, whether the msg was good or bad
        resp = s.recv()
        self.assert_(len(resp) == 0)
        s.close()
Example #13
0
    def _test_2fast(self, genresdict):
        """
            test ASK_FOR_HELP, METADATA, PIECES_RESERVED and STOP_DOWNLOAD_HELP sequence
        """
        # 1. Establish overlay connection to Tribler
        ol_connection = OLConnection(self.my_keypair,
                                     'localhost',
                                     self.hisport,
                                     mylistenport=self.mylistenport2)

        # Send ASK_FOR_HELP
        (generate_data, sent_good_values) = genresdict[ASK_FOR_HELP]
        msg = generate_data()
        ol_connection.send(msg)
        if sent_good_values:
            resp = ol_connection.recv()
            self.assert_(resp[0] == GET_METADATA)
            self.check_get_metadata(resp[1:])
            print >> sys.stderr, "test: Got GET_METADATA for torrent, sent_good_values"
        else:
            resp = ol_connection.recv()
            self.assert_(len(resp) == 0)
            ol_connection.close()
            return

        # Send METADATA
        (generate_data, sent_good_values) = genresdict[METADATA]
        msg = generate_data()
        ol_connection.send(msg)

        if sent_good_values:
            # 2. Accept the data connection Tribler wants to establish with us, the coordinator
            self.myss2.settimeout(10.0)
            conn, addr = self.myss2.accept()
            #(self,hostname,port,opensock=None,user_option_pattern=None,user_infohash=None,myid=None,mylistenport=None,myoversion=None):
            bt_connection_2 = BTConnection('',
                                           0,
                                           conn,
                                           user_infohash=self.infohash,
                                           myid=self.myid2)
            bt_connection_2.read_handshake_medium_rare()

            msg = UNCHOKE
            bt_connection_2.send(msg)
            print >> sys.stderr, "test: Got data connection to us, as coordinator, sent_good_values"
        else:
            resp = ol_connection.recv()
            self.assert_(len(resp) == 0)
            ol_connection.close()
            return

        # 3. Our tracker says there is another peer (also us) on port 4810
        # Now accept a connection on that port and pretend we're a seeder
        self.myss.settimeout(10.0)
        conn, addr = self.myss.accept()
        options = '\x00\x00\x00\x00\x00\x00\x00\x00'
        bt_connection = BTConnection('',
                                     0,
                                     conn,
                                     user_option_pattern=options,
                                     user_infohash=self.infohash,
                                     myid=self.myid)
        bt_connection.read_handshake_medium_rare()

        # Get the number of pieces from the .torrent file
        torrentfile_content = open(self.torrentfile, "rb")
        metadata_dict = bdecode(torrentfile_content.read())
        torrentfile_content.close()
        if "length" in metadata_dict["info"]:
            length = metadata_dict["info"]["length"]
        else:
            length = 0
            for file in metadata_dict["info"]["files"]:
                length += file["length"]
        numpieces = length / metadata_dict["info"]["piece length"]

        bitf = Bitfield(numpieces)
        for i in range(numpieces):
            bitf[i] = True
        self.assert_(bitf.complete())
        msg = BITFIELD + bitf.tostring()
        bt_connection.send(msg)
        msg = UNCHOKE
        bt_connection.send(msg)
        print >> sys.stderr, "test: Got BT connection to us, as fake seeder, sent_good_values"

        # 4. Await a RESERVE_PIECES message on the overlay connection
        resp = ol_connection.recv()
        self.assert_(resp[0] == RESERVE_PIECES)
        pieces = self.check_reserve_pieces(resp[1:])
        print >> sys.stderr, "test: Got RESERVE_PIECES, sent_good_values"

        # 5. Reply with PIECES_RESERVED
        (generate_data, sent_good_values) = genresdict[PIECES_RESERVED]
        msg = generate_data(pieces)
        ol_connection.send(msg)

        if sent_good_values:
            # 6. Await REQUEST on fake seeder
            while True:
                resp = bt_connection.recv()
                self.assert_(len(resp) > 0)
                print "test: Fake seeder got message", getMessageName(resp[0])
                if resp[0] == REQUEST:
                    self.check_request(resp[1:], pieces)
                    print >> sys.stderr, "test: Fake seeder got REQUEST for reserved piece, sent_good_values"
                    break
        else:
            resp = ol_connection.recv()
            self.assert_(len(resp) == 0)
            ol_connection.close()
            return

        # 7. Reply with STOP_DOWNLOAD_HELP
        (generate_data, sent_good_values) = genresdict[STOP_DOWNLOAD_HELP]
        msg = generate_data()
        ol_connection.send(msg)

        # the other side should close the connection, whether the msg was sent_good_values or bad
        resp = ol_connection.recv()
        self.assert_(len(resp) == 0)
        ol_connection.close()
Example #14
0
    def got_have_bitfield(self, have):
        if self.downloader.picker.am_I_complete() and have.complete():
            # Arno: If we're both seeds
            if self.downloader.super_seeding:
                self.connection.send_bitfield(
                    have.tostring())  # be nice, show you're a seed too

            # Niels: We're both seeds, but try to get some additional peers from this seed
            self.connection.try_send_pex()

            def auto_close():
                self.connection.close()
                self.downloader.add_disconnected_seed(
                    self.connection.get_readable_id())

            self.downloader.scheduler(auto_close, REPEX_LISTEN_TIME)
            return

        if DEBUGBF:
            st = time.time()

        if have.complete():
            # Arno: He is seed
            self.downloader.picker.got_seed()
        else:
            # Arno: pass on HAVE knowledge to PiecePicker and if LIVEWRAP:
            # filter out valid pieces

            # STBSPEED: if we haven't hooked in yet, don't iterate over whole range
            # just over the active ranges in the received Bitfield
            activerangeiterators = []
            if self.downloader.picker.videostatus and self.downloader.picker.videostatus.live_streaming and self.downloader.picker.videostatus.get_live_startpos(
            ) is None:
                # Not hooked in
                activeranges = have.get_active_ranges()

                if len(activeranges) == 0:
                    # Bug, fallback to whole range
                    activerangeiterators = [
                        self.downloader.picker.get_valid_range_iterator()
                    ]
                else:
                    # Create iterators for the active ranges
                    for (s, e) in activeranges:
                        activerangeiterators.append(xrange(s, e + 1))
            else:
                # Hooked in, use own valid range as active range

                # Arno, 2010-04-20: Not correct for VOD with seeking, then we
                # should store the HAVE info for things before playback too.

                activerangeiterators = [
                    self.downloader.picker.get_valid_range_iterator()
                ]

            if DEBUGBF:
                print >> sys.stderr, "Downloader: got_have_field: live: Filtering bitfield", activerangeiterators

            if not self.downloader.picker.videostatus or self.downloader.picker.videostatus.live_streaming:
                if DEBUGBF:
                    print >> sys.stderr, "Downloader: got_have_field: live or normal filter"
                # Transfer HAVE knowledge to PiecePicker and filter pieces if live
                validhave = Bitfield(self.downloader.numpieces)
                for iterator in activerangeiterators:
                    for i in iterator:
                        if have[i]:
                            validhave[i] = True
                            self.downloader.picker.got_have(i, self.connection)
            else:  # VOD
                if DEBUGBF:
                    print >> sys.stderr, "Downloader: got_have_field: VOD filter"
                validhave = Bitfield(self.downloader.numpieces)
                (first,
                 last) = self.downloader.picker.videostatus.download_range()
                for i in xrange(first, last):
                    if have[i]:
                        validhave[i] = True
                        self.downloader.picker.got_have(i, self.connection)
            # ProxyService_
            #
            # Aggregate the haves bitfields and send them to the doe nodes
            # ARNOPS: Shouldn't this be done after have = validhave?
            self.downloader.aggregate_and_send_haves()
            #
            # _ProxyService
            """
            # SANITY CHECK
            checkhave = Bitfield(self.downloader.numpieces)
            for i in self.downloader.picker.get_valid_range_iterator():
                if have[i]:
                    checkhave[i] = True

            assert validhave.tostring() == checkhave.tostring()
            """

            # Store filtered bitfield instead of received one
            have = validhave

        if DEBUGBF:
            et = time.time()
            diff = et - st
            print >> sys.stderr, "Download: got_have_field: took", diff

        self.have = have

        #print >>sys.stderr,"Downloader: got_have_bitfield: valid",`have.toboollist()`

        if self.downloader.endgamemode and not self.downloader.paused:
            for piece, begin, length in self.downloader.all_requests:
                if self.have[piece]:
                    self.send_interested()
                    break
            return
        self._check_interests()