Skip to content
This repository has been archived by the owner on Aug 20, 2024. It is now read-only.

Python3 and ipv6 support #9

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 33 additions & 28 deletions m2t/scraper.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import binascii, urllib, socket, random, struct
from bcode import bdecode
from urlparse import urlparse, urlunsplit
from libtorrent import bdecode
from urllib.parse import urlparse, urlunsplit, urlencode
from urllib.request import urlopen

def scrape(tracker, hashes):
"""
Expand Down Expand Up @@ -33,46 +34,50 @@ def scrape(tracker, hashes):
raise RuntimeError("Unknown tracker scheme: %s" % parsed.scheme)

def scrape_udp(parsed_tracker, hashes):
print "Scraping UDP: %s for %s hashes" % (parsed_tracker.geturl(), len(hashes))
print ("Scraping UDP: %s for %s hashes" % (parsed_tracker.geturl(), len(hashes)))
if len(hashes) > 74:
raise RuntimeError("Only 74 hashes can be scraped on a UDP tracker due to UDP limitations")
transaction_id = "\x00\x00\x04\x12\x27\x10\x19\x70";
connection_id = "\x00\x00\x04\x17\x27\x10\x19\x80";
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(8)
conn = (socket.gethostbyname(parsed_tracker.hostname), parsed_tracker.port)

#Get connection ID
req, transaction_id = udp_create_connection_request()
sock.sendto(req, conn);
buf = sock.recvfrom(2048)[0]
connection_id = udp_parse_connection_response(buf, transaction_id)

#Scrape away
req, transaction_id = udp_create_scrape_request(connection_id, hashes)
sock.sendto(req, conn)
buf = sock.recvfrom(2048)[0]
return udp_parse_scrape_response(buf, transaction_id, hashes)

for af, socktype, proto, canonname, conn in socket.getaddrinfo(parsed_tracker.hostname, parsed_tracker.port, socket.AF_UNSPEC, socket.SOCK_DGRAM):
#print ("trying af",af,"conn",conn)
try:
sock = socket.socket(af, socktype)
sock.settimeout(8)

#Get connection ID
req, transaction_id = udp_create_connection_request()
sock.sendto(req, conn);
buf = sock.recvfrom(2048)[0]
connection_id = udp_parse_connection_response(buf, transaction_id)

#Scrape away
req, transaction_id = udp_create_scrape_request(connection_id, hashes)
sock.sendto(req, conn)
buf = sock.recvfrom(2048)[0]
return udp_parse_scrape_response(buf, transaction_id, hashes)
except:
continue
raise RuntimeError("Failed to scrape UDP tracker")

def scrape_http(parsed_tracker, hashes):
print "Scraping HTTP: %s for %s hashes" % (parsed_tracker.geturl(), len(hashes))
print ("Scraping HTTP: %s for %s hashes" % (parsed_tracker.geturl(), len(hashes)))
qs = []
for hash in hashes:
url_param = binascii.a2b_hex(hash)
qs.append(("info_hash", url_param))
qs = urllib.urlencode(qs)
qs = urlencode(qs)
pt = parsed_tracker
url = urlunsplit((pt.scheme, pt.netloc, pt.path, qs, pt.fragment))
handle = urllib.urlopen(url);
handle = urlopen(url);
if handle.getcode() is not 200:
raise RuntimeError("%s status code returned" % handle.getcode())
decoded = bdecode(handle.read())
ret = {}
for hash, stats in decoded['files'].iteritems():
nice_hash = binascii.b2a_hex(hash)
s = stats["complete"]
p = stats["incomplete"]
c = stats["downloaded"]
for hash, stats in decoded[b'files'].items():
nice_hash = binascii.b2a_hex(hash).decode('UTF-8')
s = stats[b'complete']
p = stats[b'incomplete']
c = stats[b'downloaded']
ret[nice_hash] = { "seeds" : s, "peers" : p, "complete" : c}
return ret

Expand Down