@libp2p/identify 1.0.21-9d13a2f6a → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/utils.ts DELETED
@@ -1,273 +0,0 @@
1
- import { CodeError } from '@libp2p/interface'
2
- import { peerIdFromKeys } from '@libp2p/peer-id'
3
- import { RecordEnvelope, PeerRecord } from '@libp2p/peer-record'
4
- import { type Multiaddr, multiaddr } from '@multiformats/multiaddr'
5
- import { fromString as uint8ArrayFromString } from 'uint8arrays/from-string'
6
- import { isNode, isBrowser, isWebWorker, isElectronMain, isElectronRenderer, isReactNative } from 'wherearewe'
7
- import { IDENTIFY_PROTOCOL_VERSION, MAX_IDENTIFY_MESSAGE_SIZE, MAX_PUSH_CONCURRENCY } from './consts.js'
8
- import type { IdentifyComponents, IdentifyInit } from './index.js'
9
- import type { Identify as IdentifyMessage } from './pb/message.js'
10
- import type { Libp2pEvents, IdentifyResult, SignedPeerRecord, Logger, Connection, TypedEventTarget, Peer, PeerData, PeerStore, NodeInfo, Startable, PeerId, IncomingStreamData } from '@libp2p/interface'
11
- import type { AddressManager, Registrar } from '@libp2p/interface-internal'
12
-
13
- export const defaultValues = {
14
- protocolPrefix: 'ipfs',
15
- timeout: 5000,
16
- maxInboundStreams: 1,
17
- maxOutboundStreams: 1,
18
- maxObservedAddresses: 10,
19
- maxMessageSize: MAX_IDENTIFY_MESSAGE_SIZE,
20
- runOnConnectionOpen: true,
21
- runOnSelfUpdate: true,
22
- runOnTransientConnection: true,
23
- concurrency: MAX_PUSH_CONCURRENCY
24
- }
25
-
26
- /**
27
- * Takes the `addr` and converts it to a Multiaddr if possible
28
- */
29
- export function getCleanMultiaddr (addr: Uint8Array | string | null | undefined): Multiaddr | undefined {
30
- if (addr != null && addr.length > 0) {
31
- try {
32
- return multiaddr(addr)
33
- } catch {
34
-
35
- }
36
- }
37
- }
38
-
39
- export function getAgentVersion (nodeInfo: NodeInfo, agentVersion?: string): string {
40
- if (agentVersion != null) {
41
- return agentVersion
42
- }
43
-
44
- agentVersion = `${nodeInfo.name}/${nodeInfo.version}`
45
- // Append user agent version to default AGENT_VERSION depending on the environment
46
- if (isNode || isElectronMain) {
47
- agentVersion += ` UserAgent=${globalThis.process.version}`
48
- } else if (isBrowser || isWebWorker || isElectronRenderer || isReactNative) {
49
- agentVersion += ` UserAgent=${globalThis.navigator.userAgent}`
50
- }
51
-
52
- return agentVersion
53
- }
54
-
55
- export async function consumeIdentifyMessage (peerStore: PeerStore, events: TypedEventTarget<Libp2pEvents>, log: Logger, connection: Connection, message: IdentifyMessage): Promise<IdentifyResult> {
56
- log('received identify from %p', connection.remotePeer)
57
-
58
- if (message == null) {
59
- throw new CodeError('message was null or undefined', 'ERR_INVALID_MESSAGE')
60
- }
61
-
62
- const peer: PeerData = {}
63
-
64
- if (message.listenAddrs.length > 0) {
65
- peer.addresses = message.listenAddrs.map(buf => ({
66
- isCertified: false,
67
- multiaddr: multiaddr(buf)
68
- }))
69
- }
70
-
71
- if (message.protocols.length > 0) {
72
- peer.protocols = message.protocols
73
- }
74
-
75
- if (message.publicKey != null) {
76
- peer.publicKey = message.publicKey
77
-
78
- const peerId = await peerIdFromKeys(message.publicKey)
79
-
80
- if (!peerId.equals(connection.remotePeer)) {
81
- throw new CodeError('public key did not match remote PeerId', 'ERR_INVALID_PUBLIC_KEY')
82
- }
83
- }
84
-
85
- let output: SignedPeerRecord | undefined
86
-
87
- // if the peer record has been sent, prefer the addresses in the record as they are signed by the remote peer
88
- if (message.signedPeerRecord != null) {
89
- log('received signedPeerRecord from %p', connection.remotePeer)
90
-
91
- let peerRecordEnvelope = message.signedPeerRecord
92
- const envelope = await RecordEnvelope.openAndCertify(peerRecordEnvelope, PeerRecord.DOMAIN)
93
- let peerRecord = PeerRecord.createFromProtobuf(envelope.payload)
94
-
95
- // Verify peerId
96
- if (!peerRecord.peerId.equals(envelope.peerId)) {
97
- throw new CodeError('signing key does not match PeerId in the PeerRecord', 'ERR_INVALID_SIGNING_KEY')
98
- }
99
-
100
- // Make sure remote peer is the one sending the record
101
- if (!connection.remotePeer.equals(peerRecord.peerId)) {
102
- throw new CodeError('signing key does not match remote PeerId', 'ERR_INVALID_PEER_RECORD_KEY')
103
- }
104
-
105
- let existingPeer: Peer | undefined
106
-
107
- try {
108
- existingPeer = await peerStore.get(peerRecord.peerId)
109
- } catch (err: any) {
110
- if (err.code !== 'ERR_NOT_FOUND') {
111
- throw err
112
- }
113
- }
114
-
115
- if (existingPeer != null) {
116
- // don't lose any existing metadata
117
- peer.metadata = existingPeer.metadata
118
-
119
- // if we have previously received a signed record for this peer, compare it to the incoming one
120
- if (existingPeer.peerRecordEnvelope != null) {
121
- const storedEnvelope = await RecordEnvelope.createFromProtobuf(existingPeer.peerRecordEnvelope)
122
- const storedRecord = PeerRecord.createFromProtobuf(storedEnvelope.payload)
123
-
124
- // ensure seq is greater than, or equal to, the last received
125
- if (storedRecord.seqNumber >= peerRecord.seqNumber) {
126
- log('sequence number was lower or equal to existing sequence number - stored: %d received: %d', storedRecord.seqNumber, peerRecord.seqNumber)
127
- peerRecord = storedRecord
128
- peerRecordEnvelope = existingPeer.peerRecordEnvelope
129
- }
130
- }
131
- }
132
-
133
- // store the signed record for next time
134
- peer.peerRecordEnvelope = peerRecordEnvelope
135
-
136
- // override the stored addresses with the signed multiaddrs
137
- peer.addresses = peerRecord.multiaddrs.map(multiaddr => ({
138
- isCertified: true,
139
- multiaddr
140
- }))
141
-
142
- output = {
143
- seq: peerRecord.seqNumber,
144
- addresses: peerRecord.multiaddrs
145
- }
146
- } else {
147
- log('%p did not send a signed peer record', connection.remotePeer)
148
- }
149
-
150
- log('patching %p with', connection.remotePeer, peer)
151
- await peerStore.patch(connection.remotePeer, peer)
152
-
153
- if (message.agentVersion != null || message.protocolVersion != null) {
154
- const metadata: Record<string, Uint8Array> = {}
155
-
156
- if (message.agentVersion != null) {
157
- metadata.AgentVersion = uint8ArrayFromString(message.agentVersion)
158
- }
159
-
160
- if (message.protocolVersion != null) {
161
- metadata.ProtocolVersion = uint8ArrayFromString(message.protocolVersion)
162
- }
163
-
164
- log('merging %p metadata', connection.remotePeer, metadata)
165
- await peerStore.merge(connection.remotePeer, {
166
- metadata
167
- })
168
- }
169
-
170
- const result: IdentifyResult = {
171
- peerId: connection.remotePeer,
172
- protocolVersion: message.protocolVersion,
173
- agentVersion: message.agentVersion,
174
- publicKey: message.publicKey,
175
- listenAddrs: message.listenAddrs.map(buf => multiaddr(buf)),
176
- observedAddr: message.observedAddr == null ? undefined : multiaddr(message.observedAddr),
177
- protocols: message.protocols,
178
- signedPeerRecord: output,
179
- connection
180
- }
181
-
182
- events.safeDispatchEvent('peer:identify', { detail: result })
183
-
184
- return result
185
- }
186
-
187
- export interface AbstractIdentifyInit extends IdentifyInit {
188
- protocol: string
189
- log: Logger
190
- }
191
-
192
- export abstract class AbstractIdentify implements Startable {
193
- public readonly host: {
194
- protocolVersion: string
195
- agentVersion: string
196
- }
197
-
198
- protected protocol: string
199
- protected started: boolean
200
- protected readonly timeout: number
201
- protected readonly peerId: PeerId
202
- protected readonly peerStore: PeerStore
203
- protected readonly registrar: Registrar
204
- protected readonly addressManager: AddressManager
205
- private readonly maxInboundStreams: number
206
- private readonly maxOutboundStreams: number
207
- protected readonly maxMessageSize: number
208
- protected readonly maxObservedAddresses: number
209
- protected readonly events: TypedEventTarget<Libp2pEvents>
210
- protected readonly runOnTransientConnection: boolean
211
- protected readonly log: Logger
212
-
213
- constructor (components: IdentifyComponents, init: AbstractIdentifyInit) {
214
- this.protocol = init.protocol
215
- this.started = false
216
- this.peerId = components.peerId
217
- this.peerStore = components.peerStore
218
- this.registrar = components.registrar
219
- this.addressManager = components.addressManager
220
- this.events = components.events
221
- this.log = init.log
222
-
223
- this.timeout = init.timeout ?? defaultValues.timeout
224
- this.maxInboundStreams = init.maxInboundStreams ?? defaultValues.maxInboundStreams
225
- this.maxOutboundStreams = init.maxOutboundStreams ?? defaultValues.maxOutboundStreams
226
- this.maxMessageSize = init.maxMessageSize ?? defaultValues.maxMessageSize
227
- this.maxObservedAddresses = init.maxObservedAddresses ?? defaultValues.maxObservedAddresses
228
- this.runOnTransientConnection = init.runOnTransientConnection ?? defaultValues.runOnTransientConnection
229
-
230
- // Store self host metadata
231
- this.host = {
232
- protocolVersion: `${init.protocolPrefix ?? defaultValues.protocolPrefix}/${IDENTIFY_PROTOCOL_VERSION}`,
233
- agentVersion: getAgentVersion(components.nodeInfo, init.agentVersion)
234
- }
235
- }
236
-
237
- isStarted (): boolean {
238
- return this.started
239
- }
240
-
241
- async start (): Promise<void> {
242
- if (this.started) {
243
- return
244
- }
245
-
246
- await this.peerStore.merge(this.peerId, {
247
- metadata: {
248
- AgentVersion: uint8ArrayFromString(this.host.agentVersion),
249
- ProtocolVersion: uint8ArrayFromString(this.host.protocolVersion)
250
- }
251
- })
252
-
253
- await this.registrar.handle(this.protocol, (data) => {
254
- void this.handleProtocol(data).catch(err => {
255
- this.log.error(err)
256
- })
257
- }, {
258
- maxInboundStreams: this.maxInboundStreams,
259
- maxOutboundStreams: this.maxOutboundStreams,
260
- runOnTransientConnection: this.runOnTransientConnection
261
- })
262
-
263
- this.started = true
264
- }
265
-
266
- async stop (): Promise<void> {
267
- await this.registrar.unhandle(this.protocol)
268
-
269
- this.started = false
270
- }
271
-
272
- protected abstract handleProtocol (data: IncomingStreamData): Promise<void>
273
- }