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 ?
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).
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.
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.
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:
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With