如何获得对ut_metadata piece请求的响应?(node.js Bit Torrent BEP 0009)

Oli*_*hou 5 javascript bittorrent protocols node.js torrent

我正在使用Node.js构建一个Bittorrent客户端,并且无法通过PWP元数据扩展(BEP 0009)从对等方获得答案

我从DHT(BEP 0005)(我宣布的地方)获得同行,然后使用网络套接字在PWP上发送握手和扩展握手.

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))
})
Run Code Online (Sandbox Code Playgroud)

从这里开始,我得到Handshakes并将Hanshakes延伸回来(有时是Bitfields),然后我需要元数据:

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

// utMetadata is from extended Handshake dictionary m.ut_metadata 
client.write(message.buildExtRequest(utMetadata, req))
Run Code Online (Sandbox Code Playgroud)

在什么之后,我再也没有听到同伴的消息.2分钟后没有保持活着,连接超时.

有没有人知道为什么我没有得到回复?

Oli*_*hou 3

如果您像我一样是新手,那么 BitTorrent 协议消息格式可能不清楚。

消息结构始终如下(握手除外):

<len><message>
Run Code Online (Sandbox Code Playgroud)

其中len是值 message.length 的 UInt32 大端字节序, 消息是您发送的除握手之外的任何内容。

例如:

扩展协议片请求:ut_metadata片消息

<len><id><extId><ut_metadata dict>
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • len是一个 UInt32 大端字节序,其值: () 的大小
  • Id是一个值为 20 的 Uint8(它是协议扩展指示符)
  • extId是 UInt8。它的值取决于从对等方收到的扩展握手(其中给出了 ut_metadata 交换的 extId)
  • ut_metadata dict是一个编码字典:

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

    d8:msg_typei0e5:piecei0ee

(这里是第一行的对象 -字典- 第二行是编码后的同一个对象)

  • msg_type为 0(这是BEP 0009片段请求的请求消息指示符。

  • piece是您请求的片段的索引(0 表示第一个片段)

一般来说:

不给出正确的值<len>将导致对等方错误地解释消息,因此得不到正确的答案,得不到任何答案并最终关闭连接(由对等方或通过您自己的消息)