def main(argv): if len(argv) != 2: print "Usage: %s <torrent-file>" % argv[0] sys.exit(1) inputs = [] outputs = [] print "~~~ Starting BitTorrent Client ~~~" print "----------------------------------" # Read & parse torrent file tfile = Torrent(argv[1]) tfile.print_info() #My ID has to be exactly 20 characters but each ID should be random my_id = "-SilviaLearnsBT%05d"%random.randint(0,99999) # Setup tracker connection tracker = Tracker(tfile.tracker_url) tracker.connect(tfile, my_id) # Setup Brain, the dispatcher brain = Brain({ "ip": "localhost", "port": 1050, "id": my_id}, tfile, tracker) if brain.is_complete(): print "Aborting. I have the entire file!" else: print "Received list of peers from tracker: %r" % tracker.peers brain.add_peers() brain.connect_all(3) brain.run() print "~~~ GROOVY! You successfully downloaded a torrent ~~~"
def main(argv): if len(argv) != 2: print "Usage: %s <torrent-file>" % argv[0] sys.exit(1) inputs = [] outputs = [] tfile = Torrent(argv[1]) tfile.print_info() my_id = "xxxSpicyboiiixx%20d" % random.randint(0, 99999) tracker = Tracker(tfile.tracker_url) tracker.connect(tfile, my_id) brain = Brain({ "ip": "localhost", "port": 1050, "id": my_id }, tfile, tracker) if brain.is_complete(): print "Aborting" else: print "Received list of peers: %r" % tracker.peers brain.add_peers() brain.connect_all(3) brain.run() print "Downloaded a torrent"
class TorrentClient: """ The torrent client is the local peer that holds peer-to-peer connactions to download and upload pieces for a given torrent. Once started, the client makes periodic announce calls to the tracker registered in the torrent meta file. These calls results in a list of peers that should be tried in order to exchange pieces. """ def __init__(self, torrent: Torrent): self.tracker = Tracker(torrent) self.available_peers = asyncio.Queue() self.peers: List[PeerConnection] = [] self.piece_manager: PieceManager = None self.abort = False async def start(self) -> None: """ Start downloading torrent held by this client. The method stops when downloading gull complete or aborted. """ await self.tracker.connect() self.peers = [ PeerConnection(self.available_peers, self.tracker.peer_id) for _ in range(MAX_PEERS) ] last_announce_call = None interval = self.tracker.interval while True: if self.piece_manager.compete: logging.info("Downloading complete") break if self.abort: logging.info("Downloading aborted!") break current = time.time() if not last_announce_call or (last_announce_call + interval > current): try: self.tracker.connect() except TrackerError as e: logging.error(e) break last_announce_call = current interval = self.tracker.interval self.stop() def _empty_queue(self) -> None: raise NotImplementedError async def stop(self) -> None: await self.tracker.close() for peer in self.peers: peer.stop() self.piece_manager.close()
from tracker import Tracker from torrent import Torrent import sys torrent = Torrent(sys.argv[1]) tracker = Tracker(torrent) print(tracker.connect())
def write_peerlist(tfile, filename, fake_announce): ''' Zapis peerlistu. @param tfile Cesta k torrentu @param filename Cesta k suboru pre zapis peerlistu @param fake_announce Falosna announce URL @return True ak je spracovanie uspesne, inak False ''' torrent = Torrent(tfile) if not torrent.valid: Log.error("AntiPirat: Nevalidny torrent subor {}".format(tfile)) return False if fake_announce != None: Log.info( "AntiPirat: Kontaktujem tracker cez fake announce url (parameter -a): {}" .format(fake_announce)) tracker = Tracker(fake_announce, torrent) if tracker.connect(): peers = tracker.get_peerlist() if peers is not None: try: Log.info("AntiPirat: Otvaram subor k zapisu peerlistu {}". format(filename)) f = open(filename, "w") for p in peers: f.write("{}\n".format(p)) Log.info( "AntiPirat: Uspesne ukonceny zapis peerlistu z trackeru {}" .format(fake_announce)) f.close() except: Log.error( "AntiPirat: Nepodarilo sa zapisat peerlist do suboru {}" .format(filename)) return False else: Log.error("AntiPirat: Ziskavanie peerlistu zlyhalo") return False else: Log.error("AntiPirat: Spojenie s trackerom zlyhalo") return False Log.info("AntiPirat: Uspesne dokonceny zapis peerlistov do suboru {}". format(filename)) return True else: trackers = torrent.http_trackers Log.info("AntiPirat: Pocet najdenych HTTP trackerov: {}".format( len(trackers))) try: Log.info("AntiPirat: Otvaram subor k zapisu peerlistu {}".format( filename)) f = open(filename, "w") except: Log.error( "AntiPirat: Nepodarilo sa otvorit subor {}".format(filename)) return False for t in trackers: Log.info("AntiPirat: Kontaktujem tracker {}".format(t)) tracker = Tracker(t, torrent) if tracker.connect(): peers = tracker.get_peerlist() if peers is not None: for p in peers: f.write("{}\n".format(p)) Log.info( "AntiPirat: Uspesne ukonceny zapis peerlistu z trackeru {}" .format(t)) else: Log.info( "AntiPirat: Preskakujem tracker, u ktoreho doslo k chybe: {}" .format(t)) f.close() Log.info("AntiPirat: Uspesne dokonceny zapis peerlistov do suboru {}". format(filename)) return True
class TorrentClient: """ The torrent client is the local peer that holds peer-to-peer connections to download and upload pieces for a given torrent. Once started, the client makes periodic announce calls to the tracker registered in the torrent meta-data. These calls result in a list of peers that should be tried in order to exchange pieces. Each received peer is kept in a queue that a pool of PeerConnection objects consume. There is a fixed number of PeerConnections that can have a connection open to a peer. Since we are not creating expensive threads (or worse yet processes) we can create them all at once and they will be waiting until there is a peer to consume in the queue. """ def __init__(self, torrent): self.tracker = Tracker(torrent) #The list of potential peers is the work queue, consumed by the #PeerConnections self.available_peers = Queue() #The list of peers is the list of workers that *might* be connected #to a peer. Else they are waiting to consume new remote peers from #the `available_peers`. self.peers = [] #The piece manager implements on which pieces to request #as well as the logic to persist received pieces to disk self.piece_manager = PieceManager(torrent) self.abort = False async def start(self): """ Start downloading the torrent held by this client. This results in connecting to the tracker to retrieve the list of peers to communicate with. Once the torrent is fully downloaded or if the downloaded is aborted this method will complete. """ self.peers = [ PeerConnection(self.available_peers, self.tracker.torrent.info_hash, self.tracker.peer_id, self.piece_manager, self._on_block_retrieved) for _ in range(MAX_PEER_CONNECTIONS) ] #The time we last made an announce call (timestamp) previous = None #Default interval between announce calls (in seconds) interval = 30 * 60 while True: if self.piece_manager.complete: print('Torrent fully downloaded!') break if self.abort: print('Aborting download...') break current = time.time() #if first request #or default interval has not passed after prev request if (not previous) or (previous + interval < current): response = self.tracker.connect( first=False if previous else True, uploaded=self.piece_manager.bytes_uploaded, downloaded=self.piece_manager.bytes_downloaded) print(response) if response: previous = current interval = response.interval self._empty_queue() for peer in response.peers: self.available_peers.put_nowait(peer) else: await asyncio.sleep(5) self.stop() def _empty_queue(self): while not self.available_peers.empty(): self.available_peers.get_nowait() def stop(self): """ Stop the download or seeding process. """ self.abort = True for peer in self.peers: peer.stop() self.piece_manager.close() def _on_block_retrieved(self, peer_id, piece_index, block_offset, data): """ Callback function called by the `PeerConnection` when a block is retrieved from a peer. :param peer_id: The id of the peer the block was retrieved from :param piece_index: The piece index this block is a part of :param block_offset: The block offset within its piece :param data: The binary data retrieved """ self.piece_manager.block_received(peer_id=peer_id, piece_index=piece_index, block_offset=block_offset, data=data)
data = self.meta_info[b"info"][b"pieces"] pieces, offset, length = [], 0, len(data) pieces = [data[offset:offset + 20] for offset in range(0, length, 20)] return pieces @property def output_file(self): """ Returns the output filename that we will use to save the torrent data in """ logging.info("Torrent output file: {0}".format( self.meta_info[b"info"][b"name"].decode("utf-8"))) return self.meta_info[b"info"][b"name"].decode("utf-8") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("-f", "--file", help="Torrent's absolute file path", type=str, required=True) args = parser.parse_args() t = Torrent(torrent_path=args.file) tr = Tracker(t) loop = asyncio.get_event_loop() r1 = loop.run_until_complete(tr.connect()) print(r1)
from torrent_file import TorrentFile import argparse if __name__ == '__main__': parser = argparse.ArgumentParser(description='Bittorrent client') parser.add_argument('--tests', action='store_true', help='Run doctests') parser.add_argument('--url', default='http://173.230.132.32', help='URL of tracker') parser.add_argument('--gen', action='store_true', help='Generate new torrent file with random data.') parser.add_argument('--fname', metavar='filename', default='myfile.torrent', help='File to use for generation or reading.') args = parser.parse_args() if args.gen: # Generate new torrent file # torrent_file = torrent_file.TorrentFile(info_dict, args.fname, True) pass else: torrent_file = TorrentFile(args.fname) if args.tests: import doctest doctest.testmod() tracker = Tracker(torrent_file) tracker.connect()
parser.add_argument( '--url', default='http://173.230.132.32', help='URL of tracker' ) parser.add_argument( '--gen', action='store_true', help='Generate new torrent file with random data.' ) parser.add_argument( '--fname', metavar='filename', default='myfile.torrent', help='File to use for generation or reading.' ) args = parser.parse_args() if args.gen: # Generate new torrent file # torrent_file = torrent_file.TorrentFile(info_dict, args.fname, True) pass else: torrent_file = TorrentFile(args.fname) if args.tests: import doctest doctest.testmod() tracker = Tracker(torrent_file) tracker.connect()
import asyncio, bencode from torrentFile import TorrentFile from tracker import Tracker from client import Client import socket client = Client() seedsTorrent = TorrentFile('torrents/file2.torrent') seedsTorrent.describe() seedsTracker = Tracker(seedsTorrent.announce) seedsTracker.connect(seedsTorrent, client) print() seedsTracker.describe() infoHash = seedsTorrent.infoHash #byte = "BitTorrent protocol\0\0\0\0\0\0\0\0".encode() #print(byte) handshakeMessage = str(19).encode() + "BitTorrent protocol\x00\x00\x00\x00\x00\x00\x00\x00".encode() + infoHash + client.peerId.encode() print(handshakeMessage) print(len(handshakeMessage)) peers = seedsTracker.peers for peer in peers: print("nmap -p {} {}".format( peer['port'], peer['ip'])) """ tf2 = TorrentFile('torrents/file2.torrent') tf2.describe()