libp2p 2.9.0 → 2.10.0-8484de8a2

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.
Files changed (119) hide show
  1. package/dist/index.min.js +13 -17
  2. package/dist/index.min.js.map +4 -4
  3. package/dist/src/address-manager/dns-mappings.d.ts +1 -2
  4. package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
  5. package/dist/src/address-manager/dns-mappings.js +40 -44
  6. package/dist/src/address-manager/dns-mappings.js.map +1 -1
  7. package/dist/src/address-manager/index.d.ts.map +1 -1
  8. package/dist/src/address-manager/index.js +31 -14
  9. package/dist/src/address-manager/index.js.map +1 -1
  10. package/dist/src/address-manager/ip-mappings.d.ts +1 -0
  11. package/dist/src/address-manager/ip-mappings.d.ts.map +1 -1
  12. package/dist/src/address-manager/ip-mappings.js +51 -40
  13. package/dist/src/address-manager/ip-mappings.js.map +1 -1
  14. package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
  15. package/dist/src/address-manager/observed-addresses.js +1 -3
  16. package/dist/src/address-manager/observed-addresses.js.map +1 -1
  17. package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
  18. package/dist/src/address-manager/transport-addresses.js +6 -8
  19. package/dist/src/address-manager/transport-addresses.js.map +1 -1
  20. package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
  21. package/dist/src/config/connection-gater.browser.js +3 -9
  22. package/dist/src/config/connection-gater.browser.js.map +1 -1
  23. package/dist/src/config.js +1 -1
  24. package/dist/src/config.js.map +1 -1
  25. package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
  26. package/dist/src/connection-manager/address-sorter.js +1 -2
  27. package/dist/src/connection-manager/address-sorter.js.map +1 -1
  28. package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
  29. package/dist/src/connection-manager/connection-pruner.js +7 -3
  30. package/dist/src/connection-manager/connection-pruner.js.map +1 -1
  31. package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
  32. package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
  33. package/dist/src/connection-manager/constants.defaults.js +4 -0
  34. package/dist/src/connection-manager/constants.defaults.js.map +1 -1
  35. package/dist/src/connection-manager/dial-queue.d.ts +2 -2
  36. package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
  37. package/dist/src/connection-manager/dial-queue.js +13 -25
  38. package/dist/src/connection-manager/dial-queue.js.map +1 -1
  39. package/dist/src/connection-manager/index.d.ts +10 -2
  40. package/dist/src/connection-manager/index.d.ts.map +1 -1
  41. package/dist/src/connection-manager/index.js +45 -27
  42. package/dist/src/connection-manager/index.js.map +1 -1
  43. package/dist/src/connection-manager/reconnect-queue.js +1 -1
  44. package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
  45. package/dist/src/connection-manager/utils.d.ts +31 -3
  46. package/dist/src/connection-manager/utils.d.ts.map +1 -1
  47. package/dist/src/connection-manager/utils.js +99 -18
  48. package/dist/src/connection-manager/utils.js.map +1 -1
  49. package/dist/src/connection-monitor.d.ts +1 -1
  50. package/dist/src/connection-monitor.d.ts.map +1 -1
  51. package/dist/src/connection-monitor.js +2 -3
  52. package/dist/src/connection-monitor.js.map +1 -1
  53. package/dist/src/connection.d.ts +62 -0
  54. package/dist/src/connection.d.ts.map +1 -0
  55. package/dist/src/connection.js +239 -0
  56. package/dist/src/connection.js.map +1 -0
  57. package/dist/src/get-peer.js +3 -3
  58. package/dist/src/get-peer.js.map +1 -1
  59. package/dist/src/index.d.ts +2 -2
  60. package/dist/src/index.js +2 -2
  61. package/dist/src/libp2p.d.ts.map +1 -1
  62. package/dist/src/libp2p.js +5 -5
  63. package/dist/src/libp2p.js.map +1 -1
  64. package/dist/src/peer-routing.js +1 -1
  65. package/dist/src/peer-routing.js.map +1 -1
  66. package/dist/src/random-walk.d.ts.map +1 -1
  67. package/dist/src/random-walk.js +13 -3
  68. package/dist/src/random-walk.js.map +1 -1
  69. package/dist/src/registrar.d.ts +3 -3
  70. package/dist/src/registrar.d.ts.map +1 -1
  71. package/dist/src/registrar.js +50 -41
  72. package/dist/src/registrar.js.map +1 -1
  73. package/dist/src/transport-manager.js +15 -2
  74. package/dist/src/transport-manager.js.map +1 -1
  75. package/dist/src/upgrader.d.ts +27 -25
  76. package/dist/src/upgrader.d.ts.map +1 -1
  77. package/dist/src/upgrader.js +97 -336
  78. package/dist/src/upgrader.js.map +1 -1
  79. package/dist/src/utils.d.ts +3 -0
  80. package/dist/src/utils.d.ts.map +1 -0
  81. package/dist/src/utils.js +25 -0
  82. package/dist/src/utils.js.map +1 -0
  83. package/dist/src/version.d.ts +1 -1
  84. package/dist/src/version.d.ts.map +1 -1
  85. package/dist/src/version.js +1 -1
  86. package/dist/src/version.js.map +1 -1
  87. package/package.json +26 -30
  88. package/src/address-manager/dns-mappings.ts +51 -51
  89. package/src/address-manager/index.ts +37 -17
  90. package/src/address-manager/ip-mappings.ts +64 -44
  91. package/src/address-manager/observed-addresses.ts +1 -3
  92. package/src/address-manager/transport-addresses.ts +7 -9
  93. package/src/config/connection-gater.browser.ts +3 -12
  94. package/src/config.ts +1 -1
  95. package/src/connection-manager/address-sorter.ts +1 -2
  96. package/src/connection-manager/connection-pruner.ts +8 -3
  97. package/src/connection-manager/constants.defaults.ts +5 -0
  98. package/src/connection-manager/dial-queue.ts +14 -29
  99. package/src/connection-manager/index.ts +62 -29
  100. package/src/connection-manager/reconnect-queue.ts +1 -1
  101. package/src/connection-manager/utils.ts +129 -21
  102. package/src/connection-monitor.ts +3 -4
  103. package/src/connection.ts +316 -0
  104. package/src/get-peer.ts +3 -3
  105. package/src/index.ts +2 -2
  106. package/src/libp2p.ts +5 -6
  107. package/src/peer-routing.ts +1 -1
  108. package/src/random-walk.ts +13 -3
  109. package/src/registrar.ts +67 -54
  110. package/src/transport-manager.ts +18 -2
  111. package/src/upgrader.ts +143 -421
  112. package/src/utils.ts +31 -0
  113. package/src/version.ts +1 -1
  114. package/dist/src/connection/index.d.ts +0 -84
  115. package/dist/src/connection/index.d.ts.map +0 -1
  116. package/dist/src/connection/index.js +0 -144
  117. package/dist/src/connection/index.js.map +0 -1
  118. package/dist/typedoc-urls.json +0 -24
  119. package/src/connection/index.ts +0 -199
@@ -1,38 +1,146 @@
1
- import { multiaddr } from '@multiformats/multiaddr'
2
- import { convertToIpNet } from '@multiformats/multiaddr/convert'
3
- import type { IpNet } from '@chainsafe/netmask'
1
+ import { IpNet } from '@chainsafe/netmask'
2
+ import { InvalidParametersError } from '@libp2p/interface'
3
+ import { getNetConfig } from '@libp2p/utils'
4
+ import { Circuit } from '@multiformats/multiaddr-matcher'
5
+ import type { Connection, AbortOptions, PeerId } from '@libp2p/interface'
4
6
  import type { Multiaddr } from '@multiformats/multiaddr'
5
7
 
8
+ /**
9
+ * These are speculative protocols that are run automatically on connection open
10
+ * so are usually not the reason the connection was opened.
11
+ *
12
+ * Consequently when requested it should be safe to close connections that only
13
+ * have these protocol streams open.
14
+ */
15
+ const DEFAULT_CLOSABLE_PROTOCOLS = [
16
+ // identify
17
+ '/ipfs/id/1.0.0',
18
+
19
+ // identify-push
20
+ '/ipfs/id/push/1.0.0',
21
+
22
+ // autonat
23
+ '/libp2p/autonat/1.0.0',
24
+
25
+ // dcutr
26
+ '/libp2p/dcutr'
27
+ ]
28
+
29
+ export interface SafelyCloseConnectionOptions extends AbortOptions {
30
+ /**
31
+ * Only close the stream if it either has no protocol streams open or only
32
+ * ones in this list.
33
+ *
34
+ * @default ['/ipfs/id/1.0.0']
35
+ */
36
+ closableProtocols?: string[]
37
+ }
38
+
39
+ /**
40
+ * Close the passed connection if it has no streams, or only closable protocol
41
+ * streams, falling back to aborting the connection if closing it cleanly fails.
42
+ */
43
+ export async function safelyCloseConnectionIfUnused (connection?: Connection, options?: SafelyCloseConnectionOptions): Promise<void> {
44
+ const streamProtocols = connection?.streams?.map(stream => stream.protocol) ?? []
45
+ const closableProtocols = options?.closableProtocols ?? DEFAULT_CLOSABLE_PROTOCOLS
46
+
47
+ // if the connection has protocols not in the closable protocols list, do not
48
+ // close the connection
49
+ if (streamProtocols.filter(proto => proto != null && !closableProtocols.includes(proto)).length > 0) {
50
+ return
51
+ }
52
+
53
+ try {
54
+ await connection?.close(options)
55
+ } catch (err: any) {
56
+ connection?.abort(err)
57
+ }
58
+ }
59
+
6
60
  /**
7
61
  * Converts a multiaddr string or object to an IpNet object.
8
62
  * If the multiaddr doesn't include /ipcidr, it will encapsulate with the appropriate CIDR:
9
63
  * - /ipcidr/32 for IPv4
10
64
  * - /ipcidr/128 for IPv6
11
65
  *
12
- * @param {string | Multiaddr} ma - The multiaddr string or object to convert.
66
+ * @param {string | Multiaddr} ma - The multiaddr object to convert.
13
67
  * @returns {IpNet} The converted IpNet object.
14
68
  * @throws {Error} Throws an error if the multiaddr is not valid.
15
69
  */
16
- export function multiaddrToIpNet (ma: string | Multiaddr): IpNet {
17
- try {
18
- let parsedMa: Multiaddr
19
- if (typeof ma === 'string') {
20
- parsedMa = multiaddr(ma)
21
- } else {
22
- parsedMa = ma
23
- }
70
+ export function multiaddrToIpNet (ma: Multiaddr): IpNet {
71
+ const config = getNetConfig(ma)
72
+ let mask = config.cidr
24
73
 
25
- const protoNames = new Set([...parsedMa.getComponents().map(component => component.name)])
74
+ if (config.type !== 'ip4' && config.type !== 'ip6') {
75
+ throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
76
+ }
26
77
 
27
- // Check if /ipcidr is already present
28
- if (!protoNames.has('ipcidr')) {
29
- const isIPv6 = protoNames.has('ip6')
30
- const cidr = isIPv6 ? '/ipcidr/128' : '/ipcidr/32'
31
- parsedMa = parsedMa.encapsulate(cidr)
78
+ // Check if /ipcidr is already present
79
+ if (mask == null) {
80
+ switch (config.type) {
81
+ case 'ip4': {
82
+ mask = 32
83
+ break
84
+ }
85
+ case 'ip6': {
86
+ mask = 128
87
+ break
88
+ }
89
+ default: {
90
+ throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
91
+ }
32
92
  }
93
+ }
94
+
95
+ return new IpNet(config.host, mask)
96
+ }
97
+
98
+ /**
99
+ * Returns true if the passed multiaddr would result in a direct connection to
100
+ * the peer.
101
+ *
102
+ * Currently only circuit relay addresses are supported as indirect connections.
103
+ */
104
+ export function isDirect (ma: Multiaddr): boolean {
105
+ return !Circuit.exactMatch(ma)
106
+ }
107
+
108
+ /**
109
+ * If there is an existing non-limited connection to the remote peer return it,
110
+ * unless it is indirect and at least one of the passed dial addresses would
111
+ * result in a direct connection
112
+ */
113
+ export function findExistingConnection (peerId?: PeerId, connections?: Connection[], dialAddresses?: Multiaddr[]): Connection | undefined {
114
+ if (peerId == null || connections == null) {
115
+ return
116
+ }
117
+
118
+ const existingConnection = connections
119
+ .sort((a, b) => {
120
+ if (a.direct) {
121
+ return -1
122
+ }
123
+
124
+ if (b.direct) {
125
+ return 1
126
+ }
33
127
 
34
- return convertToIpNet(parsedMa)
35
- } catch (error) {
36
- throw new Error(`Can't convert to IpNet, Invalid multiaddr format: ${ma}`)
128
+ return 0
129
+ })
130
+ .find(con => con.limits == null)
131
+
132
+ if (existingConnection == null || existingConnection.direct || dialAddresses == null) {
133
+ return existingConnection
37
134
  }
135
+
136
+ // we have an indirect, but unlimited connection - test the dial addresses to
137
+ // see if any of them would result in a direct connection, in which case allow
138
+ // the attempt to upgrade to a direct connection
139
+ const wouldUpgradeToDirect = dialAddresses.some(ma => isDirect(ma))
140
+
141
+ if (wouldUpgradeToDirect) {
142
+ return
143
+ }
144
+
145
+ return existingConnection
38
146
  }
@@ -1,11 +1,10 @@
1
1
  import { randomBytes } from '@libp2p/crypto'
2
2
  import { serviceCapabilities } from '@libp2p/interface'
3
- import { AdaptiveTimeout } from '@libp2p/utils/adaptive-timeout'
4
- import { byteStream } from 'it-byte-stream'
3
+ import { AdaptiveTimeout, byteStream } from '@libp2p/utils'
5
4
  import { setMaxListeners } from 'main-event'
6
5
  import type { ComponentLogger, Logger, Metrics, Startable } from '@libp2p/interface'
7
6
  import type { ConnectionManager } from '@libp2p/interface-internal'
8
- import type { AdaptiveTimeoutInit } from '@libp2p/utils/adaptive-timeout'
7
+ import type { AdaptiveTimeoutInit } from '@libp2p/utils'
9
8
 
10
9
  const DEFAULT_PING_INTERVAL_MS = 10000
11
10
  const PROTOCOL_VERSION = '1.0.0'
@@ -120,7 +119,7 @@ export class ConnectionMonitor implements Startable {
120
119
 
121
120
  conn.rtt = Date.now() - start
122
121
 
123
- await bs.unwrap().close({
122
+ await stream.close({
124
123
  signal
125
124
  })
126
125
  } catch (err: any) {
@@ -0,0 +1,316 @@
1
+ import { connectionSymbol, LimitedConnectionError, ConnectionClosedError, TooManyOutboundProtocolStreamsError, TooManyInboundProtocolStreamsError, StreamCloseEvent } from '@libp2p/interface'
2
+ import * as mss from '@libp2p/multistream-select'
3
+ import { CODE_P2P } from '@multiformats/multiaddr'
4
+ import { setMaxListeners, TypedEventEmitter } from 'main-event'
5
+ import { CONNECTION_CLOSE_TIMEOUT, PROTOCOL_NEGOTIATION_TIMEOUT } from './connection-manager/constants.defaults.ts'
6
+ import { isDirect } from './connection-manager/utils.ts'
7
+ import { MuxerUnavailableError } from './errors.ts'
8
+ import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.ts'
9
+ import type { AbortOptions, Logger, MessageStreamDirection, Connection as ConnectionInterface, Stream, NewStreamOptions, PeerId, ConnectionLimits, StreamMuxer, Metrics, PeerStore, MultiaddrConnection, MessageStreamEvents, MultiaddrConnectionTimeline, ConnectionStatus, MessageStream } from '@libp2p/interface'
10
+ import type { Registrar } from '@libp2p/interface-internal'
11
+ import type { Multiaddr } from '@multiformats/multiaddr'
12
+
13
+ export interface ConnectionComponents {
14
+ peerStore: PeerStore
15
+ registrar: Registrar
16
+ metrics?: Metrics
17
+ }
18
+
19
+ export interface ConnectionInit {
20
+ id: string
21
+ maConn: MultiaddrConnection
22
+ stream: MessageStream
23
+ remotePeer: PeerId
24
+ direction?: MessageStreamDirection
25
+ muxer?: StreamMuxer
26
+ cryptoProtocol?: string
27
+ limits?: ConnectionLimits
28
+ outboundStreamProtocolNegotiationTimeout?: number
29
+ inboundStreamProtocolNegotiationTimeout?: number
30
+ closeTimeout?: number
31
+ }
32
+
33
+ /**
34
+ * An implementation of the js-libp2p connection.
35
+ * Any libp2p transport should use an upgrader to return this connection.
36
+ */
37
+ export class Connection extends TypedEventEmitter<MessageStreamEvents> implements ConnectionInterface {
38
+ public readonly id: string
39
+ public readonly remoteAddr: Multiaddr
40
+ public readonly remotePeer: PeerId
41
+ public direction: MessageStreamDirection
42
+ public timeline: MultiaddrConnectionTimeline
43
+ public direct: boolean
44
+ public multiplexer?: string
45
+ public encryption?: string
46
+ public limits?: ConnectionLimits
47
+ public readonly log: Logger
48
+
49
+ private readonly maConn: MultiaddrConnection
50
+ private readonly muxer?: StreamMuxer
51
+ private readonly components: ConnectionComponents
52
+ private readonly outboundStreamProtocolNegotiationTimeout: number
53
+ private readonly inboundStreamProtocolNegotiationTimeout: number
54
+ private readonly closeTimeout: number
55
+
56
+ constructor (components: ConnectionComponents, init: ConnectionInit) {
57
+ super()
58
+
59
+ this.components = components
60
+
61
+ this.id = init.id
62
+ this.remoteAddr = init.maConn.remoteAddr
63
+ this.remotePeer = init.remotePeer
64
+ this.direction = init.direction ?? 'outbound'
65
+ this.timeline = init.maConn.timeline
66
+ this.encryption = init.cryptoProtocol
67
+ this.limits = init.limits
68
+ this.maConn = init.maConn
69
+ this.log = init.maConn.log
70
+ this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
71
+ this.inboundStreamProtocolNegotiationTimeout = init.inboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
72
+ this.closeTimeout = init.closeTimeout ?? CONNECTION_CLOSE_TIMEOUT
73
+ this.direct = isDirect(init.maConn.remoteAddr)
74
+
75
+ this.onIncomingStream = this.onIncomingStream.bind(this)
76
+
77
+ if (this.remoteAddr.getComponents().find(component => component.code === CODE_P2P) == null) {
78
+ this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`)
79
+ }
80
+
81
+ if (init.muxer != null) {
82
+ this.multiplexer = init.muxer.protocol
83
+ this.muxer = init.muxer
84
+ this.muxer.addEventListener('stream', this.onIncomingStream)
85
+ }
86
+
87
+ this.maConn.addEventListener('close', (evt) => {
88
+ this.dispatchEvent(new StreamCloseEvent(evt.local, evt.error))
89
+ })
90
+ }
91
+
92
+ readonly [Symbol.toStringTag] = 'Connection'
93
+
94
+ readonly [connectionSymbol] = true
95
+
96
+ get streams (): Stream[] {
97
+ return this.muxer?.streams ?? []
98
+ }
99
+
100
+ get status (): ConnectionStatus {
101
+ return this.maConn.status
102
+ }
103
+
104
+ /**
105
+ * Create a new stream over this connection
106
+ */
107
+ newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise<Stream> => {
108
+ if (this.muxer == null) {
109
+ throw new MuxerUnavailableError('Connection is not multiplexed')
110
+ }
111
+
112
+ if (this.muxer.status !== 'open') {
113
+ throw new ConnectionClosedError(`The connection muxer is "${this.muxer.status}" and not "open"`)
114
+ }
115
+
116
+ if (this.maConn.status !== 'open') {
117
+ throw new ConnectionClosedError(`The connection is "${this.status}" and not "open"`)
118
+ }
119
+
120
+ if (this.limits != null && options?.runOnLimitedConnection !== true) {
121
+ throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
122
+ }
123
+
124
+ if (!Array.isArray(protocols)) {
125
+ protocols = [protocols]
126
+ }
127
+
128
+ this.log.trace('starting new stream for protocols %s', protocols)
129
+ const muxedStream = await this.muxer.createStream({
130
+ ...options,
131
+
132
+ // most underlying transports only support negotiating a single protocol
133
+ // so only pass the early protocol if a single protocol has been requested
134
+ // otherwise fall back to mss
135
+ protocol: protocols.length === 1 ? protocols[0] : undefined
136
+ })
137
+ this.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols)
138
+
139
+ try {
140
+ if (options.signal == null) {
141
+ muxedStream.log('no abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols)
142
+
143
+ const signal = AbortSignal.timeout(this.outboundStreamProtocolNegotiationTimeout)
144
+ setMaxListeners(Infinity, signal)
145
+
146
+ options = {
147
+ ...options,
148
+ signal
149
+ }
150
+ }
151
+
152
+ if (muxedStream.protocol === '') {
153
+ muxedStream.log.trace('selecting protocol from protocols %s', protocols)
154
+
155
+ muxedStream.protocol = await mss.select(muxedStream, protocols, options)
156
+
157
+ muxedStream.log('negotiated protocol %s', muxedStream.protocol)
158
+ } else {
159
+ muxedStream.log('pre-negotiated protocol %s', muxedStream.protocol)
160
+ }
161
+
162
+ const outgoingLimit = findOutgoingStreamLimit(muxedStream.protocol, this.components.registrar, options)
163
+ const streamCount = countStreams(muxedStream.protocol, 'outbound', this)
164
+
165
+ if (streamCount > outgoingLimit) {
166
+ const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${muxedStream.protocol}" - ${streamCount}/${outgoingLimit}`)
167
+ muxedStream.abort(err)
168
+
169
+ throw err
170
+ }
171
+
172
+ // If a protocol stream has been successfully negotiated and is to be passed to the application,
173
+ // the peer store should ensure that the peer is registered with that protocol
174
+ await this.components.peerStore.merge(this.remotePeer, {
175
+ protocols: [muxedStream.protocol]
176
+ })
177
+
178
+ this.components.metrics?.trackProtocolStream(muxedStream)
179
+
180
+ return muxedStream
181
+ } catch (err: any) {
182
+ if (muxedStream.status === 'open') {
183
+ muxedStream.abort(err)
184
+ } else {
185
+ this.log.error('could not create new outbound stream on connection %s %a for protocols %s - %e', this.direction === 'inbound' ? 'from' : 'to', this.remoteAddr, protocols, err)
186
+ }
187
+
188
+ throw err
189
+ }
190
+ }
191
+
192
+ private async onIncomingStream (evt: CustomEvent<Stream>): Promise<void> {
193
+ const muxedStream = evt.detail
194
+
195
+ const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout)
196
+ setMaxListeners(Infinity, signal)
197
+
198
+ muxedStream.log('start protocol negotiation, timing out after %dms', this.inboundStreamProtocolNegotiationTimeout)
199
+
200
+ try {
201
+ if (muxedStream.protocol === '') {
202
+ const protocols = this.components.registrar.getProtocols()
203
+
204
+ muxedStream.log.trace('selecting protocol from protocols %s', protocols)
205
+
206
+ muxedStream.protocol = await mss.handle(muxedStream, protocols, {
207
+ signal
208
+ })
209
+
210
+ muxedStream.log('negotiated protocol %s', muxedStream.protocol)
211
+ } else {
212
+ muxedStream.log('pre-negotiated protocol %s', muxedStream.protocol)
213
+ }
214
+
215
+ const incomingLimit = findIncomingStreamLimit(muxedStream.protocol, this.components.registrar)
216
+ const streamCount = countStreams(muxedStream.protocol, 'inbound', this)
217
+
218
+ if (streamCount > incomingLimit) {
219
+ throw new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${muxedStream.protocol}" - limit ${incomingLimit}`)
220
+ }
221
+
222
+ // If a protocol stream has been successfully negotiated and is to be passed to the application,
223
+ // the peer store should ensure that the peer is registered with that protocol
224
+ await this.components.peerStore.merge(this.remotePeer, {
225
+ protocols: [muxedStream.protocol]
226
+ }, {
227
+ signal
228
+ })
229
+
230
+ this.components.metrics?.trackProtocolStream(muxedStream)
231
+
232
+ const { handler, options } = this.components.registrar.getHandler(muxedStream.protocol)
233
+
234
+ if (this.limits != null && options.runOnLimitedConnection !== true) {
235
+ throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
236
+ }
237
+
238
+ await handler(muxedStream, this)
239
+ } catch (err: any) {
240
+ muxedStream.abort(err)
241
+ }
242
+ }
243
+
244
+ /**
245
+ * Close the connection
246
+ */
247
+ async close (options: AbortOptions = {}): Promise<void> {
248
+ this.log('closing connection to %a', this.remoteAddr)
249
+
250
+ if (options.signal == null) {
251
+ const signal = AbortSignal.timeout(this.closeTimeout)
252
+ setMaxListeners(Infinity, signal)
253
+
254
+ options = {
255
+ ...options,
256
+ signal
257
+ }
258
+ }
259
+
260
+ await this.muxer?.close(options)
261
+ await this.maConn.close(options)
262
+ }
263
+
264
+ abort (err: Error): void {
265
+ this.muxer?.abort(err)
266
+ this.maConn.abort(err)
267
+ }
268
+ }
269
+
270
+ export function createConnection (components: ConnectionComponents, init: ConnectionInit): ConnectionInterface {
271
+ return new Connection(components, init)
272
+ }
273
+
274
+ function findIncomingStreamLimit (protocol: string, registrar: Registrar): number {
275
+ try {
276
+ const { options } = registrar.getHandler(protocol)
277
+
278
+ if (options.maxInboundStreams != null) {
279
+ return options.maxInboundStreams
280
+ }
281
+ } catch (err: any) {
282
+ if (err.name !== 'UnhandledProtocolError') {
283
+ throw err
284
+ }
285
+ }
286
+
287
+ return DEFAULT_MAX_INBOUND_STREAMS
288
+ }
289
+
290
+ function findOutgoingStreamLimit (protocol: string, registrar: Registrar, options: NewStreamOptions = {}): number {
291
+ try {
292
+ const { options } = registrar.getHandler(protocol)
293
+
294
+ if (options.maxOutboundStreams != null) {
295
+ return options.maxOutboundStreams
296
+ }
297
+ } catch (err: any) {
298
+ if (err.name !== 'UnhandledProtocolError') {
299
+ throw err
300
+ }
301
+ }
302
+
303
+ return options.maxOutboundStreams ?? DEFAULT_MAX_OUTBOUND_STREAMS
304
+ }
305
+
306
+ function countStreams (protocol: string, direction: 'inbound' | 'outbound', connection: Connection): number {
307
+ let streamCount = 0
308
+
309
+ connection.streams.forEach(stream => {
310
+ if (stream.direction === direction && stream.protocol === protocol) {
311
+ streamCount++
312
+ }
313
+ })
314
+
315
+ return streamCount
316
+ }
package/src/get-peer.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { InvalidMultiaddrError, InvalidParametersError, isPeerId } from '@libp2p/interface'
2
2
  import { peerIdFromString } from '@libp2p/peer-id'
3
- import { isMultiaddr } from '@multiformats/multiaddr'
3
+ import { CODE_P2P, isMultiaddr } from '@multiformats/multiaddr'
4
4
  import { PEER_ID } from '@multiformats/multiaddr-matcher'
5
5
  import type { PeerId } from '@libp2p/interface'
6
6
  import type { Multiaddr } from '@multiformats/multiaddr'
@@ -24,7 +24,7 @@ export function getPeerAddress (peer: PeerId | Multiaddr | Multiaddr[]): PeerAdd
24
24
  let peerId: PeerId | undefined
25
25
 
26
26
  if (multiaddrs.length > 0) {
27
- const peerIdStr = multiaddrs[0].getPeerId()
27
+ const peerIdStr = multiaddrs[0].getComponents().findLast(c => c.code === CODE_P2P)?.value
28
28
  peerId = peerIdStr == null ? undefined : peerIdFromString(peerIdStr)
29
29
 
30
30
  // ensure PeerId is either not set or is consistent
@@ -33,7 +33,7 @@ export function getPeerAddress (peer: PeerId | Multiaddr | Multiaddr[]): PeerAdd
33
33
  throw new InvalidMultiaddrError('Invalid multiaddr')
34
34
  }
35
35
 
36
- const maPeerIdStr = ma.getPeerId()
36
+ const maPeerIdStr = ma.getComponents().findLast(c => c.code === CODE_P2P)?.value
37
37
 
38
38
  if (maPeerIdStr == null) {
39
39
  if (peerId != null) {
package/src/index.ts CHANGED
@@ -184,8 +184,8 @@ export type Libp2pOptions<T extends ServiceMap = ServiceMap> = Libp2pInit<T> & {
184
184
  * import { createLibp2p } from 'libp2p'
185
185
  * import { tcp } from '@libp2p/tcp'
186
186
  * import { mplex } from '@libp2p/mplex'
187
- * import { noise } from '@chainsafe/libp2p-noise'
188
- * import { yamux } from '@chainsafe/libp2p-yamux'
187
+ * import { noise } from '@libp2p/noise'
188
+ * import { yamux } from '@libp2p/yamux'
189
189
  *
190
190
  * // specify options
191
191
  * const options = {
package/src/libp2p.ts CHANGED
@@ -4,7 +4,7 @@ import { defaultLogger } from '@libp2p/logger'
4
4
  import { PeerSet } from '@libp2p/peer-collections'
5
5
  import { peerIdFromString } from '@libp2p/peer-id'
6
6
  import { persistentPeerStore } from '@libp2p/peer-store'
7
- import { isMultiaddr } from '@multiformats/multiaddr'
7
+ import { CODE_P2P, isMultiaddr } from '@multiformats/multiaddr'
8
8
  import { MemoryDatastore } from 'datastore-core/memory'
9
9
  import { TypedEventEmitter, setMaxListeners } from 'main-event'
10
10
  import { concat as uint8ArrayConcat } from 'uint8arrays/concat'
@@ -120,7 +120,8 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
120
120
  streamMuxers: (init.streamMuxers ?? []).map((fn, index) => this.configureComponent(`stream-muxers-${index}`, fn(this.components))),
121
121
  inboundUpgradeTimeout: init.connectionManager?.inboundUpgradeTimeout,
122
122
  inboundStreamProtocolNegotiationTimeout: init.connectionManager?.inboundStreamProtocolNegotiationTimeout ?? init.connectionManager?.protocolNegotiationTimeout,
123
- outboundStreamProtocolNegotiationTimeout: init.connectionManager?.outboundStreamProtocolNegotiationTimeout ?? init.connectionManager?.protocolNegotiationTimeout
123
+ outboundStreamProtocolNegotiationTimeout: init.connectionManager?.outboundStreamProtocolNegotiationTimeout ?? init.connectionManager?.protocolNegotiationTimeout,
124
+ connectionCloseTimeout: init.connectionManager?.connectionCloseTimeout
124
125
  })
125
126
 
126
127
  // Setup the transport manager
@@ -304,9 +305,7 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
304
305
  throw new InvalidParametersError('no protocols were provided to open a stream')
305
306
  }
306
307
 
307
- const connection = await this.dial(peer, options)
308
-
309
- return connection.newStream(protocols, options)
308
+ return this.components.connectionManager.openStream(peer, protocols, options)
310
309
  }
311
310
 
312
311
  getMultiaddrs (): Multiaddr[] {
@@ -319,7 +318,7 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
319
318
 
320
319
  async hangUp (peer: PeerId | Multiaddr, options: AbortOptions = {}): Promise<void> {
321
320
  if (isMultiaddr(peer)) {
322
- peer = peerIdFromString(peer.getPeerId() ?? '')
321
+ peer = peerIdFromString(peer.getComponents().findLast(c => c.code === CODE_P2P)?.value ?? '')
323
322
  }
324
323
 
325
324
  await this.components.connectionManager.closeConnections(peer, options)
@@ -1,5 +1,5 @@
1
1
  import { NotFoundError } from '@libp2p/interface'
2
- import { createScalableCuckooFilter } from '@libp2p/utils/filters'
2
+ import { createScalableCuckooFilter } from '@libp2p/utils'
3
3
  import merge from 'it-merge'
4
4
  import parallel from 'it-parallel'
5
5
  import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
@@ -2,7 +2,7 @@ import { randomBytes } from '@libp2p/crypto'
2
2
  import { anySignal } from 'any-signal'
3
3
  import { TypedEventEmitter, setMaxListeners } from 'main-event'
4
4
  import pDefer from 'p-defer'
5
- import { raceEvent } from 'race-event'
5
+ import { pEvent } from 'p-event'
6
6
  import { raceSignal } from 'race-signal'
7
7
  import type { AbortOptions, ComponentLogger, Logger, PeerInfo, PeerRouting, Startable } from '@libp2p/interface'
8
8
  import type { RandomWalk as RandomWalkInterface } from '@libp2p/interface-internal'
@@ -68,12 +68,22 @@ export class RandomWalk extends TypedEventEmitter<RandomWalkEvents> implements R
68
68
  this.needNext = pDefer()
69
69
 
70
70
  // wait for a walk:peer or walk:error event
71
- const event = await raceEvent<CustomEvent<PeerInfo>>(this, 'walk:peer', signal, {
72
- errorEvent: 'walk:error'
71
+ const event = await pEvent<'walk:peer', CustomEvent<PeerInfo>>(this, 'walk:peer', {
72
+ signal,
73
+ rejectionEvents: [
74
+ 'walk:error'
75
+ ]
73
76
  })
74
77
 
75
78
  yield event.detail
76
79
  }
80
+ } catch (err: any) {
81
+ // test for walk:error event
82
+ if (err.detail != null) {
83
+ throw err.detail
84
+ }
85
+
86
+ throw err
77
87
  } finally {
78
88
  signal.clear()
79
89
  this.walkers--