Exemple #1
0
    def __init__(self, btm):
        self.btm = btm
        self.info_hash = btm.metainfo.info_hash

        self.active_connection = {}

        self.downloadSpeedMonitor = SpeedMonitor()
        self.downloadSpeedMonitor.registerObserver(btm.downloadSpeedMonitor)

        self.uploadSpeedMonitor = SpeedMonitor()
        self.uploadSpeedMonitor.registerObserver(btm.uploadSpeedMonitor)
Exemple #2
0
    def __init__(self, btm):
        self.btm = btm
        self.info_hash = btm.metainfo.info_hash

        self.active_connection = {}

        self.downloadSpeedMonitor = SpeedMonitor()
        self.downloadSpeedMonitor.registerObserver(btm.downloadSpeedMonitor)

        self.uploadSpeedMonitor = SpeedMonitor()
        self.uploadSpeedMonitor.registerObserver(btm.uploadSpeedMonitor)
Exemple #3
0
    def __init__(self, protocol):
        self.protocol = protocol

        self.piece_doing = []
        self.piece_done = []

        self.peer_choke = None
        self.am_interested = None

        self.downloadSpeedMonitor = SpeedMonitor()

        self.task_max_size = 5
Exemple #4
0
    def __init__(self, protocol):
        self.protocol = protocol

        self.peer_interested = None
        self.am_choke = None

        self.uploadSpeedMonitor = SpeedMonitor()

        self.upload_todo = []
        self.upload_doing = []
        self.upload_done = []

        self.status = None
Exemple #5
0
 def __init__(self, app, config):
     self.app = app
     self.config = config
     self.metainfo = config.metainfo
     self.info_hash = self.metainfo.info_hash
     self.downloadSpeedMonitor = SpeedMonitor(5)
     self.uploadSpeedMonitor = SpeedMonitor(5)
     self.my_peer_id = generate_peer_id()
     self.connectionManager = ConnectionManager(self)
     self.pieceManager = BTPieceManager(self)
     if len(self.metainfo.announce_list) > 0:
         self.bttrackerclient = BTTrackerClient(self)
     else: 
         raise Exception("Torrent needs at least one tracker")
     self.status = None
Exemple #6
0
 def __init__(self, app, config):
     self.app = app
     self.config = config
     self.metainfo = config.metainfo
     self.info_hash = self.metainfo.info_hash
     self.downloadSpeedMonitor = SpeedMonitor(5)
     self.uploadSpeedMonitor = SpeedMonitor(5)
     self.my_peer_id = generate_peer_id()
     self.connectionManager = ConnectionManager(self)
     self.pieceManager = BTPieceManager(self)
     if len(self.metainfo.announce_list) > 0:
         self.bttrackerclient = BTTrackerClient(self)
     else:
         raise Exception("Torrent needs at least one tracker")
     self.status = None
Exemple #7
0
class ConnectionManagerBase (IConnectionManager):
    def __init__(self, btm):
        self.btm = btm
        self.info_hash = btm.metainfo.info_hash

        self.active_connection = {}

        self.downloadSpeedMonitor = SpeedMonitor()
        self.downloadSpeedMonitor.registerObserver(btm.downloadSpeedMonitor)

        self.uploadSpeedMonitor = SpeedMonitor()
        self.uploadSpeedMonitor.registerObserver(btm.uploadSpeedMonitor)


    def addActiveConnection(self, peerid, connection):
        peerid = connection.peer_id
        
        self.active_connection[peerid] = connection

    def removeActiveConnection(self, peerid):
        if peerid in self.active_connection:
            del self.active_connection[peerid]

    def isAlreadyConnected(self, peer_id) :
        return peer_id in self.active_connection
    
    def getConnection(self, peer_id) :
        return self.active_connection.get(peer_id, None)

    def broadcastHave(self, idx):
        for peerid, con in self.active_connection.iteritems():
            con.send_have(idx)

    def redownloadPiece(self, idx):
        for peerid, con in self.active_connection.iteritems():
            con.redownloadPiece(idx)

    def broadcastCancelPiece(self, idx, begin, length):
        for peerid, con in self.active_connection.iteritems():
            con.send_cancel(idx, begin, length)

    def start(self):
        pass

    def stop(self):
        pass
Exemple #8
0
class ConnectionManagerBase (IConnectionManager):
    def __init__(self, btm):
        self.btm = btm
        self.info_hash = btm.metainfo.info_hash

        self.active_connection = {}

        self.downloadSpeedMonitor = SpeedMonitor()
        self.downloadSpeedMonitor.registerObserver(btm.downloadSpeedMonitor)

        self.uploadSpeedMonitor = SpeedMonitor()
        self.uploadSpeedMonitor.registerObserver(btm.uploadSpeedMonitor)


    def addActiveConnection(self, peerid, connection):
        peerid = connection.peer_id
        self.active_connection[peerid] = connection

    def removeActiveConnection(self, peerid):
        if peerid in self.active_connection:
            del self.active_connection[peerid]

    def isAlreadyConnected(self, peer_id) :
        return peer_id in self.active_connection
    
    def getConnection(self, peer_id) :
        return self.active_connection.get(peer_id, None)

    def broadcastHave(self, idx):
        for peerid, con in self.active_connection.iteritems():
            con.send_have(idx)

    def redownloadPiece(self, idx):
        for peerid, con in self.active_connection.iteritems():
            con.redownloadPiece(idx)

    def broadcastCancelPiece(self, idx, begin, length):
        for peerid, con in self.active_connection.iteritems():
            con.send_cancel(idx, begin, length)

    def start(self):
        pass

    def stop(self):
        pass
Exemple #9
0
 def __init__(self, app, config):
     self.app = app
     self.config = config
     self.metainfo = config.metainfo
     self.info_hash = self.metainfo.info_hash
     self.downloadSpeedMonitor = SpeedMonitor(5)
     self.uploadSpeedMonitor = SpeedMonitor(5)
     self.my_peer_id = generate_peer_id()
     self.connectionManager = ConnectionManager(self)
     self.pieceManager = BTPieceManager(self)
     if len(self.metainfo.announce_list) > 0:
         self.bttrackerclient = BTTrackerClient(self)
     elif self.app.enable_DHT == True:
         print("TrackerLess Torrent, I will continue on DHT")
         self.bttrackerclient = BTTrackerClientDummy(self)
     else:
         raise Exception(
             "Torrent needs at least one tracker, and DHT is disabled.")
     self.status = None
Exemple #10
0
    def __init__(self, protocol):
        self.protocol = protocol

        self.piece_doing = []
        self.piece_done = []

        self.peer_choke = None
        self.am_interested = None

        self.downloadSpeedMonitor = SpeedMonitor()

        self.task_max_size = 5
Exemple #11
0
    def __init__(self, protocol):
        self.protocol = protocol

        self.peer_interested = None
        self.am_choke = None

        self.uploadSpeedMonitor = SpeedMonitor(10)

        self.upload_todo = []
        self.upload_doing = []
        self.upload_done = []

        self.status = None
Exemple #12
0
class BTDownload(object):

    task_max_size = 5

    def __init__(self, protocol):
        self.protocol = protocol

        self.piece_doing = []
        self.piece_done = []

        self.peer_choke = None
        self.am_interested = None

        self.downloadSpeedMonitor = SpeedMonitor()

        self.task_max_size = 5

    def start(self):
        if not self.protocol:
            return

        self.status = 'running'
        self.btm = self.protocol.factory.btm
        self.pieceManager = self.btm.pieceManager
        pm = self.pieceManager
        self.peer_bitfield = Bitfield(pm.pieces_size)
        self.downloadSpeedMonitor.start()
        self.downloadSpeedMonitor.registerObserver(
            self.protocol.factory.downloadSpeedMonitor)

    def stop(self):
        for task in self.piece_doing:
            self.pieceManager.failedPieceTask(*task)

        del self.piece_doing[:]

        self.downloadSpeedMonitor.stop()

        del self.protocol
        del self.btm
        del self.pieceManager

        self.status = 'stopped'

    def _choke(self, val):
        self.peer_choke = bool(val)

        if val:
            pass
        else:
            self.__pieceRequest()

    def interested(self, val):
        am_interested = bool(val)
        if self.am_interested is am_interested:
            return

        if am_interested:
            self.protocol.send_interested()
        else:
            self.protocol.send_not_interested()

        self.am_interested = am_interested

    def cancel(self, task):
        idx, (beg, length) = task
        self.protocol.send_cancel(idx, beg, length)

    def _downloadMonitor(self, data):
        self.downloadSpeedMonitor.addBytes(len(data))

    def __pieceRequest(self):
        if self.am_interested == True and self.peer_choke == False:
            if self.piece_doing:
                return
            new_task = self.__getTask()
            if new_task:
                self.__sendTaskRequest(new_task)

    def __getTask(self, size=None):
        if size is None:
            size = self.task_max_size
        pm = self.pieceManager
        new_task = pm.getMorePieceTask(self.peer_bitfield, size)
        return new_task

    @defer.inlineCallbacks
    def __sendTaskRequest(self, new_task, timeout=None):
        if not new_task:
            return

        if timeout is None:
            timeout = len(new_task) * 60

        for task in new_task:
            i, (beg, size) = task
            self.protocol.send_request(i, beg, size)
            self.piece_doing.append(task)

        yield sleep(timeout)
        self.__checkTimeout(new_task)

    def __checkTimeout(self, task_plan):
        if self.status == 'stopped':
            return

        set_plan = set(task_plan)
        set_ing = set(self.piece_doing)
        set_undo = set_plan & set_ing
        set_new = set_ing - set_plan

        task_size = self.task_max_size - len(set_undo)
        if set_new:
            task_size += 1

        if task_size < 1:
            task_size = 1
        elif task_size > BTDownload.task_max_size:
            task_size = BTDownload.task_max_size

        self.task_max_size = task_size

        if not set_undo:
            return

        new_task = self.__getTask(self.task_max_size)

        for task in set_undo:
            self.cancel(task)
            self.piece_doing.remove(task)
            self.pieceManager.failedPieceTask(*task)

        if new_task:
            self.__sendTaskRequest(new_task)

    def _piece(self, index, beg, piece):
        task = index, (beg, len(piece))
        if task not in self.piece_doing:
            return

        self.pieceManager.finishPieceTask(index, (beg, len(piece)), piece)
        self.piece_doing.remove(task)
        if len(self.piece_doing) == 0:
            self.__pieceRequest()

    def _bitfield(self, data):
        pm = self.pieceManager
        bf = Bitfield(pm.pieces_size, data)
        self.peer_bitfield = bf

        if self.pieceManager.amInterested(bf):
            self.interested(True)
            self.__pieceRequest()
        else:
            self.interested(False)

    def _have(self, index):
        self.peer_bitfield[index] = 1
        if self.pieceManager.amInterested(index):
            self.interested(True)
            self.__pieceRequest()
Exemple #13
0
class BTManager(object):
    def __init__(self, app, config):
        self.app = app
        self.config = config
        self.metainfo = config.metainfo
        self.info_hash = self.metainfo.info_hash
        self.downloadSpeedMonitor = SpeedMonitor(5)
        self.uploadSpeedMonitor = SpeedMonitor(5)
        self.my_peer_id = generate_peer_id()
        self.connectionManager = ConnectionManager(self)
        self.pieceManager = BTPieceManager(self)
        if len(self.metainfo.announce_list) > 0:
            self.bttrackerclient = BTTrackerClient(self)
        else:
            raise Exception("Torrent needs at least one tracker")
        self.status = None

    def startDownload(self):
        self.pieceManager.start()

        self.connectionManager.start()

        self.downloadSpeedMonitor.start()
        self.uploadSpeedMonitor.start()

        self.bttrackerclient.start()

        self.status = 'running'

    def stopDownload(self):
        self.pieceManager.stop()

        self.connectionManager.stop()

        self.downloadSpeedMonitor.stop()
        self.uploadSpeedMonitor.stop()

        self.bttrackerclient.stop()

        self.status = 'stopped'

    def get_speed(self):
        """Returns the speed in kibibit per second (Kibit/s).
        """
        return {
            "down": self.downloadSpeedMonitor.get_speed(),
            "up": self.uploadSpeedMonitor.get_speed()
        }

    def get_num_connections(self):
        return {
            "client":
            len(self.connectionManager.clientFactory.active_connection),
            "server":
            len(self.connectionManager.serverFactory.active_connection)
        }

    def get_progress(self):
        return self.pieceManager.getProgress()

    def add_peers(self, peers):
        """Adds peers to the torrent for downloading pieces.

        @param peers list of tuples e.g. [('173.248.194.166', 12005),
            ('192.166.145.8', 13915)]
        """
        self.connectionManager.clientFactory.updateTrackerPeers(peers)

    def exit(self):
        if self.status == 'running':
            self.stopDownload()

        for i in self.__dict__:
            del self.__dict__[i]
Exemple #14
0
class BTUpload(object):
    # producer interface implementation

    def __init__(self, protocol):
        self.protocol = protocol

        self.peer_interested = None
        self.am_choke = None

        self.uploadSpeedMonitor = SpeedMonitor()

        self.upload_todo = []
        self.upload_doing = []
        self.upload_done = []

        self.status = None

    def start(self):
        if self.status == 'started':
            return

        if not self.protocol:
            return

        self.btm = self.protocol.factory.btm
        self.pieceManager = self.btm.pieceManager

        self.uploadSpeedMonitor.start()
        self.uploadSpeedMonitor.registerObserver(
            self.protocol.factory.uploadSpeedMonitor)

        self.choke(False)

        self.protocol.transport.registerProducer(self, False)

        self.status = 'started'

    def stop(self):
        if self.status == 'stopped':
            return

        self.uploadSpeedMonitor.stop()

        self.protocol.transport.unregisterProducer()

        del self.protocol
        del self.btm
        del self.pieceManager

        self.status = 'stopped'

    def pause(self):
        pass

    def resume(self):
        pass

    def _interested(self, val):
        self.peer_interested = bool(val)

    def _request(self, idx, begin, length):
        if not self.pieceManager.doIHave(idx):  # I don't have
            return

        self.upload_todo.append((idx, (begin, length)))

        # data = self.pieceManager.getPieceData(idx, begin, length)
        # if data :
        #     self.protocol.send_piece(idx, begin, data)

        if self.status == 'idle':
            self.resumeProducing()

    def _cancel(self, idx, begin, length):
        task = idx, (begin, length)
        if task in self.upload_todo:
            self.upload_todo.remove(task)

    def choke(self, val):
        am_choke = bool(val)
        if self.am_choke is am_choke:
            return

        if am_choke:
            self.protocol.send_choke()
        else:
            self.protocol.send_unchoke()

        self.am_choke = am_choke

    def _uploadMonitor(self, _type, data):
        self.uploadSpeedMonitor.addBytes(len(data))

    # called by transport and do write
    def resumeProducing(self):
        for i in range(len(self.upload_todo)):
            idx, (begin, length) = self.upload_todo[i]
            data = self.pieceManager.getPieceData(idx, begin, length)
            if data:
                self.protocol.send_piece(idx, begin, data)
                self.status = 'uploading'
                del self.upload_todo[i]
                break
        else:
            self.status = 'idle'

    def stopProducing(self):
        pass
Exemple #15
0
class BTManager (object):
    def __init__(self, app, config):
        self.app = app
        self.config = config
        self.metainfo = config.metainfo
        self.info_hash = self.metainfo.info_hash
        self.downloadSpeedMonitor = SpeedMonitor(5)
        self.uploadSpeedMonitor = SpeedMonitor(5)
        self.my_peer_id = generate_peer_id()
        self.connectionManager = ConnectionManager(self)
        self.pieceManager = BTPieceManager(self)
        if len(self.metainfo.announce_list) > 0:
            self.bttrackerclient = BTTrackerClient(self)
        else: 
            raise Exception("Torrent needs at least one tracker")
        self.status = None

    def startDownload(self):
        self.pieceManager.start()

        self.connectionManager.start()
        
        self.downloadSpeedMonitor.start()
        self.uploadSpeedMonitor.start()

        self.bttrackerclient.start()

        self.status = 'running'

    def stopDownload(self):
        self.pieceManager.stop()

        self.connectionManager.stop()
        
        self.downloadSpeedMonitor.stop()
        self.uploadSpeedMonitor.stop()

        self.bttrackerclient.stop()

        self.status = 'stopped'

    def get_speed(self):
        """Returns the speed in kibibit per second (Kibit/s).
        """
        return {
            "down": self.downloadSpeedMonitor.get_speed(),
            "up":   self.uploadSpeedMonitor.get_speed()  }

    def get_num_connections(self):
        return {
            "client": len(self.connectionManager.clientFactory.active_connection),
            "server": len(self.connectionManager.serverFactory.active_connection)}
    
    def get_progress(self):
        return self.pieceManager.getProgress()

    def add_peers(self, peers):
        """Adds peers to the torrent for downloading pieces.

        @param peers list of tuples e.g. [('173.248.194.166', 12005),
            ('192.166.145.8', 13915)]
        """
        self.connectionManager.clientFactory.updateTrackerPeers(peers)

    def exit(self):
        if self.status == 'running' :
            self.stopDownload()

        for i in self.__dict__ :
            del self.__dict__[i]
Exemple #16
0
class BTDownload(object) :

    task_max_size = 5
    
    def __init__(self, protocol):
        self.protocol = protocol

        self.piece_doing = []
        self.piece_done = []

        self.peer_choke = None
        self.am_interested = None

        self.downloadSpeedMonitor = SpeedMonitor()

        self.task_max_size = 5

    def start(self):
        if not self.protocol:
            return

        self.status = 'running'
        self.btm = self.protocol.factory.btm
        self.pieceManager = self.btm.pieceManager
        pm = self.pieceManager
        self.peer_bitfield = Bitfield(pm.pieces_size)
        self.downloadSpeedMonitor.start()
        self.downloadSpeedMonitor.registerObserver(self.protocol.factory.downloadSpeedMonitor)

    def stop(self):
        for task in self.piece_doing:
            self.pieceManager.failedPieceTask(*task)

        del self.piece_doing[:]
            
        self.downloadSpeedMonitor.stop()

        del self.protocol
        del self.btm
        del self.pieceManager

        self.status = 'stopped'

    def _choke(self, val):
        self.peer_choke = bool(val)
        
        if val:
            pass
        else:
            self.__pieceRequest()

    def interested(self, val):
        am_interested = bool(val)
        if self.am_interested is am_interested :
            return

        if am_interested :
            self.protocol.send_interested()
        else :
            self.protocol.send_not_interested()

        self.am_interested = am_interested

    def cancel(self, task):
        idx, (beg, length) = task
        self.protocol.send_cancel(idx, beg, length)

    def _downloadMonitor(self, data):
        self.downloadSpeedMonitor.addBytes(len(data))        

    def __pieceRequest(self):
        if self.am_interested==True and self.peer_choke==False:
            if self.piece_doing :
                return
            new_task = self.__getTask()
            if new_task :
                self.__sendTaskRequest(new_task)
            
    def __getTask(self, size=None):
        if size is None :
            size = self.task_max_size
        pm = self.pieceManager
        new_task = pm.getMorePieceTask(self.peer_bitfield, size)
        return new_task

    @defer.inlineCallbacks
    def __sendTaskRequest(self, new_task, timeout=None):
        if not new_task:
            return

        if timeout is None:
            timeout = len(new_task) * 60

        for task in new_task :
            i, (beg, size) = task
            self.protocol.send_request(i, beg, size)
            self.piece_doing.append(task)

        yield sleep(timeout)
        self.__checkTimeout(new_task)

    def __checkTimeout(self, task_plan):
        if self.status == 'stopped' :
            return
        
        set_plan = set(task_plan)
        set_ing = set(self.piece_doing)
        set_undo = set_plan & set_ing
        set_new = set_ing - set_plan

        task_size = self.task_max_size - len(set_undo)
        if set_new:
            task_size += 1

        if task_size < 1:
            task_size = 1
        elif task_size > BTDownload.task_max_size :
            task_size = BTDownload.task_max_size

        self.task_max_size = task_size

        if not set_undo:
            return

        new_task = self.__getTask(self.task_max_size)

        for task in set_undo:
            self.cancel(task)
            self.piece_doing.remove(task)
            self.pieceManager.failedPieceTask(*task)

        if new_task:
            self.__sendTaskRequest(new_task)

    def _piece(self, index, beg, piece):
        task = index, (beg, len(piece))
        if task not in self.piece_doing: 
            return

        self.pieceManager.finishPieceTask(index, (beg, len(piece)), piece)
        self.piece_doing.remove(task)
        if len(self.piece_doing) == 0:
            self.__pieceRequest()

    def _bitfield(self, data):
        pm = self.pieceManager
        bf = Bitfield(pm.pieces_size, data)
        self.peer_bitfield = bf
        
        if self.pieceManager.amInterested(bf):
            self.interested(True)
            self.__pieceRequest()
        else:
            self.interested(False)

    def _have(self, index):
        self.peer_bitfield[index] = 1
        if self.pieceManager.amInterested(index) :
            self.interested(True)
            self.__pieceRequest()
Exemple #17
0
class BTUpload (object) :
    # producer interface implementation

    def __init__(self, protocol):
        self.protocol = protocol

        self.peer_interested = None
        self.am_choke = None

        self.uploadSpeedMonitor = SpeedMonitor(10)

        self.upload_todo = []
        self.upload_doing = []
        self.upload_done = []

        self.status = None

    def start(self):
        if self.status == 'started' :
            return

        if not self.protocol:
            return

        self.btm = self.protocol.factory.btm
        self.pieceManager = self.btm.pieceManager

        self.uploadSpeedMonitor.start()
        self.uploadSpeedMonitor.registerObserver(self.protocol.factory.uploadSpeedMonitor)

        self.choke(False)

        self.protocol.transport.registerProducer(self, False)

        self.status = 'started'

    def stop(self):
        if self.status == 'stopped':
            return

        self.uploadSpeedMonitor.stop()

        self.protocol.transport.unregisterProducer()
        
        del self.protocol
        del self.btm
        del self.pieceManager

        self.status = 'stopped'

    def pause(self):
        pass

    def resume(self):
        pass


    def _interested(self, val):
        self.peer_interested = bool(val)

    def _request(self, idx, begin, length):
        if not self.pieceManager.doIHave(idx): # I don't have
            return

        self.upload_todo.append((idx, (begin, length)))

        # data = self.pieceManager.getPieceData(idx, begin, length)
        # if data :
        #     self.protocol.send_piece(idx, begin, data)

        if self.status == 'idle' :
            self.resumeProducing()

    def _cancel(self, idx, begin, length):
        task = idx, (begin, length)
        if task in self.upload_todo :
            self.upload_todo.remove(task)

    def choke(self, val):
        am_choke = bool(val)
        if self.am_choke is am_choke :
            return

        if am_choke :
            self.protocol.send_choke()
        else :
            self.protocol.send_unchoke()

        self.am_choke = am_choke

    def _uploadMonitor(self, _type, data):
        self.uploadSpeedMonitor.addBytes(len(data))

    # called by transport and do write
    def resumeProducing(self):
        for i in range(len(self.upload_todo)) :
            idx, (begin, length) = self.upload_todo[i]
            data = self.pieceManager.getPieceData(idx, begin, length)
            if data :
                self.protocol.send_piece(idx, begin, data)
                self.status = 'uploading'
                del self.upload_todo[i]
                break
        else:
            self.status = 'idle'

    def stopProducing(self):
        pass