@libp2p/autonat 1.0.21 → 1.0.22

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/src/autonat.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { CodeError, ERR_TIMEOUT, setMaxListeners } from '@libp2p/interface'
2
2
  import { peerIdFromBytes } from '@libp2p/peer-id'
3
- import { createEd25519PeerId } from '@libp2p/peer-id-factory'
4
3
  import { isPrivateIp } from '@libp2p/utils/private-ip'
5
4
  import { multiaddr, protocols } from '@multiformats/multiaddr'
6
5
  import first from 'it-first'
@@ -15,7 +14,7 @@ import {
15
14
  } from './constants.js'
16
15
  import { Message } from './pb/index.js'
17
16
  import type { AutoNATComponents, AutoNATServiceInit } from './index.js'
18
- import type { Logger, Connection, PeerId, PeerInfo, Startable } from '@libp2p/interface'
17
+ import type { Logger, Connection, PeerId, PeerInfo, Startable, AbortOptions } from '@libp2p/interface'
19
18
  import type { IncomingStreamData } from '@libp2p/interface-internal'
20
19
 
21
20
  // if more than 3 peers manage to dial us on what we believe to be our external
@@ -95,9 +94,6 @@ export class AutoNATService implements Startable {
95
94
  // appearing in the console
96
95
  setMaxListeners(Infinity, signal)
97
96
 
98
- const ourHosts = this.components.addressManager.getAddresses()
99
- .map(ma => ma.toOptions().host)
100
-
101
97
  try {
102
98
  const self = this
103
99
 
@@ -138,193 +134,188 @@ export class AutoNATService implements Startable {
138
134
  return
139
135
  }
140
136
 
141
- const dialRequest = request.dial
142
-
143
- if (dialRequest == null) {
144
- self.log.error('dial was missing from message')
137
+ yield Message.encode(await self.handleAutonatMessage(request, data.connection, {
138
+ signal
139
+ }))
140
+ },
141
+ (source) => lp.encode(source),
142
+ data.stream
143
+ )
144
+ } catch (err) {
145
+ this.log.error('error handling incoming autonat stream', err)
146
+ } finally {
147
+ signal.removeEventListener('abort', onAbort)
148
+ }
149
+ }
145
150
 
146
- yield Message.encode({
147
- type: Message.MessageType.DIAL_RESPONSE,
148
- dialResponse: {
149
- status: Message.ResponseStatus.E_BAD_REQUEST,
150
- statusText: 'No Dial message found in message'
151
- }
152
- })
151
+ _verifyExternalAddresses (): void {
152
+ void this.verifyExternalAddresses()
153
+ .catch(err => {
154
+ this.log.error('error verifying external address', err)
155
+ })
156
+ }
153
157
 
154
- return
155
- }
158
+ private async handleAutonatMessage (message: Message, connection: Connection, options?: AbortOptions): Promise<Message> {
159
+ const ourHosts = this.components.addressManager.getAddresses()
160
+ .map(ma => ma.toOptions().host)
156
161
 
157
- let peerId: PeerId
158
- const peer = dialRequest.peer
162
+ const dialRequest = message.dial
159
163
 
160
- if (peer == null || peer.id == null) {
161
- self.log.error('PeerId missing from message')
164
+ if (dialRequest == null) {
165
+ this.log.error('dial was missing from message')
162
166
 
163
- yield Message.encode({
164
- type: Message.MessageType.DIAL_RESPONSE,
165
- dialResponse: {
166
- status: Message.ResponseStatus.E_BAD_REQUEST,
167
- statusText: 'missing peer info'
168
- }
169
- })
167
+ return {
168
+ type: Message.MessageType.DIAL_RESPONSE,
169
+ dialResponse: {
170
+ status: Message.ResponseStatus.E_BAD_REQUEST,
171
+ statusText: 'No Dial message found in message'
172
+ }
173
+ }
174
+ }
170
175
 
171
- return
172
- }
176
+ let peerId: PeerId
177
+ const peer = dialRequest.peer
173
178
 
174
- try {
175
- peerId = peerIdFromBytes(peer.id)
176
- } catch (err) {
177
- self.log.error('invalid PeerId', err)
179
+ if (peer == null || peer.id == null) {
180
+ this.log.error('PeerId missing from message')
178
181
 
179
- yield Message.encode({
180
- type: Message.MessageType.DIAL_RESPONSE,
181
- dialResponse: {
182
- status: Message.ResponseStatus.E_BAD_REQUEST,
183
- statusText: 'bad peer id'
184
- }
185
- })
182
+ return {
183
+ type: Message.MessageType.DIAL_RESPONSE,
184
+ dialResponse: {
185
+ status: Message.ResponseStatus.E_BAD_REQUEST,
186
+ statusText: 'missing peer info'
187
+ }
188
+ }
189
+ }
186
190
 
187
- return
188
- }
191
+ try {
192
+ peerId = peerIdFromBytes(peer.id)
193
+ } catch (err) {
194
+ this.log.error('invalid PeerId', err)
189
195
 
190
- self.log('incoming request from %p', peerId)
196
+ return {
197
+ type: Message.MessageType.DIAL_RESPONSE,
198
+ dialResponse: {
199
+ status: Message.ResponseStatus.E_BAD_REQUEST,
200
+ statusText: 'bad peer id'
201
+ }
202
+ }
203
+ }
191
204
 
192
- // reject any dial requests that arrive via relays
193
- if (!data.connection.remotePeer.equals(peerId)) {
194
- self.log('target peer %p did not equal sending peer %p', peerId, data.connection.remotePeer)
205
+ this.log('incoming request from %p', peerId)
195
206
 
196
- yield Message.encode({
197
- type: Message.MessageType.DIAL_RESPONSE,
198
- dialResponse: {
199
- status: Message.ResponseStatus.E_BAD_REQUEST,
200
- statusText: 'peer id mismatch'
201
- }
202
- })
207
+ // reject any dial requests that arrive via relays
208
+ if (!connection.remotePeer.equals(peerId)) {
209
+ this.log('target peer %p did not equal sending peer %p', peerId, connection.remotePeer)
203
210
 
204
- return
205
- }
211
+ return {
212
+ type: Message.MessageType.DIAL_RESPONSE,
213
+ dialResponse: {
214
+ status: Message.ResponseStatus.E_BAD_REQUEST,
215
+ statusText: 'peer id mismatch'
216
+ }
217
+ }
218
+ }
206
219
 
207
- // get a list of multiaddrs to dial
208
- const multiaddrs = peer.addrs
209
- .map(buf => multiaddr(buf))
210
- .filter(ma => {
211
- const isFromSameHost = ma.toOptions().host === data.connection.remoteAddr.toOptions().host
220
+ // get a list of multiaddrs to dial
221
+ const multiaddrs = peer.addrs
222
+ .map(buf => multiaddr(buf))
223
+ .filter(ma => {
224
+ const isFromSameHost = ma.toOptions().host === connection.remoteAddr.toOptions().host
212
225
 
213
- self.log.trace('request to dial %a was sent from %a is same host %s', ma, data.connection.remoteAddr, isFromSameHost)
214
- // skip any Multiaddrs where the target node's IP does not match the sending node's IP
215
- return isFromSameHost
216
- })
217
- .filter(ma => {
218
- const host = ma.toOptions().host
219
- const isPublicIp = !(isPrivateIp(host) ?? false)
226
+ this.log.trace('request to dial %a was sent from %a is same host %s', ma, connection.remoteAddr, isFromSameHost)
227
+ // skip any Multiaddrs where the target node's IP does not match the sending node's IP
228
+ return isFromSameHost
229
+ })
230
+ .filter(ma => {
231
+ const host = ma.toOptions().host
232
+ const isPublicIp = !(isPrivateIp(host) ?? false)
220
233
 
221
- self.log.trace('host %s was public %s', host, isPublicIp)
222
- // don't try to dial private addresses
223
- return isPublicIp
224
- })
225
- .filter(ma => {
226
- const host = ma.toOptions().host
227
- const isNotOurHost = !ourHosts.includes(host)
234
+ this.log.trace('host %s was public %s', host, isPublicIp)
235
+ // don't try to dial private addresses
236
+ return isPublicIp
237
+ })
238
+ .filter(ma => {
239
+ const host = ma.toOptions().host
240
+ const isNotOurHost = !ourHosts.includes(host)
228
241
 
229
- self.log.trace('host %s was not our host %s', host, isNotOurHost)
230
- // don't try to dial nodes on the same host as us
231
- return isNotOurHost
232
- })
233
- .filter(ma => {
234
- const isSupportedTransport = Boolean(self.components.transportManager.dialTransportForMultiaddr(ma))
242
+ this.log.trace('host %s was not our host %s', host, isNotOurHost)
243
+ // don't try to dial nodes on the same host as us
244
+ return isNotOurHost
245
+ })
246
+ .filter(ma => {
247
+ const isSupportedTransport = Boolean(this.components.transportManager.dialTransportForMultiaddr(ma))
235
248
 
236
- self.log.trace('transport for %a is supported %s', ma, isSupportedTransport)
237
- // skip any Multiaddrs that have transports we do not support
238
- return isSupportedTransport
239
- })
240
- .map(ma => {
241
- if (ma.getPeerId() == null) {
242
- // make sure we have the PeerId as part of the Multiaddr
243
- ma = ma.encapsulate(`/p2p/${peerId.toString()}`)
244
- }
249
+ this.log.trace('transport for %a is supported %s', ma, isSupportedTransport)
250
+ // skip any Multiaddrs that have transports we do not support
251
+ return isSupportedTransport
252
+ })
253
+ .map(ma => {
254
+ if (ma.getPeerId() == null) {
255
+ // make sure we have the PeerId as part of the Multiaddr
256
+ ma = ma.encapsulate(`/p2p/${peerId.toString()}`)
257
+ }
245
258
 
246
- return ma
247
- })
259
+ return ma
260
+ })
248
261
 
249
- // make sure we have something to dial
250
- if (multiaddrs.length === 0) {
251
- self.log('no valid multiaddrs for %p in message', peerId)
262
+ // make sure we have something to dial
263
+ if (multiaddrs.length === 0) {
264
+ this.log('no valid multiaddrs for %p in message', peerId)
252
265
 
253
- yield Message.encode({
254
- type: Message.MessageType.DIAL_RESPONSE,
255
- dialResponse: {
256
- status: Message.ResponseStatus.E_DIAL_REFUSED,
257
- statusText: 'no dialable addresses'
258
- }
259
- })
266
+ return {
267
+ type: Message.MessageType.DIAL_RESPONSE,
268
+ dialResponse: {
269
+ status: Message.ResponseStatus.E_DIAL_REFUSED,
270
+ statusText: 'no dialable addresses'
271
+ }
272
+ }
273
+ }
260
274
 
261
- return
262
- }
275
+ this.log('dial multiaddrs %s for peer %p', multiaddrs.map(ma => ma.toString()).join(', '), peerId)
263
276
 
264
- self.log('dial multiaddrs %s for peer %p', multiaddrs.map(ma => ma.toString()).join(', '), peerId)
277
+ let errorMessage = ''
278
+ let lastMultiaddr = multiaddrs[0]
265
279
 
266
- let errorMessage = ''
267
- let lastMultiaddr = multiaddrs[0]
280
+ for await (const multiaddr of multiaddrs) {
281
+ let connection: Connection | undefined
282
+ lastMultiaddr = multiaddr
268
283
 
269
- for await (const multiaddr of multiaddrs) {
270
- let connection: Connection | undefined
271
- lastMultiaddr = multiaddr
284
+ try {
285
+ connection = await this.components.connectionManager.openConnection(multiaddr, options)
272
286
 
273
- try {
274
- connection = await self.components.connectionManager.openConnection(multiaddr, {
275
- signal
276
- })
287
+ if (!connection.remoteAddr.equals(multiaddr)) {
288
+ this.log.error('tried to dial %a but dialed %a', multiaddr, connection.remoteAddr)
289
+ throw new Error('Unexpected remote address')
290
+ }
277
291
 
278
- if (!connection.remoteAddr.equals(multiaddr)) {
279
- self.log.error('tried to dial %a but dialed %a', multiaddr, connection.remoteAddr)
280
- throw new Error('Unexpected remote address')
281
- }
292
+ this.log('Success %p', peerId)
282
293
 
283
- self.log('Success %p', peerId)
284
-
285
- yield Message.encode({
286
- type: Message.MessageType.DIAL_RESPONSE,
287
- dialResponse: {
288
- status: Message.ResponseStatus.OK,
289
- addr: connection.remoteAddr.decapsulateCode(protocols('p2p').code).bytes
290
- }
291
- })
292
-
293
- return
294
- } catch (err: any) {
295
- self.log('could not dial %p', peerId, err)
296
- errorMessage = err.message
297
- } finally {
298
- if (connection != null) {
299
- await connection.close()
300
- }
301
- }
294
+ return {
295
+ type: Message.MessageType.DIAL_RESPONSE,
296
+ dialResponse: {
297
+ status: Message.ResponseStatus.OK,
298
+ addr: connection.remoteAddr.decapsulateCode(protocols('p2p').code).bytes
302
299
  }
303
-
304
- yield Message.encode({
305
- type: Message.MessageType.DIAL_RESPONSE,
306
- dialResponse: {
307
- status: Message.ResponseStatus.E_DIAL_ERROR,
308
- statusText: errorMessage,
309
- addr: lastMultiaddr.bytes
310
- }
311
- })
312
- },
313
- (source) => lp.encode(source),
314
- data.stream
315
- )
316
- } catch (err) {
317
- this.log.error('error handling incoming autonat stream', err)
318
- } finally {
319
- signal.removeEventListener('abort', onAbort)
300
+ }
301
+ } catch (err: any) {
302
+ this.log('could not dial %p', peerId, err)
303
+ errorMessage = err.message
304
+ } finally {
305
+ if (connection != null) {
306
+ await connection.close()
307
+ }
308
+ }
320
309
  }
321
- }
322
310
 
323
- _verifyExternalAddresses (): void {
324
- void this.verifyExternalAddresses()
325
- .catch(err => {
326
- this.log.error('error verifying external address', err)
327
- })
311
+ return {
312
+ type: Message.MessageType.DIAL_RESPONSE,
313
+ dialResponse: {
314
+ status: Message.ResponseStatus.E_DIAL_ERROR,
315
+ statusText: errorMessage,
316
+ addr: lastMultiaddr.bytes
317
+ }
318
+ }
328
319
  }
329
320
 
330
321
  /**
@@ -374,9 +365,6 @@ export class AutoNATService implements Startable {
374
365
  }
375
366
  }
376
367
  })
377
- // find some random peers
378
- const randomPeer = await createEd25519PeerId()
379
- const randomCid = randomPeer.toBytes()
380
368
 
381
369
  const results: Record<string, { success: number, failure: number }> = {}
382
370
  const networkSegments: string[] = []
@@ -449,7 +437,8 @@ export class AutoNATService implements Startable {
449
437
  }
450
438
  }
451
439
 
452
- for await (const dialResponse of parallel(map(this.components.peerRouting.getClosestPeers(randomCid, {
440
+ // find some random peers
441
+ for await (const dialResponse of parallel(map(this.components.randomWalk.walk({
453
442
  signal
454
443
  }), (peer) => async () => verifyAddress(peer)), {
455
444
  concurrency: REQUIRED_SUCCESSFUL_DIALS
package/src/index.ts CHANGED
@@ -31,8 +31,8 @@
31
31
  */
32
32
 
33
33
  import { AutoNATService } from './autonat.js'
34
- import type { ComponentLogger, PeerId, PeerRouting } from '@libp2p/interface'
35
- import type { AddressManager, ConnectionManager, Registrar, TransportManager } from '@libp2p/interface-internal'
34
+ import type { ComponentLogger, PeerId } from '@libp2p/interface'
35
+ import type { AddressManager, ConnectionManager, RandomWalk, Registrar, TransportManager } from '@libp2p/interface-internal'
36
36
 
37
37
  export interface AutoNATServiceInit {
38
38
  /**
@@ -72,8 +72,8 @@ export interface AutoNATComponents {
72
72
  transportManager: TransportManager
73
73
  peerId: PeerId
74
74
  connectionManager: ConnectionManager
75
- peerRouting: PeerRouting
76
75
  logger: ComponentLogger
76
+ randomWalk: RandomWalk
77
77
  }
78
78
 
79
79
  export function autoNAT (init: AutoNATServiceInit = {}): (components: AutoNATComponents) => unknown {