@libp2p/identify 3.0.38 → 3.0.39-a02cb0461

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,10 +1,9 @@
1
1
  import { serviceCapabilities } from '@libp2p/interface'
2
2
  import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
3
- import { debounce } from '@libp2p/utils/debounce'
3
+ import { debounce, pbStream } from '@libp2p/utils'
4
4
  import { protocols } from '@multiformats/multiaddr'
5
5
  import drain from 'it-drain'
6
6
  import parallel from 'it-parallel'
7
- import { pbStream } from 'it-protobuf-stream'
8
7
  import { setMaxListeners } from 'main-event'
9
8
  import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
10
9
  import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
@@ -16,7 +15,7 @@ import {
16
15
  import { Identify as IdentifyMessage } from './pb/message.js'
17
16
  import { AbstractIdentify, consumeIdentifyMessage, defaultValues } from './utils.js'
18
17
  import type { IdentifyPush as IdentifyPushInterface, IdentifyPushComponents, IdentifyPushInit } from './index.js'
19
- import type { Stream, Startable, IncomingStreamData } from '@libp2p/interface'
18
+ import type { Stream, Startable, Connection } from '@libp2p/interface'
20
19
  import type { ConnectionManager } from '@libp2p/interface-internal'
21
20
 
22
21
  export class IdentifyPush extends AbstractIdentify implements Startable, IdentifyPushInterface {
@@ -64,21 +63,21 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif
64
63
  }
65
64
 
66
65
  try {
67
- const listenAddresses = this.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
66
+ const listenAddresses = this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
68
67
  const peerRecord = new PeerRecord({
69
- peerId: this.peerId,
68
+ peerId: this.components.peerId,
70
69
  multiaddrs: listenAddresses
71
70
  })
72
- const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.privateKey)
73
- const supportedProtocols = this.registrar.getProtocols()
74
- const peer = await this.peerStore.get(this.peerId)
71
+ const signedPeerRecord = await RecordEnvelope.seal(peerRecord, this.components.privateKey)
72
+ const supportedProtocols = this.components.registrar.getProtocols()
73
+ const peer = await this.components.peerStore.get(this.components.peerId)
75
74
  const agentVersion = uint8ArrayToString(peer.metadata.get('AgentVersion') ?? uint8ArrayFromString(this.host.agentVersion))
76
75
  const protocolVersion = uint8ArrayToString(peer.metadata.get('ProtocolVersion') ?? uint8ArrayFromString(this.host.protocolVersion))
77
76
  const self = this
78
77
 
79
78
  async function * pushToConnections (): AsyncGenerator<() => Promise<void>> {
80
79
  for (const connection of self.connectionManager.getConnections()) {
81
- const peer = await self.peerStore.get(connection.remotePeer)
80
+ const peer = await self.components.peerStore.get(connection.remotePeer)
82
81
 
83
82
  if (!peer.protocols.includes(self.protocol)) {
84
83
  continue
@@ -114,8 +113,9 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif
114
113
  signal
115
114
  })
116
115
  } catch (err: any) {
117
- // Just log errors
118
- self.log.error('could not push identify update to peer', err)
116
+ // Just log errors if the stream was opened
117
+ const log = stream?.log.newScope('identify-push')
118
+ log?.error('could not push identify update to peer', err)
119
119
  stream?.abort(err)
120
120
  }
121
121
  }
@@ -133,32 +133,26 @@ export class IdentifyPush extends AbstractIdentify implements Startable, Identif
133
133
  /**
134
134
  * Reads the Identify Push message from the given `connection`
135
135
  */
136
- async handleProtocol (data: IncomingStreamData): Promise<void> {
137
- const { connection, stream } = data
136
+ async handleProtocol (stream: Stream, connection: Connection): Promise<void> {
137
+ const log = stream.log.newScope('identify-push')
138
138
 
139
- try {
140
- if (this.peerId.equals(connection.remotePeer)) {
141
- throw new Error('received push from ourselves?')
142
- }
139
+ if (this.components.peerId.equals(connection.remotePeer)) {
140
+ throw new Error('received push from ourselves?')
141
+ }
143
142
 
144
- const options = {
145
- signal: AbortSignal.timeout(this.timeout)
146
- }
143
+ const options = {
144
+ signal: AbortSignal.timeout(this.timeout)
145
+ }
147
146
 
148
- const pb = pbStream(stream, {
149
- maxDataLength: this.maxMessageSize
150
- }).pb(IdentifyMessage)
147
+ const pb = pbStream(stream, {
148
+ maxDataLength: this.maxMessageSize
149
+ }).pb(IdentifyMessage)
151
150
 
152
- const message = await pb.read(options)
153
- await stream.close(options)
151
+ const message = await pb.read(options)
152
+ await stream.close(options)
154
153
 
155
- await consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
156
- } catch (err: any) {
157
- this.log.error('received invalid message', err)
158
- stream.abort(err)
159
- return
160
- }
154
+ await consumeIdentifyMessage(this.components.peerStore, this.components.events, log, connection, message)
161
155
 
162
- this.log.trace('handled push from %p', connection.remotePeer)
156
+ log.trace('handled push from %p', connection.remotePeer)
163
157
  }
164
158
  }
package/src/identify.ts CHANGED
@@ -1,12 +1,10 @@
1
1
  import { publicKeyFromProtobuf, publicKeyToProtobuf } from '@libp2p/crypto/keys'
2
- import { InvalidMessageError, UnsupportedProtocolError, serviceCapabilities } from '@libp2p/interface'
2
+ import { InvalidMessageError, serviceCapabilities } from '@libp2p/interface'
3
3
  import { peerIdFromCID } from '@libp2p/peer-id'
4
4
  import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
5
- import { isGlobalUnicast } from '@libp2p/utils/multiaddr/is-global-unicast'
6
- import { isPrivate } from '@libp2p/utils/multiaddr/is-private'
7
- import { CODE_IP6, CODE_IP6ZONE, protocols } from '@multiformats/multiaddr'
5
+ import { isGlobalUnicast, isPrivate, pbStream } from '@libp2p/utils'
6
+ import { CODE_IP6, CODE_IP6ZONE, CODE_P2P } from '@multiformats/multiaddr'
8
7
  import { IP_OR_DOMAIN, TCP } from '@multiformats/multiaddr-matcher'
9
- import { pbStream } from 'it-protobuf-stream'
10
8
  import { setMaxListeners } from 'main-event'
11
9
  import {
12
10
  MULTICODEC_IDENTIFY_PROTOCOL_NAME,
@@ -15,7 +13,7 @@ import {
15
13
  import { Identify as IdentifyMessage } from './pb/message.js'
16
14
  import { AbstractIdentify, consumeIdentifyMessage, defaultValues, getCleanMultiaddr } from './utils.js'
17
15
  import type { Identify as IdentifyInterface, IdentifyComponents, IdentifyInit } from './index.js'
18
- import type { IdentifyResult, AbortOptions, Connection, Stream, Startable, IncomingStreamData } from '@libp2p/interface'
16
+ import type { IdentifyResult, AbortOptions, Connection, Stream, Startable, Logger } from '@libp2p/interface'
19
17
 
20
18
  export class Identify extends AbstractIdentify implements Startable, IdentifyInterface {
21
19
  constructor (components: IdentifyComponents, init: IdentifyInit = {}) {
@@ -30,14 +28,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
30
28
  components.events.addEventListener('connection:open', (evt) => {
31
29
  const connection = evt.detail
32
30
  this.identify(connection)
33
- .catch(err => {
34
- if (err.name === UnsupportedProtocolError.name) {
35
- // the remote did not support identify, ignore the error
36
- return
37
- }
38
-
39
- this.log.error('error during identify trigged by connection:open', err)
40
- })
31
+ .catch(() => {})
41
32
  })
42
33
  }
43
34
  }
@@ -48,6 +39,7 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
48
39
 
49
40
  async _identify (connection: Connection, options: AbortOptions = {}): Promise<IdentifyMessage> {
50
41
  let stream: Stream | undefined
42
+ let log: Logger | undefined
51
43
 
52
44
  if (options.signal == null) {
53
45
  const signal = AbortSignal.timeout(this.timeout)
@@ -64,17 +56,21 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
64
56
  ...options,
65
57
  runOnLimitedConnection: this.runOnLimitedConnection
66
58
  })
59
+ log = stream.log.newScope('identify')
67
60
 
68
61
  const pb = pbStream(stream, {
69
62
  maxDataLength: this.maxMessageSize
70
63
  }).pb(IdentifyMessage)
71
64
 
65
+ log('read response')
72
66
  const message = await pb.read(options)
73
67
 
74
- await stream.close(options)
68
+ log('close write')
69
+ await pb.unwrap().unwrap().close(options)
75
70
 
76
71
  return message
77
72
  } catch (err: any) {
73
+ log?.error('identify failed - %e', err)
78
74
  stream?.abort(err)
79
75
  throw err
80
76
  }
@@ -89,27 +85,27 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
89
85
  } = message
90
86
 
91
87
  if (publicKey == null) {
92
- throw new InvalidMessageError('public key was missing from identify message')
88
+ throw new InvalidMessageError('Public key was missing from identify message')
93
89
  }
94
90
 
95
91
  const key = publicKeyFromProtobuf(publicKey)
96
92
  const id = peerIdFromCID(key.toCID())
97
93
 
98
94
  if (!connection.remotePeer.equals(id)) {
99
- throw new InvalidMessageError('identified peer does not match the expected peer')
95
+ throw new InvalidMessageError('Identified peer does not match the expected peer')
100
96
  }
101
97
 
102
- if (this.peerId.equals(id)) {
103
- throw new InvalidMessageError('identified peer is our own peer id?')
98
+ if (this.components.peerId.equals(id)) {
99
+ throw new InvalidMessageError('Identified peer is our own peer id?')
104
100
  }
105
101
 
106
102
  // if the observed address is publicly routable, add it to the address
107
103
  // manager for verification via AutoNAT
108
104
  this.maybeAddObservedAddress(observedAddr)
109
105
 
110
- this.log('identify completed for peer %p and protocols %o', id, protocols)
106
+ this.log('completed for peer %p and protocols %o', id, protocols)
111
107
 
112
- return consumeIdentifyMessage(this.peerStore, this.events, this.log, connection, message)
108
+ return consumeIdentifyMessage(this.components.peerStore, this.components.events, this.log, connection, message)
113
109
  }
114
110
 
115
111
  private maybeAddObservedAddress (observedAddr: Uint8Array | undefined): void {
@@ -122,7 +118,6 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
122
118
  this.log.trace('our observed address was %a', cleanObservedAddr)
123
119
 
124
120
  if (isPrivate(cleanObservedAddr)) {
125
- this.log.trace('our observed address was private')
126
121
  return
127
122
  }
128
123
 
@@ -142,61 +137,61 @@ export class Identify extends AbstractIdentify implements Startable, IdentifyInt
142
137
  }
143
138
 
144
139
  this.log.trace('storing the observed address')
145
- this.addressManager.addObservedAddr(cleanObservedAddr)
140
+ this.components.addressManager.addObservedAddr(cleanObservedAddr)
146
141
  }
147
142
 
148
143
  /**
149
144
  * Sends the `Identify` response with the Signed Peer Record
150
145
  * to the requesting peer over the given `connection`
151
146
  */
152
- async handleProtocol (data: IncomingStreamData): Promise<void> {
153
- const { connection, stream } = data
147
+ async handleProtocol (stream: Stream, connection: Connection): Promise<void> {
148
+ const log = stream.log.newScope('identify')
154
149
 
155
150
  const signal = AbortSignal.timeout(this.timeout)
156
-
157
151
  setMaxListeners(Infinity, signal)
158
152
 
159
- try {
160
- const peerData = await this.peerStore.get(this.peerId)
161
- const multiaddrs = this.addressManager.getAddresses().map(ma => ma.decapsulateCode(protocols('p2p').code))
162
- let signedPeerRecord = peerData.peerRecordEnvelope
163
-
164
- if (multiaddrs.length > 0 && signedPeerRecord == null) {
165
- const peerRecord = new PeerRecord({
166
- peerId: this.peerId,
167
- multiaddrs
168
- })
169
-
170
- const envelope = await RecordEnvelope.seal(peerRecord, this.privateKey)
171
- signedPeerRecord = envelope.marshal().subarray()
172
- }
173
-
174
- let observedAddr: Uint8Array | undefined = connection.remoteAddr.bytes
175
-
176
- if (!IP_OR_DOMAIN.matches(connection.remoteAddr)) {
177
- observedAddr = undefined
178
- }
153
+ const peerData = await this.components.peerStore.get(this.components.peerId, {
154
+ signal
155
+ })
156
+ const multiaddrs = this.components.addressManager.getAddresses().map(ma => ma.decapsulateCode(CODE_P2P))
157
+ let signedPeerRecord = peerData.peerRecordEnvelope
179
158
 
180
- const pb = pbStream(stream).pb(IdentifyMessage)
181
-
182
- await pb.write({
183
- protocolVersion: this.host.protocolVersion,
184
- agentVersion: this.host.agentVersion,
185
- publicKey: publicKeyToProtobuf(this.privateKey.publicKey),
186
- listenAddrs: multiaddrs.map(addr => addr.bytes),
187
- signedPeerRecord,
188
- observedAddr,
189
- protocols: peerData.protocols
190
- }, {
191
- signal
159
+ if (multiaddrs.length > 0 && signedPeerRecord == null) {
160
+ const peerRecord = new PeerRecord({
161
+ peerId: this.components.peerId,
162
+ multiaddrs
192
163
  })
193
164
 
194
- await stream.close({
165
+ const envelope = await RecordEnvelope.seal(peerRecord, this.components.privateKey, {
195
166
  signal
196
167
  })
197
- } catch (err: any) {
198
- this.log.error('could not respond to identify request', err)
199
- stream.abort(err)
168
+ signedPeerRecord = envelope.marshal().subarray()
169
+ }
170
+
171
+ let observedAddr: Uint8Array | undefined = connection.remoteAddr.bytes
172
+
173
+ if (!IP_OR_DOMAIN.matches(connection.remoteAddr)) {
174
+ observedAddr = undefined
200
175
  }
176
+
177
+ const pb = pbStream(stream).pb(IdentifyMessage)
178
+
179
+ log('send response')
180
+ await pb.write({
181
+ protocolVersion: this.host.protocolVersion,
182
+ agentVersion: this.host.agentVersion,
183
+ publicKey: publicKeyToProtobuf(this.components.privateKey.publicKey),
184
+ listenAddrs: multiaddrs.map(addr => addr.bytes),
185
+ signedPeerRecord,
186
+ observedAddr,
187
+ protocols: peerData.protocols
188
+ }, {
189
+ signal
190
+ })
191
+
192
+ log('close write')
193
+ await pb.unwrap().unwrap().close({
194
+ signal
195
+ })
201
196
  }
202
197
  }
package/src/utils.ts CHANGED
@@ -7,8 +7,7 @@ import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
7
7
  import { IDENTIFY_PROTOCOL_VERSION, MAX_IDENTIFY_MESSAGE_SIZE, MAX_PUSH_CONCURRENCY } from './consts.js'
8
8
  import type { IdentifyComponents, IdentifyInit } from './index.js'
9
9
  import type { Identify as IdentifyMessage } from './pb/message.js'
10
- import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, Logger, Connection, Peer, PeerData, PeerStore, NodeInfo, Startable, PeerId, IncomingStreamData, PrivateKey } from '@libp2p/interface'
11
- import type { AddressManager, Registrar } from '@libp2p/interface-internal'
10
+ import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, Logger, Connection, Peer, PeerData, PeerStore, NodeInfo, Startable, Stream } from '@libp2p/interface'
12
11
  import type { Multiaddr } from '@multiformats/multiaddr'
13
12
  import type { TypedEventTarget } from 'main-event'
14
13
 
@@ -191,31 +190,21 @@ export abstract class AbstractIdentify implements Startable {
191
190
  agentVersion: string
192
191
  }
193
192
 
193
+ protected components: IdentifyComponents
194
194
  protected protocol: string
195
195
  protected started: boolean
196
196
  protected readonly timeout: number
197
- protected readonly peerId: PeerId
198
- protected readonly privateKey: PrivateKey
199
- protected readonly peerStore: PeerStore
200
- protected readonly registrar: Registrar
201
- protected readonly addressManager: AddressManager
202
197
  private readonly maxInboundStreams: number
203
198
  private readonly maxOutboundStreams: number
204
199
  protected readonly maxMessageSize: number
205
200
  protected readonly maxObservedAddresses: number
206
- protected readonly events: TypedEventTarget<Libp2pEvents>
207
201
  protected readonly runOnLimitedConnection: boolean
208
202
  protected readonly log: Logger
209
203
 
210
204
  constructor (components: IdentifyComponents, init: AbstractIdentifyInit) {
211
205
  this.protocol = init.protocol
212
206
  this.started = false
213
- this.peerId = components.peerId
214
- this.privateKey = components.privateKey
215
- this.peerStore = components.peerStore
216
- this.registrar = components.registrar
217
- this.addressManager = components.addressManager
218
- this.events = components.events
207
+ this.components = components
219
208
  this.log = init.log
220
209
 
221
210
  this.timeout = init.timeout ?? defaultValues.timeout
@@ -230,6 +219,8 @@ export abstract class AbstractIdentify implements Startable {
230
219
  protocolVersion: `${init.protocolPrefix ?? defaultValues.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`,
231
220
  agentVersion: getAgentVersion(components.nodeInfo, init.agentVersion)
232
221
  }
222
+
223
+ this.handleProtocol = this.handleProtocol.bind(this)
233
224
  }
234
225
 
235
226
  isStarted (): boolean {
@@ -241,18 +232,14 @@ export abstract class AbstractIdentify implements Startable {
241
232
  return
242
233
  }
243
234
 
244
- await this.peerStore.merge(this.peerId, {
235
+ await this.components.peerStore.merge(this.components.peerId, {
245
236
  metadata: {
246
237
  AgentVersion: uint8ArrayFromString(this.host.agentVersion),
247
238
  ProtocolVersion: uint8ArrayFromString(this.host.protocolVersion)
248
239
  }
249
240
  })
250
241
 
251
- await this.registrar.handle(this.protocol, (data) => {
252
- void this.handleProtocol(data).catch(err => {
253
- this.log.error(err)
254
- })
255
- }, {
242
+ await this.components.registrar.handle(this.protocol, this.handleProtocol, {
256
243
  maxInboundStreams: this.maxInboundStreams,
257
244
  maxOutboundStreams: this.maxOutboundStreams,
258
245
  runOnLimitedConnection: this.runOnLimitedConnection
@@ -262,10 +249,10 @@ export abstract class AbstractIdentify implements Startable {
262
249
  }
263
250
 
264
251
  async stop (): Promise<void> {
265
- await this.registrar.unhandle(this.protocol)
252
+ await this.components.registrar.unhandle(this.protocol)
266
253
 
267
254
  this.started = false
268
255
  }
269
256
 
270
- protected abstract handleProtocol (data: IncomingStreamData): Promise<void>
257
+ protected abstract handleProtocol (stream: Stream, connection: Connection): Promise<void>
271
258
  }
@@ -1,18 +0,0 @@
1
- {
2
- "Identify": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.Identify.html",
3
- ".:Identify": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.Identify.html",
4
- "IdentifyComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyComponents.html",
5
- ".:IdentifyComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyComponents.html",
6
- "IdentifyInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyInit.html",
7
- ".:IdentifyInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyInit.html",
8
- "IdentifyPush": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPush.html",
9
- ".:IdentifyPush": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPush.html",
10
- "IdentifyPushComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPushComponents.html",
11
- ".:IdentifyPushComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPushComponents.html",
12
- "IdentifyPushInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPushInit.html",
13
- ".:IdentifyPushInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_identify.IdentifyPushInit.html",
14
- "identify": "https://libp2p.github.io/js-libp2p/functions/_libp2p_identify.identify.html",
15
- ".:identify": "https://libp2p.github.io/js-libp2p/functions/_libp2p_identify.identify.html",
16
- "identifyPush": "https://libp2p.github.io/js-libp2p/functions/_libp2p_identify.identifyPush.html",
17
- ".:identifyPush": "https://libp2p.github.io/js-libp2p/functions/_libp2p_identify.identifyPush.html"
18
- }