dht-rpc 6.3.2 → 6.4.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/index.js +13 -8
- package/lib/io.js +13 -4
- package/lib/query.js +9 -2
- package/lib/session.js +41 -0
- package/package.json +1 -1
- package/test.js +21 -0
package/index.js
CHANGED
|
@@ -8,6 +8,7 @@ const NatSampler = require('nat-sampler')
|
|
|
8
8
|
const b4a = require('b4a')
|
|
9
9
|
const IO = require('./lib/io')
|
|
10
10
|
const Query = require('./lib/query')
|
|
11
|
+
const Session = require('./lib/session')
|
|
11
12
|
const peer = require('./lib/peer')
|
|
12
13
|
const { UNKNOWN_COMMAND, INVALID_TOKEN } = require('./lib/errors')
|
|
13
14
|
const { PING, PING_NAT, FIND_NODE, DOWN_HINT } = require('./lib/commands')
|
|
@@ -150,15 +151,19 @@ class DHT extends EventEmitter {
|
|
|
150
151
|
|
|
151
152
|
if (opts && opts.size && opts.size > 0) value = b4a.alloc(opts.size)
|
|
152
153
|
|
|
153
|
-
const req = this.io.createRequest({ id: null, host, port }, null, true, PING, null, value)
|
|
154
|
+
const req = this.io.createRequest({ id: null, host, port }, null, true, PING, null, value, (opts && opts.session) || null)
|
|
154
155
|
return this._requestToPromise(req, opts)
|
|
155
156
|
}
|
|
156
157
|
|
|
157
158
|
request ({ token = null, command, target = null, value = null }, { host, port }, opts) {
|
|
158
|
-
const req = this.io.createRequest({ id: null, host, port }, token, false, command, target, value)
|
|
159
|
+
const req = this.io.createRequest({ id: null, host, port }, token, false, command, target, value, (opts && opts.session) || null)
|
|
159
160
|
return this._requestToPromise(req, opts)
|
|
160
161
|
}
|
|
161
162
|
|
|
163
|
+
session () {
|
|
164
|
+
return new Session(this)
|
|
165
|
+
}
|
|
166
|
+
|
|
162
167
|
_requestToPromise (req, opts) {
|
|
163
168
|
if (req === null) return Promise.reject(new Error('Node destroyed'))
|
|
164
169
|
|
|
@@ -212,7 +217,7 @@ class DHT extends EventEmitter {
|
|
|
212
217
|
const value = b4a.allocUnsafe(2)
|
|
213
218
|
c.uint16.encode({ start: 0, end: 2, buffer: value }, self.io.serverSocket.address().port)
|
|
214
219
|
|
|
215
|
-
self._request(data.from, true, PING_NAT, null, value, () => { testNat = true }, noop)
|
|
220
|
+
self._request(data.from, true, PING_NAT, null, value, null, () => { testNat = true }, noop)
|
|
216
221
|
}
|
|
217
222
|
}
|
|
218
223
|
|
|
@@ -227,8 +232,8 @@ class DHT extends EventEmitter {
|
|
|
227
232
|
return this.io.destroy()
|
|
228
233
|
}
|
|
229
234
|
|
|
230
|
-
_request (to, internal, command, target, value, onresponse, onerror) {
|
|
231
|
-
const req = this.io.createRequest(to, null, internal, command, target, value)
|
|
235
|
+
_request (to, internal, command, target, value, session, onresponse, onerror) {
|
|
236
|
+
const req = this.io.createRequest(to, null, internal, command, target, value, session)
|
|
232
237
|
if (req === null) return null
|
|
233
238
|
|
|
234
239
|
req.onresponse = onresponse
|
|
@@ -358,7 +363,7 @@ class DHT extends EventEmitter {
|
|
|
358
363
|
oldNode.pinged = this._tick
|
|
359
364
|
|
|
360
365
|
this._repinging++
|
|
361
|
-
this._request({ id: null, host: oldNode.host, port: oldNode.port }, true, PING, null, null, onsuccess, onswap)
|
|
366
|
+
this._request({ id: null, host: oldNode.host, port: oldNode.port }, true, PING, null, null, null, onsuccess, onswap)
|
|
362
367
|
|
|
363
368
|
function onsuccess (m) {
|
|
364
369
|
if (oldNode.seen <= lastSeen) return onswap()
|
|
@@ -475,7 +480,7 @@ class DHT extends EventEmitter {
|
|
|
475
480
|
}
|
|
476
481
|
|
|
477
482
|
this._checks++
|
|
478
|
-
this._request({ id: null, host: node.host, port: node.port }, true, PING, null, null, onresponse, onerror)
|
|
483
|
+
this._request({ id: null, host: node.host, port: node.port }, true, PING, null, null, null, onresponse, onerror)
|
|
479
484
|
}
|
|
480
485
|
|
|
481
486
|
_ontick () {
|
|
@@ -699,7 +704,7 @@ function requestAll (dht, internal, command, value, nodes) {
|
|
|
699
704
|
|
|
700
705
|
return new Promise((resolve) => {
|
|
701
706
|
for (const node of nodes) {
|
|
702
|
-
const req = dht._request(node, internal, command, null, value, onsuccess, onerror)
|
|
707
|
+
const req = dht._request(node, internal, command, null, value, null, onsuccess, onerror)
|
|
703
708
|
if (!req) return resolve(replies)
|
|
704
709
|
}
|
|
705
710
|
|
package/lib/io.js
CHANGED
|
@@ -69,6 +69,8 @@ module.exports = class IO {
|
|
|
69
69
|
if (i === this.inflight.length - 1) this.inflight.pop()
|
|
70
70
|
else this.inflight[i] = this.inflight.pop()
|
|
71
71
|
|
|
72
|
+
if (req.session) req.session._detach(req)
|
|
73
|
+
|
|
72
74
|
// TODO: Auto retry here if errors.INVALID_TOKEN is returned?
|
|
73
75
|
|
|
74
76
|
if (req._timeout) {
|
|
@@ -118,6 +120,8 @@ module.exports = class IO {
|
|
|
118
120
|
req._timeout = null
|
|
119
121
|
req.destroyed = true
|
|
120
122
|
|
|
123
|
+
if (req.session) req.session._detach(req)
|
|
124
|
+
|
|
121
125
|
req.onerror(errors.createDestroyedError(), req)
|
|
122
126
|
}
|
|
123
127
|
|
|
@@ -199,7 +203,7 @@ module.exports = class IO {
|
|
|
199
203
|
}
|
|
200
204
|
}
|
|
201
205
|
|
|
202
|
-
createRequest (to, token, internal, command, target, value) {
|
|
206
|
+
createRequest (to, token, internal, command, target, value, session) {
|
|
203
207
|
if (this._destroying !== null) return null
|
|
204
208
|
|
|
205
209
|
if (this._tid === 65536) this._tid = 0
|
|
@@ -207,14 +211,15 @@ module.exports = class IO {
|
|
|
207
211
|
const tid = this._tid++
|
|
208
212
|
const socket = this.firewalled ? this.clientSocket : this.serverSocket
|
|
209
213
|
|
|
210
|
-
const req = new Request(this, socket, tid, null, to, token, internal, command, target, value)
|
|
214
|
+
const req = new Request(this, socket, tid, null, to, token, internal, command, target, value, session)
|
|
211
215
|
this.inflight.push(req)
|
|
216
|
+
if (session) session._attach(req)
|
|
212
217
|
return req
|
|
213
218
|
}
|
|
214
219
|
}
|
|
215
220
|
|
|
216
221
|
class Request {
|
|
217
|
-
constructor (io, socket, tid, from, to, token, internal, command, target, value) {
|
|
222
|
+
constructor (io, socket, tid, from, to, token, internal, command, target, value, session) {
|
|
218
223
|
this.socket = socket
|
|
219
224
|
this.tid = tid
|
|
220
225
|
this.from = from
|
|
@@ -224,6 +229,8 @@ class Request {
|
|
|
224
229
|
this.target = target
|
|
225
230
|
this.value = value
|
|
226
231
|
this.internal = internal
|
|
232
|
+
this.session = session
|
|
233
|
+
this.index = -1
|
|
227
234
|
this.sent = 0
|
|
228
235
|
this.retries = 3
|
|
229
236
|
this.destroyed = false
|
|
@@ -251,7 +258,7 @@ class Request {
|
|
|
251
258
|
|
|
252
259
|
if (id !== null) from.id = validateId(id, from)
|
|
253
260
|
|
|
254
|
-
return new Request(io, socket, tid, from, to, token, internal, command, target, value)
|
|
261
|
+
return new Request(io, socket, tid, from, to, token, internal, command, target, value, null)
|
|
255
262
|
} catch {
|
|
256
263
|
return null
|
|
257
264
|
}
|
|
@@ -317,6 +324,8 @@ class Request {
|
|
|
317
324
|
if (i === this._io.inflight.length - 1) this._io.inflight.pop()
|
|
318
325
|
else this._io.inflight[i] = this._io.inflight.pop()
|
|
319
326
|
|
|
327
|
+
if (this.session) this.session._detach(this)
|
|
328
|
+
|
|
320
329
|
this.onerror(err || errors.createDestroyedError(), this)
|
|
321
330
|
}
|
|
322
331
|
|
package/lib/query.js
CHANGED
|
@@ -31,6 +31,8 @@ module.exports = class Query extends Readable {
|
|
|
31
31
|
this._fromTable = false
|
|
32
32
|
this._commit = opts.commit === true ? autoCommit : (opts.commit || null)
|
|
33
33
|
this._commiting = false
|
|
34
|
+
this._session = opts.session || dht.session()
|
|
35
|
+
this._autoDestroySession = !opts.session
|
|
34
36
|
|
|
35
37
|
this._onvisitbound = this._onvisit.bind(this)
|
|
36
38
|
this._onerrorbound = this._onerror.bind(this)
|
|
@@ -284,7 +286,7 @@ module.exports = class Query extends Readable {
|
|
|
284
286
|
_downHint (node, down) {
|
|
285
287
|
const state = { start: 0, end: 6, buffer: b4a.allocUnsafe(6) }
|
|
286
288
|
peer.ipv4.encode(state, down)
|
|
287
|
-
this.dht._request(node, true, DOWN_HINT, null, state.buffer, noop, noop)
|
|
289
|
+
this.dht._request(node, true, DOWN_HINT, null, state.buffer, this._session, noop, noop)
|
|
288
290
|
}
|
|
289
291
|
|
|
290
292
|
_pushClosest (m) {
|
|
@@ -318,13 +320,18 @@ module.exports = class Query extends Readable {
|
|
|
318
320
|
_visit (to) {
|
|
319
321
|
this.inflight++
|
|
320
322
|
|
|
321
|
-
const req = this.dht._request(to, this.internal, this.command, this.target, this.value, this._onvisitbound, this._onerrorbound)
|
|
323
|
+
const req = this.dht._request(to, this.internal, this.command, this.target, this.value, this._session, this._onvisitbound, this._onerrorbound)
|
|
322
324
|
if (req === null) {
|
|
323
325
|
this.destroy(new Error('Node was destroyed'))
|
|
324
326
|
return
|
|
325
327
|
}
|
|
326
328
|
req.oncycle = this._oncyclebound
|
|
327
329
|
}
|
|
330
|
+
|
|
331
|
+
_destroy (cb) {
|
|
332
|
+
if (this._autoDestroySession) this._session.destroy()
|
|
333
|
+
cb(null)
|
|
334
|
+
}
|
|
328
335
|
}
|
|
329
336
|
|
|
330
337
|
function autoCommit (reply, dht, query) {
|
package/lib/session.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module.exports = class Session {
|
|
2
|
+
constructor (dht) {
|
|
3
|
+
this.dht = dht
|
|
4
|
+
this.inflight = []
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
_attach (req) {
|
|
8
|
+
req.index = this.inflight.push(req) - 1
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
_detach (req) {
|
|
12
|
+
const i = req.index
|
|
13
|
+
if (i === -1) return
|
|
14
|
+
req.index = -1
|
|
15
|
+
|
|
16
|
+
if (i === this.inflight.length - 1) this.inflight.pop()
|
|
17
|
+
else {
|
|
18
|
+
const req = this.inflight[i] = this.inflight.pop()
|
|
19
|
+
req.index = i
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
query ({ target, command, value }, opts = {}) {
|
|
24
|
+
return this.dht.query({ target, command, value }, { ...opts, session: this })
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
request ({ token, command, target, value }, { host, port }, opts = {}) {
|
|
28
|
+
return this.dht.request({ token, command, target, value }, { host, port }, { ...opts, session: this })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
ping ({ host, port }, opts = {}) {
|
|
32
|
+
return this.dht.ping({ host, port }, { ...opts, session: this })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
destroy (err) {
|
|
36
|
+
while (this.inflight.length) {
|
|
37
|
+
const req = this.inflight[0]
|
|
38
|
+
req.destroy(err)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -396,6 +396,27 @@ test('filter nodes from routing table', async function (t) {
|
|
|
396
396
|
t.absent(node.table.has(b.id), 'should not have b')
|
|
397
397
|
})
|
|
398
398
|
|
|
399
|
+
test('request session, destroy all', async function (t) {
|
|
400
|
+
const [, a, b] = await makeSwarm(3, t)
|
|
401
|
+
|
|
402
|
+
a.on('request', () => t.fail())
|
|
403
|
+
|
|
404
|
+
const s = b.session()
|
|
405
|
+
const p = [
|
|
406
|
+
s.request({ command: 42 }, a),
|
|
407
|
+
s.request({ command: 42 }, a)
|
|
408
|
+
]
|
|
409
|
+
|
|
410
|
+
const err = new Error('destroyed')
|
|
411
|
+
|
|
412
|
+
s.destroy(err)
|
|
413
|
+
|
|
414
|
+
for (const { status, reason } of await Promise.allSettled(p)) {
|
|
415
|
+
t.is(status, 'rejected')
|
|
416
|
+
t.is(reason, err)
|
|
417
|
+
}
|
|
418
|
+
})
|
|
419
|
+
|
|
399
420
|
async function freePort () {
|
|
400
421
|
const udx = new UDX()
|
|
401
422
|
const sock = udx.createSocket()
|