def test_get_peers(self): self.metainfo.announce = self.trackeraddr + "/announce" tp = TrackerProxy(self.metainfo, 6881, self.peer_id) assert tp.get_peers(10) == self.peerlist tp = TrackerProxy(self.metainfo, 6881, self.peer_id) assert tp.get_peers(2) == self.peerlist[:2] assert tp.get_peers(2) == self.peerlist[2:4] assert tp.get_peers(2) == self.peerlist[4:]
def test_announce(self): self.metainfo.announce = self.trackeraddr + "/announce" tp = TrackerProxy(self.metainfo, 6881, self.peer_id) assert tp.get_peers(5) == self.peerlist
def test_warning(self, capsys): self.metainfo.announce = self.trackeraddr + "/warning" tp = TrackerProxy(self.metainfo, 6881, self.peer_id) _, err = capsys.readouterr() assert "Warning:" in err assert tp.get_peers(5) == self.peerlist
def test_failure(self): with pytest.raises(TrackerError) as e: self.metainfo.announce = self.trackeraddr + "/failure" TrackerProxy(self.metainfo, 6881, self.peer_id) assert e.value.message.startswith("Failure reason:")
def test_notracker(self): with pytest.raises(TrackerError) as e: self.metainfo.announce = "http://localhost" TrackerProxy(self.metainfo, 6881, self.peer_id) assert e.value.message.startswith("Can't connect to the tracker")
def __init__(self, client, filename, port, peer_id): self._client = client self._filename = filename self._port = port self._peer_id = peer_id # _peers is a list of peers that the TorrentMgr is trying # to communicate with self._peers = [] # _bitfields is a dictionary mapping peers to a bitfield of the pieces # each has self._bitfields = {} try: self._metainfo = Metainfo(filename) except (IOError, ValueError) as err: if isinstance(err, IOError): message = err.strerror + ' (' + filename + ')' else: message = err.message + ' (' + filename + ')' logger.error(message) raise TorrentMgrError(message) # _have is the bitfield for this torrent. It is initialized to reflect # which pieces are already available on disk. self._filemgr = FileMgr(self._metainfo) self._have = self._filemgr.have() try: self._tracker_proxy = TrackerProxy(self._metainfo, self._port, self._peer_id) except TrackerError as err: logger.critical("Could not connect to tracker at {}".format( self._metainfo.announce)) logger.debug(" TrackerError: {}".format(err.message)) raise TorrentMgrError(err.message) # _needed is a dictionary of pieces which are still needed. # The value for each piece is a tuple of the number of peers which # have the piece and a list of those peers. self._needed = { piece: (0, []) for piece in list(self._have.findall('0b0')) } # _interested is a dictionary of peers to whom interest has been # expressed. The value for each peer is a tuple of the piece that # has been reserved for the peer, the number of bytes of the piece that # have already been received, the sha1 hash of the bytes received so # far and the value of the tick at the time interest was expressed. self._interested = {} # _requesting is a dictionary of peers to whom a block request has been # made. The value for each peer is a tuple of the piece that is being # requested, the number of bytes that have already been received, the # shal2 hash of the bytes received so far, the value of the tick at # the time the request was made and the number of retries that have # been attempted self._requesting = {} # _partial is a list which tracks pieces that were interrupted while # being downloaded. Each entry is a tuple containing the index of the # piece, the number of bytes received so far and the sha1 hash of those # bytes. self._partial = [] self._reactor = Reactor() self._reactor.schedule_timer(_TIMER_INTERVAL, self.timer_event) self._tick = 1 print "Starting to serve torrent {}".format(filename) self._connect_to_peers(20)
def initialize(self): """ initialize() returns a deferred which fires when initialization of the TorrentMgr is complete or an error has occurred. """ if self._state != self._States.Uninitialized: error = "TorrentMgr can't be reinitialized" logger.debug(error) d = Deferred() d.errback(TorrentMgrError(error)) return d try: self._metainfo = Metainfo(self._filename) except ValueError as err: logger.error(err) d = Deferred() d.errback(TorrentMgrError(err.message)) return d except IOError as err: logger.error(err) d = Deferred() d.errback(TorrentMgrError(err.strerror)) return d # _peers is a list of peers that the TorrentMgr is trying # to communicate with self._peers = [] # _bitfields is a dictionary mapping peers to a bitfield of the pieces # each has self._bitfields = {} # _have is the bitfield for this torrent. It is initialized to reflect # which pieces are already available on disk. self._filemgr = FileMgr(self._metainfo) self._have = self._filemgr.have() # _needed is a dictionary of pieces which are still needed. # The value for each piece is a tuple of the number of peers which # have the piece and a list of those peers. self._needed = { piece: (0, []) for piece in list(self._have.findall('0b0')) } # _interested is a dictionary of peers to whom interest has been # expressed. The value for each peer is a tuple of the piece that # has been reserved for the peer, the number of bytes of the piece that # have already been received, the sha1 hash of the bytes received so # far and the value of the tick at the time interest was expressed. self._interested = {} # _requesting is a dictionary of peers to whom a block request has been # made. The value for each peer is a tuple of the piece that is being # requested, the number of bytes that have already been received, the # shal2 hash of the bytes received so far, the value of the tick at # the time the request was made and the number of retries that have # been attempted self._requesting = {} # _partial is a list which tracks pieces that were interrupted while # being downloaded. Each entry is a tuple containing the index of the # piece, the number of bytes received so far and the sha1 hash of those # bytes. self._partial = [] self._tracker_proxy = TrackerProxy(self._metainfo, self._port, self._peer_id) def success(result): self._state = self._States.Initialized def failure(failure): logger.critical("Could not connect to tracker at {}".format( self._metainfo.announce)) message = failure.value.message logger.debug(" Tracker Error: {}".format(message)) raise TorrentMgrError(message) return self._tracker_proxy.start().addCallbacks(success, failure)