webtorrent / bittorrent-dht

🕸 Simple, robust, BitTorrent DHT implementation
https://webtorrent.io
MIT License
1.23k stars 203 forks source link

dht.lookup() throws uncatchable error #224

Open phillmac opened 3 years ago

phillmac commented 3 years ago

https://github.com/webtorrent/bittorrent-dht/blob/2960ebcfe6df38697572facea608639db0a245e2/client.js#L499

Version 9.0.3 node v14.15.3

The line numbers may have changed a little due to a slightly outdated version , but the above seems to be the referenced line. Moreover the cause of the error should still be present, because the underlying cause hasn't changed. The trace is as follows:

/torrent-health-scraper/node_modules/bittorrent-dht/client.js:505
  var q = query.q.toString()
                  ^

TypeError: Cannot read property 'toString' of undefined
    at DHT._onquery (/torrent-health-scraper/node_modules/bittorrent-dht/client.js:505:19)
    at RPC.onquery (/torrent-health-scraper/node_modules/bittorrent-dht/client.js:95:10)
    at RPC.emit (events.js:315:20)
    at RPC.onquery (/torrent-health-scraper/node_modules/k-rpc/index.js:67:10)
    at RPC.emit (events.js:315:20)
    at Socket.onmessage (/torrent-health-scraper/node_modules/k-rpc-socket/index.js:121:12)
    at Socket.emit (events.js:315:20)
    at UDP.onMessage [as onmessage] (dgram.js:919:8)

Possibly this is an error in k-rpc? if the q property should always be present and it somehow isn't. However imho it seems we could make some improvements here by removing the assumption that everything will always be fine and at least throw a catchable error instead of crashing.

phillmac commented 3 years ago

My code looks something like this, I don't think there's any way I can trap this error. I'd be glad to be wrong and have it pointed out.

function scrapeDHT (torrent) {
    return new Promise((resolve, reject) => {
      console.debug('Scraping DHT peers ...')
      try {
        const dht = new DHT()
        const peers = []
        dht.on('peer', function (peer, _ih, _from) {
          const peerhash = crypto.createHash('md5').update(peer.host + peer.port).digest('hex')
          if (!(peers.includes(peerhash))) {
            peers.push(peerhash)
          }
        })
        dht.lookup(torrent._id, async function () {
          console.debug('DHT scrape complete')
          torrent.dhtData = {
            infoHash: torrent._id,
            peers: peers.length,
            scraped_date: Math.floor(new Date() / 1000)
          }
          resolve()
        })
      } catch (err) {
        reject(err)
      }
    })
  }