webpeerjs 0.0.1
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/LICENSE +21 -0
- package/README.md +49 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/webpeerjs.d.ts +16 -0
- package/dist/esm/webpeerjs.js +1600 -0
- package/dist/umd/package.json +1 -0
- package/dist/umd/webpeerjs.js +44177 -0
- package/package.json +83 -0
- package/src/config.js +286 -0
- package/src/umd.js +3 -0
- package/src/utils.js +178 -0
- package/src/webpeerjs.js +1188 -0
package/src/webpeerjs.js
ADDED
|
@@ -0,0 +1,1188 @@
|
|
|
1
|
+
import * as config from './config'
|
|
2
|
+
import {
|
|
3
|
+
mkErr,
|
|
4
|
+
PBPeer,
|
|
5
|
+
uint8ArrayToString,
|
|
6
|
+
uint8ArrayFromString,
|
|
7
|
+
//first,
|
|
8
|
+
Key,
|
|
9
|
+
msgIdFnStrictNoSign,
|
|
10
|
+
metrics } from './utils'
|
|
11
|
+
//import { createDelegatedRoutingV1HttpApiClient } from '@helia/delegated-routing-v1-http-api-client'
|
|
12
|
+
import { createLibp2p } from 'libp2p'
|
|
13
|
+
import { IDBDatastore } from 'datastore-idb'
|
|
14
|
+
import { webTransport } from '@libp2p/webtransport'
|
|
15
|
+
import { noise } from '@chainsafe/libp2p-noise'
|
|
16
|
+
import { yamux } from '@chainsafe/libp2p-yamux'
|
|
17
|
+
import { pubsubPeerDiscovery } from '@libp2p/pubsub-peer-discovery'
|
|
18
|
+
import { circuitRelayTransport } from '@libp2p/circuit-relay-v2'
|
|
19
|
+
import { gossipsub } from '@chainsafe/libp2p-gossipsub'
|
|
20
|
+
import { identify, identifyPush } from '@libp2p/identify'
|
|
21
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
22
|
+
//import { peerIdFromString } from '@libp2p/peer-id'
|
|
23
|
+
import { kadDHT, removePrivateAddressesMapper } from '@libp2p/kad-dht'
|
|
24
|
+
import { simpleMetrics } from '@libp2p/simple-metrics'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class webpeerjs{
|
|
28
|
+
|
|
29
|
+
//libp2p instance
|
|
30
|
+
#libp2p
|
|
31
|
+
|
|
32
|
+
//map [id,addrs] of discovered peers (addrs is array of address)
|
|
33
|
+
#discoveredPeers
|
|
34
|
+
|
|
35
|
+
//array of all webpeers id has been found
|
|
36
|
+
#webPeersId
|
|
37
|
+
|
|
38
|
+
//map [id,addrs]
|
|
39
|
+
#webPeersAddrs
|
|
40
|
+
|
|
41
|
+
//database of best peers has been found
|
|
42
|
+
#dbstore
|
|
43
|
+
#dbstoreData
|
|
44
|
+
|
|
45
|
+
//map of [id,number_of_dialed] of good peers on #connectionTracker
|
|
46
|
+
#dialedGoodPeers
|
|
47
|
+
|
|
48
|
+
//boolean is dial websocket
|
|
49
|
+
#isDialWebsocket
|
|
50
|
+
|
|
51
|
+
//map [id,mddrs] of dialed bootstrap address
|
|
52
|
+
#dialedKnownBootstrap
|
|
53
|
+
|
|
54
|
+
//array of dialed discovered peers id
|
|
55
|
+
//#dialedDiscoveredPeers
|
|
56
|
+
|
|
57
|
+
//object from joinRoom()
|
|
58
|
+
#rooms
|
|
59
|
+
|
|
60
|
+
//map [id,addrs] of webpeers currently connected (addrs is array of address)
|
|
61
|
+
#connectedPeers
|
|
62
|
+
|
|
63
|
+
//array of we peers id proxy of #connectedPeers
|
|
64
|
+
#connectedPeersArr
|
|
65
|
+
|
|
66
|
+
//map [id,number_of_dialed] of #connectionTracker object store
|
|
67
|
+
#connectionTrackerStore
|
|
68
|
+
|
|
69
|
+
//map [id,addr] of all peers connections (addr is string of address)
|
|
70
|
+
#connections
|
|
71
|
+
|
|
72
|
+
//track disconnect event
|
|
73
|
+
#trackDisconnect
|
|
74
|
+
|
|
75
|
+
//list of dial multiaddress queue
|
|
76
|
+
#dialQueue
|
|
77
|
+
|
|
78
|
+
//is dial enabled
|
|
79
|
+
#isDialEnabled
|
|
80
|
+
|
|
81
|
+
id
|
|
82
|
+
status
|
|
83
|
+
IPFS
|
|
84
|
+
address
|
|
85
|
+
peers
|
|
86
|
+
|
|
87
|
+
constructor(libp2p,dbstore,onMetrics){
|
|
88
|
+
|
|
89
|
+
this.#libp2p = libp2p
|
|
90
|
+
this.#dbstore = dbstore
|
|
91
|
+
this.#dbstoreData = new Map()
|
|
92
|
+
this.#discoveredPeers = new Map()
|
|
93
|
+
this.#webPeersId = []
|
|
94
|
+
this.#webPeersAddrs = new Map()
|
|
95
|
+
this.#dialedGoodPeers = new Map()
|
|
96
|
+
this.#isDialWebsocket = false
|
|
97
|
+
this.#dialedKnownBootstrap = new Map()
|
|
98
|
+
//this.#dialedDiscoveredPeers = []
|
|
99
|
+
this.address = []
|
|
100
|
+
this.#rooms = {}
|
|
101
|
+
this.#connectedPeers = new Map()
|
|
102
|
+
this.#connectedPeersArr = []
|
|
103
|
+
this.#connectionTrackerStore = new Map()
|
|
104
|
+
this.#connections = new Map()
|
|
105
|
+
this.#trackDisconnect = new Map()
|
|
106
|
+
this.#dialQueue = []
|
|
107
|
+
this.#isDialEnabled = true
|
|
108
|
+
|
|
109
|
+
this.peers = (function(f) {
|
|
110
|
+
return f
|
|
111
|
+
})(this.#connectedPeersArr);
|
|
112
|
+
|
|
113
|
+
this.status = (function(libp2p) {
|
|
114
|
+
return libp2p.status
|
|
115
|
+
})(this.#libp2p);
|
|
116
|
+
|
|
117
|
+
this.IPFS = (function(libp2p,discoveredPeers) {
|
|
118
|
+
const obj = {libp2p,discoveredPeers}
|
|
119
|
+
return obj
|
|
120
|
+
})(this.#libp2p,this.#discoveredPeers);
|
|
121
|
+
|
|
122
|
+
this.id = this.#libp2p.peerId.toString()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
//listen to peer connect event
|
|
126
|
+
this.#libp2p.addEventListener("peer:connect", (evt) => {
|
|
127
|
+
|
|
128
|
+
//console.log(`Connected to ${connection.toString()}`);
|
|
129
|
+
|
|
130
|
+
const connection = evt.detail;
|
|
131
|
+
const id = evt.detail.toString()
|
|
132
|
+
|
|
133
|
+
const connections = this.#libp2p.getConnections().map((con)=>{return {id:con.remotePeer.toString(),addr:con.remoteAddr.toString()}})
|
|
134
|
+
const connect = connections.find((con)=>con.id == id)
|
|
135
|
+
const addr = connect.addr
|
|
136
|
+
this.#connections.set(id,addr)
|
|
137
|
+
|
|
138
|
+
//required by joinRoom version 1 to announce via universal connectivity
|
|
139
|
+
if(connection.toString() === config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS[0]){
|
|
140
|
+
setTimeout(()=>{
|
|
141
|
+
this.#announce()
|
|
142
|
+
},1000)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
//listen message from subscribed pupsub topic
|
|
149
|
+
this.#libp2p.services.pubsub.addEventListener('message', event => {
|
|
150
|
+
|
|
151
|
+
//console.log('on:'+event.detail.topic,event.detail.data)
|
|
152
|
+
//console.log('from '+event.detail.from.toString(),event)
|
|
153
|
+
|
|
154
|
+
if (event.detail.type !== 'signed') {
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
if(config.CONFIG_JOIN_ROOM_VERSION == 1){
|
|
158
|
+
const topic = event.detail.topic
|
|
159
|
+
const senderPeerId = event.detail.from.toString()
|
|
160
|
+
if(config.CONFIG_PUBSUB_PEER_DISCOVERY.includes(topic)){
|
|
161
|
+
try{
|
|
162
|
+
|
|
163
|
+
//if it is webpeer
|
|
164
|
+
if(this.#webPeersId.includes(senderPeerId)){
|
|
165
|
+
|
|
166
|
+
if(this.#connectedPeers.has(senderPeerId)){
|
|
167
|
+
//reset this last seen
|
|
168
|
+
const address = this.#connectedPeers.get(senderPeerId).addrs
|
|
169
|
+
const now = new Date().getTime()
|
|
170
|
+
const metadata = {addrs:address,last:now}
|
|
171
|
+
this.#connectedPeers.set(senderPeerId,metadata)
|
|
172
|
+
}
|
|
173
|
+
else{
|
|
174
|
+
//add to connected webpeers
|
|
175
|
+
this.#onConnectFn(senderPeerId)
|
|
176
|
+
const address = this.#webPeersAddrs.get(senderPeerId)
|
|
177
|
+
const now = new Date().getTime()
|
|
178
|
+
const metadata = {addrs:address,last:now}
|
|
179
|
+
this.#connectedPeers.set(senderPeerId,metadata)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
//dial if not connected
|
|
183
|
+
if(!this.#isConnected(senderPeerId)){
|
|
184
|
+
if(this.#connections.has(senderPeerId)){
|
|
185
|
+
let mddrs = []
|
|
186
|
+
const addr = this.#connections.get(senderPeerId)
|
|
187
|
+
const mddr = multiaddr(addr)
|
|
188
|
+
mddrs.push(mddr)
|
|
189
|
+
this.#dialMultiaddress(mddrs)
|
|
190
|
+
}
|
|
191
|
+
else if(this.#discoveredPeers.has(senderPeerId)){
|
|
192
|
+
const addrs = this.#discoveredPeers.get(senderPeerId)
|
|
193
|
+
let mddrs = []
|
|
194
|
+
for(const addr of addrs){
|
|
195
|
+
const mddr = multiaddr(addr)
|
|
196
|
+
mddrs.push(mddr)
|
|
197
|
+
}
|
|
198
|
+
this.#dialMultiaddress(mddrs)
|
|
199
|
+
}
|
|
200
|
+
else{
|
|
201
|
+
const addrs = this.#connectedPeers.get(senderPeerId).addrs
|
|
202
|
+
let mddrs = []
|
|
203
|
+
for(const addr of addrs){
|
|
204
|
+
const mddr = multiaddr(addr)
|
|
205
|
+
mddrs.push(mddr)
|
|
206
|
+
}
|
|
207
|
+
this.#dialMultiaddress(mddrs)
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
//parse the message over pupsub peer discovery
|
|
215
|
+
const peer = PBPeer.decode(event.detail.data)
|
|
216
|
+
const msg = uint8ArrayToString(peer.addrs[0])
|
|
217
|
+
const json = JSON.parse(msg)
|
|
218
|
+
const prefix = json.prefix
|
|
219
|
+
const room = json.room
|
|
220
|
+
const message = json.message
|
|
221
|
+
const signal = json.signal
|
|
222
|
+
const id = json.id
|
|
223
|
+
//console.log(`from ${id}:${signal} = ${message}`)
|
|
224
|
+
if(id != senderPeerId)return
|
|
225
|
+
let address = json.address
|
|
226
|
+
|
|
227
|
+
//detect special webpeer identity
|
|
228
|
+
if(prefix === config.CONFIG_PREFIX){
|
|
229
|
+
|
|
230
|
+
//add to webpeers id
|
|
231
|
+
if(!this.#webPeersId.includes(id))this.#webPeersId.push(id)
|
|
232
|
+
|
|
233
|
+
//add to connected webpeers
|
|
234
|
+
if(!this.#connectedPeers.has(id)){
|
|
235
|
+
this.#onConnectFn(id)
|
|
236
|
+
address = []
|
|
237
|
+
const now = new Date().getTime()
|
|
238
|
+
const metadata = {addrs:address,last:now}
|
|
239
|
+
this.#connectedPeers.set(id,metadata)
|
|
240
|
+
this.#webPeersAddrs.set(id,address)
|
|
241
|
+
this.#connectedPeersArr.length = 0
|
|
242
|
+
for(const peer of this.#connectedPeers){
|
|
243
|
+
const item = {id:peer[0],address:peer[1].addrs}
|
|
244
|
+
this.#connectedPeersArr.push(item)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if(room){
|
|
250
|
+
if(this.#rooms[room]){
|
|
251
|
+
|
|
252
|
+
//inbound message
|
|
253
|
+
this.#rooms[room].onMessage(message,id)
|
|
254
|
+
|
|
255
|
+
//update room members
|
|
256
|
+
if(!this.#rooms[room].members.includes(id)){
|
|
257
|
+
this.#rooms[room].members.push(id)
|
|
258
|
+
this.#rooms[room].onMembers(this.#rooms[room].members)
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
if(signal){
|
|
264
|
+
|
|
265
|
+
//repply announce with ping
|
|
266
|
+
if(signal == 'announce'){
|
|
267
|
+
setTimeout(()=>{this.#ping()},1000)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if(signal == 'ping'){
|
|
271
|
+
//do nothing
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
//update connected webpeers
|
|
275
|
+
const now = new Date().getTime()
|
|
276
|
+
const metadata = {addrs:address,last:now}
|
|
277
|
+
this.#connectedPeers.set(id,metadata)
|
|
278
|
+
this.#webPeersAddrs.set(id,address)
|
|
279
|
+
this.#connectedPeersArr.length = 0
|
|
280
|
+
for(const peer of this.#connectedPeers){
|
|
281
|
+
const item = {id:peer[0],address:peer[1].addrs}
|
|
282
|
+
this.#connectedPeersArr.push(item)
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
}catch(err){
|
|
289
|
+
//console.log('from '+event.detail.from.toString())
|
|
290
|
+
console.debug(err)
|
|
291
|
+
}
|
|
292
|
+
}else{
|
|
293
|
+
const json = JSON.parse(topic)
|
|
294
|
+
const room = json.room
|
|
295
|
+
const message = new TextDecoder().decode(event.detail.data)
|
|
296
|
+
this.#rooms[room].onMessage(message)
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
//listen to peer discovery event
|
|
304
|
+
this.#libp2p.addEventListener('peer:discovery', (evt) => {
|
|
305
|
+
|
|
306
|
+
//console.log('Discovered:', evt.detail.id.toString())
|
|
307
|
+
//console.log('Discovered: '+evt.detail.id.toString(), evt.detail.multiaddrs.toString())
|
|
308
|
+
|
|
309
|
+
//save peer discover
|
|
310
|
+
|
|
311
|
+
const multiaddrs = evt.detail.multiaddrs
|
|
312
|
+
const id = evt.detail.id
|
|
313
|
+
|
|
314
|
+
if(multiaddrs.length != 0){
|
|
315
|
+
let addrs = []
|
|
316
|
+
for(const addr of multiaddrs){
|
|
317
|
+
let peeraddr
|
|
318
|
+
if(multiaddrs.toString().includes(evt.detail.id.toString())){
|
|
319
|
+
//console.log('Discovered:', evt.detail.multiaddrs.toString())
|
|
320
|
+
//peer from pupsub peer discovery already has included self id
|
|
321
|
+
peeraddr = addr.toString()
|
|
322
|
+
}
|
|
323
|
+
else{
|
|
324
|
+
//other need to add Id
|
|
325
|
+
peeraddr = addr.toString()+'/p2p/'+id
|
|
326
|
+
}
|
|
327
|
+
addrs.push(peeraddr)
|
|
328
|
+
}
|
|
329
|
+
//save the new format multiaddrs
|
|
330
|
+
this.#discoveredPeers.set(id.toString(), addrs)
|
|
331
|
+
|
|
332
|
+
//track if peer come from relay then dial it because there is a chance it is from other browser node
|
|
333
|
+
if(multiaddrs.toString().includes('certhash')&& multiaddrs.toString().includes('webtransport') && multiaddrs.toString().includes('p2p-circuit')){
|
|
334
|
+
//console.log(addrs)
|
|
335
|
+
if(!this.#connections.has(id)){
|
|
336
|
+
let mddrs = []
|
|
337
|
+
for(const addr of addrs){
|
|
338
|
+
const mddr = multiaddr(addr)
|
|
339
|
+
mddrs.push(mddr)
|
|
340
|
+
}
|
|
341
|
+
//this.#dialMultiaddress(mddrs)
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else{
|
|
346
|
+
//peer with empty address (multiaddrs = [])
|
|
347
|
+
//this.#discoveredPeers.set(id.toString(), multiaddrs)
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
//listen to peer disconnect event
|
|
354
|
+
this.#libp2p.addEventListener("peer:disconnect",async (evt) => {
|
|
355
|
+
|
|
356
|
+
//const connection = evt.detail;
|
|
357
|
+
//console.log(`Disconnected from ${connection.toCID().toString()}`);
|
|
358
|
+
const id = evt.detail.string
|
|
359
|
+
|
|
360
|
+
//track disconnect event
|
|
361
|
+
if(this.#trackDisconnect.has(id)){
|
|
362
|
+
let count = this.#trackDisconnect.get(id)
|
|
363
|
+
count++
|
|
364
|
+
this.#trackDisconnect.set(id,count)
|
|
365
|
+
//console.log(this.#trackDisconnect)
|
|
366
|
+
if(count>5){
|
|
367
|
+
if(this.#dbstoreData.has(id)){
|
|
368
|
+
//await this.#dbstore.delete(new Key(id))
|
|
369
|
+
this.#dbstoreData.delete(id)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if(!this.#webPeersId.includes(id) && !this.#dialedKnownBootstrap.has(id)){
|
|
373
|
+
return
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
else{
|
|
378
|
+
this.#trackDisconnect.set(id,0)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
//if this disconnected peer is web peer redial it
|
|
382
|
+
if(this.#webPeersId.includes(id)){
|
|
383
|
+
const addr = this.#connections.get(id)
|
|
384
|
+
let mddrs = []
|
|
385
|
+
const mddr = multiaddr(addr)
|
|
386
|
+
mddrs.push(mddr)
|
|
387
|
+
this.#dialMultiaddress(mddrs)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
//if this disconnected peer is known bootstrap redial it
|
|
391
|
+
else if(this.#dialedKnownBootstrap.has(id)){
|
|
392
|
+
const addr = this.#connections.get(id)
|
|
393
|
+
let mddrs = []
|
|
394
|
+
const addrs = multiaddr(addr)
|
|
395
|
+
mddrs.push(addrs)
|
|
396
|
+
this.#dialMultiaddress(mddrs)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
//redial if this disconnected peer is regular peer
|
|
400
|
+
else{
|
|
401
|
+
const addr = this.#connections.get(id)
|
|
402
|
+
let mddrs = []
|
|
403
|
+
const addrs = multiaddr(addr)
|
|
404
|
+
mddrs.push(addrs)
|
|
405
|
+
this.#dialMultiaddress(mddrs)
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
//listen to self peer update
|
|
411
|
+
this.#libp2p.addEventListener('self:peer:update', ({ detail: { peer } }) => {
|
|
412
|
+
//const multiaddrs = peer.addresses.map(({ multiaddr }) => multiaddr)
|
|
413
|
+
//console.log(`changed multiaddrs: peer ${peer.id.toString()} multiaddrs: ${multiaddrs}`)
|
|
414
|
+
const id = peer.id.toString()
|
|
415
|
+
const mddrs = []
|
|
416
|
+
peer.addresses.forEach((addr)=>{
|
|
417
|
+
const maddr = addr.multiaddr.toString()+'/p2p/'+id
|
|
418
|
+
if(maddr.includes('webtransport') && maddr.includes('certhash')){
|
|
419
|
+
mddrs.push(maddr)
|
|
420
|
+
}
|
|
421
|
+
})
|
|
422
|
+
//this.#ListenAddressChange(mddrs)
|
|
423
|
+
this.address = mddrs
|
|
424
|
+
this.#ping()
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
//dial known peers from configuration
|
|
428
|
+
this.#dialKnownPeers()
|
|
429
|
+
|
|
430
|
+
//watch connection every 30s if none dial known peers again from configuration
|
|
431
|
+
this.#watchConnection()
|
|
432
|
+
|
|
433
|
+
//if found good peers save to storage and reconnect if disconnect
|
|
434
|
+
this.#connectionTracker()
|
|
435
|
+
|
|
436
|
+
//periodically dial saved bootstrap address if disconnect
|
|
437
|
+
this.#dialRandomBootstrap()
|
|
438
|
+
|
|
439
|
+
//dial random discovered peers
|
|
440
|
+
//this.#dialdiscoveredpeers()
|
|
441
|
+
|
|
442
|
+
onMetrics((data)=>{
|
|
443
|
+
const signal = metrics(data)
|
|
444
|
+
this.#isDialEnabled = signal
|
|
445
|
+
|
|
446
|
+
})
|
|
447
|
+
|
|
448
|
+
setInterval(()=>{
|
|
449
|
+
this.#dialQueueList()
|
|
450
|
+
},5e3)
|
|
451
|
+
|
|
452
|
+
setInterval(()=>{
|
|
453
|
+
this.#trackLastSeen()
|
|
454
|
+
},5e3)
|
|
455
|
+
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
/*
|
|
462
|
+
PUBLIC FUNCTION
|
|
463
|
+
*/
|
|
464
|
+
|
|
465
|
+
//Listen on new peer connection
|
|
466
|
+
#onConnectFn = () => {}
|
|
467
|
+
onJoin = f => (this.#onConnectFn = f)
|
|
468
|
+
|
|
469
|
+
|
|
470
|
+
//Listen on peer disconnect
|
|
471
|
+
#onDisconnectFn = () => {}
|
|
472
|
+
onLeave = f => (this.#onDisconnectFn = f)
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
/*
|
|
478
|
+
PRIVATE FUNCTION
|
|
479
|
+
*/
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
//check the last seen in web peer
|
|
483
|
+
#trackLastSeen(){
|
|
484
|
+
const timeout = 25*1000
|
|
485
|
+
const now = new Date().getTime()
|
|
486
|
+
|
|
487
|
+
//if webpeer last seen grather then timeout send onDisconnect
|
|
488
|
+
for(const peer of this.#connectedPeers){
|
|
489
|
+
const id = peer[0]
|
|
490
|
+
const last = peer[1].last
|
|
491
|
+
const time = now-last
|
|
492
|
+
if(time>timeout){
|
|
493
|
+
this.#connectedPeers.delete(id)
|
|
494
|
+
this.#connectedPeersArr.length = 0
|
|
495
|
+
for(const peer of this.#connectedPeers){
|
|
496
|
+
const item = {id:peer[0],address:peer[1].addrs}
|
|
497
|
+
this.#connectedPeersArr.push(item)
|
|
498
|
+
}
|
|
499
|
+
this.#onDisconnectFn(id)
|
|
500
|
+
|
|
501
|
+
//remove id from room member
|
|
502
|
+
const rooms = Object.keys(this.#rooms)
|
|
503
|
+
for(const room of rooms){
|
|
504
|
+
if(this.#rooms[room].members.includes(id)){
|
|
505
|
+
const index = this.#rooms[room].members.indexOf(id)
|
|
506
|
+
this.#rooms[room].members.splice(index,1)
|
|
507
|
+
this.#rooms[room].onMembers(this.#rooms[room].members)
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
//check if this id is connected
|
|
515
|
+
#isConnected(id){
|
|
516
|
+
let peers = []
|
|
517
|
+
for(const peer of this.#libp2p.getPeers()){
|
|
518
|
+
peers.push(peer.toString())
|
|
519
|
+
}
|
|
520
|
+
if(peers.includes(id)){
|
|
521
|
+
return true
|
|
522
|
+
}
|
|
523
|
+
else{
|
|
524
|
+
return false
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
//add multiaddr address to queue list
|
|
530
|
+
#dialMultiaddress(mddrs){
|
|
531
|
+
if(mddrs.length>0){
|
|
532
|
+
|
|
533
|
+
const id = mddrs[0].toString().split('/').pop()
|
|
534
|
+
|
|
535
|
+
const ids = this.#dialQueue.map((arr)=> arr[0].toString().split('/').pop())
|
|
536
|
+
|
|
537
|
+
//if peer id is already in the queque cancel queque
|
|
538
|
+
if(ids.includes(id)){
|
|
539
|
+
return
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if(this.#webPeersId.includes(id) || id == config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS[0] ){
|
|
543
|
+
this.#dialQueue.unshift(mddrs)
|
|
544
|
+
}
|
|
545
|
+
else{
|
|
546
|
+
this.#dialQueue.push(mddrs)
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
//dial multiaddr address in queue list
|
|
553
|
+
#dialQueueList(){
|
|
554
|
+
|
|
555
|
+
if(!this.#isDialEnabled)return
|
|
556
|
+
|
|
557
|
+
const mddrsToDial = 3
|
|
558
|
+
|
|
559
|
+
let queue = []
|
|
560
|
+
for(const item of this.#libp2p.getDialQueue()){
|
|
561
|
+
const id = item.peerId.string
|
|
562
|
+
queue.push(id)
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
if (queue.length > mddrsToDial)return
|
|
566
|
+
|
|
567
|
+
for(let i = 0; i < mddrsToDial; i++){
|
|
568
|
+
const mddrs = this.#dialQueue.shift()
|
|
569
|
+
if(mddrs != undefined && mddrs.length>0){
|
|
570
|
+
|
|
571
|
+
const id = mddrs[0].toString().split('/').pop()
|
|
572
|
+
|
|
573
|
+
if(this.#isConnected(id))continue
|
|
574
|
+
if(queue.includes(id)){continue;}
|
|
575
|
+
|
|
576
|
+
//dial with webtransport
|
|
577
|
+
this.#dialWebtransport(mddrs)
|
|
578
|
+
|
|
579
|
+
//fallback dial with websocket if enabled
|
|
580
|
+
if(this.#isDialWebsocket){
|
|
581
|
+
this.#dialWebsocket(mddrs)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
}
|
|
585
|
+
else{
|
|
586
|
+
break
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
//announce and ping via pupsub peer discovery
|
|
594
|
+
async #announce(){
|
|
595
|
+
const topics = config.CONFIG_PUBSUB_PEER_DISCOVERY
|
|
596
|
+
const data = JSON.stringify({prefix:config.CONFIG_PREFIX,signal:'announce',id:this.#libp2p.peerId.toString(),address:this.address})
|
|
597
|
+
const peer = {
|
|
598
|
+
publicKey: this.#libp2p.peerId.publicKey,
|
|
599
|
+
addrs: [uint8ArrayFromString(data)],
|
|
600
|
+
}
|
|
601
|
+
const encodedPeer = PBPeer.encode(peer)
|
|
602
|
+
for(const topic of topics){
|
|
603
|
+
await this.#libp2p.services.pubsub.publish(topic, encodedPeer)
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
async #ping(){
|
|
607
|
+
const topics = config.CONFIG_PUBSUB_PEER_DISCOVERY
|
|
608
|
+
const data = JSON.stringify({prefix:config.CONFIG_PREFIX,signal:'ping',id:this.#libp2p.peerId.toString(),address:this.address})
|
|
609
|
+
const peer = {
|
|
610
|
+
publicKey: this.#libp2p.peerId.publicKey,
|
|
611
|
+
addrs: [uint8ArrayFromString(data)],
|
|
612
|
+
}
|
|
613
|
+
const encodedPeer = PBPeer.encode(peer)
|
|
614
|
+
for(const topic of topics){
|
|
615
|
+
await this.#libp2p.services.pubsub.publish(topic, encodedPeer)
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
joinRoom = room => {
|
|
621
|
+
if (this.#rooms[room]) {
|
|
622
|
+
return [
|
|
623
|
+
this.#rooms[room].sendMessage,
|
|
624
|
+
this.#rooms[room].listenMessage,
|
|
625
|
+
this.#rooms[room].onMembersChange
|
|
626
|
+
]
|
|
627
|
+
|
|
628
|
+
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
if (!room) {
|
|
632
|
+
throw mkErr('room is required')
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
//join room version 1 user pupsub via pupsub peer discovery
|
|
636
|
+
if(config.CONFIG_JOIN_ROOM_VERSION == 1){
|
|
637
|
+
|
|
638
|
+
const topics = config.CONFIG_PUBSUB_PEER_DISCOVERY
|
|
639
|
+
|
|
640
|
+
this.#rooms[room] = {
|
|
641
|
+
onMessage : () => {},
|
|
642
|
+
listenMessage : f => (this.#rooms[room] = {...this.#rooms[room], onMessage: f}),
|
|
643
|
+
sendMessage : async (message) => {
|
|
644
|
+
const data = JSON.stringify({prefix:config.CONFIG_PREFIX,room,message,id:this.#libp2p.peerId.toString()})
|
|
645
|
+
const peer = {
|
|
646
|
+
publicKey: this.#libp2p.peerId.publicKey,
|
|
647
|
+
addrs: [uint8ArrayFromString(data)],
|
|
648
|
+
}
|
|
649
|
+
const encodedPeer = PBPeer.encode(peer)
|
|
650
|
+
for(const topic of topics){
|
|
651
|
+
await this.#libp2p.services.pubsub.publish(topic, encodedPeer)
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
members : [this.id],
|
|
655
|
+
onMembers : () => {},
|
|
656
|
+
onMembersChange : f => {this.#rooms[room] = {...this.#rooms[room], onMembers: f};this.#rooms[room].onMembers(this.#rooms[room].members)},
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
return [
|
|
661
|
+
this.#rooms[room].sendMessage,
|
|
662
|
+
this.#rooms[room].listenMessage,
|
|
663
|
+
this.#rooms[room].onMembersChange
|
|
664
|
+
]
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
|
|
668
|
+
//dial discovered peers
|
|
669
|
+
/*#dialdiscoveredpeers(){
|
|
670
|
+
setInterval(()=>{
|
|
671
|
+
const keys = Array.from(this.#discoveredPeers.keys())
|
|
672
|
+
for(const key of keys){
|
|
673
|
+
if(!this.#dialedDiscoveredPeers.includes(key)){
|
|
674
|
+
this.#dialedDiscoveredPeers.push(key)
|
|
675
|
+
const addrs = this.#discoveredPeers.get(key)
|
|
676
|
+
let mddrs = []
|
|
677
|
+
for(const addr of addrs){
|
|
678
|
+
const mddr = multiaddr(addr)
|
|
679
|
+
mddrs.push(mddr)
|
|
680
|
+
}
|
|
681
|
+
this.#dialMultiaddress(mddrs)
|
|
682
|
+
break
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
},30*1000)
|
|
686
|
+
}*/
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
//dial random known bootstrap periodically
|
|
690
|
+
#dialRandomBootstrap(){
|
|
691
|
+
setInterval(()=>{
|
|
692
|
+
//const keys = Array.from(this.#dialedKnownBootstrap.keys())
|
|
693
|
+
const keys = config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS
|
|
694
|
+
const randomKey = Math.floor(Math.random() * keys.length)
|
|
695
|
+
let ids = []
|
|
696
|
+
ids.push(keys[randomKey])
|
|
697
|
+
|
|
698
|
+
//universal connectivity id for webpeer discovery and joinRoom version 1 to work
|
|
699
|
+
ids.push(config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS[0])
|
|
700
|
+
|
|
701
|
+
for(const id of ids){
|
|
702
|
+
if(id == undefined)continue
|
|
703
|
+
//const addrs = this.#dialedKnownBootstrap.get(id)
|
|
704
|
+
|
|
705
|
+
if(!this.#isConnected(id)){
|
|
706
|
+
if(this.#connections.has(id))
|
|
707
|
+
{
|
|
708
|
+
let mddrs = []
|
|
709
|
+
const addr = this.#connections.get(id)
|
|
710
|
+
const mddr = multiaddr(addr)
|
|
711
|
+
mddrs.push(mddr)
|
|
712
|
+
this.#dialMultiaddress(mddrs)
|
|
713
|
+
}
|
|
714
|
+
else if (this.#dialedKnownBootstrap.has(id)){
|
|
715
|
+
let mddrs = []
|
|
716
|
+
const addrs = this.#dialedKnownBootstrap.get(id)
|
|
717
|
+
for(const addr of addrs){
|
|
718
|
+
const mddr = multiaddr(addr)
|
|
719
|
+
mddrs.push(mddr)
|
|
720
|
+
}
|
|
721
|
+
this.#dialMultiaddress(mddrs)
|
|
722
|
+
}
|
|
723
|
+
else{
|
|
724
|
+
const bootstrap = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_ADDRS
|
|
725
|
+
const index = bootstrap.findIndex((peer)=>peer.Peers[0].ID == id)
|
|
726
|
+
const addrs = bootstrap[index].Peers[0].Addrs
|
|
727
|
+
let mddrs = []
|
|
728
|
+
for(const addr of addrs){
|
|
729
|
+
const peeraddr = addr+'/p2p/'+id
|
|
730
|
+
const mddr = multiaddr(peeraddr)
|
|
731
|
+
mddrs.push(mddr)
|
|
732
|
+
}
|
|
733
|
+
this.#dialMultiaddress(mddrs)
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
},45*1000)
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
//track for good connection
|
|
742
|
+
async #connectionTracker(){
|
|
743
|
+
|
|
744
|
+
for await (const { key, value } of this.#dbstore.query({})) {
|
|
745
|
+
const id = key.toString().split('/')[1]
|
|
746
|
+
const addr = new TextDecoder().decode(value)
|
|
747
|
+
this.#dbstoreData.set(id,addr)
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
setInterval(async ()=>{
|
|
751
|
+
|
|
752
|
+
//save peer address if connection is good
|
|
753
|
+
const connections = this.#libp2p.getConnections()
|
|
754
|
+
for(const connect of connections){
|
|
755
|
+
const peer = connect.remotePeer
|
|
756
|
+
const remote = connect.remoteAddr
|
|
757
|
+
const upgraded = connect.timeline.upgraded
|
|
758
|
+
const bestlimit = 5*60*1000
|
|
759
|
+
const now = new Date().getTime()
|
|
760
|
+
const besttime = now-upgraded
|
|
761
|
+
if(besttime>bestlimit){
|
|
762
|
+
const addr = remote.toString()
|
|
763
|
+
const id = peer.toString()
|
|
764
|
+
if(!this.#webPeersId.includes(id) && !config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS.includes(id) && !this.#dbstoreData.get(id) && !addr.includes('p2p-circuit')){
|
|
765
|
+
//await this.#dbstore.delete(new Key(id))
|
|
766
|
+
await this.#dbstore.put(new Key(id), new TextEncoder().encode(addr))
|
|
767
|
+
this.#dbstoreData.set(id,addr)
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
const goodlimit = 60*1000
|
|
771
|
+
const goodtime = now-upgraded
|
|
772
|
+
if(goodtime>goodlimit){
|
|
773
|
+
const id = peer.toString()
|
|
774
|
+
if(!this.#dialedGoodPeers.has(id))this.#dialedGoodPeers.set(id,0)
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
|
|
780
|
+
let peers = []
|
|
781
|
+
for(const peer of this.#libp2p.getPeers()){
|
|
782
|
+
peers.push(peer.toString())
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
//connect to saved best peer address
|
|
787
|
+
//working great
|
|
788
|
+
for(const peer of this.#dbstoreData){
|
|
789
|
+
const id = peer[0]
|
|
790
|
+
const addr = peer[1]
|
|
791
|
+
if(peers.includes(id)){
|
|
792
|
+
this.#connectionTrackerStore.set(id,0)
|
|
793
|
+
continue
|
|
794
|
+
}else{
|
|
795
|
+
if(this.#connectionTrackerStore.has(id)){
|
|
796
|
+
let current = this.#connectionTrackerStore.get(id)
|
|
797
|
+
if(current>10)continue
|
|
798
|
+
current++
|
|
799
|
+
this.#connectionTrackerStore.set(id,current)
|
|
800
|
+
}
|
|
801
|
+
else{
|
|
802
|
+
this.#connectionTrackerStore.set(id,0)
|
|
803
|
+
}
|
|
804
|
+
let mddrs = []
|
|
805
|
+
const mddr = multiaddr(addr)
|
|
806
|
+
mddrs.push(mddr)
|
|
807
|
+
this.#dialMultiaddress(mddrs)
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
//connect to good peer address if it is disconnected
|
|
812
|
+
const goods = Array.from(this.#dialedGoodPeers.keys())
|
|
813
|
+
for(const id of goods){
|
|
814
|
+
if(peers.includes(id)){
|
|
815
|
+
this.#dialedGoodPeers.set(id,0)
|
|
816
|
+
continue
|
|
817
|
+
}
|
|
818
|
+
else{
|
|
819
|
+
|
|
820
|
+
let count = this.#dialedGoodPeers.get(id)
|
|
821
|
+
if (count < 15 || (count < 25 && this.#dialedKnownBootstrap.has(id))){
|
|
822
|
+
const addr = this.#connections.get(id)
|
|
823
|
+
let mddrs = []
|
|
824
|
+
const mddr = multiaddr(addr)
|
|
825
|
+
mddrs.push(mddr)
|
|
826
|
+
this.#dialMultiaddress(mddrs)
|
|
827
|
+
count++
|
|
828
|
+
this.#dialedGoodPeers.set(id,count)
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
},30*1000)
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
|
|
837
|
+
//update listen address on change
|
|
838
|
+
//#ListenAddressChange = () => {}
|
|
839
|
+
//#onSelfAddress = f => (this.#ListenAddressChange = f)
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
//Periodically watch for connection
|
|
843
|
+
#watchConnection(){
|
|
844
|
+
setInterval(()=>{
|
|
845
|
+
const peers = this.#libp2p.getPeers().length
|
|
846
|
+
if(peers == 0){
|
|
847
|
+
this.#dialKnownPeers()
|
|
848
|
+
}
|
|
849
|
+
},60*1000)
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
//dial to all known bootstrap peers and DNS
|
|
854
|
+
#dialKnownPeers(){
|
|
855
|
+
this.#dialKnownBootstrap()
|
|
856
|
+
setTimeout(()=>{
|
|
857
|
+
const peers = this.#libp2p.getPeers().length
|
|
858
|
+
if(peers == 0){
|
|
859
|
+
//currently not needed
|
|
860
|
+
//this.#dialKnownID()
|
|
861
|
+
setTimeout(()=>{
|
|
862
|
+
const peers = this.#libp2p.getPeers().length
|
|
863
|
+
if(peers == 0){
|
|
864
|
+
//currently not needed
|
|
865
|
+
//this.#dialKnownDNS()
|
|
866
|
+
setTimeout(()=>{
|
|
867
|
+
const peers = this.#libp2p.getPeers().length
|
|
868
|
+
if(peers == 0){
|
|
869
|
+
//currently not needed
|
|
870
|
+
//this.#dialKnownDNSonly()
|
|
871
|
+
}
|
|
872
|
+
},15000)
|
|
873
|
+
}
|
|
874
|
+
},15000)
|
|
875
|
+
}
|
|
876
|
+
},15000)
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
//dial based on known bootsrap peers address
|
|
881
|
+
#dialKnownBootstrap(){
|
|
882
|
+
const bootstrap = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_ADDRS
|
|
883
|
+
for(const peer of bootstrap){
|
|
884
|
+
const address = peer.Peers[0].Addrs
|
|
885
|
+
const id = peer.Peers[0].ID
|
|
886
|
+
let mddrs = []
|
|
887
|
+
let addrs = []
|
|
888
|
+
for(const addr of address){
|
|
889
|
+
const peeraddr = addr+'/p2p/'+id
|
|
890
|
+
const peermddr = multiaddr(peeraddr)
|
|
891
|
+
addrs.push(peeraddr)
|
|
892
|
+
mddrs.push(peermddr)
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
this.#dialedKnownBootstrap.set(id,addrs)
|
|
896
|
+
if(!this.#isConnected(id)){
|
|
897
|
+
this.#dialMultiaddress(mddrs)
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
|
|
904
|
+
//dial based on known peers ID
|
|
905
|
+
/*async #dialKnownID(){
|
|
906
|
+
const api = config.CONFIG_DELEGATED_API
|
|
907
|
+
const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
|
|
908
|
+
const BOOTSTRAP_PEER_IDS = config.CONFIG_KNOWN_BOOTSTRAP_PEER_IDS
|
|
909
|
+
const peers = await Promise.all(
|
|
910
|
+
BOOTSTRAP_PEER_IDS.map((peerId) => first(delegatedClient.getPeers(peerIdFromString(peerId)))),
|
|
911
|
+
)
|
|
912
|
+
for(const peer of peers){
|
|
913
|
+
if(!peer)return
|
|
914
|
+
const address = peer.Addrs
|
|
915
|
+
const id = peer.ID
|
|
916
|
+
let mddrs = []
|
|
917
|
+
let addrs = []
|
|
918
|
+
for(const addr of address){
|
|
919
|
+
const peeraddr = addr.toString()+'/p2p/'+id.toString()
|
|
920
|
+
const peermddr = multiaddr(peeraddr)
|
|
921
|
+
addrs.push(peeraddr)
|
|
922
|
+
mddrs.push(peermddr)
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
this.#dialedKnownBootstrap.set(id,addrs)
|
|
926
|
+
if(!this.#isConnected(id)){
|
|
927
|
+
this.#dialMultiaddress(mddrs)
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}*/
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
//dial based on known bootstrap DNS
|
|
934
|
+
/*async #dialKnownDNS(){
|
|
935
|
+
const dnsresolver = config.CONFIG_DNS_RESOLVER
|
|
936
|
+
const bootstrapdns = config.CONFIG_KNOWN_BOOTSTRAP_DNS
|
|
937
|
+
const response = await fetch(dnsresolver+'?name='+bootstrapdns+'&type=txt')
|
|
938
|
+
const json = await response.json()
|
|
939
|
+
const dns = json.Answer
|
|
940
|
+
const BOOTSTRAP_PEER_IDS = []
|
|
941
|
+
for(const dnsaddr of dns){
|
|
942
|
+
const id = dnsaddr.data.split('/').pop()
|
|
943
|
+
BOOTSTRAP_PEER_IDS.push(id)
|
|
944
|
+
}
|
|
945
|
+
const api = config.CONFIG_DELEGATED_API
|
|
946
|
+
const delegatedClient = createDelegatedRoutingV1HttpApiClient(api)
|
|
947
|
+
const peers = await Promise.all(
|
|
948
|
+
BOOTSTRAP_PEER_IDS.map((peerId) => first(delegatedClient.getPeers(peerIdFromString(peerId)))),
|
|
949
|
+
)
|
|
950
|
+
for(const peer of peers){
|
|
951
|
+
const address = peer.Addrs
|
|
952
|
+
const id = peer.ID
|
|
953
|
+
let mddrs = []
|
|
954
|
+
let addrs = []
|
|
955
|
+
for(const addr of address){
|
|
956
|
+
const peeraddr = addr.toString()+'/p2p/'+id.toString()
|
|
957
|
+
const peermddr = multiaddr(peeraddr)
|
|
958
|
+
addrs.push(peeraddr)
|
|
959
|
+
mddrs.push(peermddr)
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
this.#dialedKnownBootstrap.set(id,addrs)
|
|
963
|
+
if(!this.#isConnected(id)){
|
|
964
|
+
this.#dialMultiaddress(mddrs)
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
}*/
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
//dial based on known bootstrap DNS using DNS resolver only
|
|
972
|
+
/*async #dialKnownDNSonly(){
|
|
973
|
+
const dnsresolver = config.CONFIG_DNS_RESOLVER
|
|
974
|
+
const bootstrapdns = config.CONFIG_KNOWN_BOOTSTRAP_DNS
|
|
975
|
+
const response = await fetch(dnsresolver+'?name='+bootstrapdns+'&type=txt')
|
|
976
|
+
const json = await response.json()
|
|
977
|
+
const dns = json.Answer
|
|
978
|
+
|
|
979
|
+
for(const dnsitem of dns){
|
|
980
|
+
const arr = dnsitem.data.split('/')
|
|
981
|
+
const id = arr.pop()
|
|
982
|
+
const dnsaddr = '_dnsaddr.'+arr[2]
|
|
983
|
+
this.#dialDNSWebsocketWebtransport(id,dnsaddr)
|
|
984
|
+
}
|
|
985
|
+
}*/
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
//dial DNS with webtransport and websocket
|
|
989
|
+
/*async #dialDNSWebsocketWebtransport(id,dnsaddr){
|
|
990
|
+
const dnsresolver = config.CONFIG_DNS_RESOLVER
|
|
991
|
+
const response = await fetch(dnsresolver+'?name='+dnsaddr+'&type=txt')
|
|
992
|
+
const json = await response.json()
|
|
993
|
+
const dns = json.Answer
|
|
994
|
+
let mddrs = []
|
|
995
|
+
let addrs = []
|
|
996
|
+
for(const dnsitem of dns){
|
|
997
|
+
const arr = dnsitem.data.split('=')
|
|
998
|
+
const dnsaddr = arr[1]
|
|
999
|
+
const maddr = multiaddr(dnsaddr)
|
|
1000
|
+
mddrs.push(maddr)
|
|
1001
|
+
addrs.push(dnsaddr)
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
this.#isDialWebsocket = true
|
|
1006
|
+
this.#dialedKnownBootstrap.set(id,addrs)
|
|
1007
|
+
|
|
1008
|
+
this.#dialedKnownBootstrap.set(id,addrs)
|
|
1009
|
+
if(!this.#isConnected(id)){
|
|
1010
|
+
this.#dialMultiaddress(mddrs)
|
|
1011
|
+
this.#dialWebsocket(mddrs)
|
|
1012
|
+
}
|
|
1013
|
+
}*/
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
//dial only webtransport multiaddrs
|
|
1017
|
+
async #dialWebtransport(multiaddrs){
|
|
1018
|
+
const webTransportMadrs = multiaddrs.filter((maddr) => maddr.protoNames().includes('webtransport')&&maddr.protoNames().includes('certhash'))
|
|
1019
|
+
for (const addr of webTransportMadrs) {
|
|
1020
|
+
try {
|
|
1021
|
+
//console.log(`attempting to dial webtransport multiaddr: %o`, addr.toString())
|
|
1022
|
+
await this.#libp2p.dial(addr)
|
|
1023
|
+
return // if we succeed dialing the peer, no need to try another address
|
|
1024
|
+
} catch (error) {
|
|
1025
|
+
//console.log(`failed to dial webtransport multiaddr: %o`, addr.toString())
|
|
1026
|
+
console.debug(error)
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
//dial only webtransport multiaddrs
|
|
1032
|
+
/*#dialWebtransport1(multiaddrs){
|
|
1033
|
+
const webTransportMadrs = multiaddrs.filter((maddr) => maddr.protoNames().includes('webtransport')&&maddr.protoNames().includes('certhash'))
|
|
1034
|
+
if(webTransportMadrs.length == 0)return
|
|
1035
|
+
this.#libp2p.dial(webTransportMadrs).then((data)=>{console.warn(data)},(data)=>{console.warn(data)})
|
|
1036
|
+
}*/
|
|
1037
|
+
|
|
1038
|
+
//dial only websocket multiaddrs
|
|
1039
|
+
async #dialWebsocket(multiaddrs){
|
|
1040
|
+
const webSocketMadrs = multiaddrs.filter((maddr) => maddr.protoNames().includes('wss'))
|
|
1041
|
+
for (const addr of webSocketMadrs) {
|
|
1042
|
+
try {
|
|
1043
|
+
//console.log(`attempting to dial websocket multiaddr: %o`, addr)
|
|
1044
|
+
await this.#libp2p.dial(addr)
|
|
1045
|
+
return // if we succeed dialing the peer, no need to try another address
|
|
1046
|
+
} catch (error) {
|
|
1047
|
+
//console.log(`failed to dial websocket multiaddr: %o`, addr)
|
|
1048
|
+
console.debug(error)
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
|
|
1054
|
+
//entry point to webpeerjs
|
|
1055
|
+
static async createWebpeer(){
|
|
1056
|
+
|
|
1057
|
+
// all libp2p debug logs
|
|
1058
|
+
localStorage.setItem('debug', 'libp2p:*')
|
|
1059
|
+
|
|
1060
|
+
const dbstore = new IDBDatastore(config.CONFIG_DBSTORE_PATH)
|
|
1061
|
+
await dbstore.open()
|
|
1062
|
+
|
|
1063
|
+
const bootstrapAddrs = []
|
|
1064
|
+
|
|
1065
|
+
//let addrs = []
|
|
1066
|
+
const getbootstrap = config.CONFIG_KNOWN_BOOTSTRAP_PEERS_ADDRS
|
|
1067
|
+
for(const peer of getbootstrap){
|
|
1068
|
+
const addrs = peer.Peers[0].Addrs
|
|
1069
|
+
const id = peer.Peers[0].ID
|
|
1070
|
+
//let mddrs = []
|
|
1071
|
+
for(const addr of addrs){
|
|
1072
|
+
if(addr.includes('webtransport')&&addr.includes('certhash')){
|
|
1073
|
+
bootstrapAddrs.push(addr+'/p2p/'+id)
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
let onMetricsFn = () => {}
|
|
1079
|
+
const onMetrics = f => (onMetricsFn = f)
|
|
1080
|
+
|
|
1081
|
+
//create libp2p instance
|
|
1082
|
+
const libp2p = await createLibp2p({
|
|
1083
|
+
addresses: {
|
|
1084
|
+
listen: [
|
|
1085
|
+
],
|
|
1086
|
+
},
|
|
1087
|
+
transports:[
|
|
1088
|
+
webTransport(),
|
|
1089
|
+
circuitRelayTransport({
|
|
1090
|
+
discoverRelays: config.CONFIG_DISCOVER_RELAYS,
|
|
1091
|
+
reservationConcurrency: 1,
|
|
1092
|
+
maxReservationQueueLength: 3
|
|
1093
|
+
}),
|
|
1094
|
+
],
|
|
1095
|
+
connectionManager: {
|
|
1096
|
+
maxConnections: config.CONFIG_MAX_CONNECTIONS,
|
|
1097
|
+
minConnections: config.CONFIG_MIN_CONNECTIONS,
|
|
1098
|
+
autoDialInterval:60e3,
|
|
1099
|
+
autoDialConcurrency:0,
|
|
1100
|
+
autoDialMaxQueueLength:0,
|
|
1101
|
+
autoDialPriority:1000,
|
|
1102
|
+
autoDialDiscoveredPeersDebounce:30e3,
|
|
1103
|
+
maxParallelDials: 3,
|
|
1104
|
+
dialTimeout: 5e3,
|
|
1105
|
+
maxIncomingPendingConnections: 5,
|
|
1106
|
+
maxDialQueueLength:10,
|
|
1107
|
+
inboundConnectionThreshold:3,
|
|
1108
|
+
maxPeerAddrsToDial:2,
|
|
1109
|
+
inboundUpgradeTimeout:5e3
|
|
1110
|
+
},
|
|
1111
|
+
connectionEncryption: [noise()],
|
|
1112
|
+
streamMuxers: [
|
|
1113
|
+
yamux({
|
|
1114
|
+
maxInboundStreams: 50,
|
|
1115
|
+
maxOutboundStreams: 50,
|
|
1116
|
+
})
|
|
1117
|
+
],
|
|
1118
|
+
connectionGater: {
|
|
1119
|
+
filterMultiaddrForPeer: async (peer, multiaddrTest) => {
|
|
1120
|
+
const multiaddrString = multiaddrTest.toString();
|
|
1121
|
+
if (
|
|
1122
|
+
multiaddrString.includes("/ip4/127.0.0.1") ||
|
|
1123
|
+
multiaddrString.includes("/ip6/")
|
|
1124
|
+
) {
|
|
1125
|
+
return false;
|
|
1126
|
+
}
|
|
1127
|
+
return true;
|
|
1128
|
+
},
|
|
1129
|
+
denyDialMultiaddr: async (multiaddrTest) => {
|
|
1130
|
+
const multiaddrString = multiaddrTest.toString();
|
|
1131
|
+
if (
|
|
1132
|
+
multiaddrString.includes("/ip4/127.0.0.1") ||
|
|
1133
|
+
multiaddrString.includes("/ip6/")
|
|
1134
|
+
) {
|
|
1135
|
+
return true;
|
|
1136
|
+
}
|
|
1137
|
+
return false;
|
|
1138
|
+
},
|
|
1139
|
+
},
|
|
1140
|
+
peerDiscovery: [
|
|
1141
|
+
pubsubPeerDiscovery({
|
|
1142
|
+
interval: 10_000,
|
|
1143
|
+
topics: config.CONFIG_PUBSUB_PEER_DISCOVERY,
|
|
1144
|
+
listenOnly: false,
|
|
1145
|
+
}),
|
|
1146
|
+
|
|
1147
|
+
],
|
|
1148
|
+
services: {
|
|
1149
|
+
pubsub: gossipsub({
|
|
1150
|
+
allowPublishToZeroTopicPeers: true,
|
|
1151
|
+
msgIdFn: msgIdFnStrictNoSign,
|
|
1152
|
+
ignoreDuplicatePublishError: true,
|
|
1153
|
+
}),
|
|
1154
|
+
identify: identify(),
|
|
1155
|
+
identifyPush: identifyPush(),
|
|
1156
|
+
aminoDHT: kadDHT({
|
|
1157
|
+
protocol: '/ipfs/kad/1.0.0',
|
|
1158
|
+
peerInfoMapper: removePrivateAddressesMapper,
|
|
1159
|
+
clientMode: false
|
|
1160
|
+
}),
|
|
1161
|
+
|
|
1162
|
+
},
|
|
1163
|
+
peerStore: {
|
|
1164
|
+
persistence: true,
|
|
1165
|
+
threshold: 1
|
|
1166
|
+
},
|
|
1167
|
+
metrics: simpleMetrics({
|
|
1168
|
+
onMetrics: (metrics) => {onMetricsFn(metrics)},
|
|
1169
|
+
intervalMs: 1000
|
|
1170
|
+
})
|
|
1171
|
+
})
|
|
1172
|
+
|
|
1173
|
+
|
|
1174
|
+
|
|
1175
|
+
//console.log(`Node started with id ${libp2p.peerId.toString()}`)
|
|
1176
|
+
|
|
1177
|
+
//DHT server mode act as bootstrap peer in IPFS network
|
|
1178
|
+
await libp2p.services.aminoDHT.setMode("server")
|
|
1179
|
+
|
|
1180
|
+
|
|
1181
|
+
//return webpeerjs class
|
|
1182
|
+
return new webpeerjs(libp2p,dbstore,onMetrics)
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
|
|
1187
|
+
//export module
|
|
1188
|
+
export {webpeerjs}
|