libp2p 0.44.0 → 0.45.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/dist/index.min.js +30 -30
- package/dist/src/address-manager/index.d.ts +8 -4
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +37 -6
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/address-manager/utils.d.ts +2 -0
- package/dist/src/address-manager/utils.d.ts.map +1 -0
- package/dist/src/address-manager/utils.js +12 -0
- package/dist/src/address-manager/utils.js.map +1 -0
- package/dist/src/autonat/constants.d.ts +16 -2
- package/dist/src/autonat/constants.d.ts.map +1 -1
- package/dist/src/autonat/constants.js +16 -2
- package/dist/src/autonat/constants.js.map +1 -1
- package/dist/src/autonat/index.d.ts +12 -33
- package/dist/src/autonat/index.d.ts.map +1 -1
- package/dist/src/autonat/index.js +36 -30
- package/dist/src/autonat/index.js.map +1 -1
- package/dist/src/circuit-relay/server/advert-service.d.ts.map +1 -1
- package/dist/src/circuit-relay/server/advert-service.js +2 -2
- package/dist/src/circuit-relay/server/advert-service.js.map +1 -1
- package/dist/src/circuit-relay/server/index.d.ts.map +1 -1
- package/dist/src/circuit-relay/server/index.js +10 -3
- package/dist/src/circuit-relay/server/index.js.map +1 -1
- package/dist/src/circuit-relay/transport/discovery.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/discovery.js +4 -2
- package/dist/src/circuit-relay/transport/discovery.js.map +1 -1
- package/dist/src/circuit-relay/transport/index.d.ts +3 -0
- package/dist/src/circuit-relay/transport/index.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/index.js +6 -4
- package/dist/src/circuit-relay/transport/index.js.map +1 -1
- package/dist/src/circuit-relay/transport/listener.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/listener.js +30 -26
- package/dist/src/circuit-relay/transport/listener.js.map +1 -1
- package/dist/src/circuit-relay/transport/reservation-store.d.ts +5 -4
- package/dist/src/circuit-relay/transport/reservation-store.d.ts.map +1 -1
- package/dist/src/circuit-relay/transport/reservation-store.js +37 -30
- package/dist/src/circuit-relay/transport/reservation-store.js.map +1 -1
- package/dist/src/components.d.ts +6 -63
- package/dist/src/components.d.ts.map +1 -1
- package/dist/src/components.js +60 -164
- package/dist/src/components.js.map +1 -1
- package/dist/src/config/connection-gater.browser.d.ts +8 -0
- package/dist/src/config/connection-gater.browser.d.ts.map +1 -0
- package/dist/src/config/connection-gater.browser.js +27 -0
- package/dist/src/config/connection-gater.browser.js.map +1 -0
- package/dist/src/config/connection-gater.d.ts +6 -0
- package/dist/src/config/connection-gater.d.ts.map +1 -0
- package/dist/src/config/connection-gater.js +18 -0
- package/dist/src/config/connection-gater.js.map +1 -0
- package/dist/src/config.d.ts +2 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +0 -62
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/auto-dial.d.ts +3 -0
- package/dist/src/connection-manager/auto-dial.d.ts.map +1 -1
- package/dist/src/connection-manager/auto-dial.js +36 -13
- package/dist/src/connection-manager/auto-dial.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.d.ts +4 -0
- package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +23 -8
- package/dist/src/connection-manager/connection-pruner.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +2 -1
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +36 -14
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +8 -7
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +23 -34
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/content-routing/index.d.ts +0 -10
- package/dist/src/content-routing/index.d.ts.map +1 -1
- package/dist/src/content-routing/index.js +7 -42
- package/dist/src/content-routing/index.js.map +1 -1
- package/dist/src/content-routing/utils.d.ts.map +1 -1
- package/dist/src/content-routing/utils.js +3 -1
- package/dist/src/content-routing/utils.js.map +1 -1
- package/dist/src/fetch/index.d.ts +13 -35
- package/dist/src/fetch/index.d.ts.map +1 -1
- package/dist/src/fetch/index.js +7 -9
- package/dist/src/fetch/index.js.map +1 -1
- package/dist/src/identify/identify.d.ts +53 -0
- package/dist/src/identify/identify.d.ts.map +1 -0
- package/dist/src/identify/identify.js +405 -0
- package/dist/src/identify/identify.js.map +1 -0
- package/dist/src/identify/index.d.ts +12 -58
- package/dist/src/identify/index.d.ts.map +1 -1
- package/dist/src/identify/index.js +5 -388
- package/dist/src/identify/index.js.map +1 -1
- package/dist/src/index.d.ts +13 -68
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/insecure/index.js.map +1 -1
- package/dist/src/libp2p.d.ts +11 -42
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +137 -196
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/peer-routing.d.ts +1 -38
- package/dist/src/peer-routing.d.ts.map +1 -1
- package/dist/src/peer-routing.js +0 -59
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/ping/constants.d.ts +4 -0
- package/dist/src/ping/constants.d.ts.map +1 -1
- package/dist/src/ping/constants.js +10 -0
- package/dist/src/ping/constants.js.map +1 -1
- package/dist/src/ping/index.d.ts +10 -27
- package/dist/src/ping/index.d.ts.map +1 -1
- package/dist/src/ping/index.js +18 -21
- package/dist/src/ping/index.js.map +1 -1
- package/dist/src/registrar.d.ts +5 -2
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +27 -25
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.d.ts +11 -4
- package/dist/src/transport-manager.d.ts.map +1 -1
- package/dist/src/transport-manager.js +19 -10
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +15 -10
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +39 -48
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/upnp-nat/index.d.ts +42 -0
- package/dist/src/upnp-nat/index.d.ts.map +1 -0
- package/dist/src/{nat-manager.js → upnp-nat/index.js} +11 -7
- package/dist/src/upnp-nat/index.js.map +1 -0
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/typedoc-urls.json +25 -10
- package/package.json +61 -45
- package/src/address-manager/index.ts +50 -8
- package/src/address-manager/utils.ts +14 -0
- package/src/autonat/constants.ts +17 -2
- package/src/autonat/index.ts +53 -45
- package/src/circuit-relay/server/advert-service.ts +2 -2
- package/src/circuit-relay/server/index.ts +11 -3
- package/src/circuit-relay/transport/discovery.ts +5 -3
- package/src/circuit-relay/transport/index.ts +9 -4
- package/src/circuit-relay/transport/listener.ts +38 -28
- package/src/circuit-relay/transport/reservation-store.ts +34 -20
- package/src/components.ts +71 -234
- package/src/config/connection-gater.browser.ts +31 -0
- package/src/config/connection-gater.ts +19 -0
- package/src/config.ts +3 -64
- package/src/connection-manager/auto-dial.ts +44 -15
- package/src/connection-manager/connection-pruner.ts +28 -8
- package/src/connection-manager/dial-queue.ts +41 -21
- package/src/connection-manager/index.ts +31 -43
- package/src/content-routing/index.ts +7 -55
- package/src/content-routing/utils.ts +3 -1
- package/src/fetch/index.ts +51 -14
- package/src/identify/identify.ts +518 -0
- package/src/identify/index.ts +17 -507
- package/src/index.ts +14 -77
- package/src/insecure/index.ts +4 -4
- package/src/libp2p.ts +139 -260
- package/src/peer-routing.ts +1 -101
- package/src/ping/constants.ts +11 -0
- package/src/ping/index.ts +32 -28
- package/src/registrar.ts +31 -27
- package/src/transport-manager.ts +27 -13
- package/src/upgrader.ts +62 -58
- package/src/{nat-manager.ts → upnp-nat/index.ts} +16 -17
- package/src/version.ts +1 -1
- package/dist/src/dht/dht-content-routing.d.ts +0 -17
- package/dist/src/dht/dht-content-routing.d.ts.map +0 -1
- package/dist/src/dht/dht-content-routing.js +0 -32
- package/dist/src/dht/dht-content-routing.js.map +0 -1
- package/dist/src/dht/dht-peer-routing.d.ts +0 -15
- package/dist/src/dht/dht-peer-routing.d.ts.map +0 -1
- package/dist/src/dht/dht-peer-routing.js +0 -26
- package/dist/src/dht/dht-peer-routing.js.map +0 -1
- package/dist/src/dht/dummy-dht.d.ts +0 -20
- package/dist/src/dht/dummy-dht.d.ts.map +0 -1
- package/dist/src/dht/dummy-dht.js +0 -46
- package/dist/src/dht/dummy-dht.js.map +0 -1
- package/dist/src/nat-manager.d.ts +0 -74
- package/dist/src/nat-manager.d.ts.map +0 -1
- package/dist/src/nat-manager.js.map +0 -1
- package/dist/src/peer-record-updater.d.ts +0 -24
- package/dist/src/peer-record-updater.d.ts.map +0 -1
- package/dist/src/peer-record-updater.js +0 -44
- package/dist/src/peer-record-updater.js.map +0 -1
- package/src/dht/dht-content-routing.ts +0 -44
- package/src/dht/dht-peer-routing.ts +0 -36
- package/src/dht/dummy-dht.ts +0 -60
- package/src/peer-record-updater.ts +0 -65
package/src/identify/index.ts
CHANGED
|
@@ -1,70 +1,43 @@
|
|
|
1
|
-
import { logger } from '@libp2p/logger'
|
|
2
|
-
import { CodeError } from '@libp2p/interfaces/errors'
|
|
3
|
-
import * as lp from 'it-length-prefixed'
|
|
4
|
-
import { pipe } from 'it-pipe'
|
|
5
|
-
import first from 'it-first'
|
|
6
|
-
import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
|
|
7
|
-
import { Multiaddr, multiaddr, protocols } from '@multiformats/multiaddr'
|
|
8
1
|
import { Identify } from './pb/message.js'
|
|
9
|
-
import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
|
|
10
2
|
import {
|
|
11
3
|
MULTICODEC_IDENTIFY,
|
|
12
|
-
MULTICODEC_IDENTIFY_PUSH
|
|
13
|
-
IDENTIFY_PROTOCOL_VERSION,
|
|
14
|
-
MULTICODEC_IDENTIFY_PROTOCOL_NAME,
|
|
15
|
-
MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME,
|
|
16
|
-
MULTICODEC_IDENTIFY_PROTOCOL_VERSION,
|
|
17
|
-
MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION
|
|
4
|
+
MULTICODEC_IDENTIFY_PUSH
|
|
18
5
|
} from './consts.js'
|
|
19
|
-
import {
|
|
20
|
-
import type { IncomingStreamData, Registrar } from '@libp2p/interface-registrar'
|
|
21
|
-
import type { Connection, Stream } from '@libp2p/interface-connection'
|
|
22
|
-
import type { Startable } from '@libp2p/interfaces/startable'
|
|
23
|
-
import { peerIdFromKeys } from '@libp2p/peer-id'
|
|
24
|
-
import { TimeoutController } from 'timeout-abort-controller'
|
|
25
|
-
import type { AbortOptions } from '@libp2p/interfaces'
|
|
26
|
-
import { abortableDuplex } from 'abortable-iterator'
|
|
27
|
-
import { setMaxListeners } from 'events'
|
|
6
|
+
import type { Registrar } from '@libp2p/interface-registrar'
|
|
28
7
|
import type { ConnectionManager } from '@libp2p/interface-connection-manager'
|
|
29
8
|
import type { PeerId } from '@libp2p/interface-peer-id'
|
|
30
9
|
import type { PeerStore } from '@libp2p/interface-peer-store'
|
|
31
10
|
import type { AddressManager } from '@libp2p/interface-address-manager'
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
// https://github.com/libp2p/go-libp2p/blob/8d2e54e1637041d5cf4fac1e531287560bd1f4ac/p2p/protocol/identify/id.go#L52
|
|
36
|
-
const MAX_IDENTIFY_MESSAGE_SIZE = 1024 * 8
|
|
37
|
-
|
|
38
|
-
export interface HostProperties {
|
|
39
|
-
agentVersion: string
|
|
40
|
-
}
|
|
11
|
+
import type { EventEmitter } from '@libp2p/interfaces/events'
|
|
12
|
+
import type { Libp2pEvents } from '@libp2p/interface-libp2p'
|
|
13
|
+
import { DefaultIdentifyService } from './identify.js'
|
|
41
14
|
|
|
42
15
|
export interface IdentifyServiceInit {
|
|
43
16
|
/**
|
|
44
17
|
* The prefix to use for the protocol (default: 'ipfs')
|
|
45
18
|
*/
|
|
46
|
-
protocolPrefix
|
|
19
|
+
protocolPrefix?: string
|
|
47
20
|
|
|
48
21
|
/**
|
|
49
22
|
* What details we should send as part of an identify message
|
|
50
23
|
*/
|
|
51
|
-
|
|
24
|
+
agentVersion?: string
|
|
52
25
|
|
|
53
26
|
/**
|
|
54
27
|
* How long we should wait for a remote peer to send their identify response
|
|
55
28
|
*/
|
|
56
|
-
timeout
|
|
29
|
+
timeout?: number
|
|
57
30
|
|
|
58
31
|
/**
|
|
59
32
|
* Identify responses larger than this in bytes will be rejected (default: 8192)
|
|
60
33
|
*/
|
|
61
34
|
maxIdentifyMessageSize?: number
|
|
62
35
|
|
|
63
|
-
maxInboundStreams
|
|
64
|
-
maxOutboundStreams
|
|
36
|
+
maxInboundStreams?: number
|
|
37
|
+
maxOutboundStreams?: number
|
|
65
38
|
|
|
66
|
-
maxPushIncomingStreams
|
|
67
|
-
maxPushOutgoingStreams
|
|
39
|
+
maxPushIncomingStreams?: number
|
|
40
|
+
maxPushOutgoingStreams?: number
|
|
68
41
|
maxObservedAddresses?: number
|
|
69
42
|
}
|
|
70
43
|
|
|
@@ -74,474 +47,7 @@ export interface IdentifyServiceComponents {
|
|
|
74
47
|
connectionManager: ConnectionManager
|
|
75
48
|
registrar: Registrar
|
|
76
49
|
addressManager: AddressManager
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
export class IdentifyService implements Startable {
|
|
80
|
-
private readonly components: IdentifyServiceComponents
|
|
81
|
-
private readonly identifyProtocolStr: string
|
|
82
|
-
private readonly identifyPushProtocolStr: string
|
|
83
|
-
public readonly host: {
|
|
84
|
-
protocolVersion: string
|
|
85
|
-
agentVersion: string
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private readonly init: IdentifyServiceInit
|
|
89
|
-
private started: boolean
|
|
90
|
-
|
|
91
|
-
constructor (components: IdentifyServiceComponents, init: IdentifyServiceInit) {
|
|
92
|
-
this.components = components
|
|
93
|
-
this.started = false
|
|
94
|
-
this.init = init
|
|
95
|
-
|
|
96
|
-
this.identifyProtocolStr = `/${init.protocolPrefix}/${MULTICODEC_IDENTIFY_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PROTOCOL_VERSION}`
|
|
97
|
-
this.identifyPushProtocolStr = `/${init.protocolPrefix}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_NAME}/${MULTICODEC_IDENTIFY_PUSH_PROTOCOL_VERSION}`
|
|
98
|
-
|
|
99
|
-
// Store self host metadata
|
|
100
|
-
this.host = {
|
|
101
|
-
protocolVersion: `${init.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`,
|
|
102
|
-
...init.host
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// When a new connection happens, trigger identify
|
|
106
|
-
this.components.connectionManager.addEventListener('peer:connect', (evt) => {
|
|
107
|
-
const connection = evt.detail
|
|
108
|
-
this.identify(connection).catch(log.error)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
// When self multiaddrs change, trigger identify-push
|
|
112
|
-
this.components.peerStore.addEventListener('change:multiaddrs', (evt) => {
|
|
113
|
-
const { peerId } = evt.detail
|
|
114
|
-
|
|
115
|
-
if (this.components.peerId.equals(peerId)) {
|
|
116
|
-
void this.pushToPeerStore().catch(err => { log.error(err) })
|
|
117
|
-
}
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
// When self protocols change, trigger identify-push
|
|
121
|
-
this.components.peerStore.addEventListener('change:protocols', (evt) => {
|
|
122
|
-
const { peerId } = evt.detail
|
|
123
|
-
|
|
124
|
-
if (this.components.peerId.equals(peerId)) {
|
|
125
|
-
void this.pushToPeerStore().catch(err => { log.error(err) })
|
|
126
|
-
}
|
|
127
|
-
})
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
isStarted (): boolean {
|
|
131
|
-
return this.started
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
async start (): Promise<void> {
|
|
135
|
-
if (this.started) {
|
|
136
|
-
return
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'AgentVersion', uint8ArrayFromString(this.host.agentVersion))
|
|
140
|
-
await this.components.peerStore.metadataBook.setValue(this.components.peerId, 'ProtocolVersion', uint8ArrayFromString(this.host.protocolVersion))
|
|
141
|
-
|
|
142
|
-
await this.components.registrar.handle(this.identifyProtocolStr, (data) => {
|
|
143
|
-
void this._handleIdentify(data).catch(err => {
|
|
144
|
-
log.error(err)
|
|
145
|
-
})
|
|
146
|
-
}, {
|
|
147
|
-
maxInboundStreams: this.init.maxInboundStreams,
|
|
148
|
-
maxOutboundStreams: this.init.maxOutboundStreams
|
|
149
|
-
})
|
|
150
|
-
await this.components.registrar.handle(this.identifyPushProtocolStr, (data) => {
|
|
151
|
-
void this._handlePush(data).catch(err => {
|
|
152
|
-
log.error(err)
|
|
153
|
-
})
|
|
154
|
-
}, {
|
|
155
|
-
maxInboundStreams: this.init.maxPushIncomingStreams,
|
|
156
|
-
maxOutboundStreams: this.init.maxPushOutgoingStreams
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
this.started = true
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
async stop (): Promise<void> {
|
|
163
|
-
await this.components.registrar.unhandle(this.identifyProtocolStr)
|
|
164
|
-
await this.components.registrar.unhandle(this.identifyPushProtocolStr)
|
|
165
|
-
|
|
166
|
-
this.started = false
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Send an Identify Push update to the list of connections
|
|
171
|
-
*/
|
|
172
|
-
async push (connections: Connection[]): Promise<void> {
|
|
173
|
-
const signedPeerRecord = await this.components.peerStore.addressBook.getRawEnvelope(this.components.peerId)
|
|
174
|
-
const listenAddrs = this.components.addressManager.getAddresses().map((ma) => ma.bytes)
|
|
175
|
-
const protocols = await this.components.peerStore.protoBook.get(this.components.peerId)
|
|
176
|
-
|
|
177
|
-
const pushes = connections.map(async connection => {
|
|
178
|
-
let stream: Stream | undefined
|
|
179
|
-
const timeoutController = new TimeoutController(this.init.timeout)
|
|
180
|
-
|
|
181
|
-
try {
|
|
182
|
-
// fails on node < 15.4
|
|
183
|
-
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
184
|
-
} catch {}
|
|
185
|
-
|
|
186
|
-
try {
|
|
187
|
-
stream = await connection.newStream([this.identifyPushProtocolStr], {
|
|
188
|
-
signal: timeoutController.signal
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
// make stream abortable
|
|
192
|
-
const source = abortableDuplex(stream, timeoutController.signal)
|
|
193
|
-
|
|
194
|
-
await source.sink(pipe(
|
|
195
|
-
[Identify.encode({
|
|
196
|
-
listenAddrs,
|
|
197
|
-
signedPeerRecord,
|
|
198
|
-
protocols
|
|
199
|
-
})],
|
|
200
|
-
(source) => lp.encode(source)
|
|
201
|
-
))
|
|
202
|
-
} catch (err: any) {
|
|
203
|
-
// Just log errors
|
|
204
|
-
log.error('could not push identify update to peer', err)
|
|
205
|
-
} finally {
|
|
206
|
-
if (stream != null) {
|
|
207
|
-
stream.close()
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
timeoutController.clear()
|
|
211
|
-
}
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
await Promise.all(pushes)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Calls `push` on all peer connections
|
|
219
|
-
*/
|
|
220
|
-
async pushToPeerStore (): Promise<void> {
|
|
221
|
-
// Do not try to push if we are not running
|
|
222
|
-
if (!this.isStarted()) {
|
|
223
|
-
return
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
const connections: Connection[] = []
|
|
227
|
-
|
|
228
|
-
for (const conn of this.components.connectionManager.getConnections()) {
|
|
229
|
-
const peerId = conn.remotePeer
|
|
230
|
-
const peer = await this.components.peerStore.get(peerId)
|
|
231
|
-
|
|
232
|
-
if (!peer.protocols.includes(this.identifyPushProtocolStr)) {
|
|
233
|
-
continue
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
connections.push(conn)
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
await this.push(connections)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
async _identify (connection: Connection, options: AbortOptions = {}): Promise<Identify> {
|
|
243
|
-
let timeoutController
|
|
244
|
-
let signal = options.signal
|
|
245
|
-
let stream: Stream | undefined
|
|
246
|
-
|
|
247
|
-
// create a timeout if no abort signal passed
|
|
248
|
-
if (signal == null) {
|
|
249
|
-
timeoutController = new TimeoutController(this.init.timeout)
|
|
250
|
-
signal = timeoutController.signal
|
|
251
|
-
|
|
252
|
-
try {
|
|
253
|
-
// fails on node < 15.4
|
|
254
|
-
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
255
|
-
} catch {}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
try {
|
|
259
|
-
stream = await connection.newStream([this.identifyProtocolStr], {
|
|
260
|
-
signal
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
// make stream abortable
|
|
264
|
-
const source = abortableDuplex(stream, signal)
|
|
265
|
-
|
|
266
|
-
const data = await pipe(
|
|
267
|
-
[],
|
|
268
|
-
source,
|
|
269
|
-
(source) => lp.decode(source, {
|
|
270
|
-
maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
|
|
271
|
-
}),
|
|
272
|
-
async (source) => await first(source)
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
if (data == null) {
|
|
276
|
-
throw new CodeError('No data could be retrieved', codes.ERR_CONNECTION_ENDED)
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
try {
|
|
280
|
-
return Identify.decode(data)
|
|
281
|
-
} catch (err: any) {
|
|
282
|
-
throw new CodeError(String(err), codes.ERR_INVALID_MESSAGE)
|
|
283
|
-
}
|
|
284
|
-
} finally {
|
|
285
|
-
if (timeoutController != null) {
|
|
286
|
-
timeoutController.clear()
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (stream != null) {
|
|
290
|
-
stream.close()
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Requests the `Identify` message from peer associated with the given `connection`.
|
|
297
|
-
* If the identified peer does not match the `PeerId` associated with the connection,
|
|
298
|
-
* an error will be thrown.
|
|
299
|
-
*/
|
|
300
|
-
async identify (connection: Connection, options: AbortOptions = {}): Promise<void> {
|
|
301
|
-
const message = await this._identify(connection, options)
|
|
302
|
-
|
|
303
|
-
const {
|
|
304
|
-
publicKey,
|
|
305
|
-
listenAddrs,
|
|
306
|
-
protocols,
|
|
307
|
-
observedAddr,
|
|
308
|
-
signedPeerRecord,
|
|
309
|
-
agentVersion,
|
|
310
|
-
protocolVersion
|
|
311
|
-
} = message
|
|
312
|
-
|
|
313
|
-
if (publicKey == null) {
|
|
314
|
-
throw new CodeError('public key was missing from identify message', codes.ERR_MISSING_PUBLIC_KEY)
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
const id = await peerIdFromKeys(publicKey)
|
|
318
|
-
|
|
319
|
-
if (!connection.remotePeer.equals(id)) {
|
|
320
|
-
throw new CodeError('identified peer does not match the expected peer', codes.ERR_INVALID_PEER)
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
if (this.components.peerId.equals(id)) {
|
|
324
|
-
throw new CodeError('identified peer is our own peer id?', codes.ERR_INVALID_PEER)
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// Get the observedAddr if there is one
|
|
328
|
-
const cleanObservedAddr = IdentifyService.getCleanMultiaddr(observedAddr)
|
|
329
|
-
|
|
330
|
-
if (signedPeerRecord != null) {
|
|
331
|
-
log('received signed peer record from %p', id)
|
|
332
|
-
|
|
333
|
-
try {
|
|
334
|
-
const envelope = await RecordEnvelope.openAndCertify(signedPeerRecord, PeerRecord.DOMAIN)
|
|
335
|
-
|
|
336
|
-
if (!envelope.peerId.equals(id)) {
|
|
337
|
-
throw new CodeError('identified peer does not match the expected peer', codes.ERR_INVALID_PEER)
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) {
|
|
341
|
-
await this.components.peerStore.protoBook.set(id, protocols)
|
|
342
|
-
|
|
343
|
-
if (agentVersion != null) {
|
|
344
|
-
await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion))
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
if (protocolVersion != null) {
|
|
348
|
-
await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion))
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
log('identify completed for peer %p with protocols %o', id, protocols)
|
|
352
|
-
|
|
353
|
-
return
|
|
354
|
-
}
|
|
355
|
-
} catch (err: any) {
|
|
356
|
-
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
|
357
|
-
}
|
|
358
|
-
} else {
|
|
359
|
-
log('no signed peer record received from %p', id)
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
log('falling back to legacy addresses from %p', id)
|
|
363
|
-
|
|
364
|
-
// LEGACY: Update peers data in PeerStore
|
|
365
|
-
try {
|
|
366
|
-
await this.components.peerStore.addressBook.set(id, listenAddrs.map((addr) => multiaddr(addr)))
|
|
367
|
-
} catch (err: any) {
|
|
368
|
-
log.error('received invalid addrs', err)
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
await this.components.peerStore.protoBook.set(id, protocols)
|
|
372
|
-
|
|
373
|
-
if (agentVersion != null) {
|
|
374
|
-
await this.components.peerStore.metadataBook.setValue(id, 'AgentVersion', uint8ArrayFromString(agentVersion))
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
if (protocolVersion != null) {
|
|
378
|
-
await this.components.peerStore.metadataBook.setValue(id, 'ProtocolVersion', uint8ArrayFromString(protocolVersion))
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
log('identify completed for peer %p and protocols %o', id, protocols)
|
|
382
|
-
log('our observed address is %s', cleanObservedAddr)
|
|
383
|
-
|
|
384
|
-
if (cleanObservedAddr != null &&
|
|
385
|
-
this.components.addressManager.getObservedAddrs().length < (this.init.maxObservedAddresses ?? Infinity)) {
|
|
386
|
-
log('storing our observed address %s', cleanObservedAddr?.toString())
|
|
387
|
-
this.components.addressManager.addObservedAddr(cleanObservedAddr)
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Sends the `Identify` response with the Signed Peer Record
|
|
393
|
-
* to the requesting peer over the given `connection`
|
|
394
|
-
*/
|
|
395
|
-
async _handleIdentify (data: IncomingStreamData): Promise<void> {
|
|
396
|
-
const { connection, stream } = data
|
|
397
|
-
const timeoutController = new TimeoutController(this.init.timeout)
|
|
398
|
-
|
|
399
|
-
try {
|
|
400
|
-
// fails on node < 15.4
|
|
401
|
-
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
402
|
-
} catch {}
|
|
403
|
-
|
|
404
|
-
try {
|
|
405
|
-
const publicKey = this.components.peerId.publicKey ?? new Uint8Array(0)
|
|
406
|
-
const peerData = await this.components.peerStore.get(this.components.peerId)
|
|
407
|
-
const multiaddrs = this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
|
|
408
|
-
let signedPeerRecord = peerData.peerRecordEnvelope
|
|
409
|
-
|
|
410
|
-
if (multiaddrs.length > 0 && signedPeerRecord == null) {
|
|
411
|
-
const peerRecord = new PeerRecord({
|
|
412
|
-
peerId: this.components.peerId,
|
|
413
|
-
multiaddrs
|
|
414
|
-
})
|
|
415
|
-
|
|
416
|
-
const envelope = await RecordEnvelope.seal(peerRecord, this.components.peerId)
|
|
417
|
-
await this.components.peerStore.addressBook.consumePeerRecord(envelope)
|
|
418
|
-
signedPeerRecord = envelope.marshal().subarray()
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const message = Identify.encode({
|
|
422
|
-
protocolVersion: this.host.protocolVersion,
|
|
423
|
-
agentVersion: this.host.agentVersion,
|
|
424
|
-
publicKey,
|
|
425
|
-
listenAddrs: multiaddrs.map(addr => addr.bytes),
|
|
426
|
-
signedPeerRecord,
|
|
427
|
-
observedAddr: connection.remoteAddr.bytes,
|
|
428
|
-
protocols: peerData.protocols
|
|
429
|
-
})
|
|
430
|
-
|
|
431
|
-
// make stream abortable
|
|
432
|
-
const source = abortableDuplex(stream, timeoutController.signal)
|
|
433
|
-
|
|
434
|
-
const msgWithLenPrefix = pipe([message], (source) => lp.encode(source))
|
|
435
|
-
await source.sink(msgWithLenPrefix)
|
|
436
|
-
} catch (err: any) {
|
|
437
|
-
log.error('could not respond to identify request', err)
|
|
438
|
-
} finally {
|
|
439
|
-
stream.close()
|
|
440
|
-
timeoutController.clear()
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* Reads the Identify Push message from the given `connection`
|
|
446
|
-
*/
|
|
447
|
-
async _handlePush (data: IncomingStreamData): Promise<void> {
|
|
448
|
-
const { connection, stream } = data
|
|
449
|
-
const timeoutController = new TimeoutController(this.init.timeout)
|
|
450
|
-
|
|
451
|
-
try {
|
|
452
|
-
// fails on node < 15.4
|
|
453
|
-
setMaxListeners?.(Infinity, timeoutController.signal)
|
|
454
|
-
} catch {}
|
|
455
|
-
|
|
456
|
-
let message: Identify | undefined
|
|
457
|
-
try {
|
|
458
|
-
// make stream abortable
|
|
459
|
-
const source = abortableDuplex(stream, timeoutController.signal)
|
|
460
|
-
|
|
461
|
-
const data = await pipe(
|
|
462
|
-
[],
|
|
463
|
-
source,
|
|
464
|
-
(source) => lp.decode(source, {
|
|
465
|
-
maxDataLength: this.init.maxIdentifyMessageSize ?? MAX_IDENTIFY_MESSAGE_SIZE
|
|
466
|
-
}),
|
|
467
|
-
async (source) => await first(source)
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
if (data != null) {
|
|
471
|
-
message = Identify.decode(data)
|
|
472
|
-
}
|
|
473
|
-
} catch (err: any) {
|
|
474
|
-
log.error('received invalid message', err)
|
|
475
|
-
return
|
|
476
|
-
} finally {
|
|
477
|
-
stream.close()
|
|
478
|
-
timeoutController.clear()
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
if (message == null) {
|
|
482
|
-
log.error('received invalid message')
|
|
483
|
-
return
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
const id = connection.remotePeer
|
|
487
|
-
|
|
488
|
-
if (this.components.peerId.equals(id)) {
|
|
489
|
-
log('received push from ourselves?')
|
|
490
|
-
return
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
log('received push from %p', id)
|
|
494
|
-
|
|
495
|
-
if (message.signedPeerRecord != null) {
|
|
496
|
-
log('received signedPeerRecord in push')
|
|
497
|
-
|
|
498
|
-
try {
|
|
499
|
-
const envelope = await RecordEnvelope.openAndCertify(message.signedPeerRecord, PeerRecord.DOMAIN)
|
|
500
|
-
|
|
501
|
-
if (await this.components.peerStore.addressBook.consumePeerRecord(envelope)) {
|
|
502
|
-
log('consumed signedPeerRecord sent in push')
|
|
503
|
-
|
|
504
|
-
await this.components.peerStore.protoBook.set(id, message.protocols)
|
|
505
|
-
return
|
|
506
|
-
} else {
|
|
507
|
-
log('failed to consume signedPeerRecord sent in push')
|
|
508
|
-
}
|
|
509
|
-
} catch (err: any) {
|
|
510
|
-
log('received invalid envelope, discard it and fallback to listenAddrs is available', err)
|
|
511
|
-
}
|
|
512
|
-
} else {
|
|
513
|
-
log('did not receive signedPeerRecord in push')
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
// LEGACY: Update peers data in PeerStore
|
|
517
|
-
try {
|
|
518
|
-
await this.components.peerStore.addressBook.set(id, message.listenAddrs.map((addr) => multiaddr(addr)))
|
|
519
|
-
} catch (err: any) {
|
|
520
|
-
log.error('received invalid addrs', err)
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
// Update the protocols
|
|
524
|
-
try {
|
|
525
|
-
await this.components.peerStore.protoBook.set(id, message.protocols)
|
|
526
|
-
} catch (err: any) {
|
|
527
|
-
log.error('received invalid protocols', err)
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
log('handled push from %p', id)
|
|
531
|
-
}
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Takes the `addr` and converts it to a Multiaddr if possible
|
|
535
|
-
*/
|
|
536
|
-
static getCleanMultiaddr (addr: Uint8Array | string | null | undefined): Multiaddr | undefined {
|
|
537
|
-
if (addr != null && addr.length > 0) {
|
|
538
|
-
try {
|
|
539
|
-
return multiaddr(addr)
|
|
540
|
-
} catch {
|
|
541
|
-
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
}
|
|
50
|
+
events: EventEmitter<Libp2pEvents>
|
|
545
51
|
}
|
|
546
52
|
|
|
547
53
|
/**
|
|
@@ -553,3 +59,7 @@ export const multicodecs = {
|
|
|
553
59
|
}
|
|
554
60
|
|
|
555
61
|
export const Message = { Identify }
|
|
62
|
+
|
|
63
|
+
export function identifyService (init: IdentifyServiceInit = {}): (components: IdentifyServiceComponents) => {} {
|
|
64
|
+
return (components) => new DefaultIdentifyService(components, init)
|
|
65
|
+
}
|