Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get responses to ut_metadata piece request ? (node.js Bit Torrent BEP 0009)

I'm building a Bittorrent client using Node.js and am failing at getting answer from peers over the PWP metadata extension (BEP 0009)

I get peers from the DHT (BEP 0005) (where i announce), then send Handshake and Extended Handshake over PWP using a net Socket.

buildHandshake = (torrent, ext) => { // torrent contains mainly infoHash
    const buf = Buffer.alloc(68)
    buf.writeUInt8(19, 0)
    buf.write('BitTorrent protocol', 1)
    if (ext) {
        const big = new Uint64BE(1048576)
        big.toBuffer().copy(buf, 20)
    } else {
        buf.writeUInt32BE(0, 20)
        buf.writeUInt32BE(0, 24)
    }
    torrent.infoHashBuffer.copy(buf, 28)
    anon.nodeId().copy(buf, 48) // tool that generates a nodeId once.
    return buf
}

buildExtRequest = (id, msg) => {
    const size = msg.length + 1
    const buf = Buffer.alloc(size + 5)
    buf.writeUInt32BE(size, 0)
    buf.writeUInt8(20, 4)
    buf.writeUInt8(id, 5)
    msg.copy(buf, 6)
    return buf
}

const client = new net.Socket()
     client.connect(peer.port, peer.ip, () => {
        client.write(buildHandshake(torrent, true))
        const extHandshake = bencode.encode({
            m: {
                ut_metadata: 2,
            },
            metadata_size: self.metaDataSize, // 0 by default
            p: client.localPort,
            v: Buffer.from('Hypertube 0.1')
        })
        client.write(buildExtRequest(0, extHandshake))
})

From here, i get Handshakes and extended Hanshakes back (and sometimes Bitfields), then i require metadata pieces:

const req = bencode.encode({ msg_type: 0, piece: 0 })

// utMetadata is from extended Handshake dictionary m.ut_metadata 
client.write(message.buildExtRequest(utMetadata, req))

After what, i don't hear from the peer anymore. After 2mins without keeping alive, connection timeouts.

Has anybody got an idea why i don't get answered back ?

like image 980
Olivier Pichou Avatar asked Dec 28 '16 21:12

Olivier Pichou


People also ask

How is data communicated through applications like BitTorrent?

A P2P communication protocol like BitTorrent breaks down the files into pieces and moves them from uploaders (seeders) to downloaders (leechers) via a torrent client (a separate program that reads all the information in the . torrent file and connects users to exchange data).

How many bytes long are message identifiers in the peer wire protocol?

Data Types Unless specified otherwise, all integers in the peer wire protocol are encoded as four byte big-endian values. This includes the length prefix on all messages that come after the handshake.

How is BitTorrent implemented?

In its original implementation, BitTorrent base its operation around the concept of a torrent file, a centralized tracker and an associated swarm of peers. The centralized tracker provides the different entities with an address list over available peers.


1 Answers

BitTorrent protocol message formating can be unclear if you're a first timer, like me.

message structure is always as follows (except for handshake):

<len><message>

where len is a UInt32 big endian of value message.length, message is whatever you're sending except handshake.

For example:

Extended protocol piece request: ut_metadata piece message

<len><id><extId><ut_metadata dict>

where:

  • len is a UInt32 big endian of value: size of ()
  • Id is a Uint8 of value 20 (it's the protocol extension indicator)
  • extId is a UInt8. Its value depends on the extended handshake received from the peer (in which the extId of ut_metadata exchange is given)
  • ut_metadata dict is a bencoded dictionary:

    { 'msg_type': 0, 'piece': 0 }

    d8:msg_typei0e5:piecei0ee

(here is on the first line the object - the dictionary - and on the second line is the same object once bencoded)

  • msg_type is 0 (it's the request message indicator for BEP 0009 piece request.

  • piece is the index of the piece you request (0 would be the first piece)

In general:

Not giving the right value to <len> will result in messages badly interpreted by peer, and therefore not getting the right answers, not getting any answer and eventually connection being closed (by the peer or through your own messages)

like image 86
Olivier Pichou Avatar answered Sep 19 '22 23:09

Olivier Pichou