dht-rpc 5.0.4 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,10 +6,6 @@ Make RPC calls over a [Kademlia](https://pdos.csail.mit.edu/~petar/papers/maymou
6
6
  npm install dht-rpc
7
7
  ```
8
8
 
9
- ## NOTE: v5
10
-
11
- Note that the latest release is v5. To see the v4 documentation/code go to https://github.com/mafintosh/dht-rpc/tree/v4
12
-
13
9
  ## Key Features
14
10
 
15
11
  * Remote IP / firewall detection
@@ -116,12 +112,12 @@ Options include:
116
112
  {
117
113
  // A list of bootstrap nodes
118
114
  bootstrap: [ 'bootstrap-node.com:24242', ... ],
119
- // Optionally pass in your own UDP socket to use.
120
- socket: udpSocket,
121
115
  // Optionally pass in array of { host, port } to add to the routing table if you know any peers
122
116
  nodes: [{ host, port }, ...],
123
117
  // Optionally pass a port you prefer to bind to instead of a random one
124
- bind: 0,
118
+ port: 0,
119
+ // Optionally pass a UDX instance on which sockets will be created.
120
+ udx,
125
121
  // dht-rpc will automatically detect if you are firewalled. If you know that you are not set this to false
126
122
  firewalled: true
127
123
  }
@@ -133,7 +129,7 @@ For the vast majority of use-cases you should always use adaptive mode to ensure
133
129
 
134
130
  Your DHT routing id is `hash(publicIp + publicPort)` and will be autoconfigured internally.
135
131
 
136
- #### `const node = DHT.boostrapper(bind, [options])`
132
+ #### `const node = DHT.bootrapper(port, [options])`
137
133
 
138
134
  Sugar for the options needed to run a bootstrap node, ie
139
135
 
@@ -144,7 +140,7 @@ Sugar for the options needed to run a bootstrap node, ie
144
140
  }
145
141
  ```
146
142
 
147
- Additionally since you'll want a known port for a bootstrap node it adds the bind option as a primary argument.
143
+ Additionally since you'll want a known port for a bootstrap node it adds the `port` option as a primary argument.
148
144
 
149
145
  #### `await node.ready()`
150
146
 
@@ -165,7 +161,7 @@ Emitted when the routing table is fully bootstrapped. Emitted as a conveinience.
165
161
 
166
162
  #### `node.on('listening')`
167
163
 
168
- Emitted when the underlying UDP socket is listening. Emitted as a conveinience.
164
+ Emitted when the underlying UDX socket is listening. Emitted as a conveinience.
169
165
 
170
166
  #### `node.on('persistent')`
171
167
 
@@ -179,6 +175,10 @@ you are on an open NAT.
179
175
  Emitted when the node has detected that the computer has gone to sleep. If this happens,
180
176
  it will switch from persistent mode to ephemeral again.
181
177
 
178
+ #### `node.on('network-change', interfaces)`
179
+
180
+ Emitted when the network interfaces of the computer change.
181
+
182
182
  #### `node.refresh()`
183
183
 
184
184
  Refresh the routing table by looking up a random node in the background.
@@ -201,12 +201,12 @@ Boolean indicated if your node is behind a firewall.
201
201
  This is auto detected by having other node's trying to do a PING to you
202
202
  without you contacting them first.
203
203
 
204
- #### `const udpAddr = node.address()`
204
+ #### `const addr = node.address()`
205
205
 
206
206
  Get the local address of the UDP socket bound.
207
207
 
208
208
  Note that if you are in ephemeral mode, this will return a different
209
- port than the one you provided in the constructor (under bind), as ephemeral
209
+ port than the one you provided in the constructor (under `port`), as ephemeral
210
210
  mode always uses a random port.
211
211
 
212
212
  #### `node.on('request', req)`
@@ -242,7 +242,7 @@ Options include:
242
242
  ```js
243
243
  {
244
244
  retry: true, // whether the request should retry on timeout
245
- socket: udpSocket // request on this specific socket
245
+ socket: udxSocket // request on this specific socket
246
246
  }
247
247
  ```
248
248
 
@@ -309,6 +309,10 @@ nodes are stored in `stream.closestNodes` array.
309
309
 
310
310
  If you want to access the closest replies to your provided target you can see those at `stream.closestReplies`.
311
311
 
312
+ #### `stream = node.findNode(target, [options])`
313
+
314
+ Find the node closest to the node with id `target`. Returns a stream encapsulating the query (see `node.query()`). `options` are the same as `node.query()`.
315
+
312
316
  #### `node.destroy()`
313
317
 
314
318
  Shutdown the DHT node.
package/index.js CHANGED
@@ -2,16 +2,18 @@ const dns = require('dns')
2
2
  const { EventEmitter } = require('events')
3
3
  const Table = require('kademlia-routing-table')
4
4
  const TOS = require('time-ordered-set')
5
+ const UDX = require('udx-native')
5
6
  const sodium = require('sodium-universal')
6
7
  const c = require('compact-encoding')
7
8
  const NatSampler = require('nat-sampler')
9
+ const b4a = require('b4a')
8
10
  const IO = require('./lib/io')
9
11
  const Query = require('./lib/query')
10
12
  const peer = require('./lib/peer')
11
13
  const { UNKNOWN_COMMAND, INVALID_TOKEN } = require('./lib/errors')
12
14
  const { PING, PING_NAT, FIND_NODE, DOWN_HINT } = require('./lib/commands')
13
15
 
14
- const TMP = Buffer.allocUnsafe(32)
16
+ const TMP = b4a.allocUnsafe(32)
15
17
  const TICK_INTERVAL = 5000
16
18
  const SLEEPING_INTERVAL = 3 * TICK_INTERVAL
17
19
  const STABLE_TICKS = 240 // if nothing major bad happens in ~20mins we can consider this node stable (if nat is friendly)
@@ -27,7 +29,8 @@ class DHT extends EventEmitter {
27
29
  this.bootstrapNodes = opts.bootstrap === false ? [] : (opts.bootstrap || []).map(parseNode)
28
30
  this.table = new Table(opts.id || randomBytes(32))
29
31
  this.nodes = new TOS()
30
- this.io = new IO(this.table, {
32
+ this.udx = opts.udx || new UDX()
33
+ this.io = new IO(this.table, this.udx, {
31
34
  ...opts,
32
35
  onrequest: this._onrequest.bind(this),
33
36
  onresponse: this._onresponse.bind(this),
@@ -42,7 +45,7 @@ class DHT extends EventEmitter {
42
45
  this.destroyed = false
43
46
 
44
47
  this._nat = new NatSampler()
45
- this._bind = opts.bind || 0
48
+ this._port = opts.port || 0
46
49
  this._quickFirewall = opts.quickFirewall !== false
47
50
  this._forcePersistent = opts.ephemeral === false
48
51
  this._repinging = 0
@@ -59,13 +62,15 @@ class DHT extends EventEmitter {
59
62
 
60
63
  this.table.on('row', this._onrow)
61
64
 
65
+ this.io.networkInterfaces.on('change', (interfaces) => this._onnetworkchange(interfaces))
66
+
62
67
  if (opts.nodes) {
63
68
  for (const node of opts.nodes) this.addNode(node)
64
69
  }
65
70
  }
66
71
 
67
- static bootstrapper (bind, opts) {
68
- return new this({ bind, firewalled: false, bootstrap: [], ...opts })
72
+ static bootstrapper (port, opts) {
73
+ return new this({ port, firewalled: false, bootstrap: [], ...opts })
69
74
  }
70
75
 
71
76
  get id () {
@@ -194,7 +199,7 @@ class DHT extends EventEmitter {
194
199
  if (!first) return
195
200
  first = false
196
201
 
197
- const value = Buffer.allocUnsafe(2)
202
+ const value = b4a.allocUnsafe(2)
198
203
  c.uint16.encode({ start: 0, end: 2, buffer: value }, self.io.serverSocket.address().port)
199
204
 
200
205
  self._request(data.from, true, PING_NAT, null, value, () => { testNat = true }, noop)
@@ -269,7 +274,7 @@ class DHT extends EventEmitter {
269
274
  }
270
275
 
271
276
  _addNode (node) {
272
- if (this.nodes.has(node) || node.id.equals(this.table.id)) return
277
+ if (this.nodes.has(node) || b4a.equals(node.id, this.table.id)) return
273
278
 
274
279
  node.added = node.pinged = node.seen = this._tick
275
280
 
@@ -328,6 +333,10 @@ class DHT extends EventEmitter {
328
333
  this._repingAndSwap(newNode, oldest)
329
334
  }
330
335
 
336
+ _onnetworkchange (interfaces) {
337
+ this.emit('network-change', interfaces)
338
+ }
339
+
331
340
  _repingAndSwap (newNode, oldNode) {
332
341
  const self = this
333
342
  const lastSeen = oldNode.seen
@@ -529,13 +538,13 @@ class DHT extends EventEmitter {
529
538
  // as possible, vs blindly copying them over...
530
539
 
531
540
  // all good! copy over the old routing table to the new one
532
- if (!this.table.id.equals(id)) {
541
+ if (!b4a.equals(this.table.id, id)) {
533
542
  const nodes = this.table.toArray()
534
543
 
535
544
  this.table = this.io.table = new Table(id)
536
545
 
537
546
  for (const node of nodes) {
538
- if (node.id.equals(id)) continue
547
+ if (b4a.equals(node.id, id)) continue
539
548
  if (!this.table.add(node)) this.nodes.remove(node)
540
549
  }
541
550
 
@@ -586,7 +595,7 @@ class DHT extends EventEmitter {
586
595
  if (nodes.length === 0) return true
587
596
 
588
597
  const hosts = []
589
- const value = Buffer.allocUnsafe(2)
598
+ const value = b4a.allocUnsafe(2)
590
599
 
591
600
  c.uint16.encode({ start: 0, end: 2, buffer: value }, this.io.serverSocket.address().port)
592
601
 
@@ -618,8 +627,8 @@ class DHT extends EventEmitter {
618
627
 
619
628
  return false
620
629
 
621
- function onmessage (_, rinfo) {
622
- hosts.push(rinfo.address)
630
+ function onmessage (_, { host }) {
631
+ hosts.push(host)
623
632
  }
624
633
  }
625
634
 
@@ -659,7 +668,7 @@ function parseNode (s) {
659
668
  }
660
669
 
661
670
  function randomBytes (n) {
662
- const b = Buffer.alloc(n)
671
+ const b = b4a.alloc(n)
663
672
  sodium.randombytes_buf(b)
664
673
  return b
665
674
  }
package/lib/errors.js CHANGED
@@ -1,8 +1,14 @@
1
1
  exports.UNKNOWN_COMMAND = 1
2
2
  exports.INVALID_TOKEN = 2
3
3
 
4
- exports.TIMEOUT = new Error('Request timed out')
5
- exports.TIMEOUT.code = 'ETIMEDOUT'
4
+ exports.createTimeoutError = () => {
5
+ const timeoutErr = new Error('Request timed out')
6
+ timeoutErr.code = 'ETIMEDOUT'
7
+ return timeoutErr
8
+ }
6
9
 
7
- exports.DESTROY = new Error('Request destroyed')
8
- exports.DESTROY.code = 'EDESTROYED'
10
+ exports.createDestroyedError = () => {
11
+ const destroyErr = new Error('Request destroyed')
12
+ destroyErr.code = 'EDESTROYED'
13
+ return destroyErr
14
+ }
package/lib/io.js CHANGED
@@ -1,25 +1,27 @@
1
1
  const FIFO = require('fast-fifo')
2
2
  const sodium = require('sodium-universal')
3
3
  const c = require('compact-encoding')
4
- const bind = require('bind-easy')
4
+ const b4a = require('b4a')
5
5
  const peer = require('./peer')
6
- const { INVALID_TOKEN, TIMEOUT, DESTROY } = require('./errors')
6
+ const errors = require('./errors')
7
7
 
8
8
  const VERSION = 0b11
9
9
  const RESPONSE_ID = (0b0001 << 4) | VERSION
10
10
  const REQUEST_ID = (0b0000 << 4) | VERSION
11
- const TMP = Buffer.alloc(32)
11
+ const TMP = b4a.alloc(32)
12
12
  const EMPTY_ARRAY = []
13
13
 
14
14
  module.exports = class IO {
15
- constructor (table, { maxWindow = 80, bind = 0, firewalled = true, onrequest, onresponse = noop, ontimeout = noop } = {}) {
15
+ constructor (table, udx, { maxWindow = 80, port = 0, firewalled = true, onrequest, onresponse = noop, ontimeout = noop } = {}) {
16
16
  this.table = table
17
+ this.udx = udx
17
18
  this.inflight = []
18
19
  this.clientSocket = null
19
20
  this.serverSocket = null
20
21
  this.firewalled = firewalled !== false
21
22
  this.ephemeral = true
22
23
  this.congestion = new CongestionWindow(maxWindow)
24
+ this.networkInterfaces = udx.watchNetworkInterfaces()
23
25
 
24
26
  this.onrequest = onrequest
25
27
  this.onresponse = onresponse
@@ -32,13 +34,13 @@ module.exports = class IO {
32
34
  this._drainInterval = null
33
35
  this._destroying = null
34
36
  this._binding = null
35
- this._bind = bind
37
+ this._port = port
36
38
  }
37
39
 
38
- onmessage (socket, buffer, rinfo) {
39
- if (buffer.byteLength < 2 || !(rinfo.port > 0 && rinfo.port < 65536)) return
40
+ onmessage (socket, buffer, { host, port }) {
41
+ if (buffer.byteLength < 2 || !(port > 0 && port < 65536)) return
40
42
 
41
- const from = { id: null, host: rinfo.address, port: rinfo.port }
43
+ const from = { id: null, host, port }
42
44
  const state = { start: 1, end: buffer.byteLength, buffer }
43
45
  const expectedSocket = this.firewalled ? this.clientSocket : this.serverSocket
44
46
  const external = socket !== expectedSocket
@@ -46,8 +48,8 @@ module.exports = class IO {
46
48
  if (buffer[0] === REQUEST_ID) {
47
49
  const req = Request.decode(this, socket, from, state)
48
50
  if (req === null) return
49
- if (req.token !== null && !req.token.equals(this.token(req.from, 1)) && !req.token.equals(this.token(req.from, 0))) {
50
- req.error(INVALID_TOKEN, { token: true })
51
+ if (req.token !== null && !b4a.equals(req.token, this.token(req.from, 1)) && !b4a.equals(req.token, this.token(req.from, 0))) {
52
+ req.error(errors.INVALID_TOKEN, { token: true })
51
53
  return
52
54
  }
53
55
  this.onrequest(req, external)
@@ -65,7 +67,7 @@ module.exports = class IO {
65
67
  if (i === this.inflight.length - 1) this.inflight.pop()
66
68
  else this.inflight[i] = this.inflight.pop()
67
69
 
68
- // TODO: Auto retry here if INVALID_TOKEN is returned?
70
+ // TODO: Auto retry here if errors.INVALID_TOKEN is returned?
69
71
 
70
72
  if (req._timeout) {
71
73
  clearTimeout(req._timeout)
@@ -82,14 +84,14 @@ module.exports = class IO {
82
84
 
83
85
  token (addr, i) {
84
86
  if (this._secrets === null) {
85
- const buf = Buffer.alloc(64)
87
+ const buf = b4a.alloc(64)
86
88
  this._secrets = [buf.subarray(0, 32), buf.subarray(32, 64)]
87
89
  sodium.randombytes_buf(this._secrets[0])
88
90
  sodium.randombytes_buf(this._secrets[1])
89
91
  }
90
92
 
91
- const token = Buffer.allocUnsafe(32)
92
- sodium.crypto_generichash(token, Buffer.from(addr.host), this._secrets[i])
93
+ const token = b4a.allocUnsafe(32)
94
+ sodium.crypto_generichash(token, b4a.from(addr.host), this._secrets[i])
93
95
  return token
94
96
  }
95
97
 
@@ -109,19 +111,15 @@ module.exports = class IO {
109
111
  if (req._timeout) clearTimeout(req._timeout)
110
112
  req._timeout = null
111
113
  req.destroyed = true
112
- req.onerror(DESTROY, req)
113
- }
114
-
115
- this._destroying = new Promise((resolve) => {
116
- let missing = 2
117
114
 
118
- this.serverSocket.close(done)
119
- this.clientSocket.close(done)
115
+ req.onerror(errors.createDestroyedError(), req)
116
+ }
120
117
 
121
- function done () {
122
- if (--missing === 0) resolve()
123
- }
124
- })
118
+ this._destroying = Promise.allSettled([
119
+ this.serverSocket.close(),
120
+ this.clientSocket.close(),
121
+ this.networkInterfaces.destroy()
122
+ ])
125
123
 
126
124
  return this._destroying
127
125
  }
@@ -133,19 +131,32 @@ module.exports = class IO {
133
131
  }
134
132
 
135
133
  async _bindSockets () {
136
- const serverSocket = typeof this._bind === 'function' ? await this._bind() : await bind.udp(this._bind)
134
+ const serverSocket = this.udx.createSocket()
137
135
 
138
136
  try {
139
- // TODO: we should reroll the socket is it's close to our preferred range of ports
140
- // to avoid it being accidentally opened
141
- // We'll prop need additional APIs for that
142
- this.clientSocket = await bind.udp()
143
- this.serverSocket = serverSocket
137
+ serverSocket.bind(this._port)
138
+ } catch {
139
+ try {
140
+ serverSocket.bind()
141
+ } catch (err) {
142
+ await serverSocket.close()
143
+ throw err
144
+ }
145
+ }
146
+
147
+ const clientSocket = this.udx.createSocket()
148
+
149
+ try {
150
+ clientSocket.bind()
144
151
  } catch (err) {
145
- await new Promise((resolve) => serverSocket.close(resolve))
152
+ await serverSocket.close()
153
+ await clientSocket.close()
146
154
  throw err
147
155
  }
148
156
 
157
+ this.clientSocket = clientSocket
158
+ this.serverSocket = serverSocket
159
+
149
160
  this.serverSocket.on('message', this.onmessage.bind(this, this.serverSocket))
150
161
  this.clientSocket.on('message', this.onmessage.bind(this, this.clientSocket))
151
162
 
@@ -240,8 +251,7 @@ class Request {
240
251
  reply (value, opts = {}) {
241
252
  const socket = opts.socket || this.socket
242
253
  const to = opts.to || this.from
243
- const onflush = opts.onflush || null
244
- this._sendReply(0, value || null, opts.token !== false, opts.closerNodes !== false, to, socket, onflush)
254
+ this._sendReply(0, value || null, opts.token !== false, opts.closerNodes !== false, to, socket)
245
255
  }
246
256
 
247
257
  error (code, opts = {}) {
@@ -253,7 +263,7 @@ class Request {
253
263
  relay (value, to, opts) {
254
264
  const socket = (opts && opts.socket) || this.socket
255
265
  const buffer = this._encodeRequest(null, value, to, socket)
256
- socket.send(buffer, 0, buffer.byteLength, to.port, to.host)
266
+ socket.trySend(buffer, to.port, to.host)
257
267
  }
258
268
 
259
269
  send (force = false) {
@@ -278,7 +288,7 @@ class Request {
278
288
  if (this.destroyed) return
279
289
  this.sent++
280
290
  this._io.congestion.send()
281
- this.socket.send(this._buffer, 0, this._buffer.byteLength, this.to.port, this.to.host)
291
+ this.socket.trySend(this._buffer, this.to.port, this.to.host)
282
292
  if (this._timeout) clearTimeout(this._timeout)
283
293
  this._timeout = setTimeout(oncycle, 1000, this)
284
294
  }
@@ -293,10 +303,10 @@ class Request {
293
303
  if (i === this._io.inflight.length - 1) this._io.inflight.pop()
294
304
  else this._io.inflight[i] = this._io.inflight.pop()
295
305
 
296
- this.onerror(err || DESTROY, this)
306
+ this.onerror(err || errors.createDestroyedError(), this)
297
307
  }
298
308
 
299
- _sendReply (error, value, token, hasCloserNodes, from, socket, onflush) {
309
+ _sendReply (error, value, token, hasCloserNodes, from, socket) {
300
310
  if (socket === null || this.destroyed) return
301
311
 
302
312
  const id = this._io.ephemeral === false && socket === this._io.serverSocket
@@ -309,7 +319,7 @@ class Request {
309
319
  if (error > 0) c.uint.preencode(state, error)
310
320
  if (value) c.buffer.preencode(state, value)
311
321
 
312
- state.buffer = Buffer.allocUnsafe(state.end)
322
+ state.buffer = b4a.allocUnsafe(state.end)
313
323
  state.buffer[state.start++] = RESPONSE_ID
314
324
  state.buffer[state.start++] = (id ? 1 : 0) | (token ? 2 : 0) | (closerNodes.length > 0 ? 4 : 0) | (error > 0 ? 8 : 0) | (value ? 16 : 0)
315
325
 
@@ -322,7 +332,7 @@ class Request {
322
332
  if (error > 0) c.uint.encode(state, error)
323
333
  if (value) c.buffer.encode(state, value)
324
334
 
325
- socket.send(state.buffer, 0, state.buffer.byteLength, from.port, from.host, onflush)
335
+ socket.trySend(state.buffer, from.port, from.host)
326
336
  }
327
337
 
328
338
  _encodeRequest (token, value, to, socket) {
@@ -337,7 +347,7 @@ class Request {
337
347
  if (this.target) state.end += 32
338
348
  if (value) c.buffer.preencode(state, value)
339
349
 
340
- state.buffer = Buffer.allocUnsafe(state.end)
350
+ state.buffer = b4a.allocUnsafe(state.end)
341
351
  state.buffer[state.start++] = REQUEST_ID
342
352
  state.buffer[state.start++] = (id ? 1 : 0) | (token ? 2 : 0) | (this.internal ? 4 : 0) | (this.target ? 8 : 0) | (value ? 16 : 0)
343
353
 
@@ -393,7 +403,7 @@ function oncycle (req) {
393
403
  req._timeout = null
394
404
  req.oncycle(req)
395
405
  if (req.sent >= req.retries) {
396
- req.destroy(TIMEOUT)
406
+ req.destroy(errors.createTimeoutError())
397
407
  req._io.ontimeout(req)
398
408
  } else {
399
409
  req.send()
@@ -420,5 +430,5 @@ function decodeReply (from, state) {
420
430
  }
421
431
 
422
432
  function validateId (id, from) {
423
- return peer.id(from.host, from.port, TMP).equals(id) ? id : null
433
+ return b4a.equals(peer.id(from.host, from.port, TMP), id) ? id : null
424
434
  }
package/lib/peer.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const sodium = require('sodium-universal')
2
2
  const c = require('compact-encoding')
3
3
  const net = require('compact-encoding-net')
4
+ const b4a = require('b4a')
4
5
 
5
6
  const ipv4 = {
6
7
  ...net.ipv4Address,
@@ -16,7 +17,7 @@ const ipv4 = {
16
17
 
17
18
  module.exports = { id, ipv4, ipv4Array: c.array(ipv4) }
18
19
 
19
- function id (host, port, out = Buffer.allocUnsafe(32)) {
20
+ function id (host, port, out = b4a.allocUnsafe(32)) {
20
21
  const addr = out.subarray(0, 6)
21
22
  ipv4.encode(
22
23
  { start: 0, end: 6, buffer: addr },
package/lib/query.js CHANGED
@@ -1,4 +1,5 @@
1
1
  const { Readable } = require('streamx')
2
+ const b4a = require('b4a')
2
3
  const peer = require('./peer')
3
4
  const { DOWN_HINT } = require('./commands')
4
5
 
@@ -240,7 +241,7 @@ module.exports = class Query extends Readable {
240
241
  if (m.closerNodes !== null) {
241
242
  for (const node of m.closerNodes) {
242
243
  node.id = peer.id(node.host, node.port)
243
- if (node.id.equals(this.dht.table.id)) continue
244
+ if (b4a.equals(node.id, this.dht.table.id)) continue
244
245
  // TODO: we could continue here instead of breaking to ensure that one of the nodes in the closer list
245
246
  // is later marked as DOWN that we gossip that back
246
247
  if (!this._addPending(node, m.from)) break
@@ -281,7 +282,7 @@ module.exports = class Query extends Readable {
281
282
  }
282
283
 
283
284
  _downHint (node, down) {
284
- const state = { start: 0, end: 6, buffer: Buffer.allocUnsafe(6) }
285
+ const state = { start: 0, end: 6, buffer: b4a.allocUnsafe(6) }
285
286
  peer.ipv4.encode(state, down)
286
287
  this.dht._request(node, true, DOWN_HINT, null, state.buffer, noop, noop)
287
288
  }
package/package.json CHANGED
@@ -1,21 +1,23 @@
1
1
  {
2
2
  "name": "dht-rpc",
3
- "version": "5.0.4",
3
+ "version": "6.0.0",
4
4
  "description": "Make RPC calls over a Kademlia based DHT",
5
5
  "main": "index.js",
6
6
  "dependencies": {
7
- "bind-easy": "^1.0.0",
7
+ "b4a": "^1.3.1",
8
8
  "compact-encoding": "^2.1.0",
9
9
  "compact-encoding-net": "^1.0.1",
10
+ "events": "^3.3.0",
10
11
  "fast-fifo": "^1.0.0",
11
12
  "kademlia-routing-table": "^1.0.0",
12
13
  "nat-sampler": "^1.0.1",
13
14
  "sodium-universal": "^3.0.4",
14
15
  "streamx": "^2.10.3",
15
- "time-ordered-set": "^1.0.2"
16
+ "time-ordered-set": "^1.0.2",
17
+ "udx-native": "^1.1.0"
16
18
  },
17
19
  "devDependencies": {
18
- "brittle": "^1.4.3",
20
+ "brittle": "^2.3.1",
19
21
  "standard": "^16.0.3"
20
22
  },
21
23
  "scripts": {
package/test.js CHANGED
@@ -2,14 +2,12 @@ const test = require('brittle')
2
2
  const dgram = require('dgram')
3
3
  const DHT = require('./')
4
4
 
5
- test.configure({ serial: true })
6
-
7
5
  test('make tiny swarm', async function (t) {
8
6
  await makeSwarm(2, t)
9
7
  t.pass('could make swarm')
10
8
  })
11
9
 
12
- test('make bigger swarm', async function (t) {
10
+ test('make bigger swarm', { timeout: 60000 }, async function (t) {
13
11
  const swarm = await makeSwarm(500, t)
14
12
 
15
13
  const targetNode = swarm[25]
@@ -165,23 +163,6 @@ test('request with/without retries', async function (t) {
165
163
  t.is(tries, 4)
166
164
  })
167
165
 
168
- test('reply onflush', async function (t) {
169
- const [, a, b] = await makeSwarm(3, t)
170
-
171
- let flushed = false
172
-
173
- b.on('request', function (req) {
174
- req.reply(null, {
175
- onflush () {
176
- flushed = true
177
- }
178
- })
179
- })
180
-
181
- await a.request({ command: 42 }, { host: '127.0.0.1', port: b.address().port })
182
- t.ok(flushed)
183
- })
184
-
185
166
  test('shorthand commit', async function (t) {
186
167
  const swarm = await makeSwarm(40, t)
187
168
 
@@ -290,12 +271,12 @@ test('addNode / nodes option', async function (t) {
290
271
  test('set bind', async function (t) {
291
272
  const port = await freePort()
292
273
 
293
- const a = new DHT({ bind: port, firewalled: false })
274
+ const a = new DHT({ port, firewalled: false })
294
275
  await a.ready()
295
276
 
296
277
  t.alike(a.address().port, port, 'bound to explicit port')
297
278
 
298
- const b = new DHT({ bind: port })
279
+ const b = new DHT({ port })
299
280
  await b.ready()
300
281
 
301
282
  t.not(b.address().port, port, 'bound to different port as explicit one is taken')