libp2p 0.42.2 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/index.min.js +29 -29
- package/dist/src/address-manager/index.d.ts +1 -10
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +46 -29
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/autonat/constants.d.ts +4 -0
- package/dist/src/autonat/constants.d.ts.map +1 -0
- package/dist/src/autonat/constants.js +4 -0
- package/dist/src/autonat/constants.js.map +1 -0
- package/dist/src/autonat/index.d.ts +64 -0
- package/dist/src/autonat/index.d.ts.map +1 -0
- package/dist/src/autonat/index.js +417 -0
- package/dist/src/autonat/index.js.map +1 -0
- package/dist/src/autonat/pb/index.d.ts +57 -0
- package/dist/src/autonat/pb/index.d.ts.map +1 -0
- package/dist/src/autonat/pb/index.js +250 -0
- package/dist/src/autonat/pb/index.js.map +1 -0
- package/dist/src/circuit/constants.d.ts +31 -6
- package/dist/src/circuit/constants.d.ts.map +1 -1
- package/dist/src/circuit/constants.js +37 -7
- package/dist/src/circuit/constants.js.map +1 -1
- package/dist/src/circuit/index.d.ts +16 -61
- package/dist/src/circuit/index.d.ts.map +1 -1
- package/dist/src/circuit/index.js +2 -68
- package/dist/src/circuit/index.js.map +1 -1
- package/dist/src/circuit/pb/index.d.ts +83 -43
- package/dist/src/circuit/pb/index.d.ts.map +1 -1
- package/dist/src/circuit/pb/index.js +363 -127
- package/dist/src/circuit/pb/index.js.map +1 -1
- package/dist/src/circuit/server/advert-service.d.ts +43 -0
- package/dist/src/circuit/server/advert-service.d.ts.map +1 -0
- package/dist/src/circuit/server/advert-service.js +69 -0
- package/dist/src/circuit/server/advert-service.js.map +1 -0
- package/dist/src/circuit/server/index.d.ts +60 -0
- package/dist/src/circuit/server/index.d.ts.map +1 -0
- package/dist/src/circuit/server/index.js +287 -0
- package/dist/src/circuit/server/index.js.map +1 -0
- package/dist/src/circuit/server/reservation-store.d.ts +49 -0
- package/dist/src/circuit/server/reservation-store.d.ts.map +1 -0
- package/dist/src/circuit/server/reservation-store.js +57 -0
- package/dist/src/circuit/server/reservation-store.js.map +1 -0
- package/dist/src/circuit/server/reservation-voucher.d.ts +18 -0
- package/dist/src/circuit/server/reservation-voucher.d.ts.map +1 -0
- package/dist/src/circuit/server/reservation-voucher.js +33 -0
- package/dist/src/circuit/server/reservation-voucher.js.map +1 -0
- package/dist/src/circuit/transport/discovery.d.ts +45 -0
- package/dist/src/circuit/transport/discovery.d.ts.map +1 -0
- package/dist/src/circuit/transport/discovery.js +82 -0
- package/dist/src/circuit/transport/discovery.js.map +1 -0
- package/dist/src/circuit/transport/index.d.ts +33 -0
- package/dist/src/circuit/transport/index.d.ts.map +1 -0
- package/dist/src/circuit/transport/index.js +225 -0
- package/dist/src/circuit/transport/index.js.map +1 -0
- package/dist/src/circuit/transport/listener.d.ts +9 -0
- package/dist/src/circuit/transport/listener.d.ts.map +1 -0
- package/dist/src/circuit/transport/listener.js +76 -0
- package/dist/src/circuit/transport/listener.js.map +1 -0
- package/dist/src/circuit/transport/reservation-store.d.ts +60 -0
- package/dist/src/circuit/transport/reservation-store.d.ts.map +1 -0
- package/dist/src/circuit/transport/reservation-store.js +165 -0
- package/dist/src/circuit/transport/reservation-store.js.map +1 -0
- package/dist/src/circuit/utils.d.ts +7 -0
- package/dist/src/circuit/utils.d.ts.map +1 -1
- package/dist/src/circuit/utils.js +87 -0
- package/dist/src/circuit/utils.js.map +1 -1
- package/dist/src/components.d.ts +2 -1
- package/dist/src/components.d.ts.map +1 -1
- package/dist/src/components.js +13 -13
- package/dist/src/components.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +21 -25
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection/index.d.ts +2 -2
- package/dist/src/connection/index.d.ts.map +1 -1
- package/dist/src/connection/index.js +4 -4
- package/dist/src/connection/index.js.map +1 -1
- package/dist/src/connection-manager/auto-dialler.d.ts +0 -4
- package/dist/src/connection-manager/auto-dialler.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dialler.js +18 -18
- package/dist/src/connection-manager/auto-dialler.js.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/dial-request.js +13 -6
- package/dist/src/connection-manager/dialer/dial-request.js.map +1 -1
- package/dist/src/connection-manager/dialer/index.d.ts +10 -1
- package/dist/src/connection-manager/dialer/index.d.ts.map +1 -1
- package/dist/src/connection-manager/dialer/index.js +24 -9
- package/dist/src/connection-manager/dialer/index.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +1 -4
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +8 -5
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/latency-monitor.d.ts.map +1 -1
- package/dist/src/connection-manager/latency-monitor.js +1 -1
- package/dist/src/connection-manager/latency-monitor.js.map +1 -1
- package/dist/src/connection-manager/visibility-change-emitter.d.ts.map +1 -1
- package/dist/src/content-routing/index.d.ts +6 -4
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/index.js +9 -9
- package/dist/src/content-routing/index.js.map +1 -1
- package/dist/src/content-routing/utils.d.ts +3 -3
- package/dist/src/content-routing/utils.d.ts.map +1 -1
- package/dist/src/content-routing/utils.js +2 -2
- package/dist/src/content-routing/utils.js.map +1 -1
- package/dist/src/dht/dht-content-routing.d.ts +2 -1
- package/dist/src/dht/dht-content-routing.d.ts.map +1 -1
- package/dist/src/dht/dht-content-routing.js +2 -2
- package/dist/src/dht/dht-content-routing.js.map +1 -1
- package/dist/src/dht/dht-peer-routing.d.ts +3 -2
- package/dist/src/dht/dht-peer-routing.d.ts.map +1 -1
- package/dist/src/dht/dht-peer-routing.js +2 -2
- package/dist/src/dht/dht-peer-routing.js.map +1 -1
- package/dist/src/dht/dummy-dht.d.ts +1 -1
- package/dist/src/dht/dummy-dht.d.ts.map +1 -1
- package/dist/src/dht/dummy-dht.js +12 -12
- package/dist/src/dht/dummy-dht.js.map +1 -1
- package/dist/src/errors.d.ts +2 -1
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +1 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +6 -6
- package/dist/src/fetch/index.js.map +1 -1
- package/dist/src/fetch/pb/proto.d.ts +3 -3
- package/dist/src/fetch/pb/proto.d.ts.map +1 -1
- package/dist/src/fetch/pb/proto.js +4 -3
- package/dist/src/fetch/pb/proto.js.map +1 -1
- package/dist/src/get-peer.js +2 -2
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/identify/index.d.ts +3 -1
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +19 -14
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/identify/pb/message.d.ts +2 -2
- package/dist/src/identify/pb/message.d.ts.map +1 -1
- package/dist/src/identify/pb/message.js +1 -0
- package/dist/src/identify/pb/message.js.map +1 -1
- package/dist/src/index.d.ts +14 -8
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/insecure/index.d.ts.map +1 -1
- package/dist/src/insecure/index.js.map +1 -1
- package/dist/src/insecure/pb/proto.d.ts +3 -3
- package/dist/src/insecure/pb/proto.d.ts.map +1 -1
- package/dist/src/insecure/pb/proto.js +4 -5
- package/dist/src/insecure/pb/proto.js.map +1 -1
- package/dist/src/libp2p.d.ts +7 -3
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +35 -35
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/nat-manager.d.ts.map +1 -1
- package/dist/src/nat-manager.js +5 -3
- package/dist/src/nat-manager.js.map +1 -1
- package/dist/src/peer-record-updater.d.ts.map +1 -1
- package/dist/src/peer-routing.d.ts.map +1 -1
- package/dist/src/peer-routing.js +5 -5
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +2 -2
- package/dist/src/ping/index.js.map +1 -1
- package/dist/src/pnet/crypto.d.ts +1 -1
- package/dist/src/pnet/crypto.d.ts.map +1 -1
- package/dist/src/pnet/crypto.js +1 -1
- package/dist/src/pnet/crypto.js.map +1 -1
- package/dist/src/pnet/index.js +3 -3
- package/dist/src/pnet/index.js.map +1 -1
- package/dist/src/pnet/key-generator.d.ts.map +1 -1
- package/dist/src/pubsub/dummy-pubsub.js +9 -9
- package/dist/src/pubsub/dummy-pubsub.js.map +1 -1
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +4 -4
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.d.ts.map +1 -1
- package/dist/src/transport-manager.js +8 -9
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +2 -1
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +38 -33
- package/dist/src/upgrader.js.map +1 -1
- package/dist/typedoc-urls.json +19 -6
- package/package.json +36 -33
- package/src/address-manager/index.ts +62 -35
- package/src/autonat/constants.ts +4 -0
- package/src/autonat/index.ts +567 -0
- package/src/autonat/pb/index.proto +35 -0
- package/src/autonat/pb/index.ts +320 -0
- package/src/circuit/constants.ts +48 -7
- package/src/circuit/index.ts +17 -129
- package/src/circuit/pb/index.proto +57 -32
- package/src/circuit/pb/index.ts +448 -138
- package/src/circuit/server/advert-service.ts +108 -0
- package/src/circuit/server/index.ts +421 -0
- package/src/circuit/server/reservation-store.ts +111 -0
- package/src/circuit/server/reservation-voucher.ts +51 -0
- package/src/circuit/transport/discovery.ts +127 -0
- package/src/circuit/transport/index.ts +325 -0
- package/src/circuit/transport/listener.ts +99 -0
- package/src/circuit/transport/reservation-store.ts +249 -0
- package/src/circuit/utils.ts +108 -0
- package/src/components.ts +22 -21
- package/src/config.ts +21 -25
- package/src/connection/index.ts +10 -10
- package/src/connection-manager/auto-dialler.ts +36 -40
- package/src/connection-manager/dialer/dial-request.ts +13 -6
- package/src/connection-manager/dialer/index.ts +34 -15
- package/src/connection-manager/index.ts +22 -23
- package/src/connection-manager/latency-monitor.ts +9 -9
- package/src/connection-manager/visibility-change-emitter.ts +4 -4
- package/src/content-routing/index.ts +18 -16
- package/src/content-routing/utils.ts +5 -5
- package/src/dht/dht-content-routing.ts +5 -4
- package/src/dht/dht-peer-routing.ts +5 -4
- package/src/dht/dummy-dht.ts +13 -13
- package/src/errors.ts +2 -1
- package/src/fetch/index.ts +13 -13
- package/src/fetch/pb/proto.ts +8 -7
- package/src/get-peer.ts +3 -3
- package/src/identify/index.ts +29 -24
- package/src/identify/pb/message.ts +3 -2
- package/src/index.ts +15 -8
- package/src/insecure/index.ts +2 -1
- package/src/insecure/pb/proto.ts +8 -9
- package/src/libp2p.ts +52 -46
- package/src/nat-manager.ts +11 -9
- package/src/peer-record-updater.ts +4 -4
- package/src/peer-routing.ts +9 -9
- package/src/ping/index.ts +6 -6
- package/src/pnet/crypto.ts +3 -3
- package/src/pnet/index.ts +3 -3
- package/src/pnet/key-generator.ts +1 -1
- package/src/pubsub/dummy-pubsub.ts +9 -9
- package/src/registrar.ts +12 -12
- package/src/transport-manager.ts +17 -18
- package/src/upgrader.ts +43 -42
- package/src/version.ts +1 -1
- package/dist/src/circuit/auto-relay.d.ts +0 -46
- package/dist/src/circuit/auto-relay.d.ts.map +0 -1
- package/dist/src/circuit/auto-relay.js +0 -220
- package/dist/src/circuit/auto-relay.js.map +0 -1
- package/dist/src/circuit/circuit/hop.d.ts +0 -42
- package/dist/src/circuit/circuit/hop.d.ts.map +0 -1
- package/dist/src/circuit/circuit/hop.js +0 -142
- package/dist/src/circuit/circuit/hop.js.map +0 -1
- package/dist/src/circuit/circuit/stop.d.ts +0 -24
- package/dist/src/circuit/circuit/stop.d.ts.map +0 -1
- package/dist/src/circuit/circuit/stop.js +0 -51
- package/dist/src/circuit/circuit/stop.js.map +0 -1
- package/dist/src/circuit/circuit/stream-handler.d.ts +0 -40
- package/dist/src/circuit/circuit/stream-handler.d.ts.map +0 -1
- package/dist/src/circuit/circuit/stream-handler.js +0 -59
- package/dist/src/circuit/circuit/stream-handler.js.map +0 -1
- package/dist/src/circuit/circuit/utils.d.ts +0 -7
- package/dist/src/circuit/circuit/utils.d.ts.map +0 -1
- package/dist/src/circuit/circuit/utils.js +0 -43
- package/dist/src/circuit/circuit/utils.js.map +0 -1
- package/dist/src/circuit/listener.d.ts +0 -9
- package/dist/src/circuit/listener.d.ts.map +0 -1
- package/dist/src/circuit/listener.js +0 -62
- package/dist/src/circuit/listener.js.map +0 -1
- package/dist/src/circuit/multicodec.d.ts +0 -2
- package/dist/src/circuit/multicodec.d.ts.map +0 -1
- package/dist/src/circuit/multicodec.js +0 -2
- package/dist/src/circuit/multicodec.js.map +0 -1
- package/dist/src/circuit/transport.d.ts +0 -51
- package/dist/src/circuit/transport.d.ts.map +0 -1
- package/dist/src/circuit/transport.js +0 -223
- package/dist/src/circuit/transport.js.map +0 -1
- package/dist/src/keychain/cms.d.ts +0 -33
- package/dist/src/keychain/cms.d.ts.map +0 -1
- package/dist/src/keychain/cms.js +0 -129
- package/dist/src/keychain/cms.js.map +0 -1
- package/dist/src/keychain/index.d.ts +0 -151
- package/dist/src/keychain/index.d.ts.map +0 -1
- package/dist/src/keychain/index.js +0 -519
- package/dist/src/keychain/index.js.map +0 -1
- package/dist/src/keychain/util.d.ts +0 -21
- package/dist/src/keychain/util.d.ts.map +0 -1
- package/dist/src/keychain/util.js +0 -79
- package/dist/src/keychain/util.js.map +0 -1
- package/src/circuit/IMPLEMENTATION_NOTES.md +0 -128
- package/src/circuit/README.md +0 -111
- package/src/circuit/auto-relay.ts +0 -292
- package/src/circuit/circuit/hop.ts +0 -220
- package/src/circuit/circuit/stop.ts +0 -83
- package/src/circuit/circuit/stream-handler.ts +0 -87
- package/src/circuit/circuit/utils.ts +0 -44
- package/src/circuit/listener.ts +0 -83
- package/src/circuit/multicodec.ts +0 -2
- package/src/circuit/transport.ts +0 -278
- package/src/keychain/README.md +0 -55
- package/src/keychain/cms.ts +0 -150
- package/src/keychain/doc/private-key.png +0 -0
- package/src/keychain/doc/private-key.xml +0 -1
- package/src/keychain/index.ts +0 -629
- package/src/keychain/util.ts +0 -82
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
import type { AddressManager } from '@libp2p/interface-address-manager'
|
|
2
|
+
import type { Connection } from '@libp2p/interface-connection'
|
|
3
|
+
import type { ConnectionManager, Dialer } from '@libp2p/interface-connection-manager'
|
|
4
|
+
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
5
|
+
import type { PeerInfo } from '@libp2p/interface-peer-info'
|
|
6
|
+
import type { PeerRouting } from '@libp2p/interface-peer-routing'
|
|
7
|
+
import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar'
|
|
8
|
+
import type { TransportManager } from '@libp2p/interface-transport'
|
|
9
|
+
import type { Startable } from '@libp2p/interfaces/startable'
|
|
10
|
+
import { logger } from '@libp2p/logger'
|
|
11
|
+
import { peerIdFromBytes } from '@libp2p/peer-id'
|
|
12
|
+
import { createEd25519PeerId } from '@libp2p/peer-id-factory'
|
|
13
|
+
import { multiaddr, protocols } from '@multiformats/multiaddr'
|
|
14
|
+
import { abortableDuplex } from 'abortable-iterator'
|
|
15
|
+
import { setMaxListeners } from 'events'
|
|
16
|
+
import first from 'it-first'
|
|
17
|
+
import * as lp from 'it-length-prefixed'
|
|
18
|
+
import map from 'it-map'
|
|
19
|
+
import parallel from 'it-parallel'
|
|
20
|
+
import { pipe } from 'it-pipe'
|
|
21
|
+
import isPrivateIp from 'private-ip'
|
|
22
|
+
import { TimeoutController } from 'timeout-abort-controller'
|
|
23
|
+
import {
|
|
24
|
+
PROTOCOL
|
|
25
|
+
} from './constants.js'
|
|
26
|
+
import { Message } from './pb/index.js'
|
|
27
|
+
|
|
28
|
+
const log = logger('libp2p:autonat')
|
|
29
|
+
|
|
30
|
+
// if more than 3 peers manage to dial us on what we believe to be our external
|
|
31
|
+
// IP then we are convinced that it is, in fact, our external IP
|
|
32
|
+
// https://github.com/libp2p/specs/blob/master/autonat/README.md#autonat-protocol
|
|
33
|
+
const REQUIRED_SUCCESSFUL_DIALS = 4
|
|
34
|
+
|
|
35
|
+
// Wait this long before we start to query autonat nodes
|
|
36
|
+
const AUTONAT_STARTUP_DELAY = 5000
|
|
37
|
+
|
|
38
|
+
// Only try to verify our external address this often
|
|
39
|
+
const AUTONAT_REFRESH_INTERVAL = 60000
|
|
40
|
+
|
|
41
|
+
export interface AutonatServiceInit {
|
|
42
|
+
/**
|
|
43
|
+
* Allows overriding the protocol prefix used
|
|
44
|
+
*/
|
|
45
|
+
protocolPrefix: string
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* How long we should wait for a remote peer to verify our external address
|
|
49
|
+
*/
|
|
50
|
+
timeout: number
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* How long to wait after startup before trying to verify our external address
|
|
54
|
+
*/
|
|
55
|
+
startupDelay: number
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Verify our external addresses this often
|
|
59
|
+
*/
|
|
60
|
+
refreshInterval: number
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* How many parallel inbound autonat streams we allow per-connection
|
|
64
|
+
*/
|
|
65
|
+
maxInboundStreams: number
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* How many parallel outbound autonat streams we allow per-connection
|
|
69
|
+
*/
|
|
70
|
+
maxOutboundStreams: number
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface DefaultAutonatComponents {
|
|
74
|
+
registrar: Registrar
|
|
75
|
+
addressManager: AddressManager
|
|
76
|
+
transportManager: TransportManager
|
|
77
|
+
dialer: Dialer
|
|
78
|
+
peerId: PeerId
|
|
79
|
+
connectionManager: ConnectionManager
|
|
80
|
+
peerRouting: PeerRouting
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export class AutonatService implements Startable {
|
|
84
|
+
private readonly components: DefaultAutonatComponents
|
|
85
|
+
private readonly _init: AutonatServiceInit
|
|
86
|
+
private readonly startupDelay: number
|
|
87
|
+
private readonly refreshInterval: number
|
|
88
|
+
private verifyAddressTimeout?: ReturnType<typeof setTimeout>
|
|
89
|
+
private started: boolean
|
|
90
|
+
|
|
91
|
+
constructor (components: DefaultAutonatComponents, init: AutonatServiceInit) {
|
|
92
|
+
this.components = components
|
|
93
|
+
this.started = false
|
|
94
|
+
this._init = init
|
|
95
|
+
this.startupDelay = init.startupDelay ?? AUTONAT_STARTUP_DELAY
|
|
96
|
+
this.refreshInterval = init.refreshInterval ?? AUTONAT_REFRESH_INTERVAL
|
|
97
|
+
|
|
98
|
+
this._verifyExternalAddresses = this._verifyExternalAddresses.bind(this)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
isStarted (): boolean {
|
|
102
|
+
return this.started
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async start (): Promise<void> {
|
|
106
|
+
if (this.started) {
|
|
107
|
+
return
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
await this.components.registrar.handle(PROTOCOL, (data) => {
|
|
111
|
+
void this.handleIncomingAutonatStream(data)
|
|
112
|
+
.catch(err => {
|
|
113
|
+
log.error(err)
|
|
114
|
+
})
|
|
115
|
+
}, {
|
|
116
|
+
maxInboundStreams: this._init.maxInboundStreams,
|
|
117
|
+
maxOutboundStreams: this._init.maxOutboundStreams
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.startupDelay)
|
|
121
|
+
|
|
122
|
+
this.started = true
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async stop (): Promise<void> {
|
|
126
|
+
await this.components.registrar.unhandle(PROTOCOL)
|
|
127
|
+
clearTimeout(this.verifyAddressTimeout)
|
|
128
|
+
|
|
129
|
+
this.started = false
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Handle an incoming autonat request
|
|
134
|
+
*/
|
|
135
|
+
async handleIncomingAutonatStream (data: IncomingStreamData): Promise<void> {
|
|
136
|
+
const controller = new TimeoutController(this._init.timeout)
|
|
137
|
+
|
|
138
|
+
// this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning
|
|
139
|
+
// appearing in the console
|
|
140
|
+
try {
|
|
141
|
+
// fails on node < 15.4
|
|
142
|
+
setMaxListeners?.(Infinity, controller.signal)
|
|
143
|
+
} catch {}
|
|
144
|
+
|
|
145
|
+
const ourHosts = this.components.addressManager.getAddresses()
|
|
146
|
+
.map(ma => ma.toOptions().host)
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
const source = abortableDuplex(data.stream, controller.signal)
|
|
150
|
+
const self = this
|
|
151
|
+
|
|
152
|
+
await pipe(
|
|
153
|
+
source,
|
|
154
|
+
lp.decode(),
|
|
155
|
+
async function * (stream) {
|
|
156
|
+
const buf = await first(stream)
|
|
157
|
+
|
|
158
|
+
if (buf == null) {
|
|
159
|
+
log('No message received')
|
|
160
|
+
yield Message.encode({
|
|
161
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
162
|
+
dialResponse: {
|
|
163
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
164
|
+
statusText: 'No message was sent'
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
let request: Message
|
|
172
|
+
|
|
173
|
+
try {
|
|
174
|
+
request = Message.decode(buf)
|
|
175
|
+
} catch (err) {
|
|
176
|
+
log.error('Could not decode message', err)
|
|
177
|
+
|
|
178
|
+
yield Message.encode({
|
|
179
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
180
|
+
dialResponse: {
|
|
181
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
182
|
+
statusText: 'Could not decode message'
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const dialRequest = request.dial
|
|
190
|
+
|
|
191
|
+
if (dialRequest == null) {
|
|
192
|
+
log.error('Dial was missing from message')
|
|
193
|
+
|
|
194
|
+
yield Message.encode({
|
|
195
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
196
|
+
dialResponse: {
|
|
197
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
198
|
+
statusText: 'No Dial message found in message'
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
return
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let peerId: PeerId
|
|
206
|
+
const peer = dialRequest.peer
|
|
207
|
+
|
|
208
|
+
if (peer == null || peer.id == null) {
|
|
209
|
+
log.error('PeerId missing from message')
|
|
210
|
+
|
|
211
|
+
yield Message.encode({
|
|
212
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
213
|
+
dialResponse: {
|
|
214
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
215
|
+
statusText: 'missing peer info'
|
|
216
|
+
}
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
return
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
try {
|
|
223
|
+
peerId = peerIdFromBytes(peer.id)
|
|
224
|
+
} catch (err) {
|
|
225
|
+
log.error('Invalid PeerId', err)
|
|
226
|
+
|
|
227
|
+
yield Message.encode({
|
|
228
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
229
|
+
dialResponse: {
|
|
230
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
231
|
+
statusText: 'bad peer id'
|
|
232
|
+
}
|
|
233
|
+
})
|
|
234
|
+
|
|
235
|
+
return
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
log('Incoming request from %p', peerId)
|
|
239
|
+
|
|
240
|
+
// reject any dial requests that arrive via relays
|
|
241
|
+
if (!data.connection.remotePeer.equals(peerId)) {
|
|
242
|
+
log('Target peer %p did not equal sending peer %p', peerId, data.connection.remotePeer)
|
|
243
|
+
|
|
244
|
+
yield Message.encode({
|
|
245
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
246
|
+
dialResponse: {
|
|
247
|
+
status: Message.ResponseStatus.E_BAD_REQUEST,
|
|
248
|
+
statusText: 'peer id mismatch'
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// get a list of multiaddrs to dial
|
|
256
|
+
const multiaddrs = peer.addrs
|
|
257
|
+
.map(buf => multiaddr(buf))
|
|
258
|
+
.filter(ma => {
|
|
259
|
+
const isFromSameHost = ma.toOptions().host === data.connection.remoteAddr.toOptions().host
|
|
260
|
+
|
|
261
|
+
log.trace('Request to dial %s was sent from %s is same host %s', ma, data.connection.remoteAddr, isFromSameHost)
|
|
262
|
+
// skip any Multiaddrs where the target node's IP does not match the sending node's IP
|
|
263
|
+
return isFromSameHost
|
|
264
|
+
})
|
|
265
|
+
.filter(ma => {
|
|
266
|
+
const host = ma.toOptions().host
|
|
267
|
+
const isPublicIp = !(isPrivateIp(host) ?? false)
|
|
268
|
+
|
|
269
|
+
log.trace('Host %s was public %s', host, isPublicIp)
|
|
270
|
+
// don't try to dial private addresses
|
|
271
|
+
return isPublicIp
|
|
272
|
+
})
|
|
273
|
+
.filter(ma => {
|
|
274
|
+
const host = ma.toOptions().host
|
|
275
|
+
const isNotOurHost = !ourHosts.includes(host)
|
|
276
|
+
|
|
277
|
+
log.trace('Host %s was not our host %s', host, isNotOurHost)
|
|
278
|
+
// don't try to dial nodes on the same host as us
|
|
279
|
+
return isNotOurHost
|
|
280
|
+
})
|
|
281
|
+
.filter(ma => {
|
|
282
|
+
const isSupportedTransport = Boolean(self.components.transportManager.transportForMultiaddr(ma))
|
|
283
|
+
|
|
284
|
+
log.trace('Transport for %s is supported %s', ma, isSupportedTransport)
|
|
285
|
+
// skip any Multiaddrs that have transports we do not support
|
|
286
|
+
return isSupportedTransport
|
|
287
|
+
})
|
|
288
|
+
.map(ma => {
|
|
289
|
+
if (ma.getPeerId() == null) {
|
|
290
|
+
// make sure we have the PeerId as part of the Multiaddr
|
|
291
|
+
ma = ma.encapsulate(`/p2p/${peerId.toString()}`)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return ma
|
|
295
|
+
})
|
|
296
|
+
|
|
297
|
+
// make sure we have something to dial
|
|
298
|
+
if (multiaddrs.length === 0) {
|
|
299
|
+
log('No valid multiaddrs for %p in message', peerId)
|
|
300
|
+
|
|
301
|
+
yield Message.encode({
|
|
302
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
303
|
+
dialResponse: {
|
|
304
|
+
status: Message.ResponseStatus.E_DIAL_REFUSED,
|
|
305
|
+
statusText: 'no dialable addresses'
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
return
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
log('Dial multiaddrs %s for peer %p', multiaddrs.map(ma => ma.toString()).join(', '), peerId)
|
|
313
|
+
|
|
314
|
+
let errorMessage = ''
|
|
315
|
+
let lastMultiaddr = multiaddrs[0]
|
|
316
|
+
|
|
317
|
+
for await (const multiaddr of multiaddrs) {
|
|
318
|
+
let connection: Connection | undefined
|
|
319
|
+
lastMultiaddr = multiaddr
|
|
320
|
+
|
|
321
|
+
try {
|
|
322
|
+
// use the dialer so we can dial a specific multiaddr instead of every known
|
|
323
|
+
// multiaddr for the peer
|
|
324
|
+
connection = await self.components.dialer.dial(multiaddr, {
|
|
325
|
+
signal: controller.signal
|
|
326
|
+
})
|
|
327
|
+
|
|
328
|
+
if (!connection.remoteAddr.equals(multiaddr)) {
|
|
329
|
+
log.error('Tried to dial %s but dialed %s', multiaddr, connection.remoteAddr)
|
|
330
|
+
throw new Error('Unexpected remote address')
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
log('Success %p', peerId)
|
|
334
|
+
|
|
335
|
+
yield Message.encode({
|
|
336
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
337
|
+
dialResponse: {
|
|
338
|
+
status: Message.ResponseStatus.OK,
|
|
339
|
+
addr: connection.remoteAddr.decapsulateCode(protocols('p2p').code).bytes
|
|
340
|
+
}
|
|
341
|
+
})
|
|
342
|
+
|
|
343
|
+
return
|
|
344
|
+
} catch (err: any) {
|
|
345
|
+
log('Could not dial %p', peerId, err)
|
|
346
|
+
errorMessage = err.message
|
|
347
|
+
} finally {
|
|
348
|
+
if (connection != null) {
|
|
349
|
+
await connection.close()
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
yield Message.encode({
|
|
355
|
+
type: Message.MessageType.DIAL_RESPONSE,
|
|
356
|
+
dialResponse: {
|
|
357
|
+
status: Message.ResponseStatus.E_DIAL_ERROR,
|
|
358
|
+
statusText: errorMessage,
|
|
359
|
+
addr: lastMultiaddr.bytes
|
|
360
|
+
}
|
|
361
|
+
})
|
|
362
|
+
},
|
|
363
|
+
lp.encode(),
|
|
364
|
+
// pipe to the stream, not the abortable source other wise we
|
|
365
|
+
// can't tell the remote when a dial timed out..
|
|
366
|
+
data.stream
|
|
367
|
+
)
|
|
368
|
+
} finally {
|
|
369
|
+
controller.clear()
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
_verifyExternalAddresses (): void {
|
|
374
|
+
void this.verifyExternalAddresses()
|
|
375
|
+
.catch(err => {
|
|
376
|
+
log.error(err)
|
|
377
|
+
})
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Our multicodec topology noticed a new peer that supports autonat
|
|
382
|
+
*/
|
|
383
|
+
async verifyExternalAddresses (): Promise<void> {
|
|
384
|
+
clearTimeout(this.verifyAddressTimeout)
|
|
385
|
+
|
|
386
|
+
// Do not try to push if we are not running
|
|
387
|
+
if (!this.isStarted()) {
|
|
388
|
+
return
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
const addressManager = this.components.addressManager
|
|
392
|
+
|
|
393
|
+
const multiaddrs = addressManager.getObservedAddrs()
|
|
394
|
+
.filter(ma => {
|
|
395
|
+
const options = ma.toOptions()
|
|
396
|
+
|
|
397
|
+
return !(isPrivateIp(options.host) ?? false)
|
|
398
|
+
})
|
|
399
|
+
|
|
400
|
+
if (multiaddrs.length === 0) {
|
|
401
|
+
log('No public addresses found, not requesting verification')
|
|
402
|
+
this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.refreshInterval)
|
|
403
|
+
|
|
404
|
+
return
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const controller = new TimeoutController(this._init.timeout)
|
|
408
|
+
|
|
409
|
+
// this controller may be used while dialing lots of peers so prevent MaxListenersExceededWarning
|
|
410
|
+
// appearing in the console
|
|
411
|
+
try {
|
|
412
|
+
// fails on node < 15.4
|
|
413
|
+
setMaxListeners?.(Infinity, controller.signal)
|
|
414
|
+
} catch {}
|
|
415
|
+
|
|
416
|
+
const self = this
|
|
417
|
+
|
|
418
|
+
try {
|
|
419
|
+
log('verify multiaddrs %s', multiaddrs.map(ma => ma.toString()).join(', '))
|
|
420
|
+
|
|
421
|
+
const request = Message.encode({
|
|
422
|
+
type: Message.MessageType.DIAL,
|
|
423
|
+
dial: {
|
|
424
|
+
peer: {
|
|
425
|
+
id: this.components.peerId.toBytes(),
|
|
426
|
+
addrs: multiaddrs.map(map => map.bytes)
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
})
|
|
430
|
+
// find some random peers
|
|
431
|
+
const randomPeer = await createEd25519PeerId()
|
|
432
|
+
const randomCid = randomPeer.toBytes()
|
|
433
|
+
|
|
434
|
+
const results: Record<string, { success: number, failure: number }> = {}
|
|
435
|
+
const networkSegments: string[] = []
|
|
436
|
+
|
|
437
|
+
async function verifyAddress (peer: PeerInfo): Promise<Message.DialResponse | undefined> {
|
|
438
|
+
try {
|
|
439
|
+
log('Asking %p to verify multiaddr', peer.id)
|
|
440
|
+
|
|
441
|
+
const connection = await self.components.connectionManager.openConnection(peer.id, {
|
|
442
|
+
signal: controller.signal
|
|
443
|
+
})
|
|
444
|
+
|
|
445
|
+
const stream = await connection.newStream(PROTOCOL, {
|
|
446
|
+
signal: controller.signal
|
|
447
|
+
})
|
|
448
|
+
const source = abortableDuplex(stream, controller.signal)
|
|
449
|
+
|
|
450
|
+
const buf = await pipe(
|
|
451
|
+
[request],
|
|
452
|
+
lp.encode(),
|
|
453
|
+
source,
|
|
454
|
+
lp.decode(),
|
|
455
|
+
async (stream) => await first(stream)
|
|
456
|
+
)
|
|
457
|
+
if (buf == null) {
|
|
458
|
+
log('No response received from %s', connection.remotePeer)
|
|
459
|
+
return undefined
|
|
460
|
+
}
|
|
461
|
+
const response = Message.decode(buf)
|
|
462
|
+
|
|
463
|
+
if (response.type !== Message.MessageType.DIAL_RESPONSE || response.dialResponse == null) {
|
|
464
|
+
log('Invalid autonat response from %s', connection.remotePeer)
|
|
465
|
+
return undefined
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (response.dialResponse.status === Message.ResponseStatus.OK) {
|
|
469
|
+
// make sure we use different network segments
|
|
470
|
+
const options = connection.remoteAddr.toOptions()
|
|
471
|
+
let segment: string
|
|
472
|
+
|
|
473
|
+
if (options.family === 4) {
|
|
474
|
+
const octets = options.host.split('.')
|
|
475
|
+
segment = octets[0]
|
|
476
|
+
} else if (options.family === 6) {
|
|
477
|
+
const octets = options.host.split(':')
|
|
478
|
+
segment = octets[0]
|
|
479
|
+
} else {
|
|
480
|
+
log('Remote address "%s" was not IP4 or IP6?', options.host)
|
|
481
|
+
return undefined
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (networkSegments.includes(segment)) {
|
|
485
|
+
log('Already have response from network segment %d - %s', segment, options.host)
|
|
486
|
+
return undefined
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
networkSegments.push(segment)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return response.dialResponse
|
|
493
|
+
} catch (err) {
|
|
494
|
+
log.error(err)
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
for await (const dialResponse of parallel(map(this.components.peerRouting.getClosestPeers(randomCid, {
|
|
499
|
+
signal: controller.signal
|
|
500
|
+
}), (peer) => async () => await verifyAddress(peer)), {
|
|
501
|
+
concurrency: REQUIRED_SUCCESSFUL_DIALS
|
|
502
|
+
})) {
|
|
503
|
+
try {
|
|
504
|
+
if (dialResponse == null) {
|
|
505
|
+
continue
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// they either told us which address worked/didn't work, or we only sent them one address
|
|
509
|
+
const addr = dialResponse.addr == null ? multiaddrs[0] : multiaddr(dialResponse.addr)
|
|
510
|
+
|
|
511
|
+
log('Autonat response for %s is %s', addr, dialResponse.status)
|
|
512
|
+
|
|
513
|
+
if (dialResponse.status === Message.ResponseStatus.E_BAD_REQUEST) {
|
|
514
|
+
// the remote could not parse our request
|
|
515
|
+
continue
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (dialResponse.status === Message.ResponseStatus.E_DIAL_REFUSED) {
|
|
519
|
+
// the remote could not honour our request
|
|
520
|
+
continue
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
if (dialResponse.addr == null && multiaddrs.length > 1) {
|
|
524
|
+
// we sent the remote multiple addrs but they didn't tell us which ones worked/didn't work
|
|
525
|
+
continue
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (!multiaddrs.some(ma => ma.equals(addr))) {
|
|
529
|
+
log('Peer reported %s as %s but it was not in our observed address list', addr, dialResponse.status)
|
|
530
|
+
continue
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const addrStr = addr.toString()
|
|
534
|
+
|
|
535
|
+
if (results[addrStr] == null) {
|
|
536
|
+
results[addrStr] = { success: 0, failure: 0 }
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
if (dialResponse.status === Message.ResponseStatus.OK) {
|
|
540
|
+
results[addrStr].success++
|
|
541
|
+
} else if (dialResponse.status === Message.ResponseStatus.E_DIAL_ERROR) {
|
|
542
|
+
results[addrStr].failure++
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
if (results[addrStr].success === REQUIRED_SUCCESSFUL_DIALS) {
|
|
546
|
+
// we are now convinced
|
|
547
|
+
log('%s is externally dialable', addr)
|
|
548
|
+
addressManager.confirmObservedAddr(addr)
|
|
549
|
+
return
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (results[addrStr].failure === REQUIRED_SUCCESSFUL_DIALS) {
|
|
553
|
+
// we are now unconvinced
|
|
554
|
+
log('%s is not externally dialable', addr)
|
|
555
|
+
addressManager.removeObservedAddr(addr)
|
|
556
|
+
return
|
|
557
|
+
}
|
|
558
|
+
} catch (err) {
|
|
559
|
+
log.error('Could not verify external address', err)
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
} finally {
|
|
563
|
+
controller.clear()
|
|
564
|
+
this.verifyAddressTimeout = setTimeout(this._verifyExternalAddresses, this.refreshInterval)
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
syntax = "proto3";
|
|
2
|
+
|
|
3
|
+
message Message {
|
|
4
|
+
enum MessageType {
|
|
5
|
+
DIAL = 0;
|
|
6
|
+
DIAL_RESPONSE = 1;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
enum ResponseStatus {
|
|
10
|
+
OK = 0;
|
|
11
|
+
E_DIAL_ERROR = 100;
|
|
12
|
+
E_DIAL_REFUSED = 101;
|
|
13
|
+
E_BAD_REQUEST = 200;
|
|
14
|
+
E_INTERNAL_ERROR = 300;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
message PeerInfo {
|
|
18
|
+
optional bytes id = 1;
|
|
19
|
+
repeated bytes addrs = 2;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
message Dial {
|
|
23
|
+
optional PeerInfo peer = 1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
message DialResponse {
|
|
27
|
+
optional ResponseStatus status = 1;
|
|
28
|
+
optional string statusText = 2;
|
|
29
|
+
optional bytes addr = 3;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
optional MessageType type = 1;
|
|
33
|
+
optional Dial dial = 2;
|
|
34
|
+
optional DialResponse dialResponse = 3;
|
|
35
|
+
}
|