def test_dict(self): self.assertEqual({'a':2}, bdecode('d1:ai2ee')) self.assertEqual({'b':[1,2]}, bdecode('d1:bli1ei2eee')) self.assertEqual({'cow':'moo', 'spam':'eggs'}, bdecode('d3:cow3:moo4:spam4:eggse')) self.assertEqual({'spam':['a', 'b']}, bdecode('d4:spaml1:a1:bee')) self.assertEqual({'publisher':'bob', 'publisher-webpage':'www.example.com', 'publisher.location':'home' }, bdecode('d9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee'))
def test_list(self): self.assertEqual(['a', 'c', 'e'], bdecode('l1:a1:c1:ee')) self.assertEqual([1,2,3], bdecode('li1ei2ei3ee')) self.assertEqual([1,'a',3], bdecode('li1e1:ai3ee')) self.assertEqual([[1,2],['a','b']], bdecode('lli1ei2eel1:a1:bee')) self.assertEqual(['spam', 'eggs'], bdecode('l4:spam4:eggse'))
def test_list(self): self.assertEqual(['a', 'c', 'e'], bdecode('l1:a1:c1:ee')) self.assertEqual([1, 2, 3], bdecode('li1ei2ei3ee')) self.assertEqual([1, 'a', 3], bdecode('li1e1:ai3ee')) self.assertEqual([[1, 2], ['a', 'b']], bdecode('lli1ei2eel1:a1:bee')) self.assertEqual(['spam', 'eggs'], bdecode('l4:spam4:eggse'))
def clean_torrent(self): torrent = self.cleaned_data["torrent"] # Check that the torrent is actually a torrent file and set the info_hash _, ext = os.path.splitext(torrent.name) if ext != '.torrent': raise forms.ValidationError('File must end with .torrent') try: data = bdecode(torrent.read()) except ValueError: raise forms.ValidationError('Problem parsing torrent file') if 'info' not in data: raise forms.ValidationError('Info dict not in torrent file') #Verify uniqueness the_hash = hashlib.sha1(bencode(data['info'])).hexdigest() if Torrent.objects.filter(info_hash=the_hash).count() != 0: raise forms.ValidationError('Torrent already exists [%s]' % the_hash) #encode the name torrent.name = '%s.torrent' % hashlib.sha1( the_hash + settings.SECRET_KEY).hexdigest() return torrent
def __init__(self, filename, client_id): '''Opens file with context manager''' self.client_id = client_id self.peers = {} self._cached_messages = {} self._trackers = set() with io.open(filename, 'rb') as f: self._data = bdecode(f) # just so this init function doesn't get any bigger... self._calculate_properties() self._file_handler = FileHandler(self.query('name'), self.files, [p['length'] for p in self.pieces], self.piece_hashes) self._message_dispatch = { messages.Handshake: self._handshake_maker, messages.Bitfield: self._bitfield_maker } self._message_handlers = { messages.INCOMING: { messages.Have: lambda msg: self._increment_frequency(msg.index), messages.Bitfield: self._process_bitfield, messages.Piece: lambda m: self.file_handler.write(*m.payload) }, messages.OUTGOING: { } } self._exception_handlers = {}
async def announce(self, event: TrackerEvent): params = { 'info_hash': urllib.parse.quote(self.file.info_hash), 'peer_id': self.peer_id, 'port': self.server_port, 'uploaded': self.session.uploaded, 'downloaded': self.file.pieces_completed * self.file.piece_size, 'remaining': self.file.file_size - self.file.pieces_completed * self.file.piece_size, 'compact': 1, 'event': event.name, } if self.tracker_id: params['trackerid'] = self.tracker_id url = f"{self.announce_url}?{urllib.parse.urlencode(params)}" try: timeout = aiohttp.ClientTimeout(total=REQUEST_TIMEOUT) async with aiohttp.ClientSession(timeout=timeout) as session: async with session.get(url) as response: resp_bytes = await response.read() data, _ = bdecode(resp_bytes.decode('utf-8'), strict=False) if 'failure reason' in data: raise ValueError(data['failure reason']) elif 'warning message' in data: # LOG WARNING MESSAGE pass if isinstance(data['peers'], dict): peers = [(entry['ip'], entry['port']) for entry in data['peers'].items()] else: # In compact mode peers is string consisting of ip & port only. I.e.: # ip,port,ip,port,... data['peers'] = data['peers'].encode('utf-8') if not len(data['peers']) % 6 == 0: raise ValueError() # LOG peers = list(struct.iter_unpack( "!IH", data['peers'])) # List[(ip: int, port: int)] self.tracker_id = data['tracker id'] return data['interval'], peers except asyncio.TimeoutError: raise ConnectionAbortedError() # TODO: Log except Exception as e: raise e # TODO: Log
def test_dict(self): self.assertEqual({'a': 2}, bdecode('d1:ai2ee')) self.assertEqual({'b': [1, 2]}, bdecode('d1:bli1ei2eee')) self.assertEqual({ 'cow': 'moo', 'spam': 'eggs' }, bdecode('d3:cow3:moo4:spam4:eggse')) self.assertEqual({'spam': ['a', 'b']}, bdecode('d4:spaml1:a1:bee')) self.assertEqual( { 'publisher': 'bob', 'publisher-webpage': 'www.example.com', 'publisher.location': 'home' }, bdecode( 'd9:publisher3:bob17:publisher-webpage15:www.example.com18:publisher.location4:homee' ))
def handle_response(self, response): '''Parses response, updates tracker data, raises appropriate event''' info = bdecode(io.BytesIO(response.content)) if 'failure reason' in info or 'warning message' in info: self.handle_event(events.TrackerFailure(tracker=self, info=info)) else: old_peers = set(self.peer_addresses) self.data.update(info) new_peers = set(self.peer_addresses) - old_peers self.handle_event(events .TrackerResponse(tracker=self, new_peer_addresses=new_peers))
def download_torrent(request, object_id): torrent = get_object_or_404(Torrent, pk=object_id) #load the file into memory data = torrent.torrent.read() decoded_data = bdecode(data) #set the tracker, reverse announce url announce_url = 'http://%s%s' % (Site.objects.get_current().domain, reverse('tracker.views.announce')) decoded_data['announce'] = announce_url #generate a response with correct mimetype and file as the attachment response = HttpResponse(mimetype='application/x-bittorrent') response['Content-Disposition'] = 'attachment; filename=%s.torrent' % torrent.info_hash response.write(bencode(decoded_data)) return response
def download_torrent(request, object_id): torrent = get_object_or_404(Torrent, pk=object_id) #load the file into memory data = torrent.torrent.read() decoded_data = bdecode(data) #set the tracker, reverse announce url announce_url = 'http://%s%s' % (Site.objects.get_current().domain, reverse('tracker.views.announce')) decoded_data['announce'] = announce_url #generate a response with correct mimetype and file as the attachment response = HttpResponse(mimetype='application/x-bittorrent') response[ 'Content-Disposition'] = 'attachment; filename=%s.torrent' % torrent.info_hash response.write(bencode(decoded_data)) return response
def clean_torrent(self): torrent = self.cleaned_data["torrent"] # Check that the torrent is actually a torrent file and set the info_hash _, ext = os.path.splitext(torrent.name) if ext != '.torrent': raise forms.ValidationError('File must end with .torrent') try: data = bdecode(torrent.read()) except ValueError: raise forms.ValidationError('Problem parsing torrent file') if 'info' not in data: raise forms.ValidationError('Info dict not in torrent file') #Verify uniqueness the_hash = hashlib.sha1(bencode(data['info'])).hexdigest() if Torrent.objects.filter(info_hash=the_hash).count() != 0: raise forms.ValidationError('Torrent already exists [%s]' % the_hash) #encode the name torrent.name = '%s.torrent' % hashlib.sha1(the_hash + settings.SECRET_KEY).hexdigest() return torrent
def test_reciprical(self): for i in xrange(100): element = self.rand_element() self.assertEqual(bdecode(bencode(element)), element)
def test_str(self): self.assertEqual('abc', bdecode('3:abc')) self.assertEqual('aasdfbc', bdecode('7:aasdfbc')) self.assertEqual('spam', bdecode('4:spam'))
def test_int(self): self.assertEqual(1, bdecode('i1e')) self.assertEqual(1832, bdecode('i1832e')) self.assertEqual(3, bdecode('i3e'))
raise Exception # trouver mieux? self.msg_dict = {'len': msg_len, 'id': msg_id, 'payload': msg_payload} def send(self): msg_send = self.msg_dict['len'] msg_send += self.msg_dict.get('id', '') msg_send += self.sg_dict.get('payload', '') return ''.join(self.msg_dict.values) # PROBLEME D'ORDRE... GROS PBME... LIST? return msg_send if __name__ == '__main__': import utils import io with io.open('flagfromserver.torrent', 'rb') as iostream: tom_torrent = Torrent(utils.bdecode(iostream)) print(tom_torrent.tracker_info) print(tom_torrent.info_hash) print(tom_torrent.request_tracker()) peers = tom_torrent.get_peers() print(peers) print(tom_torrent._handshake(('96.126.104.219', 62859))) # user repr! # ord and chr # see as number # check struct # x.decode / encode