helia-coord 1.2.1 → 1.2.2

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.
@@ -120,6 +120,9 @@ class TimerControllers {
120
120
  // Disable the timer while processing is happening.
121
121
  clearInterval(this.circuitRelayTimerHandle)
122
122
 
123
+ // Renew connections to V1 Circuit Relays
124
+ await useCases.relays.connectToV1Relays()
125
+
123
126
  // Remove any duplicate entries
124
127
  useCases.relays.removeDuplicates(thisNode)
125
128
 
@@ -18,6 +18,23 @@ class RelayUseCases {
18
18
  'Must inject instance of adapters when instantiating Relay Use Cases library.'
19
19
  )
20
20
  }
21
+
22
+ // Initialize v1 relay list. Allows user to overwrite with local config.
23
+ this.v1Relays = []
24
+ if (localConfig.v1Relays) {
25
+ this.v1Relays = localConfig.v1Relays
26
+ // console.log('v1Relays: ', this.v1Relays)
27
+ }
28
+
29
+ // Bind 'this' object to all subfunctions
30
+ this.connectToV1Relays = this.connectToV1Relays.bind(this)
31
+ this.initializeRelays = this.initializeRelays.bind(this)
32
+ this.getCRGist = this.getCRGist.bind(this)
33
+ this.connectToCRs = this.connectToCRs.bind(this)
34
+ this.sortRelays = this.sortRelays.bind(this)
35
+ this.addRelay = this.addRelay.bind(this)
36
+ this.measureRelays = this.measureRelays.bind(this)
37
+ this.removeDuplicates = this.removeDuplicates.bind(this)
21
38
  }
22
39
 
23
40
  // Connect to the pre-programmed circuit relays for the first time at startup.
@@ -183,11 +200,35 @@ class RelayUseCases {
183
200
  // `status: ${now.toLocaleString()}: Renewed connections to all known Circuit Relay nodes.`
184
201
  // )
185
202
  } catch (err) {
186
- console.log('Error in connectToCRs()')
203
+ console.error('Error in connectToCRs()')
187
204
  return false
188
205
  }
189
206
  }
190
207
 
208
+ // If a list of v1 Circuit Relays is provided, then renew connections to them.
209
+ async connectToV1Relays (relays) {
210
+ try {
211
+ for (let i = 0; i < this.v1Relays.length; i++) {
212
+ const thisRelay = this.v1Relays[i]
213
+
214
+ try {
215
+ this.adapters.log.statusLog(2, `Connecting to v1 Relay: ${thisRelay}`)
216
+
217
+ await this.adapters.ipfs.connectToPeer(
218
+ { multiaddr: thisRelay }
219
+ )
220
+ } catch (err) {
221
+ /* exit quietly */
222
+ }
223
+ }
224
+
225
+ return true
226
+ } catch (err) {
227
+ console.error('Error in connectToV1Relays()')
228
+ throw err
229
+ }
230
+ }
231
+
191
232
  // Sort the relay data relative to the measured latency metrics.
192
233
  sortRelays (relayData) {
193
234
  try {
@@ -299,6 +340,8 @@ class RelayUseCases {
299
340
  if (x.includes('udp')) return false
300
341
  if (x.includes('quic')) return false
301
342
  if (x.includes('p2p-circuit')) return false
343
+ if (x.includes('192.168.')) return false
344
+ if (x.includes('172.16.')) return false
302
345
  return true
303
346
  })
304
347
  // console.log('filteredMultiaddrs: ', filteredMultiaddrs)
@@ -2,13 +2,10 @@
2
2
  Use Cases library for the thisNode entity.
3
3
  */
4
4
 
5
+ // Local libraries
5
6
  import ThisNodeEntity from '../entities/this-node-entity.js'
6
7
  import Schema from './schema.js'
7
8
 
8
- // A global variable that maintains scope to the instance of this class, when
9
- // the context of 'this' is lost.
10
- let _this
11
-
12
9
  class ThisNodeUseCases {
13
10
  constructor (localConfig = {}) {
14
11
  // Dependency Injection.
@@ -31,7 +28,22 @@ class ThisNodeUseCases {
31
28
  // Additional information for connecting to the circuit relay.
32
29
  this.circuitRelayInfo = localConfig.circuitRelayInfo
33
30
 
34
- _this = this
31
+ // Initialize v1 relay list. Allows user to overwrite with local config.
32
+ this.v1Relays = []
33
+ if (localConfig.v1Relays) {
34
+ this.v1Relays = localConfig.v1Relays
35
+ // console.log('v1Relays: ', this.v1Relays)
36
+ }
37
+ console.log('this-node-use-cases.js v1Relays: ', this.v1Relays)
38
+
39
+ // Bind 'this' object to all subfunctions
40
+ this.updateUseCases = this.updateUseCases.bind(this)
41
+ this.createSelf = this.createSelf.bind(this)
42
+ this.addSubnetPeer = this.addSubnetPeer.bind(this)
43
+ this.isFreshPeer = this.isFreshPeer.bind(this)
44
+ this.refreshPeerConnections = this.refreshPeerConnections.bind(this)
45
+ this.enforceBlacklist = this.enforceBlacklist.bind(this)
46
+ this.enforceWhitelist = this.enforceWhitelist.bind(this)
35
47
  }
36
48
 
37
49
  // Update this instance with copies of the other Use Case libraries.
@@ -107,60 +119,60 @@ class ThisNodeUseCases {
107
119
  // console.log('announceObj: ', announceObj)
108
120
 
109
121
  // Exit if the announcement object is stale.
110
- if (!_this.isFreshPeer(announceObj)) return
122
+ if (!this.isFreshPeer(announceObj)) return
111
123
 
112
124
  const thisPeerId = announceObj.from.toString()
113
- _this.adapters.log.statusLog(
125
+ this.adapters.log.statusLog(
114
126
  2,
115
127
  `announcement recieved from ${thisPeerId}`
116
128
  )
117
129
 
118
- _this.adapters.log.statusLog(
130
+ this.adapters.log.statusLog(
119
131
  3,
120
132
  `announcement recieved from ${thisPeerId}: `,
121
133
  announceObj
122
134
  )
123
135
 
124
- // console.log('_this.thisNode.peerList: ', _this.thisNode.peerList)
136
+ // console.log('this.thisNode.peerList: ', this.thisNode.peerList)
125
137
 
126
138
  // Add a timestamp.
127
139
  const now = new Date()
128
140
  announceObj.data.updatedAt = now.toISOString()
129
141
 
130
142
  // If the peer is not already in the list of known peers, then add it.
131
- if (!_this.thisNode.peerList.includes(thisPeerId)) {
132
- _this.adapters.log.statusLog(1, `New peer found: ${thisPeerId}`)
143
+ if (!this.thisNode.peerList.includes(thisPeerId)) {
144
+ this.adapters.log.statusLog(1, `New peer found: ${thisPeerId}`)
133
145
 
134
146
  // Add this peer to the list of subnet peers tracked by this node.
135
- _this.thisNode.peerList.push(thisPeerId)
147
+ this.thisNode.peerList.push(thisPeerId)
136
148
 
137
149
  // Add the announcement data object to the peerData array tracked by This Node.
138
- _this.thisNode.peerData.push(announceObj)
150
+ this.thisNode.peerData.push(announceObj)
139
151
 
140
152
  // Subscribe to pubsub channel for private messages to peer.
141
153
  // Ignore any messages on this channel, since it is only used for
142
154
  // broadcasting encrypted messages to the new peer, and they will
143
155
  // respond on our own channel.
144
- _this.adapters.ipfs.ipfs.libp2p.services.pubsub.subscribe(thisPeerId)
145
- // _this.adapters.ipfs.ipfs.libp2p.services.pubsub.addEventListener('message', (msg) => {})
146
- _this.adapters.log.statusLog(2, `Subscribed to peer pubsub channel ${thisPeerId}`)
156
+ this.adapters.ipfs.ipfs.libp2p.services.pubsub.subscribe(thisPeerId)
157
+ // this.adapters.ipfs.ipfs.libp2p.services.pubsub.addEventListener('message', (msg) => {})
158
+ this.adapters.log.statusLog(2, `Subscribed to peer pubsub channel ${thisPeerId}`)
147
159
 
148
160
  // If the new peer has the isCircuitRelay flag set, then try to add it
149
161
  // to the list of Circuit Relays.
150
162
  if (announceObj.data.isCircuitRelay) {
151
- // console.log('_this.thisNode: ', _this.thisNode)
152
- await _this.useCases.relays.addRelay(thisPeerId, _this.thisNode)
163
+ // console.log('this.thisNode: ', this.thisNode)
164
+ await this.useCases.relays.addRelay(thisPeerId, this.thisNode)
153
165
  }
154
166
  } else {
155
167
  // Peer already exists in the list.
156
168
  // console.log(`debug: Updating existing peer: ${thisPeerId}`)
157
169
 
158
170
  // Get the data for this peer.
159
- let thisPeerData = _this.thisNode.peerData.filter(
171
+ let thisPeerData = this.thisNode.peerData.filter(
160
172
  x => x.from === thisPeerId
161
173
  )
162
174
  thisPeerData = thisPeerData[0]
163
- const dataIndex = _this.thisNode.peerData.indexOf(thisPeerData)
175
+ const dataIndex = this.thisNode.peerData.indexOf(thisPeerData)
164
176
  // console.log(`dataIndex: ${dataIndex}`)
165
177
 
166
178
  // If the new announceObj is older than the last announceObj, then
@@ -172,7 +184,7 @@ class ThisNodeUseCases {
172
184
  }
173
185
 
174
186
  // Replace the old data with the new data.
175
- _this.thisNode.peerData[dataIndex] = announceObj
187
+ this.thisNode.peerData[dataIndex] = announceObj
176
188
  }
177
189
 
178
190
  // console.log(`addSubnetPeer() finished processing pubsub message from ${announceObj.from}`)
@@ -181,7 +193,7 @@ class ThisNodeUseCases {
181
193
  } catch (err) {
182
194
  console.error('Error in this-node-use-cases.js/addSubnetPeer(): ', err)
183
195
 
184
- _this.adapters.log.statusLog(
196
+ this.adapters.log.statusLog(
185
197
  2,
186
198
  'Error in this-node-use-cases.js/addSubnetPeer(): ',
187
199
  err
@@ -274,10 +286,12 @@ class ThisNodeUseCases {
274
286
  const sortedRelays = this.thisNode.useCases.relays.sortRelays(relays)
275
287
  // console.log(`sortedRelays: ${JSON.stringify(sortedRelays, null, 2)}`)
276
288
 
289
+ let connected = false
290
+
277
291
  // Loop through each known circuit relay and attempt to connect to the
278
292
  // peer through a relay.
279
- for (let i = 0; i < sortedRelays.length; i++) {
280
- const thisRelay = sortedRelays[i]
293
+ for (let j = 0; j < sortedRelays.length; j++) {
294
+ const thisRelay = sortedRelays[j]
281
295
  // console.log(`thisRelay: ${JSON.stringify(thisRelay, null, 2)}`)
282
296
 
283
297
  // Generate a multiaddr for connecting to the peer through a circuit relay.
@@ -289,7 +303,7 @@ class ThisNodeUseCases {
289
303
  this.adapters.log.statusLog(2, `refreshPeerConnections() connecting to peer with this multiaddr: ${multiaddr}`)
290
304
 
291
305
  // Attempt to connect to the node through a circuit relay.
292
- const connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
306
+ connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
293
307
 
294
308
  // If the connection was successful, break out of the relay loop.
295
309
  // Otherwise try to connect through the next relay.
@@ -303,6 +317,25 @@ class ThisNodeUseCases {
303
317
  }
304
318
  }
305
319
  }
320
+
321
+ // If we could not connect to the node through the v2 Circuit Relays,
322
+ // try connecting to it through the v1 Circuit Relays.
323
+ if (!connected) {
324
+ for (let j = 0; j < this.v1Relays.length; j++) {
325
+ const thisV1Relay = this.v1Relays[j]
326
+
327
+ // Generate a multiaddr for connecting to the peer through a circuit relay.
328
+ const multiaddr = `${thisV1Relay.multiaddr}/p2p-circuit/p2p/${thisPeer}`
329
+
330
+ console.log(`refreshPeerConnections() connecting to peer through V1 Circuit Relay with this multiaddr: ${multiaddr}`)
331
+ this.adapters.log.statusLog(2, `refreshPeerConnections() connecting to peer through V1 Circuit Relay with this multiaddr: ${multiaddr}`)
332
+
333
+ // Attempt to connect to the node through a circuit relay.
334
+ connected = await this.adapters.ipfs.connectToPeer({ multiaddr })
335
+
336
+ if (connected) break
337
+ }
338
+ }
306
339
  }
307
340
 
308
341
  const now = new Date()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "helia-coord",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "A JS library for helping IPFS peers coordinate, find a common interest, and stay connected around that interest.",
5
5
  "main": "./index.js",
6
6
  "type": "module",
@@ -14,7 +14,8 @@ class UseCasesMock {
14
14
  addRelay: () => {},
15
15
  measureRelays: () => {},
16
16
  sortRelays: obj => obj,
17
- removeDuplicates: () => {}
17
+ removeDuplicates: () => {},
18
+ connectToV1Relays: async () => {}
18
19
  }
19
20
  this.pubsub = {}
20
21
  this.peer = {}
@@ -34,7 +34,8 @@ describe('#relay-Use-Cases', () => {
34
34
  uut = new RelayUseCases({
35
35
  adapters,
36
36
  statusLog: () => {
37
- }
37
+ },
38
+ v1Relays: ['fake-multiaddr']
38
39
  })
39
40
  })
40
41
 
@@ -432,7 +433,9 @@ describe('#relay-Use-Cases', () => {
432
433
  'ip4/udp/123.456.789.1/addr1',
433
434
  'ip4/quic/123.456.789.1/addr1',
434
435
  'ip4/tcp/123.456.789.1/p2p-circuit/p2p/addr1',
435
- '/ip4/addr1'
436
+ '/ip4/addr1',
437
+ '/ip4/192.168.0.1/addr1',
438
+ '/ip4/172.16.0.1/addr1'
436
439
  ],
437
440
  isCircuitRelay: true
438
441
  }
@@ -680,4 +683,31 @@ describe('#relay-Use-Cases', () => {
680
683
  }
681
684
  })
682
685
  })
686
+
687
+ describe('#connectToV1Relays', () => {
688
+ it('should connect to a list of v1 Circuit Relays', async () => {
689
+ // Mock dependencies
690
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer').resolves()
691
+
692
+ uut.v1Relays = ['fake-multiaddr']
693
+
694
+ const result = await uut.connectToV1Relays()
695
+
696
+ assert.equal(result, true)
697
+ })
698
+
699
+ it('should catch, report, and throw errors', async () => {
700
+ try {
701
+ // Force and error
702
+ uut.v1Relays = null
703
+
704
+ await uut.connectToV1Relays()
705
+
706
+ assert.fail('Unexpected code path')
707
+ } catch (err) {
708
+ // console.log(err)
709
+ assert.include(err.message, 'Cannot read')
710
+ }
711
+ })
712
+ })
683
713
  })
@@ -23,7 +23,8 @@ describe('#thisNode-Use-Cases', () => {
23
23
  sandbox = sinon.createSandbox()
24
24
 
25
25
  uut = new ThisNodeUseCases({
26
- adapters
26
+ adapters,
27
+ v1Relays: ['fake-addr']
27
28
  })
28
29
 
29
30
  const useCases = new UseCasesMock()
@@ -235,6 +236,34 @@ describe('#thisNode-Use-Cases', () => {
235
236
  assert.equal(result, true)
236
237
  })
237
238
 
239
+ it('should connect over v1 Circuit Relay if v2 Circuit Relays fail', async () => {
240
+ await uut.createSelf({ type: 'node.js' })
241
+ // Add a peer that is not in the list of connected peers.
242
+ const ipfsId = 'QmbyYXKbnAmMbMGo8LRBZ58jYs58anqUzY1m4jxDmhDsje'
243
+ uut.thisNode.peerList = [ipfsId]
244
+ uut.thisNode.peerData = [{ from: ipfsId }]
245
+
246
+ // Add a peer
247
+ await uut.addSubnetPeer(mockData.announceObj)
248
+
249
+ // Force circuit relay to be used.
250
+ uut.thisNode.relayData = mockData.mockRelayData
251
+
252
+ // Mock dependencies
253
+ sandbox.stub(uut.adapters.ipfs, 'getPeers').resolves(mockData.swarmPeers)
254
+ sandbox.stub(uut, 'isFreshPeer').returns(true)
255
+ sandbox.stub(uut.adapters.ipfs, 'connectToPeer')
256
+ .onCall(0).resolves(false)
257
+ .onCall(1).resolves(true)
258
+
259
+ uut.v1Relays = ['fake-v1-relay']
260
+
261
+ // Connect to that peer.
262
+ const result = await uut.refreshPeerConnections()
263
+
264
+ assert.equal(result, true)
265
+ })
266
+
238
267
  it('should skip if peer is stale', async () => {
239
268
  await uut.createSelf({ type: 'node.js' })
240
269
  // Add a peer that is not in the list of connected peers.