@libp2p/autonat 2.0.12-b248eefc0 → 2.0.12-d19974d93

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.
@@ -1,30 +1,32 @@
1
- import { AbortError, serviceCapabilities, setMaxListeners } from '@libp2p/interface';
1
+ import { serviceCapabilities, serviceDependencies, setMaxListeners } from '@libp2p/interface';
2
+ import { peerSet } from '@libp2p/peer-collections';
2
3
  import { peerIdFromMultihash } from '@libp2p/peer-id';
3
- import { isPrivateIp } from '@libp2p/utils/private-ip';
4
+ import { createScalableCuckooFilter } from '@libp2p/utils/filters';
5
+ import { isPrivate } from '@libp2p/utils/multiaddr/is-private';
6
+ import { PeerQueue } from '@libp2p/utils/peer-queue';
7
+ import { repeatingTask } from '@libp2p/utils/repeating-task';
4
8
  import { multiaddr, protocols } from '@multiformats/multiaddr';
5
- import first from 'it-first';
6
- import * as lp from 'it-length-prefixed';
7
- import map from 'it-map';
8
- import parallel from 'it-parallel';
9
- import { pipe } from 'it-pipe';
9
+ import { anySignal } from 'any-signal';
10
+ import { pbStream } from 'it-protobuf-stream';
10
11
  import * as Digest from 'multiformats/hashes/digest';
11
- import { MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS, PROTOCOL_NAME, PROTOCOL_PREFIX, PROTOCOL_VERSION, REFRESH_INTERVAL, STARTUP_DELAY, TIMEOUT } from './constants.js';
12
+ import { MAX_INBOUND_STREAMS, MAX_OUTBOUND_STREAMS, PROTOCOL_NAME, PROTOCOL_PREFIX, PROTOCOL_VERSION, TIMEOUT } from './constants.js';
12
13
  import { Message } from './pb/index.js';
13
14
  // if more than 3 peers manage to dial us on what we believe to be our external
14
15
  // IP then we are convinced that it is, in fact, our external IP
15
- // https://github.com/libp2p/specs/blob/master/autonat/README.md#autonat-protocol
16
+ // https://github.com/libp2p/specs/blob/master/autonat/autonat-v1.md#autonat-protocol
16
17
  const REQUIRED_SUCCESSFUL_DIALS = 4;
17
18
  export class AutoNATService {
18
19
  components;
19
- startupDelay;
20
- refreshInterval;
21
20
  protocol;
22
21
  timeout;
23
22
  maxInboundStreams;
24
23
  maxOutboundStreams;
25
- verifyAddressTimeout;
26
24
  started;
27
25
  log;
26
+ topologyId;
27
+ dialResults;
28
+ findPeers;
29
+ addressFilter;
28
30
  constructor(components, init) {
29
31
  this.components = components;
30
32
  this.log = components.logger.forComponent('libp2p:autonat');
@@ -33,14 +35,19 @@ export class AutoNATService {
33
35
  this.timeout = init.timeout ?? TIMEOUT;
34
36
  this.maxInboundStreams = init.maxInboundStreams ?? MAX_INBOUND_STREAMS;
35
37
  this.maxOutboundStreams = init.maxOutboundStreams ?? MAX_OUTBOUND_STREAMS;
36
- this.startupDelay = init.startupDelay ?? STARTUP_DELAY;
37
- this.refreshInterval = init.refreshInterval ?? REFRESH_INTERVAL;
38
- this._verifyExternalAddresses = this._verifyExternalAddresses.bind(this);
38
+ this.dialResults = new Map();
39
+ this.findPeers = repeatingTask(this.findRandomPeers.bind(this), 60_000);
40
+ this.addressFilter = createScalableCuckooFilter(1024);
39
41
  }
40
42
  [Symbol.toStringTag] = '@libp2p/autonat';
41
43
  [serviceCapabilities] = [
42
44
  '@libp2p/autonat'
43
45
  ];
46
+ get [serviceDependencies]() {
47
+ return [
48
+ '@libp2p/identify'
49
+ ];
50
+ }
44
51
  isStarted() {
45
52
  return this.started;
46
53
  }
@@ -51,79 +58,94 @@ export class AutoNATService {
51
58
  await this.components.registrar.handle(this.protocol, (data) => {
52
59
  void this.handleIncomingAutonatStream(data)
53
60
  .catch(err => {
54
- this.log.error('error handling incoming autonat stream', err);
61
+ this.log.error('error handling incoming autonat stream - %e', err);
55
62
  });
56
63
  }, {
57
64
  maxInboundStreams: this.maxInboundStreams,
58
65
  maxOutboundStreams: this.maxOutboundStreams
59
66
  });
60
- this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.startupDelay);
67
+ this.topologyId = await this.components.registrar.register(this.protocol, {
68
+ onConnect: (peerId, connection) => {
69
+ this.verifyExternalAddresses(connection)
70
+ .catch(err => {
71
+ this.log.error('could not verify addresses - %e', err);
72
+ });
73
+ }
74
+ });
75
+ this.findPeers.start();
61
76
  this.started = true;
62
77
  }
63
78
  async stop() {
64
79
  await this.components.registrar.unhandle(this.protocol);
65
- clearTimeout(this.verifyAddressTimeout);
80
+ if (this.topologyId != null) {
81
+ await this.components.registrar.unhandle(this.topologyId);
82
+ }
83
+ this.dialResults.clear();
84
+ this.findPeers.stop();
66
85
  this.started = false;
67
86
  }
87
+ allAddressesAreVerified() {
88
+ return this.components.addressManager.getAddressesWithMetadata().every(addr => addr.verified);
89
+ }
90
+ async findRandomPeers(options) {
91
+ // skip if all addresses are verified
92
+ if (this.allAddressesAreVerified()) {
93
+ return;
94
+ }
95
+ const signal = anySignal([
96
+ AbortSignal.timeout(10_000),
97
+ options?.signal
98
+ ]);
99
+ // spend a few seconds finding random peers - dial them which will run
100
+ // identify to trigger the topology callbacks and run AutoNAT
101
+ try {
102
+ this.log('starting random walk to find peers to run AutoNAT');
103
+ for await (const peer of this.components.randomWalk.walk({ signal })) {
104
+ if (!(await this.components.connectionManager.isDialable(peer.multiaddrs))) {
105
+ this.log.trace('random peer %p was not dialable %s', peer.id, peer.multiaddrs.map(ma => ma.toString()).join(', '));
106
+ // skip peers we can't dial
107
+ continue;
108
+ }
109
+ try {
110
+ this.log.trace('dial random peer %p', peer.id);
111
+ await this.components.connectionManager.openConnection(peer.multiaddrs, {
112
+ signal
113
+ });
114
+ }
115
+ catch { }
116
+ if (this.allAddressesAreVerified()) {
117
+ this.log('stopping random walk, all addresses are verified');
118
+ return;
119
+ }
120
+ }
121
+ }
122
+ catch { }
123
+ }
68
124
  /**
69
125
  * Handle an incoming AutoNAT request
70
126
  */
71
127
  async handleIncomingAutonatStream(data) {
72
128
  const signal = AbortSignal.timeout(this.timeout);
73
- const onAbort = () => {
74
- data.stream.abort(new AbortError());
75
- };
76
- signal.addEventListener('abort', onAbort, { once: true });
77
- // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning
78
- // appearing in the console
79
129
  setMaxListeners(Infinity, signal);
130
+ const messages = pbStream(data.stream).pb(Message);
80
131
  try {
81
- const self = this;
82
- await pipe(data.stream, (source) => lp.decode(source), async function* (stream) {
83
- const buf = await first(stream);
84
- if (buf == null) {
85
- self.log('no message received');
86
- yield Message.encode({
87
- type: Message.MessageType.DIAL_RESPONSE,
88
- dialResponse: {
89
- status: Message.ResponseStatus.E_BAD_REQUEST,
90
- statusText: 'No message was sent'
91
- }
92
- });
93
- return;
94
- }
95
- let request;
96
- try {
97
- request = Message.decode(buf);
98
- }
99
- catch (err) {
100
- self.log.error('could not decode message', err);
101
- yield Message.encode({
102
- type: Message.MessageType.DIAL_RESPONSE,
103
- dialResponse: {
104
- status: Message.ResponseStatus.E_BAD_REQUEST,
105
- statusText: 'Could not decode message'
106
- }
107
- });
108
- return;
109
- }
110
- yield Message.encode(await self.handleAutonatMessage(request, data.connection, {
111
- signal
112
- }));
113
- }, (source) => lp.encode(source), data.stream);
132
+ const request = await messages.read({
133
+ signal
134
+ });
135
+ const response = await this.handleAutonatMessage(request, data.connection, {
136
+ signal
137
+ });
138
+ await messages.write(response, {
139
+ signal
140
+ });
141
+ await messages.unwrap().unwrap().close({
142
+ signal
143
+ });
114
144
  }
115
145
  catch (err) {
116
- this.log.error('error handling incoming autonat stream', err);
146
+ this.log.error('error handling incoming autonat stream - %e', err);
147
+ data.stream.abort(err);
117
148
  }
118
- finally {
119
- signal.removeEventListener('abort', onAbort);
120
- }
121
- }
122
- _verifyExternalAddresses() {
123
- void this.verifyExternalAddresses()
124
- .catch(err => {
125
- this.log.error('error verifying external address', err);
126
- });
127
149
  }
128
150
  async handleAutonatMessage(message, connection, options) {
129
151
  const ourHosts = this.components.addressManager.getAddresses()
@@ -156,7 +178,7 @@ export class AutoNATService {
156
178
  peerId = peerIdFromMultihash(digest);
157
179
  }
158
180
  catch (err) {
159
- this.log.error('invalid PeerId', err);
181
+ this.log.error('invalid PeerId - %e', err);
160
182
  return {
161
183
  type: Message.MessageType.DIAL_RESPONSE,
162
184
  dialResponse: {
@@ -187,9 +209,8 @@ export class AutoNATService {
187
209
  return isFromSameHost;
188
210
  })
189
211
  .filter(ma => {
190
- const host = ma.toOptions().host;
191
- const isPublicIp = !(isPrivateIp(host) ?? false);
192
- this.log.trace('host %s was public %s', host, isPublicIp);
212
+ const isPublicIp = !isPrivate(ma);
213
+ this.log.trace('%a was public %s', ma, isPublicIp);
193
214
  // don't try to dial private addresses
194
215
  return isPublicIp;
195
216
  })
@@ -236,7 +257,7 @@ export class AutoNATService {
236
257
  this.log.error('tried to dial %a but dialed %a', multiaddr, connection.remoteAddr);
237
258
  throw new Error('Unexpected remote address');
238
259
  }
239
- this.log('Success %p', peerId);
260
+ this.log('successfully dialed %p via %a', peerId, multiaddr);
240
261
  return {
241
262
  type: Message.MessageType.DIAL_RESPONSE,
242
263
  dialResponse: {
@@ -246,7 +267,7 @@ export class AutoNATService {
246
267
  };
247
268
  }
248
269
  catch (err) {
249
- this.log('could not dial %p', peerId, err);
270
+ this.log('could not dial %p - %e', peerId, err);
250
271
  errorMessage = err.message;
251
272
  }
252
273
  finally {
@@ -264,157 +285,234 @@ export class AutoNATService {
264
285
  }
265
286
  };
266
287
  }
288
+ /**
289
+ * The AutoNAT v1 server is only required to send us the address that it
290
+ * dialed successfully.
291
+ *
292
+ * When addresses fail, it can be because they are NATed, or because the peer
293
+ * did't support the transport, we have no way of knowing, so just send them
294
+ * one address so we can treat the response as:
295
+ *
296
+ * - OK - the dial request worked and the address is not NATed
297
+ * - E_DIAL_ERROR - the dial request failed and the address may be NATed
298
+ * - E_DIAL_REFUSED/E_BAD_REQUEST/E_INTERNAL_ERROR - the remote didn't dial the address
299
+ */
300
+ getFirstUnverifiedMultiaddr(segment) {
301
+ const addrs = this.components.addressManager.getAddressesWithMetadata()
302
+ .sort((a, b) => {
303
+ // sort addresses, prioritize DNS/IP mapped addresses over observed ones
304
+ if (a.type === 'dns-mapping') {
305
+ return -1;
306
+ }
307
+ if (b.type === 'dns-mapping') {
308
+ return 1;
309
+ }
310
+ if (a.type === 'ip-mapping') {
311
+ return -1;
312
+ }
313
+ if (b.type === 'ip-mapping') {
314
+ return 1;
315
+ }
316
+ return 0;
317
+ })
318
+ .filter(addr => {
319
+ if (addr.verified && addr.expires > Date.now()) {
320
+ // skip verified addresses within their TTL
321
+ return false;
322
+ }
323
+ if (isPrivate(addr.multiaddr)) {
324
+ // skip private addresses
325
+ return false;
326
+ }
327
+ return true;
328
+ });
329
+ for (const addr of addrs) {
330
+ const addrString = addr.multiaddr.toString();
331
+ let results = this.dialResults.get(addrString);
332
+ if (results != null) {
333
+ if (results.networkSegments.includes(segment)) {
334
+ this.log.trace('%a already has a network segment result from %s', results.multiaddr, segment);
335
+ // skip this address if we already have a dial result from the
336
+ // network segment the peer is in
337
+ continue;
338
+ }
339
+ if (results.queue.size > 10) {
340
+ this.log.trace('%a already has enough peers queued', results.multiaddr);
341
+ // already have enough peers verifying this address, skip on to the
342
+ // next one
343
+ continue;
344
+ }
345
+ }
346
+ // will include this multiaddr, ensure we have a results object
347
+ if (results == null) {
348
+ const needsRevalidating = addr.expires < Date.now();
349
+ // allow re-validating addresses that worked previously
350
+ if (needsRevalidating) {
351
+ this.addressFilter.remove?.(addrString);
352
+ }
353
+ if (this.addressFilter.has(addrString)) {
354
+ continue;
355
+ }
356
+ // only try to validate the address once
357
+ this.addressFilter.add(addrString);
358
+ this.log.trace('creating dial result %s %s', needsRevalidating ? 'to revalidate' : 'for', addrString);
359
+ results = {
360
+ multiaddr: addr.multiaddr,
361
+ success: 0,
362
+ failure: 0,
363
+ networkSegments: [],
364
+ verifyingPeers: peerSet(),
365
+ queue: new PeerQueue({
366
+ concurrency: 3,
367
+ maxSize: 50
368
+ })
369
+ };
370
+ this.dialResults.set(addrString, results);
371
+ }
372
+ return results;
373
+ }
374
+ }
375
+ /**
376
+ * Removes any multiaddr result objects created for old multiaddrs that we are
377
+ * no longer waiting on
378
+ */
379
+ removeOutdatedMultiaddrResults() {
380
+ const unverifiedMultiaddrs = new Set(this.components.addressManager.getAddressesWithMetadata()
381
+ .filter(({ verified }) => !verified)
382
+ .map(({ multiaddr }) => multiaddr.toString()));
383
+ for (const multiaddr of this.dialResults.keys()) {
384
+ if (!unverifiedMultiaddrs.has(multiaddr)) {
385
+ this.log.trace('remove results for %a', multiaddr);
386
+ this.dialResults.delete(multiaddr);
387
+ }
388
+ }
389
+ }
267
390
  /**
268
391
  * Our multicodec topology noticed a new peer that supports autonat
269
392
  */
270
- async verifyExternalAddresses() {
271
- clearTimeout(this.verifyAddressTimeout);
272
- // Do not try to push if we are not running
393
+ async verifyExternalAddresses(connection) {
394
+ // do nothing if we are not running
273
395
  if (!this.isStarted()) {
274
396
  return;
275
397
  }
276
- const addressManager = this.components.addressManager;
277
- const multiaddrs = addressManager.getObservedAddrs()
278
- .filter(ma => {
279
- const options = ma.toOptions();
280
- return !(isPrivateIp(options.host) ?? false);
281
- });
282
- if (multiaddrs.length === 0) {
283
- this.log('no public addresses found, not requesting verification');
284
- this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.refreshInterval);
398
+ // perform cleanup
399
+ this.removeOutdatedMultiaddrResults();
400
+ // get multiaddrs this peer is eligible to verify
401
+ const segment = this.getNetworkSegment(connection.remoteAddr);
402
+ let results = this.getFirstUnverifiedMultiaddr(segment);
403
+ if (results == null) {
404
+ this.log.trace('no unverified public addresses found for peer %p to verify, not requesting verification', connection.remotePeer);
285
405
  return;
286
406
  }
287
- const signal = AbortSignal.timeout(this.timeout);
288
- // this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning
289
- // appearing in the console
290
- setMaxListeners(Infinity, signal);
291
- const self = this;
292
- try {
293
- this.log('verify multiaddrs %s', multiaddrs.map(ma => ma.toString()).join(', '));
294
- const request = Message.encode({
295
- type: Message.MessageType.DIAL,
296
- dial: {
297
- peer: {
298
- id: this.components.peerId.toMultihash().bytes,
299
- addrs: multiaddrs.map(map => map.bytes)
300
- }
301
- }
407
+ results.queue.add(async (options) => {
408
+ results = this.dialResults.get(options.multiaddr.toString());
409
+ if (results == null) {
410
+ this.log('%a was verified while %p was queued', options.multiaddr, connection.remotePeer);
411
+ return;
412
+ }
413
+ const signal = AbortSignal.timeout(this.timeout);
414
+ setMaxListeners(Infinity, signal);
415
+ this.log.trace('asking %p to verify multiaddr %s', connection.remotePeer, options.multiaddr);
416
+ const stream = await connection.newStream(this.protocol, {
417
+ signal
302
418
  });
303
- const results = {};
304
- const networkSegments = [];
305
- const verifyAddress = async (peer) => {
306
- let onAbort = () => { };
307
- try {
308
- this.log('asking %p to verify multiaddr', peer.id);
309
- const connection = await self.components.connectionManager.openConnection(peer.id, {
310
- signal
311
- });
312
- const stream = await connection.newStream(this.protocol, {
313
- signal
314
- });
315
- onAbort = () => { stream.abort(new AbortError()); };
316
- signal.addEventListener('abort', onAbort, { once: true });
317
- const buf = await pipe([request], (source) => lp.encode(source), stream, (source) => lp.decode(source), async (stream) => first(stream));
318
- if (buf == null) {
319
- this.log('no response received from %p', connection.remotePeer);
320
- return undefined;
321
- }
322
- const response = Message.decode(buf);
323
- if (response.type !== Message.MessageType.DIAL_RESPONSE || response.dialResponse == null) {
324
- this.log('invalid autonat response from %p', connection.remotePeer);
325
- return undefined;
326
- }
327
- if (response.dialResponse.status === Message.ResponseStatus.OK) {
328
- // make sure we use different network segments
329
- const options = connection.remoteAddr.toOptions();
330
- let segment;
331
- if (options.family === 4) {
332
- const octets = options.host.split('.');
333
- segment = octets[0];
334
- }
335
- else if (options.family === 6) {
336
- const octets = options.host.split(':');
337
- segment = octets[0];
338
- }
339
- else {
340
- this.log('remote address "%s" was not IP4 or IP6?', options.host);
341
- return undefined;
342
- }
343
- if (networkSegments.includes(segment)) {
344
- this.log('already have response from network segment %d - %s', segment, options.host);
345
- return undefined;
419
+ try {
420
+ const messages = pbStream(stream).pb(Message);
421
+ const [, response] = await Promise.all([
422
+ messages.write({
423
+ type: Message.MessageType.DIAL,
424
+ dial: {
425
+ peer: {
426
+ id: this.components.peerId.toMultihash().bytes,
427
+ addrs: [options.multiaddr.bytes]
428
+ }
346
429
  }
347
- networkSegments.push(segment);
348
- }
349
- return response.dialResponse;
430
+ }, { signal }),
431
+ messages.read({ signal })
432
+ ]);
433
+ if (response.type !== Message.MessageType.DIAL_RESPONSE || response.dialResponse == null) {
434
+ this.log('invalid autonat response from %p - %j', connection.remotePeer, response);
435
+ return;
350
436
  }
351
- catch (err) {
352
- this.log.error('error asking remote to verify multiaddr', err);
437
+ const status = response.dialResponse.status;
438
+ this.log.trace('autonat response from %p for %a is %s', connection.remotePeer, options.multiaddr, status);
439
+ if (status !== Message.ResponseStatus.OK && status !== Message.ResponseStatus.E_DIAL_ERROR) {
440
+ return;
353
441
  }
354
- finally {
355
- signal.removeEventListener('abort', onAbort);
442
+ results = this.dialResults.get(options.multiaddr.toString());
443
+ if (results == null) {
444
+ this.log.trace('peer reported %a as %s but there is no result object', options.multiaddr, response.dialResponse.status);
445
+ return;
356
446
  }
357
- };
358
- // find some random peers
359
- for await (const dialResponse of parallel(map(this.components.randomWalk.walk({
360
- signal
361
- }), (peer) => async () => verifyAddress(peer)), {
362
- concurrency: REQUIRED_SUCCESSFUL_DIALS
363
- })) {
447
+ if (results.networkSegments.includes(segment)) {
448
+ this.log.trace('%a results included network segment %s', options.multiaddr, segment);
449
+ return;
450
+ }
451
+ if (results.result != null) {
452
+ this.log.trace('already resolved result for %a, ignoring response from', options.multiaddr, connection.remotePeer);
453
+ return;
454
+ }
455
+ if (results.verifyingPeers.has(connection.remotePeer)) {
456
+ this.log.trace('peer %p has already verified %a, ignoring response', connection.remotePeer, options.multiaddr);
457
+ return;
458
+ }
459
+ results.verifyingPeers.add(connection.remotePeer);
460
+ results.networkSegments.push(segment);
461
+ if (status === Message.ResponseStatus.OK) {
462
+ results.success++;
463
+ }
464
+ else if (status === Message.ResponseStatus.E_DIAL_ERROR) {
465
+ results.failure++;
466
+ }
467
+ this.log('%a success %d failure %d', results.multiaddr, results.success, results.failure);
468
+ if (results.success === REQUIRED_SUCCESSFUL_DIALS) {
469
+ // we are now convinced
470
+ this.log('%a is externally dialable', results.multiaddr);
471
+ this.components.addressManager.confirmObservedAddr(results.multiaddr);
472
+ this.dialResults.delete(results.multiaddr.toString());
473
+ // abort & remove any outstanding verification jobs for this multiaddr
474
+ results.result = true;
475
+ results.queue.abort();
476
+ }
477
+ if (results.failure === REQUIRED_SUCCESSFUL_DIALS) {
478
+ // we are now unconvinced
479
+ this.log('%a is not externally dialable', results.multiaddr);
480
+ this.components.addressManager.removeObservedAddr(results.multiaddr);
481
+ this.dialResults.delete(results.multiaddr.toString());
482
+ // abort & remove any outstanding verification jobs for this multiaddr
483
+ results.result = false;
484
+ results.queue.abort();
485
+ }
486
+ }
487
+ finally {
364
488
  try {
365
- if (dialResponse == null) {
366
- continue;
367
- }
368
- // they either told us which address worked/didn't work, or we only sent them one address
369
- const addr = dialResponse.addr == null ? multiaddrs[0] : multiaddr(dialResponse.addr);
370
- this.log('autonat response for %a is %s', addr, dialResponse.status);
371
- if (dialResponse.status === Message.ResponseStatus.E_BAD_REQUEST) {
372
- // the remote could not parse our request
373
- continue;
374
- }
375
- if (dialResponse.status === Message.ResponseStatus.E_DIAL_REFUSED) {
376
- // the remote could not honour our request
377
- continue;
378
- }
379
- if (dialResponse.addr == null && multiaddrs.length > 1) {
380
- // we sent the remote multiple addrs but they didn't tell us which ones worked/didn't work
381
- continue;
382
- }
383
- if (!multiaddrs.some(ma => ma.equals(addr))) {
384
- this.log('peer reported %a as %s but it was not in our observed address list', addr, dialResponse.status);
385
- continue;
386
- }
387
- const addrStr = addr.toString();
388
- if (results[addrStr] == null) {
389
- results[addrStr] = { success: 0, failure: 0 };
390
- }
391
- if (dialResponse.status === Message.ResponseStatus.OK) {
392
- results[addrStr].success++;
393
- }
394
- else if (dialResponse.status === Message.ResponseStatus.E_DIAL_ERROR) {
395
- results[addrStr].failure++;
396
- }
397
- if (results[addrStr].success === REQUIRED_SUCCESSFUL_DIALS) {
398
- // we are now convinced
399
- this.log('%a is externally dialable', addr);
400
- addressManager.confirmObservedAddr(addr);
401
- return;
402
- }
403
- if (results[addrStr].failure === REQUIRED_SUCCESSFUL_DIALS) {
404
- // we are now unconvinced
405
- this.log('%a is not externally dialable', addr);
406
- addressManager.removeObservedAddr(addr);
407
- return;
408
- }
489
+ await stream.close({
490
+ signal
491
+ });
409
492
  }
410
493
  catch (err) {
411
- this.log.error('could not verify external address', err);
494
+ stream.abort(err);
412
495
  }
413
496
  }
497
+ }, {
498
+ peerId: connection.remotePeer,
499
+ multiaddr: results.multiaddr
500
+ })
501
+ .catch(err => {
502
+ if (results?.result == null) {
503
+ this.log.error('error from %p verifying address %a - %e', connection.remotePeer, results?.multiaddr, err);
504
+ }
505
+ });
506
+ }
507
+ getNetworkSegment(ma) {
508
+ // make sure we use different network segments
509
+ const options = ma.toOptions();
510
+ if (options.family === 4) {
511
+ const octets = options.host.split('.');
512
+ return octets[0].padStart(3, '0');
414
513
  }
415
- finally {
416
- this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.refreshInterval);
417
- }
514
+ const octets = options.host.split(':');
515
+ return octets[0].padStart(4, '0');
418
516
  }
419
517
  }
420
518
  //# sourceMappingURL=autonat.js.map