nmbarel
nmbarel

Reputation: 21

UDP Tracker only gives me my ip as answer to announce request

I've recently been trying to create a torrent client in python, and have just got the UDP announce protocol to work. The tracker accepts my connect request just fine but only returns my IP and port as the peer list when I announce to it... I've tried to look at the same torrents in other torrent clients and they have multiple working peers while my request only shows me my computer (I've tried this on many torrents, all return just my IP and port)

Here's the code for the sending function itself:

    async def announce_udp(self, try_num = 1):
    self.sock.settimeout(15)
    answer = {}
    inner_while = False
    while try_num < 4:
        while try_num < 4:
            try:
                print("trying to send")
                sended = self.send(1, self.announce_payload())
                print("sending the following packet: {0}".format(sended))
                print(self.url)
                inner_while = True
                break
            except Exception:
                print("problem in sending")
                try_num += 1
        if not inner_while:
            break
        try:
            answer = self.interpret(15)
            break
        except Exception:
            print("problem in receiving")
            try_num += 1
    print("announce answer is: {0}".format(answer))
    return answer

here's the code for the make payload function:

def announce_payload(self, downloaded = 0, left = 0, uploaded = 0, event = 0, key = get_transaction_id()):
    payload = [self.torrent.get_torrent_info_hash_decoded(), get_peer_id().encode(), downloaded,
               self.torrent.get_torrent_size(), uploaded, event, 0, key, -1, 6988]
    p_tosend = None
    try:
        p_tosend = struct.pack('!20s20sqqqiIIiH', *payload)
    except Exception as e:
        print("there was an error: {0}".format(e))
    return p_tosend

here's the code for the interpret + process function:

def interpret(self, timeout=10):
    self.sock.settimeout(timeout)
    print("got to interpret")
    try:
        response = self.sock.recv(10240)
        print("answer recieved")
    except socket.timeout:
        print("no answer, try again")
        raise TrackerResponseException("no answer", 0)

    headers = response[:8]
    payload = response[8:]

    action, trans_id = struct.unpack('!ll', headers)

    try:
        trans = self.transactions[trans_id]
    except KeyError:
        raise TrackerResponseException("InvalidTransaction: id not found", trans_id)

    try:
        trans['response'] = self.process(action, payload, trans)
    except Exception as e:
        trans['response'] = None
        print("error occured: {0}".format(e))
    trans['completed'] = True
    del self.transactions[trans_id]
    #print(trans)
    return trans

  def process_announce(self, payload, trans):
    response = {}
    info = payload[:struct.calcsize("!lll")]
    interval, leechers, seeders = struct.unpack("!lll", info)
    print(interval, leechers, seeders, "noamsssssss")
    peer_data = payload[struct.calcsize("!lll"):]
    peer_size = struct.calcsize("!lH")
    num_of_peers = int(len(peer_data) / peer_size)
    print("the number of peers is: {0} and the peer data is: {1}".format(num_of_peers, peer_data))
    print()
    peers = []
    for peer_offset in range(num_of_peers):
        off = peer_size * peer_offset
        peer = peer_data[off:off + peer_size]
        addr, port = struct.unpack("!lH", peer)
        peers.append({
            'addr': socket.inet_ntoa(struct.pack('!L', addr)),
            'port': port,
        })
    print(payload)
    return dict(interval=interval, leechers=leechers, seeders=seeders, peers=peers)

I'm sorry if any of this is irrelevant, but I want to give you all of the code incase it tells you something.

(get_peer_id() returns a random peer id per the tracker protocol specification, and the get_transaction_id() returns random.randint(0, 1 << 32 - 1))

EDIT: Alright, I've found the problem and now I'm feeling pretty dumb... turns out even in the udp tracker whenever you send the info hash it has to be SHA1 encoded. Hopefully this can help someone if they are stuck in the same problem :)

Upvotes: 0

Views: 483

Answers (0)

Related Questions