Ejemplo n.º 1
0
    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:]
Ejemplo n.º 2
0
 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
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
 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:")
Ejemplo n.º 5
0
 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")
Ejemplo n.º 6
0
    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)
Ejemplo n.º 7
0
    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)