fix: drop buffer (#465)

This commit is contained in:
Cas 2023-05-26 18:54:30 +02:00 committed by GitHub
parent 6864ef9a24
commit c99eb89208
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 85 additions and 99 deletions

View File

@ -4,6 +4,7 @@ import once from 'once'
import parallel from 'run-parallel' import parallel from 'run-parallel'
import Peer from 'simple-peer' import Peer from 'simple-peer'
import queueMicrotask from 'queue-microtask' import queueMicrotask from 'queue-microtask'
import { hex2arr, hex2bin, text2arr, arr2hex, arr2text } from 'uint8-util'
import common from './lib/common.js' import common from './lib/common.js'
import HTTPTracker from './lib/client/http-tracker.js' // empty object in browser import HTTPTracker from './lib/client/http-tracker.js' // empty object in browser
@ -18,8 +19,8 @@ const debug = Debug('bittorrent-tracker:client')
* Find torrent peers, to help a torrent client participate in a torrent swarm. * Find torrent peers, to help a torrent client participate in a torrent swarm.
* *
* @param {Object} opts options object * @param {Object} opts options object
* @param {string|Buffer} opts.infoHash torrent info hash * @param {string|Uint8Array} opts.infoHash torrent info hash
* @param {string|Buffer} opts.peerId peer id * @param {string|Uint8Array} opts.peerId peer id
* @param {string|Array.<string>} opts.announce announce * @param {string|Array.<string>} opts.announce announce
* @param {number} opts.port torrent client listening port * @param {number} opts.port torrent client listening port
* @param {function} opts.getAnnounceOpts callback to provide data to tracker * @param {function} opts.getAnnounceOpts callback to provide data to tracker
@ -39,15 +40,15 @@ class Client extends EventEmitter {
this.peerId = typeof opts.peerId === 'string' this.peerId = typeof opts.peerId === 'string'
? opts.peerId ? opts.peerId
: opts.peerId.toString('hex') : arr2hex(opts.peerId)
this._peerIdBuffer = Buffer.from(this.peerId, 'hex') this._peerIdBuffer = hex2arr(this.peerId)
this._peerIdBinary = this._peerIdBuffer.toString('binary') this._peerIdBinary = hex2bin(this.peerId)
this.infoHash = typeof opts.infoHash === 'string' this.infoHash = typeof opts.infoHash === 'string'
? opts.infoHash.toLowerCase() ? opts.infoHash.toLowerCase()
: opts.infoHash.toString('hex') : arr2hex(opts.infoHash)
this._infoHashBuffer = Buffer.from(this.infoHash, 'hex') this._infoHashBuffer = hex2arr(this.infoHash)
this._infoHashBinary = this._infoHashBuffer.toString('binary') this._infoHashBinary = hex2bin(this.infoHash)
debug('new client %s', this.infoHash) debug('new client %s', this.infoHash)
@ -69,7 +70,7 @@ class Client extends EventEmitter {
// Remove trailing slash from trackers to catch duplicates // Remove trailing slash from trackers to catch duplicates
announce = announce.map(announceUrl => { announce = announce.map(announceUrl => {
announceUrl = announceUrl.toString() announceUrl = arr2text(announceUrl)
if (announceUrl[announceUrl.length - 1] === '/') { if (announceUrl[announceUrl.length - 1] === '/') {
announceUrl = announceUrl.substring(0, announceUrl.length - 1) announceUrl = announceUrl.substring(0, announceUrl.length - 1)
} }
@ -260,7 +261,7 @@ Client.scrape = (opts, cb) => {
const clientOpts = Object.assign({}, opts, { const clientOpts = Object.assign({}, opts, {
infoHash: Array.isArray(opts.infoHash) ? opts.infoHash[0] : opts.infoHash, infoHash: Array.isArray(opts.infoHash) ? opts.infoHash[0] : opts.infoHash,
peerId: Buffer.from('01234567890123456789'), // dummy value peerId: text2arr('01234567890123456789'), // dummy value
port: 6881 // dummy value port: 6881 // dummy value
}) })
@ -284,9 +285,6 @@ Client.scrape = (opts, cb) => {
} }
}) })
opts.infoHash = Array.isArray(opts.infoHash)
? opts.infoHash.map(infoHash => Buffer.from(infoHash, 'hex'))
: Buffer.from(opts.infoHash, 'hex')
client.scrape({ infoHash: opts.infoHash }) client.scrape({ infoHash: opts.infoHash })
return client return client
} }

View File

@ -4,6 +4,7 @@ import clone from 'clone'
import Debug from 'debug' import Debug from 'debug'
import get from 'simple-get' import get from 'simple-get'
import Socks from 'socks' import Socks from 'socks'
import { bin2hex, hex2bin, arr2text } from 'uint8-util'
import common from '../common.js' import common from '../common.js'
import Tracker from './tracker.js' import Tracker from './tracker.js'
@ -65,8 +66,8 @@ class HTTPTracker extends Tracker {
} }
const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
? opts.infoHash.map(infoHash => infoHash.toString('binary')) ? opts.infoHash.map(infoHash => hex2bin(infoHash))
: (opts.infoHash && opts.infoHash.toString('binary')) || this.client._infoHashBinary : (opts.infoHash && hex2bin(opts.infoHash)) || this.client._infoHashBinary
const params = { const params = {
info_hash: infoHashes info_hash: infoHashes
} }
@ -159,13 +160,13 @@ class HTTPTracker extends Tracker {
} catch (err) { } catch (err) {
return cb(new Error(`Error decoding tracker response: ${err.message}`)) return cb(new Error(`Error decoding tracker response: ${err.message}`))
} }
const failure = data['failure reason'] && Buffer.from(data['failure reason']).toString() const failure = data['failure reason'] && arr2text(data['failure reason'])
if (failure) { if (failure) {
debug(`failure from ${requestUrl} (${failure})`) debug(`failure from ${requestUrl} (${failure})`)
return cb(new Error(failure)) return cb(new Error(failure))
} }
const warning = data['warning message'] && Buffer.from(data['warning message']).toString() const warning = data['warning message'] && arr2text(data['warning message'])
if (warning) { if (warning) {
debug(`warning from ${requestUrl} (${warning})`) debug(`warning from ${requestUrl} (${warning})`)
self.client.emit('warning', new Error(warning)) self.client.emit('warning', new Error(warning))
@ -189,7 +190,7 @@ class HTTPTracker extends Tracker {
const response = Object.assign({}, data, { const response = Object.assign({}, data, {
announce: this.announceUrl, announce: this.announceUrl,
infoHash: common.binaryToHex(data.info_hash) infoHash: bin2hex(data.info_hash || String(data.info_hash))
}) })
this.client.emit('update', response) this.client.emit('update', response)
@ -248,7 +249,7 @@ class HTTPTracker extends Tracker {
// (separate from announce interval) // (separate from announce interval)
const response = Object.assign(data[infoHash], { const response = Object.assign(data[infoHash], {
announce: this.announceUrl, announce: this.announceUrl,
infoHash: common.binaryToHex(infoHash) infoHash: bin2hex(infoHash)
}) })
this.client.emit('scrape', response) this.client.emit('scrape', response)
}) })

View File

@ -1,10 +1,9 @@
import arrayRemove from 'unordered-array-remove' import arrayRemove from 'unordered-array-remove'
import BN from 'bn.js'
import clone from 'clone' import clone from 'clone'
import Debug from 'debug' import Debug from 'debug'
import dgram from 'dgram' import dgram from 'dgram'
import randombytes from 'randombytes'
import Socks from 'socks' import Socks from 'socks'
import { concat, hex2arr, randomBytes } from 'uint8-util'
import common from '../common.js' import common from '../common.js'
import Tracker from './tracker.js' import Tracker from './tracker.js'
@ -131,7 +130,7 @@ class UDPTracker extends Tracker {
}, common.REQUEST_TIMEOUT) }, common.REQUEST_TIMEOUT)
if (timeout.unref) timeout.unref() if (timeout.unref) timeout.unref()
send(Buffer.concat([ send(concat([
common.CONNECTION_ID, common.CONNECTION_ID,
common.toUInt32(common.ACTIONS.CONNECT), common.toUInt32(common.ACTIONS.CONNECT),
transactionId transactionId
@ -175,7 +174,8 @@ class UDPTracker extends Tracker {
function onSocketMessage (msg) { function onSocketMessage (msg) {
if (proxySocket) msg = msg.slice(10) if (proxySocket) msg = msg.slice(10)
if (msg.length < 8 || msg.readUInt32BE(4) !== transactionId.readUInt32BE(0)) { const view = new DataView(transactionId.buffer)
if (msg.length < 8 || msg.readUInt32BE(4) !== view.getUint32(0)) {
return onError(new Error('tracker sent invalid transaction id')) return onError(new Error('tracker sent invalid transaction id'))
} }
@ -270,14 +270,14 @@ class UDPTracker extends Tracker {
function announce (connectionId, opts) { function announce (connectionId, opts) {
transactionId = genTransactionId() transactionId = genTransactionId()
send(Buffer.concat([ send(concat([
connectionId, connectionId,
common.toUInt32(common.ACTIONS.ANNOUNCE), common.toUInt32(common.ACTIONS.ANNOUNCE),
transactionId, transactionId,
self.client._infoHashBuffer, self.client._infoHashBuffer,
self.client._peerIdBuffer, self.client._peerIdBuffer,
toUInt64(opts.downloaded), toUInt64(opts.downloaded),
opts.left != null ? toUInt64(opts.left) : Buffer.from('FFFFFFFFFFFFFFFF', 'hex'), opts.left != null ? toUInt64(opts.left) : hex2arr('ffffffffffffffff'),
toUInt64(opts.uploaded), toUInt64(opts.uploaded),
common.toUInt32(common.EVENTS[opts.event] || 0), common.toUInt32(common.EVENTS[opts.event] || 0),
common.toUInt32(0), // ip address (optional) common.toUInt32(0), // ip address (optional)
@ -291,10 +291,10 @@ class UDPTracker extends Tracker {
transactionId = genTransactionId() transactionId = genTransactionId()
const infoHash = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) const infoHash = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
? Buffer.concat(opts.infoHash) ? concat(opts.infoHash)
: (opts.infoHash || self.client._infoHashBuffer) : (opts.infoHash || self.client._infoHashBuffer)
send(Buffer.concat([ send(concat([
connectionId, connectionId,
common.toUInt32(common.ACTIONS.SCRAPE), common.toUInt32(common.ACTIONS.SCRAPE),
transactionId, transactionId,
@ -307,12 +307,13 @@ class UDPTracker extends Tracker {
UDPTracker.prototype.DEFAULT_ANNOUNCE_INTERVAL = 30 * 60 * 1000 // 30 minutes UDPTracker.prototype.DEFAULT_ANNOUNCE_INTERVAL = 30 * 60 * 1000 // 30 minutes
function genTransactionId () { function genTransactionId () {
return randombytes(4) return randomBytes(4)
} }
function toUInt16 (n) { function toUInt16 (n) {
const buf = Buffer.allocUnsafe(2) const buf = new Uint8Array(2)
buf.writeUInt16BE(n, 0) const view = new DataView(buf.buffer)
view.setUint16(0, n)
return buf return buf
} }
@ -320,13 +321,12 @@ const MAX_UINT = 4294967295
function toUInt64 (n) { function toUInt64 (n) {
if (n > MAX_UINT || typeof n === 'string') { if (n > MAX_UINT || typeof n === 'string') {
const bytes = new BN(n).toArray() const buf = new Uint8Array(8)
while (bytes.length < 8) { const view = new DataView(buf.buffer)
bytes.unshift(0) view.setBigUint64(0, n)
} return buf
return Buffer.from(bytes)
} }
return Buffer.concat([common.toUInt32(0), common.toUInt32(n)]) return concat([new Uint8Array(4), common.toUInt32(n)])
} }
function noop () {} function noop () {}

View File

@ -1,11 +1,11 @@
import clone from 'clone' import clone from 'clone'
import Debug from 'debug' import Debug from 'debug'
import Peer from 'simple-peer' import Peer from 'simple-peer'
import randombytes from 'randombytes'
import Socket from '@thaunknown/simple-websocket' import Socket from '@thaunknown/simple-websocket'
import Socks from 'socks' import Socks from 'socks'
import { arr2text, arr2hex, hex2bin, bin2hex, randomBytes } from 'uint8-util'
import common from '../common.js' import { DESTROY_TIMEOUT } from '../common.js'
import Tracker from './tracker.js' import Tracker from './tracker.js'
const debug = Debug('bittorrent-tracker:websocket-tracker') const debug = Debug('bittorrent-tracker:websocket-tracker')
@ -80,8 +80,8 @@ class WebSocketTracker extends Tracker {
} }
const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0) const infoHashes = (Array.isArray(opts.infoHash) && opts.infoHash.length > 0)
? opts.infoHash.map(infoHash => infoHash.toString('binary')) ? opts.infoHash.map(infoHash => hex2bin(infoHash))
: (opts.infoHash && opts.infoHash.toString('binary')) || this.client._infoHashBinary : (opts.infoHash && hex2bin(opts.infoHash)) || this.client._infoHashBinary
const params = { const params = {
action: 'scrape', action: 'scrape',
info_hash: infoHashes info_hash: infoHashes
@ -138,7 +138,7 @@ class WebSocketTracker extends Tracker {
// Otherwise, wait a short time for potential responses to come in from the // Otherwise, wait a short time for potential responses to come in from the
// server, then force close the socket. // server, then force close the socket.
timeout = setTimeout(destroyCleanup, common.DESTROY_TIMEOUT) timeout = setTimeout(destroyCleanup, DESTROY_TIMEOUT)
// But, if a response comes from the server before the timeout fires, do cleanup // But, if a response comes from the server before the timeout fires, do cleanup
// right away. // right away.
@ -214,7 +214,7 @@ class WebSocketTracker extends Tracker {
this.expectingResponse = false this.expectingResponse = false
try { try {
data = JSON.parse(Buffer.from(data)) data = JSON.parse(arr2text(data))
} catch (err) { } catch (err) {
this.client.emit('warning', new Error('Invalid tracker response')) this.client.emit('warning', new Error('Invalid tracker response'))
return return
@ -233,7 +233,7 @@ class WebSocketTracker extends Tracker {
if (data.info_hash !== this.client._infoHashBinary) { if (data.info_hash !== this.client._infoHashBinary) {
debug( debug(
'ignoring websocket data from %s for %s (looking for %s: reused socket)', 'ignoring websocket data from %s for %s (looking for %s: reused socket)',
this.announceUrl, common.binaryToHex(data.info_hash), this.client.infoHash this.announceUrl, bin2hex(data.info_hash), this.client.infoHash
) )
return return
} }
@ -266,7 +266,7 @@ class WebSocketTracker extends Tracker {
if (data.complete != null) { if (data.complete != null) {
const response = Object.assign({}, data, { const response = Object.assign({}, data, {
announce: this.announceUrl, announce: this.announceUrl,
infoHash: common.binaryToHex(data.info_hash) infoHash: bin2hex(data.info_hash)
}) })
this.client.emit('update', response) this.client.emit('update', response)
} }
@ -275,7 +275,7 @@ class WebSocketTracker extends Tracker {
if (data.offer && data.peer_id) { if (data.offer && data.peer_id) {
debug('creating peer (from remote offer)') debug('creating peer (from remote offer)')
peer = this._createPeer() peer = this._createPeer()
peer.id = common.binaryToHex(data.peer_id) peer.id = bin2hex(data.peer_id)
peer.once('signal', answer => { peer.once('signal', answer => {
const params = { const params = {
action: 'announce', action: 'announce',
@ -293,10 +293,10 @@ class WebSocketTracker extends Tracker {
} }
if (data.answer && data.peer_id) { if (data.answer && data.peer_id) {
const offerId = common.binaryToHex(data.offer_id) const offerId = bin2hex(data.offer_id)
peer = this.peers[offerId] peer = this.peers[offerId]
if (peer) { if (peer) {
peer.id = common.binaryToHex(data.peer_id) peer.id = bin2hex(data.peer_id)
this.client.emit('peer', peer) this.client.emit('peer', peer)
peer.signal(data.answer) peer.signal(data.answer)
@ -323,7 +323,7 @@ class WebSocketTracker extends Tracker {
// (separate from announce interval) // (separate from announce interval)
const response = Object.assign(data[infoHash], { const response = Object.assign(data[infoHash], {
announce: this.announceUrl, announce: this.announceUrl,
infoHash: common.binaryToHex(infoHash) infoHash: bin2hex(infoHash)
}) })
this.client.emit('scrape', response) this.client.emit('scrape', response)
}) })
@ -376,13 +376,13 @@ class WebSocketTracker extends Tracker {
checkDone() checkDone()
function generateOffer () { function generateOffer () {
const offerId = randombytes(20).toString('hex') const offerId = arr2hex(randomBytes(20))
debug('creating peer (from _generateOffers)') debug('creating peer (from _generateOffers)')
const peer = self.peers[offerId] = self._createPeer({ initiator: true }) const peer = self.peers[offerId] = self._createPeer({ initiator: true })
peer.once('signal', offer => { peer.once('signal', offer => {
offers.push({ offers.push({
offer, offer,
offer_id: common.hexToBinary(offerId) offer_id: hex2bin(offerId)
}) })
checkDone() checkDone()
}) })

View File

@ -4,12 +4,13 @@
*/ */
import querystring from 'querystring' import querystring from 'querystring'
import { concat } from 'uint8-util'
export const IPV4_RE = /^[\d.]+$/ export const IPV4_RE = /^[\d.]+$/
export const IPV6_RE = /^[\da-fA-F:]+$/ export const IPV6_RE = /^[\da-fA-F:]+$/
export const REMOVE_IPV4_MAPPED_IPV6_RE = /^::ffff:/ export const REMOVE_IPV4_MAPPED_IPV6_RE = /^::ffff:/
export const CONNECTION_ID = Buffer.concat([toUInt32(0x417), toUInt32(0x27101980)]) export const CONNECTION_ID = concat([toUInt32(0x417), toUInt32(0x27101980)])
export const ACTIONS = { CONNECT: 0, ANNOUNCE: 1, SCRAPE: 2, ERROR: 3 } export const ACTIONS = { CONNECT: 0, ANNOUNCE: 1, SCRAPE: 2, ERROR: 3 }
export const EVENTS = { update: 0, completed: 1, started: 2, stopped: 3, paused: 4 } export const EVENTS = { update: 0, completed: 1, started: 2, stopped: 3, paused: 4 }
export const EVENT_IDS = { export const EVENT_IDS = {
@ -40,8 +41,9 @@ export const REQUEST_TIMEOUT = 15000
export const DESTROY_TIMEOUT = 1000 export const DESTROY_TIMEOUT = 1000
export function toUInt32 (n) { export function toUInt32 (n) {
const buf = Buffer.allocUnsafe(4) const buf = new Uint8Array(4)
buf.writeUInt32BE(n, 0) const view = new DataView(buf.buffer)
view.setUint32(0, n)
return buf return buf
} }

View File

@ -2,24 +2,11 @@
* Functions/constants needed by both the client and server. * Functions/constants needed by both the client and server.
*/ */
import * as common from './common-node.js' import * as common from './common-node.js'
export * from './common-node.js'
export const DEFAULT_ANNOUNCE_PEERS = 50 export const DEFAULT_ANNOUNCE_PEERS = 50
export const MAX_ANNOUNCE_PEERS = 82 export const MAX_ANNOUNCE_PEERS = 82
export const binaryToHex = str => {
if (typeof str !== 'string') {
str = String(str)
}
return Buffer.from(str, 'binary').toString('hex')
}
export const hexToBinary = str => {
if (typeof str !== 'string') {
str = String(str)
}
return Buffer.from(str, 'hex').toString('binary')
}
// HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like // HACK: Fix for WHATWG URL object not parsing non-standard URL schemes like
// 'udp:'. Just replace it with 'http:' since we only need a few properties. // 'udp:'. Just replace it with 'http:' since we only need a few properties.
// //
@ -49,8 +36,6 @@ export const parseUrl = str => {
export default { export default {
DEFAULT_ANNOUNCE_PEERS, DEFAULT_ANNOUNCE_PEERS,
MAX_ANNOUNCE_PEERS, MAX_ANNOUNCE_PEERS,
binaryToHex,
hexToBinary,
parseUrl, parseUrl,
...common ...common
} }

View File

@ -1,8 +1,8 @@
import { bin2hex } from 'uint8-util'
import common from '../common.js' import common from '../common.js'
export default parseHttpRequest export default function (req, opts) {
function parseHttpRequest (req, opts) {
if (!opts) opts = {} if (!opts) opts = {}
const s = req.url.split('?') const s = req.url.split('?')
const params = common.querystringParse(s[1]) const params = common.querystringParse(s[1])
@ -14,12 +14,12 @@ function parseHttpRequest (req, opts) {
if (typeof params.info_hash !== 'string' || params.info_hash.length !== 20) { if (typeof params.info_hash !== 'string' || params.info_hash.length !== 20) {
throw new Error('invalid info_hash') throw new Error('invalid info_hash')
} }
params.info_hash = common.binaryToHex(params.info_hash) params.info_hash = bin2hex(params.info_hash)
if (typeof params.peer_id !== 'string' || params.peer_id.length !== 20) { if (typeof params.peer_id !== 'string' || params.peer_id.length !== 20) {
throw new Error('invalid peer_id') throw new Error('invalid peer_id')
} }
params.peer_id = common.binaryToHex(params.peer_id) params.peer_id = bin2hex(params.peer_id)
params.port = Number(params.port) params.port = Number(params.port)
if (!params.port) throw new Error('invalid port') if (!params.port) throw new Error('invalid port')
@ -56,7 +56,7 @@ function parseHttpRequest (req, opts) {
if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) { if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) {
throw new Error('invalid info_hash') throw new Error('invalid info_hash')
} }
return common.binaryToHex(binaryInfoHash) return bin2hex(binaryInfoHash)
}) })
} }
} else { } else {

View File

@ -1,9 +1,8 @@
import ipLib from 'ip' import ipLib from 'ip'
import common from '../common.js' import common from '../common.js'
import { equal } from 'uint8-util'
export default parseUdpRequest export default function (msg, rinfo) {
function parseUdpRequest (msg, rinfo) {
if (msg.length < 16) throw new Error('received packet is too short') if (msg.length < 16) throw new Error('received packet is too short')
const params = { const params = {
@ -13,7 +12,7 @@ function parseUdpRequest (msg, rinfo) {
type: 'udp' type: 'udp'
} }
if (!common.CONNECTION_ID.equals(params.connectionId)) { if (!equal(common.CONNECTION_ID, params.connectionId)) {
throw new Error('received packet with invalid connection id') throw new Error('received packet with invalid connection id')
} }

View File

@ -1,8 +1,8 @@
import { bin2hex } from 'uint8-util'
import common from '../common.js' import common from '../common.js'
export default parseWebSocketRequest export default function (socket, opts, params) {
function parseWebSocketRequest (socket, opts, params) {
if (!opts) opts = {} if (!opts) opts = {}
params = JSON.parse(params) // may throw params = JSON.parse(params) // may throw
@ -14,18 +14,18 @@ function parseWebSocketRequest (socket, opts, params) {
if (typeof params.info_hash !== 'string' || params.info_hash.length !== 20) { if (typeof params.info_hash !== 'string' || params.info_hash.length !== 20) {
throw new Error('invalid info_hash') throw new Error('invalid info_hash')
} }
params.info_hash = common.binaryToHex(params.info_hash) params.info_hash = bin2hex(params.info_hash)
if (typeof params.peer_id !== 'string' || params.peer_id.length !== 20) { if (typeof params.peer_id !== 'string' || params.peer_id.length !== 20) {
throw new Error('invalid peer_id') throw new Error('invalid peer_id')
} }
params.peer_id = common.binaryToHex(params.peer_id) params.peer_id = bin2hex(params.peer_id)
if (params.answer) { if (params.answer) {
if (typeof params.to_peer_id !== 'string' || params.to_peer_id.length !== 20) { if (typeof params.to_peer_id !== 'string' || params.to_peer_id.length !== 20) {
throw new Error('invalid `to_peer_id` (required with `answer`)') throw new Error('invalid `to_peer_id` (required with `answer`)')
} }
params.to_peer_id = common.binaryToHex(params.to_peer_id) params.to_peer_id = bin2hex(params.to_peer_id)
} }
params.left = Number(params.left) params.left = Number(params.left)
@ -45,7 +45,7 @@ function parseWebSocketRequest (socket, opts, params) {
if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) { if (typeof binaryInfoHash !== 'string' || binaryInfoHash.length !== 20) {
throw new Error('invalid info_hash') throw new Error('invalid info_hash')
} }
return common.binaryToHex(binaryInfoHash) return bin2hex(binaryInfoHash)
}) })
} }
} else { } else {

View File

@ -30,7 +30,6 @@
"@thaunknown/simple-websocket": "^9.1.0", "@thaunknown/simple-websocket": "^9.1.0",
"bencode": "^3.0.3", "bencode": "^3.0.3",
"bittorrent-peerid": "^1.3.3", "bittorrent-peerid": "^1.3.3",
"bn.js": "^5.2.0",
"chrome-dgram": "^3.0.6", "chrome-dgram": "^3.0.6",
"clone": "^2.0.0", "clone": "^2.0.0",
"compact2string": "^1.4.1", "compact2string": "^1.4.1",
@ -41,13 +40,13 @@
"once": "^1.4.0", "once": "^1.4.0",
"queue-microtask": "^1.2.3", "queue-microtask": "^1.2.3",
"random-iterate": "^1.0.1", "random-iterate": "^1.0.1",
"randombytes": "^2.1.0",
"run-parallel": "^1.2.0", "run-parallel": "^1.2.0",
"run-series": "^1.1.9", "run-series": "^1.1.9",
"simple-get": "^4.0.0", "simple-get": "^4.0.0",
"simple-peer": "^9.11.0", "simple-peer": "^9.11.0",
"socks": "^2.0.0", "socks": "^2.0.0",
"string2compact": "^2.0.0", "string2compact": "^2.0.0",
"uint8-util": "^2.1.9",
"unordered-array-remove": "^1.0.2", "unordered-array-remove": "^1.0.2",
"ws": "^8.0.0" "ws": "^8.0.0"
}, },

View File

@ -7,6 +7,7 @@ import peerid from 'bittorrent-peerid'
import series from 'run-series' import series from 'run-series'
import string2compact from 'string2compact' import string2compact from 'string2compact'
import { WebSocketServer } from 'ws' import { WebSocketServer } from 'ws'
import { hex2bin } from 'uint8-util'
import common from './lib/common.js' import common from './lib/common.js'
import Swarm from './lib/server/swarm.js' import Swarm from './lib/server/swarm.js'
@ -488,7 +489,7 @@ class Server extends EventEmitter {
socket.send(JSON.stringify({ socket.send(JSON.stringify({
action: params.action === common.ACTIONS.ANNOUNCE ? 'announce' : 'scrape', action: params.action === common.ACTIONS.ANNOUNCE ? 'announce' : 'scrape',
'failure reason': err.message, 'failure reason': err.message,
info_hash: common.hexToBinary(params.info_hash) info_hash: hex2bin(params.info_hash)
}), socket.onSend) }), socket.onSend)
this.emit('warning', err) this.emit('warning', err)
@ -506,7 +507,7 @@ class Server extends EventEmitter {
socket.infoHashes.push(params.info_hash) socket.infoHashes.push(params.info_hash)
} }
response.info_hash = common.hexToBinary(params.info_hash) response.info_hash = hex2bin(params.info_hash)
// WebSocket tracker should have a shorter interval default: 2 minutes // WebSocket tracker should have a shorter interval default: 2 minutes
response.interval = Math.ceil(this.intervalMs / 1000 / 5) response.interval = Math.ceil(this.intervalMs / 1000 / 5)
@ -526,8 +527,8 @@ class Server extends EventEmitter {
action: 'announce', action: 'announce',
offer: params.offers[i].offer, offer: params.offers[i].offer,
offer_id: params.offers[i].offer_id, offer_id: params.offers[i].offer_id,
peer_id: common.hexToBinary(params.peer_id), peer_id: hex2bin(params.peer_id),
info_hash: common.hexToBinary(params.info_hash) info_hash: hex2bin(params.info_hash)
}), peer.socket.onSend) }), peer.socket.onSend)
debug('sent offer to %s from %s', peer.peerId, params.peer_id) debug('sent offer to %s from %s', peer.peerId, params.peer_id)
}) })
@ -559,8 +560,8 @@ class Server extends EventEmitter {
action: 'announce', action: 'announce',
answer: params.answer, answer: params.answer,
offer_id: params.offer_id, offer_id: params.offer_id,
peer_id: common.hexToBinary(params.peer_id), peer_id: hex2bin(params.peer_id),
info_hash: common.hexToBinary(params.info_hash) info_hash: hex2bin(params.info_hash)
}), toPeer.socket.onSend) }), toPeer.socket.onSend)
debug('sent answer to %s from %s', toPeer.peerId, params.peer_id) debug('sent answer to %s from %s', toPeer.peerId, params.peer_id)
@ -685,7 +686,7 @@ class Server extends EventEmitter {
} else if (params.compact === 0) { } else if (params.compact === 0) {
// IPv6 peers are not separate for non-compact responses // IPv6 peers are not separate for non-compact responses
response.peers = response.peers.map(peer => ({ response.peers = response.peers.map(peer => ({
'peer id': common.hexToBinary(peer.peerId), 'peer id': hex2bin(peer.peerId),
ip: peer.ip, ip: peer.ip,
port: peer.port port: peer.port
})) }))
@ -729,7 +730,7 @@ class Server extends EventEmitter {
} }
results.forEach(result => { results.forEach(result => {
response.files[common.hexToBinary(result.infoHash)] = { response.files[hex2bin(result.infoHash)] = {
complete: result.complete || 0, complete: result.complete || 0,
incomplete: result.incomplete || 0, incomplete: result.incomplete || 0,
downloaded: result.complete || 0 // TODO: this only provides a lower-bound downloaded: result.complete || 0 // TODO: this only provides a lower-bound

View File

@ -5,6 +5,7 @@ import commonLib from '../lib/common.js'
import fixtures from 'webtorrent-fixtures' import fixtures from 'webtorrent-fixtures'
import get from 'simple-get' import get from 'simple-get'
import test from 'tape' import test from 'tape'
import { hex2bin } from 'uint8-util'
const peerId = Buffer.from('01234567890123456789') const peerId = Buffer.from('01234567890123456789')
@ -152,8 +153,8 @@ test('udp: MULTI scrape using Client.scrape static method', t => {
test('server: multiple info_hash scrape (manual http request)', t => { test('server: multiple info_hash scrape (manual http request)', t => {
t.plan(13) t.plan(13)
const binaryInfoHash1 = commonLib.hexToBinary(fixtures.leaves.parsedTorrent.infoHash) const binaryInfoHash1 = hex2bin(fixtures.leaves.parsedTorrent.infoHash)
const binaryInfoHash2 = commonLib.hexToBinary(fixtures.alice.parsedTorrent.infoHash) const binaryInfoHash2 = hex2bin(fixtures.alice.parsedTorrent.infoHash)
common.createServer(t, 'http', (server, announceUrl) => { common.createServer(t, 'http', (server, announceUrl) => {
const scrapeUrl = announceUrl.replace('/announce', '/scrape') const scrapeUrl = announceUrl.replace('/announce', '/scrape')
@ -189,7 +190,7 @@ test('server: multiple info_hash scrape (manual http request)', t => {
test('server: all info_hash scrape (manual http request)', t => { test('server: all info_hash scrape (manual http request)', t => {
t.plan(10) t.plan(10)
const binaryInfoHash = commonLib.hexToBinary(fixtures.leaves.parsedTorrent.infoHash) const binaryInfoHash = hex2bin(fixtures.leaves.parsedTorrent.infoHash)
common.createServer(t, 'http', (server, announceUrl) => { common.createServer(t, 'http', (server, announceUrl) => {
const scrapeUrl = announceUrl.replace('/announce', '/scrape') const scrapeUrl = announceUrl.replace('/announce', '/scrape')