2014-04-01 10 views
5

मैं https://wiki.theory.org/BitTorrent_Tracker_ProtocolBitTorrent ग्राहक: ट्रैकर्स [अजगर] से हो रही सहकर्मी सूची

लेकिन शुद्ध उपयोग पर धार फ़ाइलों के सबसे उपलब्ध एक udp ट्रैकर का उपयोग कर ट्रैकर से सहकर्मी सूची प्राप्त करने की कोशिश कर रहा हूँ। उपर्युक्त वेबसाइट HTTP ट्रैकर्स के लिए है। HTTP आधारित ट्रैकर के साथ धार फ़ाइलों एक त्रुटि देना (Passkey error , or hash error or user error or 404 not found response)

अभी सभी HTTP ट्रैकर के लिए मेरे अनुरोध कोड की तरह लग रहे:।

payload = urllib.urlencode(payload) 
     for ann in self.torrent.announce_list: 
      if("udp" not in ann[0]): 
       url = ann[0] 
       print "Encoded Request URL :",(url + "?" + payload) 
       print "Requesting Tracker for Peer List" 
       try: 
        response = urllib.urlopen(url + "?" + payload).read() 
        print "RESPONSE :",response 
       except Exception, e: 
        print e 

मैं अनुरोध के खिलाफ मेरे अनुरोध यूआरएल crosschecked है uTorrent के द्वारा बनाया जा रहा है Wireshark का उपयोग कर। वे सभी मेल खाते हैं। जानकारी-हैश सही ढंग से उत्पन्न किया जा रहा है।

मैं यूडीपी के साथ-साथ HTTP ट्रैकर्स से पीयर सूची कैसे प्राप्त करूं? मैं lib-torrent जैसे बाहरी पुस्तकालय का उपयोग न करने की कोशिश कर रहा हूं। कुछ मार्गदर्शन वास्तव में सहायक होंगे।

उत्तर

5

निम्नलिखित कोड मेरे लिए काम किया। ट्रैकर यूआरएल और सभी यूआरएल पैरामीटर्स के साथ पेलोड डिक्शनरी के साथ announce_udp() को कॉल करना।

import binascii, urllib, socket, random, struct 
from bcode import bdecode 
from urlparse import urlparse, urlunsplit 

def announce_udp(tracker,payload): 
    tracker = tracker.lower() 
    parsed = urlparse(tracker) 

    # Teporarly Change udp:// to http:// to get hostname and portnumbe 
    url = parsed.geturl()[3:] 
    url = "http" + url 
    hostname = urlparse(url).hostname 
    port = urlparse(url).port 


    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
    sock.settimeout(8) 
    conn = (socket.gethostbyname(hostname), port) 
    #sock.bind((socket.gethostname(),s_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) 

    #Annoucing 
    s_port = sock.getsockname()[1] #get port number to which socket is connected 
    req, transaction_id = udp_create_announce_request(connection_id, payload,s_port) 
    sock.sendto(req, conn) 
    print "Announce Request Sent" 
    buf = sock.recvfrom(2048)[0] 
    print "Response received" 
    return udp_parse_announce_response(buf, transaction_id) 

def udp_create_announce_request(connection_id, payload, s_port): 
    action = 0x1 #action (1 = announce) 
    transaction_id = udp_get_transaction_id() 
    # print "2.Transaction ID :", transaction_id 
    buf = struct.pack("!q", connection_id)         #first 8 bytes is connection id 
    buf += struct.pack("!i", action)          #next 4 bytes is action 
    buf += struct.pack("!i", transaction_id)        #followed by 4 byte transaction id 
    buf += struct.pack("!20s", urllib.unquote(payload['info_hash']))  #the info hash of the torrent we announce ourselves in 
    buf += struct.pack("!20s", urllib.unquote(payload['peer_id']))   #the peer_id we announce 
    buf += struct.pack("!q", int(urllib.unquote(payload['downloaded']))) #number of bytes downloaded 
    buf += struct.pack("!q", int(urllib.unquote(payload['left'])))   #number of bytes left 
    buf += struct.pack("!q", int(urllib.unquote(payload['uploaded'])))  #number of bytes uploaded 
    buf += struct.pack("!i", 0x2)           #event 2 denotes start of downloading 
    buf += struct.pack("!i", 0x0)           #IP address set to 0. Response received to the sender of this packet 
    key = udp_get_transaction_id()           #Unique key randomized by client 
    buf += struct.pack("!i", key) 
    buf += struct.pack("!i", -1)           #Number of peers required. Set to -1 for default 
    buf += struct.pack("!i", s_port)          #port on which response will be sent 
    return (buf, transaction_id) 

def udp_parse_announce_response(buf, sent_transaction_id): 
    #print "Response is:"+str(buf) 
    if len(buf) < 20: 
     raise RuntimeError("Wrong response length while announcing: %s" % len(buf)) 
    action = struct.unpack_from("!i", buf)[0] #first 4 bytes is action 
    res_transaction_id = struct.unpack_from("!i", buf, 4)[0] #next 4 bytes is transaction id  
    if res_transaction_id != sent_transaction_id: 
     raise RuntimeError("Transaction ID doesnt match in announce response! Expected %s, got %s" 
      % (sent_transaction_id, res_transaction_id)) 
    print "Reading Response" 
    if action == 0x1: 
     print "Action is 3" 
     ret = dict() 
     offset = 8; #next 4 bytes after action is transaction_id, so data doesnt start till byte 8  
     ret['interval'] = struct.unpack_from("!i", buf, offset)[0] 
     print "Interval:"+str(ret['interval']) 
     offset += 4 
     ret['leeches'] = struct.unpack_from("!i", buf, offset)[0] 
     print "Leeches:"+str(ret['leeches']) 
     offset += 4 
     ret['seeds'] = struct.unpack_from("!i", buf, offset)[0] 
     print "Seeds:"+str(ret['seeds']) 
     offset += 4 
     peers = list() 
     x = 0 
     while offset != len(buf): 
      peers.append(dict()) 
      peers[x]['IP'] = struct.unpack_from("!i",buf,offset)[0] 
      print "IP: "+socket.inet_ntoa(struct.pack("!i",peers[x]['IP'])) 
      offset += 4 
      if offset >= len(buf): 
       raise RuntimeError("Error while reading peer port") 
      peers[x]['port'] = struct.unpack_from("!H",buf,offset)[0] 
      print "Port: "+str(peers[x]['port']) 
      offset += 2 
      x += 1 
     return ret,peers 
    else: 
     #an error occured, try and extract the error string 
     error = struct.unpack_from("!s", buf, 8) 
     print "Action="+str(action) 
     raise RuntimeError("Error while annoucing: %s" % error) 

def udp_create_connection_request(): 
    connection_id = 0x41727101980     #default connection id 
    action = 0x0         #action (0 = give me a new connection id) 
    transaction_id = udp_get_transaction_id() 
    print "1.Transaction ID :", transaction_id 
    buf = struct.pack("!q", connection_id)   #first 8 bytes is connection id 
    buf += struct.pack("!i", action)    #next 4 bytes is action 
    buf += struct.pack("!i", transaction_id)  #next 4 bytes is transaction id 
    return (buf, transaction_id) 

def udp_parse_connection_response(buf, sent_transaction_id): 
    if len(buf) < 16: 
     raise RuntimeError("Wrong response length getting connection id: %s" % len(buf))    
    action = struct.unpack_from("!i", buf)[0] #first 4 bytes is action 

    res_transaction_id = struct.unpack_from("!i", buf, 4)[0] #next 4 bytes is transaction id 
    if res_transaction_id != sent_transaction_id: 
     raise RuntimeError("Transaction ID doesnt match in connection response! Expected %s, got %s" 
      % (sent_transaction_id, res_transaction_id)) 

    if action == 0x0: 
     connection_id = struct.unpack_from("!q", buf, 8)[0] #unpack 8 bytes from byte 8, should be the connection_id 
     return connection_id 
    elif action == 0x3:  
     error = struct.unpack_from("!s", buf, 8) 
     raise RuntimeError("Error while trying to get a connection response: %s" % error) 
    pass 

def udp_get_transaction_id(): 
    return int(random.randrange(0, 255)) 
+3

अगर कोई इस उत्कृष्ट उत्तर में आश्चर्यचकित हो जाता है और चमत्कार करता है कि 'स्क्रैपिंग' ट्रैकर्स के बारे में कैसे जाना है; उदाहरण कोड यहां पाया जा सकता है: https://github.com/erindru/m2t/blob/master/m2t/scraper.py –

संबंधित मुद्दे