def __init__(self, peers_data, torrent): # initialize the peers class with peer data recieved self.torrent = deepcopy(torrent) self.interval = peers_data['interval'] self.seeders = peers_data['seeders'] self.leechers = peers_data['leechers'] # create a peer instance for all the peers recieved self.peers_list = [] # used for AWS Cloud test if self.torrent.client_request['AWS']: self.peers_list.append(peer('34.238.166.126', 6881, torrent)) for peer_IP, peer_port in peers_data['peers']: self.peers_list.append(peer(peer_IP, peer_port, torrent)) # bitfields from all peers self.bitfield_pieces_count = dict() # selecting the top N peers / pieces self.top_n = self.torrent.client_request['max peers'] # peers logger object self.swarm_logger = torrent_logger('swarm', SWARM_LOG_FILE, DEBUG) # torrent stats logger object self.torrent_stats_logger = torrent_logger('torrent_statistics', TORRENT_STATS_LOG_FILE, DEBUG) self.torrent_stats_logger.set_console_logging() # bitfield for pieces downloaded from peers self.bitfield_pieces_downloaded = set([]) # file handler for downloading / uploading file data self.file_handler = None # minimum pieces to recieve randomly self.minimum_pieces = 10 # check if the torrent file is for seeding if torrent.client_request['seeding'] != None: # client peer only need incase of seeding torrent self.client_peer = peer(self.torrent.client_IP, self.torrent.client_port, self.torrent) self.client_peer.initialize_seeding() # swarm lock for required for updating the global state self.swarm_lock = Lock()
def __init__(self, torrent): # the responding tracker instance for client self.client_tracker = None # connection status of the trackers self.connection_success = 1 self.connection_failure = 2 self.connection_not_attempted = 3 # trackers loggers object self.trackers_logger = torrent_logger('trackers', TRACKER_LOG_FILE, DEBUG) # get all the trackers list of the torrent data self.trackers_list = [] self.trackers_connection_status = [] for tracker_url in torrent.torrent_metadata.trackers_url_list: # classify HTTP and UDP torrent trackers if 'http' in tracker_url[:4]: tracker = http_torrent_tracker(torrent, tracker_url) if 'udp' in tracker_url[:4]: tracker = udp_torrent_tracker(torrent, tracker_url) # append the tracker class instance self.trackers_list.append(tracker) # append the connection status self.trackers_connection_status.append( self.connection_not_attempted)
def __init__(self, peer_IP, peer_port, torrent, init_peer_socket=None): # peer IP, port and torrent instance self.IP = peer_IP self.port = peer_port self.torrent = deepcopy(torrent) # initialize the peer_state self.state = peer_state() # string used for idenfiying the peer self.unique_id = '(' + self.IP + ' : ' + str(self.port) + ')' # unique peer ID recieved from peer self.peer_id = None # maximum download block message length self.max_block_length = torrent.block_length # handshake flag with peer self.handshake_flag = False # bitfield representing which data file pieces peer has self.bitfield_pieces = set([]) # peer socket for communication self.peer_sock = peer_socket(self.IP, self.port, init_peer_socket) # file handler used for reading/writing the file file self.file_handler = None # peer logger object with unique ID logger_name = 'peer' + self.unique_id self.peer_logger = torrent_logger(logger_name, PEER_LOG_FILE, DEBUG) if torrent.client_request['seeding'] != None: self.peer_logger.set_console_logging() # response message handler for recieved message self.response_handler = { KEEP_ALIVE: self.recieved_keep_alive, CHOKE: self.recieved_choke, UNCHOKE: self.recieved_unchoke, INTERESTED: self.recieved_interested, UNINTERESTED: self.recieved_uninterested, HAVE: self.recieved_have, BITFIELD: self.recieved_bitfield, REQUEST: self.recieved_request, PIECE: self.recieved_piece, CANCEL: self.recieved_cancel, PORT: self.recieved_port } # keep alive timeout : 10 second self.keep_alive_timeout = 10 # keep alive timer self.keep_alive_timer = None
def __init__(self, user_arguments): # extract the torrent file path torrent_file_path = user_arguments[TORRENT_FILE_PATH] # bittorrent client logger self.bittorrent_logger = torrent_logger('bittorrent', BITTORRENT_LOG_FILE, DEBUG) self.bittorrent_logger.set_console_logging() self.bittorrent_logger.log('Reading ' + torrent_file_path + ' file ...') # read metadata from the torrent torrent file self.torrent_info = torrent_file_reader(torrent_file_path) # decide whether the user want to download or seed the torrent self.client_request = { 'seeding': None, 'downloading': None, 'uploading rate': sys.maxsize, 'downloading rate': sys.maxsize, 'max peers': 4, 'AWS': False } # user wants to download the torrent file if user_arguments[DOWNLOAD_DIR_PATH]: self.client_request['downloading'] = user_arguments[ DOWNLOAD_DIR_PATH] if user_arguments[RATE_LIMIT]: self.client_request['downloading rate'] = int( user_arguments[RATE_LIMIT]) # user wants to seed the torrent file elif user_arguments[SEEDING_DIR_PATH]: self.client_request['seeding'] = user_arguments[SEEDING_DIR_PATH] if user_arguments[RATE_LIMIT]: self.client_request['uploading rate'] = int( user_arguments[RATE_LIMIT]) # max peer connections if user_arguments[MAX_PEERS]: self.client_request['max peers'] = int(user_arguments[MAX_PEERS]) # AWS Cloud test if user_arguments[AWS]: self.client_request['AWS'] = True else: self.client_request['AWS'] = False # make torrent class instance from torrent data extracted from torrent file self.torrent = torrent(self.torrent_info.get_data(), self.client_request) self.bittorrent_logger.log(str(self.torrent))
def __init__(self, torrent, tracker_url): super().__init__(torrent) # extract the tracker hostname and tracker port number self.tracker_url, self.tracker_port = self.parse_udp_tracker_url( tracker_url) # tracker logger self.tracker_logger = torrent_logger(self.tracker_url, TRACKER_LOG_FILE, DEBUG) # connection id : initially a magic number self.connection_id = 0x41727101980 # action : initially set to connection request action self.action = 0x0 # transaction id : random id to be set by the client self.transaction_id = int(rd.randrange(0, 255))
def __init__(self, torrent_file_path): # the torrent_class logger self.torrent_file_logger = torrent_logger('torrent file', TORRENT_LOG_FILE, DEBUG) try: # raw extract of the torrent file self.torrent_file_raw_extract = bencodepy.decode_from_file( torrent_file_path) # used for EXCECUTION LOGGING torrent_read_log = 'Torrent file decoded successfully ' + SUCCESS self.torrent_file_logger.log(torrent_read_log) except Exception as err: # used for EXCECUTION LOGGING torrent_read_log = 'Torrent file decoding failure ! ' + FAILURE + str( err) self.torrent_file_logger.log(torrent_read_log) sys.exit() # check if encoding scheme is given in dictionary if b'encoding' in self.torrent_file_raw_extract.keys(): self.encoding = self.torrent_file_raw_extract[b'encoding'].decode() else: self.encoding = 'UTF-8' # formatted metadata from the torrent file self.torrent_file_extract = self.extract_torrent_metadata( self.torrent_file_raw_extract) # check if there is list of trackers if 'announce-list' in self.torrent_file_extract.keys(): trackers_url_list = self.torrent_file_extract['announce-list'] else: trackers_url_list = [self.torrent_file_extract['announce']] # file name file_name = self.torrent_file_extract['info']['name'] # piece length in bytes piece_length = self.torrent_file_extract['info']['piece length'] # sha1 hash concatenation of all pieces of files pieces = self.torrent_file_extract['info']['pieces'] # info hash generated for trackers info_hash = self.generate_info_hash() # files is list of tuple of size and path in case of multifile torrent files = None # check if torrent file contains multiple paths if 'files' in self.torrent_file_extract['info'].keys(): # file information - (length, path) files_dictionary = self.torrent_file_extract['info']['files'] files = [(file_data['length'], file_data['path']) for file_data in files_dictionary] file_size = 0 for file_length, file_path in files: file_size += file_length else: # file size in bytes file_size = self.torrent_file_extract['info']['length'] # base class constructor super().__init__(trackers_url_list, file_name, file_size, piece_length, pieces, info_hash, files) # used for EXCECUTION LOGGING self.torrent_file_logger.log(self.__str__())
def __init__(self, torrent, tracker_url): super().__init__(torrent) self.tracker_url = tracker_url # tracker logger self.tracker_logger = torrent_logger(self.tracker_url, TRACKER_LOG_FILE, DEBUG)