def subtest_add_content_piece_length(self): """ Add a single file with piece length to a TorrentDef """ t = TorrentDef() fn = os.path.join(TESTS_API_DIR, "video.avi") t.add_content(fn) t.set_piece_length(2**16) t.set_tracker(TRACKER) t.finalize() metainfo = t.get_metainfo() self.general_check(metainfo) self.assert_(metainfo['info']['piece length'] == 2**16)
def subtest_add_content_piece_length(self): """ Add a single file with piece length to a TorrentDef """ t = TorrentDef() fn = os.path.join(TESTS_API_DIR, "video.avi") t.add_content(fn) t.set_piece_length(2 ** 16) t.set_tracker(TRACKER) t.finalize() metainfo = t.get_metainfo() self.general_check(metainfo) self.assert_(metainfo['info']['piece length'] == 2 ** 16)
def test_add_content_piece_length(self): """ Add a single file with piece length to a TorrentDef """ t = TorrentDef() fn = os.path.join(TESTS_DATA_DIR, VIDEO_FILE_NAME) t.add_content(fn) t.set_piece_length(2**16) t.save() metainfo = t.get_metainfo() self.assertEqual(metainfo['info']['piece length'], 2**16)
def test_add_content_piece_length(self): """ Add a single file with piece length to a TorrentDef """ t = TorrentDef() fn = os.path.join(TESTS_DATA_DIR, self.VIDEO_FILE_NAME) t.add_content(fn) t.set_piece_length(2 ** 16) t.set_tracker(TRACKER) t.finalize() metainfo = t.get_metainfo() self.general_check(metainfo) self.assertEqual(metainfo['info']['piece length'], 2 ** 16)
def test_add_content_piece_length(self): """ Add a single file with piece length to a TorrentDef """ t = TorrentDef() fn = os.path.join(TESTS_DATA_DIR, self.VIDEO_FILE_NAME) t.add_content(fn) t.set_piece_length(2**16) t.set_tracker(TRACKER) t.finalize() metainfo = t.get_metainfo() self.general_check(metainfo) self.assertEqual(metainfo['info']['piece length'], 2**16)
class TestVideoOnDemand(TestAsServer): """ Testing Merkle hashpiece messages for both: * Merkle BEP style * old Tribler <= 4.5.2 that did not use the Extention protocol (BEP 10). See BitTornado/BT1/Connecter.py """ @inlineCallbacks def setUp(self): yield TestAsServer.setUp(self) self.content = None self.tdef = None self.test_deferred = Deferred() self.contentlen = None self.piecelen = 0 def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent_enabled(True) def create_torrent(self): [srchandle, sourcefn] = mkstemp() self.content = Rand.rand_bytes(self.contentlen) os.write(srchandle, self.content) os.close(srchandle) self.tdef = TorrentDef() self.tdef.add_content(sourcefn) self.tdef.set_piece_length(self.piecelen) self.tdef.set_tracker("http://127.0.0.1:12/announce") self.tdef.finalize() torrentfn = os.path.join(self.session.config.get_state_dir(), "gen.torrent") self.tdef.save(torrentfn) dscfg = DownloadStartupConfig() destdir = os.path.dirname(sourcefn) dscfg.set_dest_dir(destdir) dscfg.set_mode(DLMODE_VOD) download = self.session.start_download_from_tdef(self.tdef, dscfg) download.set_state_callback(self.state_callback) self.session.set_download_states_callback(self.states_callback) def states_callback(self, dslist): ds = dslist[0] d = ds.get_download() self._logger.debug('%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s', d.get_def().get_name(), dlstatus_strings[ds.get_status()], ds.get_progress() * 100, ds.get_error(), ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) return [] def state_callback(self, ds): download = ds.get_download() if ds.get_vod_prebuffering_progress() == 1.0: self._logger.debug("Test: state_callback") stream = VODFile(open(download.get_content_dest(), 'rb'), download) # Read last piece lastpieceoff = ((self.contentlen - 1) / self.piecelen) * self.piecelen lastpiecesize = self.contentlen - lastpieceoff self._logger.debug("stream: lastpieceoff %s %s", lastpieceoff, lastpiecesize) self.stream_read(stream, lastpieceoff, lastpiecesize, self.piecelen) # Read second,3rd,4th byte, only secoff = 1 secsize = 3 blocksize = 3 self.stream_read(stream, secoff, secsize, blocksize) # Read last byte lastoff = self.contentlen - 1 lastsize = 1 self.stream_read(stream, lastoff, lastsize, self.piecelen) self.test_deferred.callback(None) return 0 return 1.0 def stream_read(self, stream, off, size, blocksize): stream.seek(off) data = stream.read(blocksize) self._logger.debug("stream: Got data %s", len(data)) self.assertEquals(len(data), size) self.assertEquals(data, self.content[off:off + size]) @trial_timeout(10) def test_99(self): self.contentlen = 99 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred @trial_timeout(10) def test_100(self): self.contentlen = 100 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred @trial_timeout(10) def test_101(self): self.contentlen = 101 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred
class TestMetadata(TestAsServer, MagnetHelpers): """ Once we are downloading a torrent, our client should respond to the ut_metadata extention message. This allows other clients to obtain the info part of the metadata from us. """ def setUp(self): """ override TestAsServer """ TestAsServer.setUp(self) print >>sys.stderr,"test: Giving MyLaunchMany time to startup" time.sleep(5) print >>sys.stderr,"test: MyLaunchMany should have started up" # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(os.getcwd(), "API", "file.wmv")) self.tdef.set_tracker(self.session.get_internal_tracker_url()) # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() # self.tdef.save(os.path.join(self.session.get_state_dir(), "gen.torrent")) MagnetHelpers.__init__(self, self.tdef) def setup_seeder(self): self.seeder_setup_complete = False self.seeder_teardown_complete = False self.seeder_teardown = False self.dscfg = DownloadStartupConfig() self.dscfg.set_dest_dir(os.getcwd()) self.download = self.session.start_download(self.tdef, self.dscfg) self.download.set_state_callback(self.seeder_state_callback) counter = 0 while not self.seeder_setup_complete: counter += 1 time.sleep(1) assert counter < 30, "timeout" print >> sys.stderr, "test: setup_seeder() complete" def teardown_seeder(self): self.seeder_teardown_complete = False self.session.remove_download(self.download) counter = 0 while not self.seeder_setup_complete: counter += 1 time.sleep(1) assert counter < 30, "timeout" print >> sys.stderr, "test: teardown_seeder() complete" def seeder_state_callback(self,ds): assert not self.seeder_teardown_complete self.seeder_setup_complete = (ds.get_status() == DLSTATUS_DOWNLOADING) d = ds.get_download() print >> sys.stderr, "test: seeder:", `d.get_def().get_name()`, dlstatus_strings[ds.get_status()], ds.get_progress() if self.seeder_teardown: self.seeder_teardown_complete = True else: return (1.0, False) def test_all(self): self.setup_seeder() try: self.subtest_good_flood() finally: self.teardown_seeder() self.setup_seeder() try: self.subtest_good_request() self.subtest_bad_request() finally: self.teardown_seeder() def subtest_good_request(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # request metadata block 0, 2, 3, and the last conn.send(self.create_good_extend_metadata_request(metadata_id, 0)) conn.send(self.create_good_extend_metadata_request(metadata_id, 2)) conn.send(self.create_good_extend_metadata_request(metadata_id, 3)) conn.send(self.create_good_extend_metadata_request(metadata_id, len(self.metadata_list) - 1)) self.read_extend_metadata_reply(conn, 0) self.read_extend_metadata_reply(conn, 2) self.read_extend_metadata_reply(conn, 3) self.read_extend_metadata_reply(conn, len(self.metadata_list) - 1) def subtest_good_flood(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) for counter in xrange(len(self.metadata_list) * 2): piece = counter % len(self.metadata_list) conn.send(self.create_good_extend_metadata_request(metadata_id, piece)) if counter > len(self.metadata_list): self.read_extend_metadata_reject(conn, piece) else: self.read_extend_metadata_reply(conn, piece) def subtest_bad_request(self): self.bad_request_and_disconnect({"msg_type":0, "piece":len(self.metadata_list)}) self.bad_request_and_disconnect({"msg_type":0, "piece":-1}) self.bad_request_and_disconnect({"msg_type":0, "piece":"1"}) self.bad_request_and_disconnect({"msg_type":0, "piece":[1,2]}) self.bad_request_and_disconnect({"msg_type":0, "PIECE":1}) def bad_request_and_disconnect(self, payload): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) conn.send(EXTEND + chr(metadata_id) + bencode(payload)) self.read_extend_metadata_close(conn)
def test_set_piece_length_invalid_type(self): t = TorrentDef() t.set_piece_length("20")
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", repr(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", repr(hash1) print >> sys.stderr, "hash piece2", repr(hash2) f2 = open("piece1.bin", "wb") f2.write(piece2) f2.close()
class TestMagnetFakePeer(TestAsServer, MagnetHelpers): """ A MiniBitTorrent instance is used to connect to BitTorrent clients and download the info part from the metadata. """ def setUp(self): # listener for incoming connections from MiniBitTorrent self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.bind(("", self.session.get_listen_port())) self.server.listen(5) TestAsServer.setUp(self) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(TESTS_API_DIR, "video.avi")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() MagnetHelpers.__init__(self, self.tdef) def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) def create_good_url(self, infohash=None, title=None, tracker=None): url = "magnet:?xt=urn:btih:" if infohash: assert isinstance(infohash, str) url += hexlify(infohash) else: url += hexlify(self.tdef.get_infohash()) if title: assert isinstance(title, str) url += "&dn=" + title if tracker: assert isinstance(tracker, str) url += "&tr=" + tracker return url @skip("not working, seems to return binary data") def test_good_transfer(self): def torrentdef_retrieved(meta_info): tags["metainfo"] = meta_info tags["retrieved"].set() tags = {"retrieved": threading.Event()} self.session.lm.ltmgr.get_metainfo(self.create_good_url(), torrentdef_retrieved, timeout=60) def do_supply(): # supply fake addresses (regular dht obviously wont work here) ltmgr = LibtorrentMgr.getInstance() for infohash in ltmgr.metainfo_requests: handle = ltmgr.ltsession.find_torrent( lt.big_number(infohash.decode('hex'))) handle.connect_peer( ("127.0.0.1", self.session.get_listen_port()), 0) self.session.lm.threadpool.add_task(do_supply, delay=5.0) # accept incoming connection # self.server.settimeout(10.0) sock, address = self.server.accept() assert sock, "No incoming connection" # handshakes conn = BTConnection(address[0], address[1], opensock=sock, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # serve pieces for counter in xrange(len(self.metadata_list)): piece = self.read_extend_metadata_request(conn) assert 0 <= piece < len(self.metadata_list) conn.send( self.create_good_extend_metadata_reply(metadata_id, piece)) # no more metadata request may be send and the connection must # be closed self.read_extend_metadata_close(conn) assert tags["retrieved"].wait(5) assert tags["metainfo"]["info"] == self.tdef.get_metainfo()["info"]
class TestVideoOnDemand(TestAsServer): """ Testing Merkle hashpiece messages for both: * Merkle BEP style * old Tribler <= 4.5.2 that did not use the Extention protocol (BEP 10). See BitTornado/BT1/Connecter.py """ @blocking_call_on_reactor_thread @inlineCallbacks def setUp(self, autoload_discovery=True): yield TestAsServer.setUp(self, autoload_discovery=autoload_discovery) self.content = None self.tdef = None self.test_deferred = Deferred() self.contentlen = None self.piecelen = 0 def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent_enabled(True) def create_torrent(self): [srchandle, sourcefn] = mkstemp() self.content = Rand.rand_bytes(self.contentlen) os.write(srchandle, self.content) os.close(srchandle) self.tdef = TorrentDef() self.tdef.add_content(sourcefn) self.tdef.set_piece_length(self.piecelen) self.tdef.set_tracker("http://127.0.0.1:12/announce") self.tdef.finalize() torrentfn = os.path.join(self.session.config.get_state_dir(), "gen.torrent") self.tdef.save(torrentfn) dscfg = DownloadStartupConfig() destdir = os.path.dirname(sourcefn) dscfg.set_dest_dir(destdir) dscfg.set_mode(DLMODE_VOD) download = self.session.start_download_from_tdef(self.tdef, dscfg) download.set_state_callback(self.state_callback) self.session.set_download_states_callback(self.states_callback) def states_callback(self, dslist): ds = dslist[0] d = ds.get_download() self._logger.debug('%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s', d.get_def().get_name(), dlstatus_strings[ds.get_status()], ds.get_progress() * 100, ds.get_error(), ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) return [] def state_callback(self, ds): download = ds.get_download() if ds.get_vod_prebuffering_progress() == 1.0: self._logger.debug("Test: state_callback") stream = VODFile(open(download.get_content_dest(), 'rb'), download) # Read last piece lastpieceoff = ( (self.contentlen - 1) / self.piecelen) * self.piecelen lastpiecesize = self.contentlen - lastpieceoff self._logger.debug("stream: lastpieceoff %s %s", lastpieceoff, lastpiecesize) self.stream_read(stream, lastpieceoff, lastpiecesize, self.piecelen) # Read second,3rd,4th byte, only secoff = 1 secsize = 3 blocksize = 3 self.stream_read(stream, secoff, secsize, blocksize) # Read last byte lastoff = self.contentlen - 1 lastsize = 1 self.stream_read(stream, lastoff, lastsize, self.piecelen) self.test_deferred.callback(None) return 0 return 1.0 def stream_read(self, stream, off, size, blocksize): stream.seek(off) data = stream.read(blocksize) self._logger.debug("stream: Got data %s", len(data)) self.assertEquals(len(data), size) self.assertEquals(data, self.content[off:off + size]) @deferred(timeout=10) def test_99(self): self.contentlen = 99 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred @deferred(timeout=10) def test_100(self): self.contentlen = 100 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred @deferred(timeout=10) def test_101(self): self.contentlen = 101 self.piecelen = 16 self.create_torrent() self._logger.debug("Letting network thread create Download, sleeping") return self.test_deferred
def make_meta_file(srcpaths, params, userabortflag, progressCallback, torrentfilenameCallback): tdef = TorrentDef() basedir = None if len(srcpaths) > 1: basepath = [] for srcpath in srcpaths: path, filename = os.path.split(srcpath) basepath.append(path) basepath, basedir = os.path.split(os.path.commonprefix(basepath)) for srcpath in srcpaths: outpath = os.path.relpath(srcpath, basepath) # h4x0r playtime if "playtime" in params: tdef.add_content(srcpath, outpath, playtime=params["playtime"]) else: tdef.add_content(srcpath, outpath) else: srcpath = srcpaths[0] basepath, _ = os.path.split(srcpath) if "playtime" in params: tdef.add_content(srcpath, playtime=params["playtime"]) else: tdef.add_content(srcpath) if params["name"]: tdef.set_name(params["name"]) if params["comment"]: tdef.set_comment(params["comment"]) if params["created by"]: tdef.set_created_by(params["created by"]) if params["announce"]: tdef.set_tracker(params["announce"]) if params["announce-list"]: tdef.set_tracker_hierarchy(params["announce-list"]) if params["nodes"]: # mainline DHT tdef.set_dht_nodesmax(params["nodes"]) if params["httpseeds"]: tdef.set_httpseeds(params["httpseeds"]) if params["encoding"]: tdef.set_encoding(params["encoding"]) if params["piece length"]: tdef.set_piece_length(params["piece length"]) if params["makehash_md5"]: print >>sys.stderr, "TorrentMaker: make MD5" tdef.set_add_md5hash(params["makehash_md5"]) if params["makehash_crc32"]: print >>sys.stderr, "TorrentMaker: make CRC32" tdef.set_add_crc32(params["makehash_crc32"]) if params["makehash_sha1"]: print >>sys.stderr, "TorrentMaker: make SHA1" tdef.set_add_sha1hash(params["makehash_sha1"]) if params["createmerkletorrent"]: tdef.set_create_merkle_torrent(params["createmerkletorrent"]) if params["torrentsigkeypairfilename"]: tdef.set_signature_keypair_filename(params["torrentsigkeypairfilename"]) if params["thumb"]: tdef.set_thumbnail(params["thumb"]) tdef.finalize(userabortflag=userabortflag, userprogresscallback=progressCallback) if params["createmerkletorrent"]: postfix = TRIBLER_TORRENT_EXT else: postfix = ".torrent" if params.get("target", False): torrentfilename = os.path.join(params["target"], os.path.split(os.path.normpath(srcpath))[1] + postfix) else: torrentfilename = os.path.join(basepath, tdef.get_name() + postfix) tdef.save(torrentfilename) # Inform higher layer we created torrent torrentfilenameCallback(basepath, basedir, torrentfilename)
class TestQueryReplyActive(TestAsServer): """ Testing QUERY_REPLY message of Query extension V1 This test checks how the Tribler code responds to good and bad QUERY_REPLY messages. I.e. the Tribler client initiates the dialback by connecting to us and sending a QUERY and we reply with good and bad messages. This test allows authoritative answers from superpeers. WARNING: Each of the test_ methods should be tested by running the TestCase in a separate Python interpreter to prevent problems with our singleton classes, e.g. SuperPeerDB, etc. """ def setUpPreSession(self): """ override TestAsServer """ print >> sys.stderr,"test: Pre Tribler Init" TestAsServer.setUpPreSession(self) print >> sys.stderr,"test: Pre Tribler Init: config_path",self.config_path # Enable remote querying self.config.set_remote_query(True) def setUpPostSession(self): """ override TestAsServer """ TestAsServer.setUpPostSession(self) self.hispermid = str(self.his_keypair.pub().get_der()) self.my_permid = str(self.my_keypair.pub().get_der()) def pretest_simple(self,keyword): self.pretest_q('SIMPLE',keyword) def pretest_simpleplustorrents(self,keyword): self.pretest_q('SIMPLE+METADATA',keyword) def pretest_q(self,queryprefix,keyword): query = queryprefix+' '+keyword self.content_name = keyword.upper()+' S22E44' self.tdef = TorrentDef() self.tdef.set_tracker('http://localhost:0/announce') self.tdef.set_piece_length(2 ** 15) self.tdef.create_live(self.content_name,2 ** 16) self.tdef.finalize() # 1. First connect to Tribler self.openconn = OLConnection(self.my_keypair,'localhost',self.hisport) sleep(3) # 2. Make Tribler send query self.query = query self.session.query_connected_peers(query,self.query_usercallback,max_peers_to_query=10) def query_usercallback(self,permid,query,hits): print >>sys.stderr,"test: query_usercallback:",`permid`,`query`,`hits` self.assert_(query == self.query) self.assert_(permid == self.my_permid) self.check_good_qreply(hits) # TODO: if SIMPLE+METADATA: check torrent now in db. # # Good SIMPLE QUERY, builds on TestQueryReply code # def singtest_good_simple_reply(self): self.pretest_simple('hallo') self._test_qreply(self.create_good_simple_reply,True) # # Good SIMPLE+METADATA QUERY, builds on TestQueryReply code # def singtest_good_simpleplustorrents_reply(self): self.pretest_simpleplustorrents('hallo') self._test_qreply(self.create_good_simpleplustorrents_reply,True) # # Good SIMPLE QUERY Unicode, builds on TestQueryReply code # def singtest_good_simple_reply_unicode(self): self.pretest_simple(u'Ch\u00e8rie') self._test_qreply(self.create_good_simple_reply,True) # # Good SIMPLE+METADATA QUERY Unicode, builds on TestQueryReply code # def singtest_good_simpleplustorrents_reply_unicode(self): self.pretest_simpleplustorrents(u'Ch\u00e8rie') self._test_qreply(self.create_good_simpleplustorrents_reply,True) # # Bad QUERY, builds on TestQueryReply code # def singtest_bad_not_bdecodable(self): self.pretest_simple('hallo') self._test_qreply(self.create_not_bdecodable,False) # # Bad SIMPLE+METADATA QUERY, builds on TestQueryReply code # def singtest_bad_not_bdecodable_torrentfile(self): self.pretest_simpleplustorrents('hallo') self._test_qreply(self.create_not_bdecodable_torrentfile,False) ### TODO: send different valid answers so consensus not reached # # Main test code # def _test_qreply(self,gen_qreply,good): print >> sys.stderr,"test: waiting for reply" s = self.openconn msg = s.recv() self.assert_(len(msg) > 0) print >> sys.stderr,"test: Received overlay message",getMessageName(msg[0]) self.assert_(msg[0] == QUERY) id = self.check_rquery(msg[1:]) resp = gen_qreply(id) print >> sys.stderr,"test: sending QUERY_REPLY" s.send(resp) if good: time.sleep(10) # the other side should not have closed the connection, as # this is all valid, so this should not throw an exception: s.send('bla') s.close() else: # the other side should not like this and close the connection self.assert_(len(s.recv())==0) s.close() def create_good_simple_reply_dict(self,id): r = {} r['content_name'] = self.content_name.encode("UTF-8") r['length'] = LENGTH r['leecher'] = LEECHERS r['seeder'] = SEEDERS r['category'] = CATEGORY # OLPROTO_PROTO_ELEVENTH # set later r['torrent_size'] = 42 r['channel_permid'] = '$' * 83 r['channel_name'] = 'Nitin Channel' d2 = {} d2[self.tdef.get_infohash()] = r d = {} d['id'] = id d['a'] = d2 return d def create_good_simple_reply(self,id): d = self.create_good_simple_reply_dict(id) bmetainfo = bencode(self.tdef.get_metainfo()) d['a'][self.tdef.get_infohash()]['torrent_size'] = len(bmetainfo) b = bencode(d) return QUERY_REPLY+b def create_good_simpleplustorrents_reply(self,id): d = self.create_good_simple_reply_dict(id) bmetainfo = bencode(self.tdef.get_metainfo()) d['a'][self.tdef.get_infohash()]['torrent_size'] = len(bmetainfo) d['a'][self.tdef.get_infohash()]['metatype'] = 'application/x-tribler-stream' d['a'][self.tdef.get_infohash()]['metadata'] = bmetainfo b = bencode(d) return QUERY_REPLY+b def check_good_qreply(self,hits): self.assert_(len(hits) == 1) self.assert_(hits.keys()[0] == self.tdef.get_infohash()) hit = hits[self.tdef.get_infohash()] self.assert_(hit['content_name'] == self.content_name) self.assert_(hit['length'] == LENGTH) self.assert_(hit['leecher'] == LEECHERS) self.assert_(hit['seeder'] == SEEDERS) self.assert_(hit['category'] == CATEGORY) # OLPROTO_VERSION_ELEVENTH bmetainfo = bencode(self.tdef.get_metainfo()) self.assert_(hit['torrent_size'] == len(bmetainfo)) if self.query.startswith('SIMPLE+METADATA'): self.assert_(hit['metadata'] == bmetainfo) def create_not_bdecodable(self,id): return QUERY_REPLY+"bla" def create_not_bdecodable_torrentfile(self,id): d = self.create_good_simple_reply_dict(id) d['a'][self.tdef.get_infohash()]['torrent_size'] = 3 # consistent with metadata. Should be named "metasize" d['a'][self.tdef.get_infohash()]['metadata'] = 'bla' b = bencode(d) return QUERY_REPLY+b 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']
class TestVideoOnDemand(TestAsServer): """ Testing Merkle hashpiece messages for both: * Merkle BEP style * old Tribler <= 4.5.2 that did not use the Extention protocol (BEP 10). See BitTornado/BT1/Connecter.py """ def setUp(self): """ override TestAsServer """ TestAsServer.setUp(self) self.vodstarted = False def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) def create_torrent(self): [srchandle, self.sourcefn] = mkstemp() self.content = Rand.rand_bytes(self.contentlen) os.write(srchandle, self.content) os.close(srchandle) self.tdef = TorrentDef() self.tdef.add_content(self.sourcefn) self.tdef.set_piece_length(self.piecelen) 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 = DownloadStartupConfig() destdir = os.path.dirname(self.sourcefn) dscfg.set_dest_dir(destdir) dscfg.set_video_event_callback(self.sesscb_vod_event_callback) self.session.set_download_states_callback(self.states_callback) self.session.start_download(self.tdef, dscfg) def states_callback(self, dslist): ds = dslist[0] d = ds.get_download() # print >>sys.stderr,`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD) print >> sys.stderr, '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s' % \ (d.get_def().get_name(), dlstatus_strings[ds.get_status()], ds.get_progress() * 100, ds.get_error(), ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) return (1.0, []) def sesscb_vod_event_callback(self, d, event, params): if self.vodstarted: return self.vodstarted = True print >> sys.stderr, "Test: vod_event_callback", event, params if event == VODEVENT_START: stream = params['stream'] # Read last piece lastpieceoff = ( (self.contentlen - 1) / self.piecelen) * self.piecelen lastpiecesize = self.contentlen - lastpieceoff print >> sys.stderr, "Test: stream: lastpieceoff", lastpieceoff, lastpiecesize self.stream_read(stream, lastpieceoff, lastpiecesize, self.piecelen) # Read second,3rd,4th byte, only secoff = 1 secsize = 3 blocksize = 3 self.stream_read(stream, secoff, secsize, blocksize) # Read last byte lastoff = self.contentlen - 1 lastsize = 1 self.stream_read(stream, lastoff, lastsize, self.piecelen) def stream_read(self, stream, off, size, blocksize): stream.seek(off) data = stream.read(blocksize) print >> sys.stderr, "Test: stream: Got data", len(data) self.assertEquals(len(data), size) self.assertEquals(data, self.content[off:off + size]) def test_99(self): self.contentlen = 99 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (9, 8)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 9) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 9) self.assertEqual(vs.movie_numpieces, 10) def test_100(self): self.contentlen = 100 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (9, 9)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 10) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 9) self.assertEqual(vs.movie_numpieces, 10) def test_101(self): self.contentlen = 101 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (10, 0)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 1) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 10) self.assertEqual(vs.movie_numpieces, 11)
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", repr(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", repr(hash1) print >> sys.stderr, "hash piece2", repr(hash2) f2 = open("piece1.bin", "wb") f2.write(piece2) f2.close()
class TestMagnetMiniBitTorrent(TestAsServer, MagnetHelpers): """ A MiniBitTorrent instance is used to connect to BitTorrent clients and download the info part from the metadata. """ def setUp(self): """ override TestAsServer """ # listener for incoming connections from MiniBitTorrent self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server.bind(("localhost", LISTEN_PORT)) self.server.listen(1) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(os.getcwd(), "API", "file.wmv")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() MagnetHelpers.__init__(self, self.tdef) # startup the client TestAsServer.setUp(self) print >> sys.stderr, "test: Giving MyLaunchMany time to startup" time.sleep(5) print >> sys.stderr, "test: MyLaunchMany should have started up" def create_good_url(self, infohash=None, title=None, tracker=None): url = "magnet:?xt=urn:btih:" if infohash: assert isinstance(infohash, str) url += hexlify(infohash) else: url += hexlify(self.tdef.get_infohash()) if title: assert isinstance(title, str) url += "&dn=" + title if tracker: assert isinstance(tracker, str) url += "&tr=" + tracker return url def test_good_transfer(self): def torrentdef_retrieved(tdef): tags["retrieved"] = True tags["metainfo"] = tdef.get_metainfo() tags = {"retrieved": False} assert TorrentDef.retrieve_from_magnet(self.create_good_url(), torrentdef_retrieved) # supply fake addresses (regular dht obviously wont work here) for magnetlink in MagnetHandler.get_instance().get_magnets(): magnetlink._swarm.add_potential_peers([("localhost", LISTEN_PORT)]) # accept incoming connection self.server.settimeout(10.0) sock, address = self.server.accept() assert sock, "No incoming connection" # handshakes conn = BTConnection(address[0], address[1], opensock=sock, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # serve pieces for counter in xrange(len(self.metadata_list)): piece = self.read_extend_metadata_request(conn) assert 0 <= piece < len(self.metadata_list) conn.send( self.create_good_extend_metadata_reply(metadata_id, piece)) # no more metadata request may be send and the connection must # be closed self.read_extend_metadata_close(conn) time.sleep(5) assert tags["retrieved"] assert tags["metainfo"]["info"] == self.tdef.get_metainfo()["info"]
def make_meta_file(srcpaths, params, userabortflag, progressCallback, torrentfilenameCallback): tdef = TorrentDef() basedir = None nrFiles = len([file for file in srcpaths if os.path.isfile(file)]) if nrFiles > 1: #outpaths should start with a common prefix, this prefix is the swarmname of the torrent #if srcpaths contain c:\a\1, c:\a\2 -> basepath should be c:\ and basedir a and outpaths should be a\1 and a\2 #if srcpaths contain c:\a\1, c:\a\2, c:\a\b\1, c:\a\b\2 -> basepath should be c:\ and outpaths should be a\1, a\2, a\b\1 and a\b\2 basepath = os.path.abspath(os.path.commonprefix(srcpaths)) basepath, basedir = os.path.split(basepath) for srcpath in srcpaths: if os.path.isfile(srcpath): outpath = os.path.relpath(srcpath, basepath) # h4x0r playtime if 'playtime' in params: tdef.add_content(srcpath, outpath, playtime=params['playtime']) else: tdef.add_content(srcpath, outpath) else: srcpaths = [file for file in srcpaths if os.path.isfile(file)] srcpath = srcpaths[0] basepath, _ = os.path.split(srcpath) if 'playtime' in params: tdef.add_content(srcpath, playtime=params['playtime']) else: tdef.add_content(srcpath) if params.get('urllist', False): tdef.set_urllist(params['urllist']) if params['name']: tdef.set_name(params['name']) if params['comment']: tdef.set_comment(params['comment']) if params['created by']: tdef.set_created_by(params['created by']) if params['announce']: tdef.set_tracker(params['announce']) if params['announce-list']: tdef.set_tracker_hierarchy(params['announce-list']) if params['nodes']: # mainline DHT tdef.set_dht_nodesmax(params['nodes']) if params['httpseeds']: tdef.set_httpseeds(params['httpseeds']) if params['encoding']: tdef.set_encoding(params['encoding']) if params['piece length']: tdef.set_piece_length(params['piece length']) if params['makehash_md5']: print >> sys.stderr, "TorrentMaker: make MD5" tdef.set_add_md5hash(params['makehash_md5']) if params['makehash_crc32']: print >> sys.stderr, "TorrentMaker: make CRC32" tdef.set_add_crc32(params['makehash_crc32']) if params['makehash_sha1']: print >> sys.stderr, "TorrentMaker: make SHA1" tdef.set_add_sha1hash(params['makehash_sha1']) if params['createmerkletorrent']: tdef.set_create_merkle_torrent(params['createmerkletorrent']) if params['torrentsigkeypairfilename']: tdef.set_signature_keypair_filename( params['torrentsigkeypairfilename']) if params['thumb']: tdef.set_thumbnail(params['thumb']) tdef.finalize(userabortflag=userabortflag, userprogresscallback=progressCallback) if params['createmerkletorrent']: postfix = TRIBLER_TORRENT_EXT else: postfix = '.torrent' if params.get('target', False): torrentfilename = os.path.join( params['target'], os.path.split(os.path.normpath(srcpath))[1] + postfix) else: torrentfilename = os.path.join(basepath, tdef.get_name() + postfix) tdef.save(torrentfilename) # Inform higher layer we created torrent torrentfilenameCallback(basepath, basedir, torrentfilename)
class TestMetadata(TestAsServer, MagnetHelpers): """ Once we are downloading a torrent, our client should respond to the ut_metadata extention message. This allows other clients to obtain the info part of the metadata from us. """ def setUp(self): """ override TestAsServer """ TestAsServer.setUp(self) print >> sys.stderr, "test: Giving MyLaunchMany time to startup" time.sleep(5) print >> sys.stderr, "test: MyLaunchMany should have started up" # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(os.getcwd(), "API", "file.wmv")) self.tdef.set_tracker(self.session.get_internal_tracker_url()) # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() # self.tdef.save(os.path.join(self.session.get_state_dir(), "gen.torrent")) MagnetHelpers.__init__(self, self.tdef) def setup_seeder(self): self.seeder_setup_complete = False self.seeder_teardown_complete = False self.seeder_teardown = False self.dscfg = DownloadStartupConfig() self.dscfg.set_dest_dir(os.getcwd()) self.download = self.session.start_download(self.tdef, self.dscfg) self.download.set_state_callback(self.seeder_state_callback) counter = 0 while not self.seeder_setup_complete: counter += 1 time.sleep(1) assert counter < 30, "timeout" print >> sys.stderr, "test: setup_seeder() complete" def teardown_seeder(self): self.seeder_teardown_complete = False self.session.remove_download(self.download) counter = 0 while not self.seeder_setup_complete: counter += 1 time.sleep(1) assert counter < 30, "timeout" print >> sys.stderr, "test: teardown_seeder() complete" def seeder_state_callback(self, ds): assert not self.seeder_teardown_complete self.seeder_setup_complete = (ds.get_status() == DLSTATUS_DOWNLOADING) d = ds.get_download() print >> sys.stderr, "test: seeder:", ` d.get_def().get_name( ) `, dlstatus_strings[ds.get_status()], ds.get_progress() if self.seeder_teardown: self.seeder_teardown_complete = True else: return (1.0, False) def test_all(self): self.setup_seeder() try: self.subtest_good_flood() finally: self.teardown_seeder() self.setup_seeder() try: self.subtest_good_request() self.subtest_bad_request() finally: self.teardown_seeder() def subtest_good_request(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # request metadata block 0, 2, 3, and the last conn.send(self.create_good_extend_metadata_request(metadata_id, 0)) conn.send(self.create_good_extend_metadata_request(metadata_id, 2)) conn.send(self.create_good_extend_metadata_request(metadata_id, 3)) conn.send( self.create_good_extend_metadata_request( metadata_id, len(self.metadata_list) - 1)) self.read_extend_metadata_reply(conn, 0) self.read_extend_metadata_reply(conn, 2) self.read_extend_metadata_reply(conn, 3) self.read_extend_metadata_reply(conn, len(self.metadata_list) - 1) def subtest_good_flood(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) for counter in xrange(len(self.metadata_list) * 2): piece = counter % len(self.metadata_list) conn.send( self.create_good_extend_metadata_request(metadata_id, piece)) if counter > len(self.metadata_list): self.read_extend_metadata_reject(conn, piece) else: self.read_extend_metadata_reply(conn, piece) def subtest_bad_request(self): self.bad_request_and_disconnect({ "msg_type": 0, "piece": len(self.metadata_list) }) self.bad_request_and_disconnect({"msg_type": 0, "piece": -1}) self.bad_request_and_disconnect({"msg_type": 0, "piece": "1"}) self.bad_request_and_disconnect({"msg_type": 0, "piece": [1, 2]}) self.bad_request_and_disconnect({"msg_type": 0, "PIECE": 1}) def bad_request_and_disconnect(self, payload): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) conn.send(EXTEND + chr(metadata_id) + bencode(payload)) self.read_extend_metadata_close(conn)
class TestMetadataFakePeer(TestAsServer, MagnetHelpers): """ Once we are downloading a torrent, our client should respond to the ut_metadata extention message. This allows other clients to obtain the info part of the metadata from us. """ def setUp(self): TestAsServer.setUp(self) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(TESTS_API_DIR, "file.wmv")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() self.setup_seeder() MagnetHelpers.__init__(self, self.tdef) def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) self.config2 = self.config.copy() self.config2.set_state_dir(self.getStateDir(2)) def tearDown(self): self.teardown_seeder() TestAsServer.tearDown(self) def setup_seeder(self): self.seeder_setup_complete = threading.Event() self.dscfg = DownloadStartupConfig() self.dscfg.set_dest_dir(TESTS_API_DIR) self.download = self.session.start_download(self.tdef, self.dscfg) self.download.set_state_callback(self.seeder_state_callback) assert self.seeder_setup_complete.wait(30) def teardown_seeder(self): self.session.remove_download(self.download) def seeder_state_callback(self, ds): if ds.get_status() == DLSTATUS_SEEDING: self.seeder_setup_complete.set() d = ds.get_download() self._logger.debug("seeder: %s %s %s", repr(d.get_def().get_name()), dlstatus_strings[ds.get_status()], ds.get_progress()) return 1.0, False def test_good_request(self): conn = BTConnection("localhost", self.session.get_listen_port(), user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # request metadata block 0, 2, 3, and the last conn.send(self.create_good_extend_metadata_request(metadata_id, 0)) conn.send(self.create_good_extend_metadata_request(metadata_id, 2)) conn.send(self.create_good_extend_metadata_request(metadata_id, 3)) conn.send( self.create_good_extend_metadata_request( metadata_id, len(self.metadata_list) - 1)) self.read_extend_metadata_reply(conn, 0) self.read_extend_metadata_reply(conn, 2) self.read_extend_metadata_reply(conn, 3) self.read_extend_metadata_reply(conn, len(self.metadata_list) - 1) def test_good_flood(self): conn = BTConnection("localhost", self.session.get_listen_port(), user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) for counter in xrange(len(self.metadata_list) * 2): piece = counter % len(self.metadata_list) conn.send( self.create_good_extend_metadata_request(metadata_id, piece)) if counter > len(self.metadata_list): self.read_extend_metadata_reject(conn, piece) else: self.read_extend_metadata_reply(conn, piece) def test_bad_request(self): self.bad_request_and_disconnect({ "msg_type": 0, "piece": len(self.metadata_list) }) self.bad_request_and_disconnect({"msg_type": 0, "piece": -1}) self.bad_request_and_disconnect({"msg_type": 0, "piece": "1"}) self.bad_request_and_disconnect({"msg_type": 0, "piece": [1, 2]}) self.bad_request_and_disconnect({"msg_type": 0, "PIECE": 1}) def bad_request_and_disconnect(self, payload): conn = BTConnection("localhost", self.session.get_listen_port(), user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) conn.send(EXTEND + chr(metadata_id) + bencode(payload)) self.read_extend_metadata_close(conn)
class TestMagnetFakePeer(TestAsServer, MagnetHelpers): """ A MiniBitTorrent instance is used to connect to BitTorrent clients and download the info part from the metadata. """ def setUp(self): # listener for incoming connections from MiniBitTorrent self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.bind(("", LISTEN_PORT)) self.server.listen(5) TestAsServer.setUp(self) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(BASE_DIR, "API", "file.wmv")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() MagnetHelpers.__init__(self, self.tdef) def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) def create_good_url(self, infohash=None, title=None, tracker=None): url = "magnet:?xt=urn:btih:" if infohash: assert isinstance(infohash, str) url += hexlify(infohash) else: url += hexlify(self.tdef.get_infohash()) if title: assert isinstance(title, str) url += "&dn=" + title if tracker: assert isinstance(tracker, str) url += "&tr=" + tracker return url @skip("not working, seems to return binary data") def test_good_transfer(self): def torrentdef_retrieved(tdef): tags["retrieved"].set() tags["metainfo"] = tdef.get_metainfo() tags = {"retrieved": threading.Event()} assert TorrentDef.retrieve_from_magnet(self.create_good_url(), torrentdef_retrieved, timeout=60) def do_supply(): # supply fake addresses (regular dht obviously wont work here) ltmgr = LibtorrentMgr.getInstance() for infohash in ltmgr.metainfo_requests: handle = ltmgr.ltsession.find_torrent(lt.big_number(infohash.decode('hex'))) handle.connect_peer(("127.0.0.1", LISTEN_PORT), 0) self.session.lm.rawserver.add_task(do_supply, delay=5.0) # accept incoming connection # self.server.settimeout(10.0) sock, address = self.server.accept() assert sock, "No incoming connection" # handshakes conn = BTConnection(address[0], address[1], opensock=sock, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # serve pieces for counter in xrange(len(self.metadata_list)): piece = self.read_extend_metadata_request(conn) assert 0 <= piece < len(self.metadata_list) conn.send(self.create_good_extend_metadata_reply(metadata_id, piece)) # no more metadata request may be send and the connection must # be closed self.read_extend_metadata_close(conn) assert tags["retrieved"].wait(5) assert tags["metainfo"]["info"] == self.tdef.get_metainfo()["info"]
class TestMetadataFakePeer(TestAsServer, MagnetHelpers): """ Once we are downloading a torrent, our client should respond to the ut_metadata extention message. This allows other clients to obtain the info part of the metadata from us. """ def setUp(self): TestAsServer.setUp(self) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(BASE_DIR, "API", "file.wmv")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() self.setup_seeder() MagnetHelpers.__init__(self, self.tdef) def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) self.config2 = self.config.copy() self.config2.set_state_dir(self.getStateDir(2)) self.config2.set_listen_port(4810) def tearDown(self): self.teardown_seeder() TestAsServer.tearDown(self) def setup_seeder(self): self.seeder_setup_complete = threading.Event() self.dscfg = DownloadStartupConfig() self.dscfg.set_dest_dir(os.path.join(BASE_DIR, "API")) self.download = self.session.start_download(self.tdef, self.dscfg) self.download.set_state_callback(self.seeder_state_callback) assert self.seeder_setup_complete.wait(30) def teardown_seeder(self): self.session.remove_download(self.download) def seeder_state_callback(self, ds): if ds.get_status() == DLSTATUS_SEEDING: self.seeder_setup_complete.set() d = ds.get_download() print >> sys.stderr, "test: seeder:", repr(d.get_def().get_name()), dlstatus_strings[ds.get_status()], ds.get_progress() return (1.0, False) def test_good_request(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # request metadata block 0, 2, 3, and the last conn.send(self.create_good_extend_metadata_request(metadata_id, 0)) conn.send(self.create_good_extend_metadata_request(metadata_id, 2)) conn.send(self.create_good_extend_metadata_request(metadata_id, 3)) conn.send(self.create_good_extend_metadata_request(metadata_id, len(self.metadata_list) - 1)) self.read_extend_metadata_reply(conn, 0) self.read_extend_metadata_reply(conn, 2) self.read_extend_metadata_reply(conn, 3) self.read_extend_metadata_reply(conn, len(self.metadata_list) - 1) def test_good_flood(self): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) for counter in xrange(len(self.metadata_list) * 2): piece = counter % len(self.metadata_list) conn.send(self.create_good_extend_metadata_request(metadata_id, piece)) if counter > len(self.metadata_list): self.read_extend_metadata_reject(conn, piece) else: self.read_extend_metadata_reply(conn, piece) def test_bad_request(self): self.bad_request_and_disconnect({"msg_type": 0, "piece": len(self.metadata_list)}) self.bad_request_and_disconnect({"msg_type": 0, "piece":-1}) self.bad_request_and_disconnect({"msg_type": 0, "piece": "1"}) self.bad_request_and_disconnect({"msg_type": 0, "piece": [1, 2]}) self.bad_request_and_disconnect({"msg_type": 0, "PIECE": 1}) def bad_request_and_disconnect(self, payload): conn = BTConnection("localhost", self.hisport, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) conn.send(EXTEND + chr(metadata_id) + bencode(payload)) self.read_extend_metadata_close(conn)
class TestMagnetMiniBitTorrent(TestAsServer, MagnetHelpers): """ A MiniBitTorrent instance is used to connect to BitTorrent clients and download the info part from the metadata. """ def setUp(self): """ override TestAsServer """ # listener for incoming connections from MiniBitTorrent self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server.bind(("localhost", LISTEN_PORT)) self.server.listen(1) # the metadata that we want to transfer self.tdef = TorrentDef() self.tdef.add_content(os.path.join(os.getcwd(), "API", "file.wmv")) self.tdef.set_tracker("http://fake.net/announce") # we use a small piece length to obtain multiple pieces self.tdef.set_piece_length(1) self.tdef.finalize() MagnetHelpers.__init__(self, self.tdef) # startup the client TestAsServer.setUp(self) print >>sys.stderr,"test: Giving MyLaunchMany time to startup" time.sleep(5) print >>sys.stderr,"test: MyLaunchMany should have started up" def create_good_url(self, infohash=None, title=None, tracker=None): url = "magnet:?xt=urn:btih:" if infohash: assert isinstance(infohash, str) url += hexlify(infohash) else: url += hexlify(self.tdef.get_infohash()) if title: assert isinstance(title, str) url += "&dn=" + title if tracker: assert isinstance(tracker, str) url += "&tr=" + tracker return url def test_good_transfer(self): def torrentdef_retrieved(tdef): tags["retrieved"] = True tags["metainfo"] = tdef.get_metainfo() tags = {"retrieved":False} assert TorrentDef.retrieve_from_magnet(self.create_good_url(), torrentdef_retrieved) # supply fake addresses (regular dht obviously wont work here) for magnetlink in MagnetHandler.get_instance().get_magnets(): magnetlink._swarm.add_potential_peers([("localhost", LISTEN_PORT)]) # accept incoming connection self.server.settimeout(10.0) sock, address = self.server.accept() assert sock, "No incoming connection" # handshakes conn = BTConnection(address[0], address[1], opensock=sock, user_infohash=self.tdef.get_infohash()) conn.send(self.create_good_extend_handshake()) conn.read_handshake_medium_rare() metadata_id = self.read_extend_handshake(conn) # serve pieces for counter in xrange(len(self.metadata_list)): piece = self.read_extend_metadata_request(conn) assert 0 <= piece < len(self.metadata_list) conn.send(self.create_good_extend_metadata_reply(metadata_id, piece)) # no more metadata request may be send and the connection must # be closed self.read_extend_metadata_close(conn) time.sleep(5) assert tags["retrieved"] assert tags["metainfo"]["info"] == self.tdef.get_metainfo()["info"]
def make_meta_file(srcpaths, params, userabortflag, progressCallback, torrentfilenameCallback): tdef = TorrentDef() if len(srcpaths) > 1: basepath = [] for srcpath in srcpaths: path, filename = os.path.split(srcpath) basepath.append(path) basepath, _ = os.path.split(os.path.commonprefix(basepath)) for srcpath in srcpaths: outpath = os.path.relpath(srcpath, basepath) # h4x0r playtime if 'playtime' in params: tdef.add_content(srcpath, outpath, playtime=params['playtime']) else: tdef.add_content(srcpath, outpath) else: srcpath = srcpaths[0] basepath, _ = os.path.split(srcpath) if 'playtime' in params: tdef.add_content(srcpath,playtime=params['playtime']) else: tdef.add_content(srcpath) if params['comment']: tdef.set_comment(params['comment']) if params['created by']: tdef.set_created_by(params['created by']) if params['announce']: tdef.set_tracker(params['announce']) if params['announce-list']: tdef.set_tracker_hierarchy(params['announce-list']) if params['nodes']: # mainline DHT tdef.set_dht_nodesmax(params['nodes']) if params['httpseeds']: tdef.set_httpseeds(params['httpseeds']) if params['encoding']: tdef.set_encoding(params['encoding']) if params['piece length']: tdef.set_piece_length(params['piece length']) if params['makehash_md5']: print >>sys.stderr,"TorrentMaker: make MD5" tdef.set_add_md5hash(params['makehash_md5']) if params['makehash_crc32']: print >>sys.stderr,"TorrentMaker: make CRC32" tdef.set_add_crc32(params['makehash_crc32']) if params['makehash_sha1']: print >>sys.stderr,"TorrentMaker: make SHA1" tdef.set_add_sha1hash(params['makehash_sha1']) if params['createmerkletorrent']: tdef.set_create_merkle_torrent(params['createmerkletorrent']) if params['torrentsigkeypairfilename']: tdef.set_signature_keypair_filename(params['torrentsigkeypairfilename']) if params['thumb']: tdef.set_thumbnail(params['thumb']) tdef.finalize(userabortflag=userabortflag,userprogresscallback=progressCallback) if params['createmerkletorrent']: postfix = TRIBLER_TORRENT_EXT else: postfix = '.torrent' if 'target' in params and params['target']: torrentfilename = os.path.join(params['target'], os.path.split(os.path.normpath(srcpath))[1] + postfix) else: a, b = os.path.split(srcpaths[0]) if b == '': torrentfilename = a + postfix else: torrentfilename = os.path.join(a, b + postfix) tdef.save(torrentfilename) # Inform higher layer we created torrent torrentfilenameCallback(basepath, torrentfilename)
class TestVideoOnDemand(TestAsServer): """ Testing Merkle hashpiece messages for both: * Merkle BEP style * old Tribler <= 4.5.2 that did not use the Extention protocol (BEP 10). See BitTornado/BT1/Connecter.py """ def setUp(self): """ override TestAsServer """ TestAsServer.setUp(self) self.vodstarted = False def setUpPreSession(self): TestAsServer.setUpPreSession(self) self.config.set_libtorrent(True) def create_torrent(self): [srchandle, self.sourcefn] = mkstemp() self.content = Rand.rand_bytes(self.contentlen) os.write(srchandle, self.content) os.close(srchandle) self.tdef = TorrentDef() self.tdef.add_content(self.sourcefn) self.tdef.set_piece_length(self.piecelen) 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 = DownloadStartupConfig() destdir = os.path.dirname(self.sourcefn) dscfg.set_dest_dir(destdir) dscfg.set_video_event_callback(self.sesscb_vod_event_callback) self.session.set_download_states_callback(self.states_callback) self.session.start_download(self.tdef, dscfg) def states_callback(self, dslist): ds = dslist[0] d = ds.get_download() # print >>sys.stderr,`d.get_def().get_name()`,dlstatus_strings[ds.get_status()],ds.get_progress(),"%",ds.get_error(),"up",ds.get_current_speed(UPLOAD),"down",ds.get_current_speed(DOWNLOAD) print >> sys.stderr, '%s %s %5.2f%% %s up %8.2fKB/s down %8.2fKB/s' % \ (d.get_def().get_name(), dlstatus_strings[ds.get_status()], ds.get_progress() * 100, ds.get_error(), ds.get_current_speed(UPLOAD), ds.get_current_speed(DOWNLOAD)) return (1.0, []) def sesscb_vod_event_callback(self, d, event, params): if self.vodstarted: return self.vodstarted = True print >> sys.stderr, "Test: vod_event_callback", event, params if event == VODEVENT_START: stream = params['stream'] # Read last piece lastpieceoff = ((self.contentlen - 1) / self.piecelen) * self.piecelen lastpiecesize = self.contentlen - lastpieceoff print >> sys.stderr, "Test: stream: lastpieceoff", lastpieceoff, lastpiecesize self.stream_read(stream, lastpieceoff, lastpiecesize, self.piecelen) # Read second,3rd,4th byte, only secoff = 1 secsize = 3 blocksize = 3 self.stream_read(stream, secoff, secsize, blocksize) # Read last byte lastoff = self.contentlen - 1 lastsize = 1 self.stream_read(stream, lastoff, lastsize, self.piecelen) def stream_read(self, stream, off, size, blocksize): stream.seek(off) data = stream.read(blocksize) print >> sys.stderr, "Test: stream: Got data", len(data) self.assertEquals(len(data), size) self.assertEquals(data, self.content[off:off + size]) def test_99(self): self.contentlen = 99 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (9, 8)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 9) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 9) self.assertEqual(vs.movie_numpieces, 10) def test_100(self): self.contentlen = 100 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (9, 9)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 10) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 9) self.assertEqual(vs.movie_numpieces, 10) def test_101(self): self.contentlen = 101 self.piecelen = 10 self.create_torrent() print >> sys.stderr, "Test: Letting network thread create Download, sleeping" time.sleep(5) dlist = self.session.get_downloads() d = dlist[0] vs = d.get_vod_info()['status'] if vs: goodrange = ((0, 0), (10, 0)) self.assertEqual(vs.movie_range, goodrange) self.assertEqual(vs.first_piecelen, 10) self.assertEqual(vs.last_piecelen, 1) self.assertEqual(vs.first_piece, 0) self.assertEqual(vs.last_piece, 10) self.assertEqual(vs.movie_numpieces, 11)
def make_meta_file(srcpaths, params, userabortflag, progressCallback, torrentfilenameCallback): tdef = TorrentDef() basedir = None nrFiles = len([file for file in srcpaths if os.path.isfile(file)]) if nrFiles > 1: # outpaths should start with a common prefix, this prefix is the swarmname of the torrent # if srcpaths contain c:\a\1, c:\a\2 -> basepath should be c:\ and basedir a and outpaths should be a\1 and a\2 # if srcpaths contain c:\a\1, c:\a\2, c:\a\b\1, c:\a\b\2 -> basepath should be c:\ and outpaths should be a\1, a\2, a\b\1 and a\b\2 basepath = os.path.abspath(os.path.commonprefix(srcpaths)) basepath, basedir = os.path.split(basepath) for srcpath in srcpaths: if os.path.isfile(srcpath): outpath = os.path.relpath(srcpath, basepath) # h4x0r playtime if 'playtime' in params: tdef.add_content(srcpath, outpath, playtime=params['playtime']) else: tdef.add_content(srcpath, outpath) else: srcpaths = [file for file in srcpaths if os.path.isfile(file)] srcpath = srcpaths[0] basepath, _ = os.path.split(srcpath) if 'playtime' in params: tdef.add_content(srcpath, playtime=params['playtime']) else: tdef.add_content(srcpath) if params.get('urllist', False): tdef.set_urllist(params['urllist']) if params['name']: tdef.set_name(params['name']) if params['comment']: tdef.set_comment(params['comment']) if params['created by']: tdef.set_created_by(params['created by']) if params['announce']: tdef.set_tracker(params['announce']) if params['announce-list']: tdef.set_tracker_hierarchy(params['announce-list']) if params['nodes']: # mainline DHT tdef.set_dht_nodesmax(params['nodes']) if params['httpseeds']: tdef.set_httpseeds(params['httpseeds']) if params['encoding']: tdef.set_encoding(params['encoding']) if params['piece length']: tdef.set_piece_length(params['piece length']) if params['makehash_md5']: print >> sys.stderr, "TorrentMaker: make MD5" tdef.set_add_md5hash(params['makehash_md5']) if params['makehash_crc32']: print >> sys.stderr, "TorrentMaker: make CRC32" tdef.set_add_crc32(params['makehash_crc32']) if params['makehash_sha1']: print >> sys.stderr, "TorrentMaker: make SHA1" tdef.set_add_sha1hash(params['makehash_sha1']) if params['createmerkletorrent']: tdef.set_create_merkle_torrent(params['createmerkletorrent']) if params['torrentsigkeypairfilename']: tdef.set_signature_keypair_filename(params['torrentsigkeypairfilename']) if params['thumb']: tdef.set_thumbnail(params['thumb']) tdef.finalize(userabortflag=userabortflag, userprogresscallback=progressCallback) if params['createmerkletorrent']: postfix = TRIBLER_TORRENT_EXT else: postfix = '.torrent' if params.get('target', False): torrentfilename = os.path.join(params['target'], os.path.split(os.path.normpath(srcpath))[1] + postfix) else: torrentfilename = os.path.join(basepath, tdef.get_name() + postfix) tdef.save(torrentfilename) # Inform higher layer we created torrent torrentfilenameCallback(basepath, basedir, torrentfilename)