Stuck in Receive metadata (Stage XI4)

I’m stuck on Stage XI4

after send request metadata, can’t receive metadata back

but works locally

(venv) > python -m app.main magnet_info "magnet3.gif.torrent: magnet:?xt=urn:btih:c5fb9894bdaba464811b088d806bdd611ba490af&dn=magnet3.gif&tr=http%3A%2F%2Fbittorrent-test-tracker.codecrafters.io%2Fannounce"
http://bittorrent-test-tracker.codecrafters.io/announce c5fb9894bdaba464811b088d806bdd611ba490af
random peer_id: jczhcpscvlcdyfcwkjwr
{b'peers': b'\xa7G\x8f6\xc8\xe2\xa5\xe8#\x8b\xc9\x03\x8b;\xb8\xff\xc9\\', b'complete': 3, b'incomplete': 0, b'interval': 60, b'min interval': 60}
b'\x13BitTorrent protocol\x00\x00\x00\x00\x00\x10\x00\x04\xc5\xfb\x98\x94\xbd\xab\xa4d\x81\x1b\x08\x8d\x80k\xdda\x1b\xa4\x90\xaf-RN0.0.0-\xe3=\xb7flI\xecPO\xfd\xcb'
reserve bytes: b'\x00\x00\x00\x00\x00\x10\x00\x04'
Peer ID: 2d524e302e302e302de33db7666c49ec504ffdcb
receive length: 2
waiting for bitfield message: PeerMessage(length=2, message_id=5, pay_load=b'\x05\xe0')
bytearray(b'\x00\x00\x00%\x14\x00d1:md11:ut_metadatai1e6:ut_pexi2eee')
receive length: 99
b"d1:md11:ut_metadatai1e6:ut_pexi2ee13:metadata_sizei132e4:reqqi250e1:v10:Rain 0.0.06:yourip4:'\xa8P7e"
receive dict {b'm': {b'ut_metadata': 1, b'ut_pex': 2}, b'metadata_size': 132, b'reqq': 250, b'v': b'Rain 0.0.0', b'yourip': b"'\xa8P7"}
Peer Metadata Extension ID: 1
sending message: PeerMessage(length=27, message_id=20, pay_load=bytearray(b'\x01d8:msg_typei0e5:piecei0ee'))
receive length: 177
b"\x14\x01d8:msg_typei1e5:piecei0e10:total_sizei132eed6:lengthi629944e4:name11:magnet3.gif12:piece le
ngthi262144e6:pieces60:\xca\x80\xfd\x83\xff\xb3Mn\x1b\xbd&\xa8\xefm0X'\xf1\xcd\np\x7f\xd7\xc6W\xf6\xd66\xf0X4f\xc3\xcf\xe14\xdd\xb2\xc0\x8aG\x07m\x10M!L\x00R\x96\x0e\xf7g&&I\xa8\xaf\x0e\xa8e"
Tracker URL: http://bittorrent-test-tracker.codecrafters.io/announce
Length: 629944
Info Hash: c5fb9894bdaba464811b088d806bdd611ba490af
Piece Length: 262144
Piece Hashes:
ca80fd83ffb34d6e1bbd26a8ef6d305827f1cd0a
707fd7c657f6d636f0583466c3cfe134ddb2c08a
47076d104d214c0052960ef767262649a8af0ea8

Here are my logs:

remote: [tester::#XI4] Running tests for Stage #XI4 (Magnet Links - Send extension handshake)        
remote: [tester::#XI4] Running ./your_bittorrent.sh magnet_handshake "magnet:?xt=urn:btih:3f994a835e090238873498636b98a3e78d1c34ca&dn=magnet2.gif&tr=http%3A%2F%2F127.0.0.1:45067%2Fannounce"
remote: [tester::#XI4] Peer listening on address: 127.0.0.1:45943
remote: [tester::#XI4] Tracker started on address 127.0.0.1:45067...
remote: [tester::#XI4]
remote: [your_program] http://127.0.0.1:45067/announce 3f994a835e090238873498636b98a3e78d1c34ca      
remote: [your_program] random peer_id: lsrpkvmkjljxvxzvzhyq
remote: [your_program] {b'complete': 1, b'incomplete': 0, b'mininterval': 1800, b'peers': b'\x7f\x00\x00\x01\xb3w'}
remote: [tester::#XI4] Waiting to receive handshake message
remote: [tester::#XI4] Received handshake: [infohash: 3f994a835e090238873498636b98a3e78d1c34ca, peer_id: 4aaace2dc04ecf1a2f1b0498ccadd57771fa40fe]
remote: [tester::#XI4]
remote: [tester::#XI4] Sending back handshake with peer_id: ac16c2e4c7138e80b6c405e38321022fa0b3871b 
remote: [tester::#XI4] Sending bitfield message
remote: [tester::#XI4] Sending extension handshake
remote: [tester::#XI4] Waiting to receive extension handshake message
remote: [tester::#XI4] Received extension handshake with payload: ing metadata extension id received 
remote: [your_program] b'\x13BitTorrent protocol\x00\x00\x00\x00\x00\x10\x00\x00?\x99J\x83^\t\x028\x8
74\x98ck\x98\xa3\xe7\x8d\x1c4\xca\xac\x16\xc2\xe4\xc7\x13\x8e\x80\xb6\xc4\x05\xe3\x83!\x02/\xa0\xb3\x87\x1b'
remote: [your_program] reserve bytes: b'\x00\x00\x00\x00\x00\x10\x00\x00'
remote: [your_program] Peer ID: ac16c2e4c7138e80b6c405e38321022fa0b3871b
remote: [your_program] b'\x00\x00\x00\x02'
remote: [your_program] receive length: 2
remote: [your_program] waiting for bitfield message: PeerMessage(length=2, message_id=5, pay_load=b'\x05\x80')
remote: [your_program] bytearray(b'\x00\x00\x00%\x14\x00d1:md11:ut_metadatai1e6:ut_pexi2eee')        
remote: [your_program] b'\x00\x00\x000'
remote: [your_program] receive length: 48
remote: [your_program] b'd1:md11:ut_metadatai156ee13:metadata_sizei91ee'
remote: [your_program] receive dict {b'm': {b'ut_metadata': 156}, b'metadata_size': 91}
remote: [your_program] Peer Metadata Extension ID: 156
remote: [your_program] sending message: PeerMessage(length=27, message_id=20, pay_load=bytearray(b'\x9cd8:msg_typei0e5:piecei0ee'))
remote: [tester::#XI4] timed out, test exceeded 10 seconds
remote: [tester::#XI4] Test failed

And here’s a snippet of my code:

def magnet_handshake_peer(tracker_url, info_hash, peer_ip, peer_port):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect((peer_ip, int(peer_port)))

        reserved_bytes = (1 << 20).to_bytes(8, "big")
        p = PeerProtocol(reserved_bytes=reserved_bytes, info_hash=info_hash)
        s.send(p.serialize_to_message())
        msg = s.recv(68)
        print(msg)
        reserved_bytes = int.from_bytes(msg[20:28], "big")
        if reserved_bytes >> 20 & 1 == 0:
            print(f"peer {peer_ip}:{peer_port} don't support the extension protocol")
            return False
        print(f"reserve bytes: {msg[20:28]}")
        print(f"Peer ID: {msg[48:].hex()}")

        while 1:
            length, message = receive_message(s)
            bitfield_msg = deserialize_peer_message(length, message)
            print(f"waiting for bitfield message: {bitfield_msg}")
            # The message id for this message type is 5.
            if bitfield_msg.message_id == 5:
                break

        pay_load = bytearray()
        pay_load.append(0)  # message_id
        dic = {"m": {"ut_metadata": 1, "ut_pex": 2}}
        # dic = {"m": {"ut_metadata": 18}}
        pay_load.extend(bencodepy.encode(dic))

        msg = PeerMessage(1 + len(pay_load), message_id=20, pay_load=pay_load)
        print(serialize_peer_message(msg))
        s.send(serialize_peer_message(msg))

        length, msg = receive_message(s)
        print(msg[2:])
        dic = bencodepy.decode(msg[2:])
        metadata_extension_id = dic[b"m"][b"ut_metadata"]

        print(f"receive dict {dic}")
        print(f"Peer Metadata Extension ID: {metadata_extension_id}")

        pay_load = bytearray()
        pay_load.append(metadata_extension_id)  # extension message id
        dic = {"msg_type": 0, "piece": 0}
        pay_load.extend(bencodepy.encode(dic))
        msg = PeerMessage(1 + len(pay_load), message_id=20, pay_load=pay_load)
        print(f"sending message: {msg}")

        s.send(serialize_peer_message(msg))
        length, msg = receive_message(s)
        print(msg)
        dic_split_index = msg.find(b"d", 3)  # we find the second 'd'
        dic = bencodepy.decode(msg[2:dic_split_index])
        # print(dic)
        msg_type = dic[b"msg_type"]
        assert msg_type == 1  # data
        piece = dic[b"piece"]
        assert piece == 0
        total_size = dic[b"total_size"]
        info = bencodepy.decode(msg[dic_split_index:])  # meta_info
        # print(info)
        length = info[b"length"]
        _info_hash = sha1(bencodepy.encode(info)).hexdigest()
        # print(_info_hash, str(binascii.hexlify(info_hash)))
        # assert _info_hash == info_hash
        piece_length = info[b"piece length"]
        piece_hashes = info[b"pieces"]

        print(f"Tracker URL: {tracker_url}")
        print(f"Length: {length}")
        print(f"Info Hash: {_info_hash}")
        print(f"Piece Length: {piece_length}")
        print("Piece Hashes: ")
        for i in range(0, len(piece_hashes), 20):
            print(piece_hashes[i : i + 20].hex())
        return True

solved, i use one function for both magnet_handshake and manget_info command.
and magnet_handshake should early stop, shouldn’t send extension message

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.