dht-rpc 6.18.1 → 6.19.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 +38 -35
- package/index.js +167 -88
- package/lib/errors.js +5 -5
- package/lib/io.js +107 -54
- package/lib/peer.js +3 -6
- package/lib/query.js +67 -34
- package/lib/session.js +13 -9
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -8,9 +8,9 @@ npm install dht-rpc
|
|
|
8
8
|
|
|
9
9
|
## Key Features
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
- Remote IP / firewall detection
|
|
12
|
+
- Easily add any command to your DHT
|
|
13
|
+
- Streaming queries and updates
|
|
14
14
|
|
|
15
15
|
Note that internally V5 of dht-rpc differs significantly from V4, due to a series
|
|
16
16
|
of improvements to NAT detection, secure routing IDs and more.
|
|
@@ -23,7 +23,7 @@ First spin up a bootstrap node. You can make multiple if you want for redundancy
|
|
|
23
23
|
There is nothing special about a bootstrap node, except it needs to know it's own host and port,
|
|
24
24
|
since it knows no other nodes to infer it from.
|
|
25
25
|
|
|
26
|
-
```
|
|
26
|
+
```js
|
|
27
27
|
import DHT from 'dht-rpc'
|
|
28
28
|
|
|
29
29
|
const bootstrap = DHT.bootstrapper(10001, '127.0.0.1')
|
|
@@ -31,18 +31,16 @@ const bootstrap = DHT.bootstrapper(10001, '127.0.0.1')
|
|
|
31
31
|
|
|
32
32
|
Now lets make some dht nodes that can store values in our key value store.
|
|
33
33
|
|
|
34
|
-
```
|
|
34
|
+
```js
|
|
35
35
|
import DHT from 'dht-rpc'
|
|
36
36
|
import crypto from 'crypto'
|
|
37
37
|
|
|
38
38
|
// Let's create 100 dht nodes for our example.
|
|
39
39
|
for (var i = 0; i < 100; i++) createNode()
|
|
40
40
|
|
|
41
|
-
function createNode
|
|
41
|
+
function createNode() {
|
|
42
42
|
const node = new DHT({
|
|
43
|
-
bootstrap: [
|
|
44
|
-
'localhost:10001'
|
|
45
|
-
]
|
|
43
|
+
bootstrap: ['localhost:10001']
|
|
46
44
|
})
|
|
47
45
|
|
|
48
46
|
const values = new Map()
|
|
@@ -50,7 +48,8 @@ function createNode () {
|
|
|
50
48
|
|
|
51
49
|
node.on('request', function (req) {
|
|
52
50
|
if (req.command === VALUES) {
|
|
53
|
-
if (req.token) {
|
|
51
|
+
if (req.token) {
|
|
52
|
+
// if we are the closest node store the value (ie the node sent a valid roundtrip token)
|
|
54
53
|
const key = hash(req.value).toString('hex')
|
|
55
54
|
values.set(key, req.value)
|
|
56
55
|
console.log('Storing', key, '-->', req.value.toString())
|
|
@@ -63,32 +62,35 @@ function createNode () {
|
|
|
63
62
|
})
|
|
64
63
|
}
|
|
65
64
|
|
|
66
|
-
function hash
|
|
65
|
+
function hash(value) {
|
|
67
66
|
return crypto.createHash('sha256').update(value).digest()
|
|
68
67
|
}
|
|
69
68
|
```
|
|
70
69
|
|
|
71
70
|
To insert a value into this dht make another script that does this following
|
|
72
71
|
|
|
73
|
-
```
|
|
72
|
+
```js
|
|
74
73
|
const node = new DHT()
|
|
75
74
|
|
|
76
|
-
const q = node.query(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
const q = node.query(
|
|
76
|
+
{
|
|
77
|
+
target: hash(val),
|
|
78
|
+
command: VALUES,
|
|
79
|
+
value
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
// commit true will make the query re-request the 20 closest
|
|
83
|
+
// nodes with a valid round trip token to update the values
|
|
84
|
+
commit: true
|
|
85
|
+
}
|
|
86
|
+
)
|
|
85
87
|
|
|
86
88
|
await q.finished()
|
|
87
89
|
```
|
|
88
90
|
|
|
89
91
|
Then after inserting run this script to query for a value
|
|
90
92
|
|
|
91
|
-
```
|
|
93
|
+
```js
|
|
92
94
|
const target = Buffer.from(hexFromAbove, 'hex')
|
|
93
95
|
for await (const data of node.query({ target, command: VALUES })) {
|
|
94
96
|
if (data.value && hash(data.value).toString('hex') === hexFromAbove) {
|
|
@@ -108,7 +110,7 @@ Create a new DHT node.
|
|
|
108
110
|
|
|
109
111
|
Options include:
|
|
110
112
|
|
|
111
|
-
```
|
|
113
|
+
```js
|
|
112
114
|
{
|
|
113
115
|
// A list of bootstrap nodes. Optionally prefix a suggested-IP, i.e. '192.168.1.10@bootstrap-node.com:24242'
|
|
114
116
|
bootstrap: [ 'bootstrap-node.com:24242', ... ],
|
|
@@ -179,6 +181,7 @@ it will switch from persistent mode to ephemeral again.
|
|
|
179
181
|
Emitted when the network interfaces of the computer change.
|
|
180
182
|
|
|
181
183
|
#### `node.on('nat-update', (host, port) => {})`
|
|
184
|
+
|
|
182
185
|
Emitted when `node.host` or `node.port` were changed.
|
|
183
186
|
|
|
184
187
|
#### `node.on('close')`
|
|
@@ -223,11 +226,11 @@ mode always uses a random port.
|
|
|
223
226
|
|
|
224
227
|
Emitted when an incoming DHT request is received. This is where you can add your own RPC methods.
|
|
225
228
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
229
|
+
- `req.target` - the dht target the peer is looking (routing is handled behind the scene)
|
|
230
|
+
- `req.command` - the RPC command enum
|
|
231
|
+
- `req.value` - the RPC value buffer
|
|
232
|
+
- `req.token` - If the remote peer echoed back a valid roundtrip token, proving their "from address" this is set
|
|
233
|
+
- `req.from` - who sent this request (host, port)
|
|
231
234
|
|
|
232
235
|
To reply to a request use the `req.reply(value)` method and to reply with an error code use `req.error(errorCode)`.
|
|
233
236
|
|
|
@@ -236,7 +239,7 @@ from error code `16` and up, to avoid future clashes with `dht-rpc` internals.
|
|
|
236
239
|
|
|
237
240
|
Currently dht-rpc defines the following errors
|
|
238
241
|
|
|
239
|
-
```
|
|
242
|
+
```js
|
|
240
243
|
DHT.OK = 0 // ie no error
|
|
241
244
|
DHT.ERROR_UNKNOWN_COMMAND = 1 // the command requested does not exist
|
|
242
245
|
DHT.ERROR_INVALID_TOKEN = 2 // the round trip token sent is invalid
|
|
@@ -274,14 +277,14 @@ Additional options include:
|
|
|
274
277
|
|
|
275
278
|
Query the DHT. Will move as close as possible to the `target` provided, which should be a 32-byte uniformly distributed buffer (ie a hash).
|
|
276
279
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
+
- `target` - find nodes close to this (should be a 32 byte buffer like a hash)
|
|
281
|
+
- `command` - an enum (uint) indicating the method you want to invoke
|
|
282
|
+
- `value` - optional binary payload to send with it
|
|
280
283
|
|
|
281
284
|
If you want to modify state stored in the dht, you can use the commit flag to signal the closest
|
|
282
285
|
nodes.
|
|
283
286
|
|
|
284
|
-
```
|
|
287
|
+
```js
|
|
285
288
|
{
|
|
286
289
|
// "commit" the query to the 20 closest nodes so they can modify/update their state
|
|
287
290
|
commit: true
|
|
@@ -292,7 +295,7 @@ Commiting a query will just re-request your command to the closest nodes once th
|
|
|
292
295
|
If you want to do some more specific logic with the closest nodes you can specify a function instead,
|
|
293
296
|
that is called for each close reply.
|
|
294
297
|
|
|
295
|
-
```
|
|
298
|
+
```js
|
|
296
299
|
{
|
|
297
300
|
async commit (reply, dht, query) {
|
|
298
301
|
// normally you'd send back the roundtrip token here, to prove to the remote that you own
|
|
@@ -304,7 +307,7 @@ that is called for each close reply.
|
|
|
304
307
|
|
|
305
308
|
Other options include:
|
|
306
309
|
|
|
307
|
-
```
|
|
310
|
+
```js
|
|
308
311
|
{
|
|
309
312
|
nodes: [
|
|
310
313
|
// start the query by querying these nodes
|