libp2p 2.10.0 → 3.0.0-049bfa0fa
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -37
- package/dist/index.min.js +14 -17
- package/dist/index.min.js.map +4 -4
- package/dist/src/address-manager/dns-mappings.d.ts +1 -2
- package/dist/src/address-manager/dns-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/dns-mappings.js +39 -43
- package/dist/src/address-manager/dns-mappings.js.map +1 -1
- package/dist/src/address-manager/index.d.ts.map +1 -1
- package/dist/src/address-manager/index.js +31 -14
- package/dist/src/address-manager/index.js.map +1 -1
- package/dist/src/address-manager/ip-mappings.d.ts +1 -0
- package/dist/src/address-manager/ip-mappings.d.ts.map +1 -1
- package/dist/src/address-manager/ip-mappings.js +51 -40
- package/dist/src/address-manager/ip-mappings.js.map +1 -1
- package/dist/src/address-manager/observed-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/observed-addresses.js +1 -3
- package/dist/src/address-manager/observed-addresses.js.map +1 -1
- package/dist/src/address-manager/transport-addresses.d.ts.map +1 -1
- package/dist/src/address-manager/transport-addresses.js +6 -8
- package/dist/src/address-manager/transport-addresses.js.map +1 -1
- package/dist/src/config/connection-gater.browser.d.ts.map +1 -1
- package/dist/src/config/connection-gater.browser.js +8 -22
- package/dist/src/config/connection-gater.browser.js.map +1 -1
- package/dist/src/config/connection-gater.d.ts.map +1 -1
- package/dist/src/config/connection-gater.js +1 -12
- package/dist/src/config/connection-gater.js.map +1 -1
- package/dist/src/config.d.ts.map +1 -1
- package/dist/src/config.js +3 -22
- package/dist/src/config.js.map +1 -1
- package/dist/src/connection-manager/address-sorter.d.ts.map +1 -1
- package/dist/src/connection-manager/address-sorter.js +1 -2
- package/dist/src/connection-manager/address-sorter.js.map +1 -1
- package/dist/src/connection-manager/connection-pruner.d.ts.map +1 -1
- package/dist/src/connection-manager/connection-pruner.js +7 -3
- package/dist/src/connection-manager/connection-pruner.js.map +1 -1
- package/dist/src/connection-manager/constants.defaults.d.ts +4 -0
- package/dist/src/connection-manager/constants.defaults.d.ts.map +1 -1
- package/dist/src/connection-manager/constants.defaults.js +4 -0
- package/dist/src/connection-manager/constants.defaults.js.map +1 -1
- package/dist/src/connection-manager/dial-queue.d.ts +2 -2
- package/dist/src/connection-manager/dial-queue.d.ts.map +1 -1
- package/dist/src/connection-manager/dial-queue.js +11 -23
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +10 -18
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +44 -26
- package/dist/src/connection-manager/index.js.map +1 -1
- package/dist/src/connection-manager/reconnect-queue.js +1 -1
- package/dist/src/connection-manager/reconnect-queue.js.map +1 -1
- package/dist/src/connection-manager/utils.d.ts +31 -3
- package/dist/src/connection-manager/utils.d.ts.map +1 -1
- package/dist/src/connection-manager/utils.js +99 -18
- package/dist/src/connection-manager/utils.js.map +1 -1
- package/dist/src/connection-monitor.d.ts +1 -1
- package/dist/src/connection-monitor.d.ts.map +1 -1
- package/dist/src/connection-monitor.js +2 -3
- package/dist/src/connection-monitor.js.map +1 -1
- package/dist/src/connection.d.ts +14 -9
- package/dist/src/connection.d.ts.map +1 -1
- package/dist/src/connection.js +118 -139
- package/dist/src/connection.js.map +1 -1
- package/dist/src/get-peer.js +3 -3
- package/dist/src/get-peer.js.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.js +2 -2
- package/dist/src/libp2p.d.ts +3 -1
- package/dist/src/libp2p.d.ts.map +1 -1
- package/dist/src/libp2p.js +13 -7
- package/dist/src/libp2p.js.map +1 -1
- package/dist/src/peer-routing.js +1 -1
- package/dist/src/peer-routing.js.map +1 -1
- package/dist/src/random-walk.d.ts.map +1 -1
- package/dist/src/random-walk.js +13 -3
- package/dist/src/random-walk.js.map +1 -1
- package/dist/src/registrar.d.ts +8 -4
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +66 -46
- package/dist/src/registrar.js.map +1 -1
- package/dist/src/transport-manager.js +15 -2
- package/dist/src/transport-manager.js.map +1 -1
- package/dist/src/upgrader.d.ts +26 -16
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +88 -122
- package/dist/src/upgrader.js.map +1 -1
- package/dist/src/utils.d.ts +3 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +25 -0
- package/dist/src/utils.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/package.json +27 -30
- package/src/address-manager/dns-mappings.ts +50 -50
- package/src/address-manager/index.ts +37 -17
- package/src/address-manager/ip-mappings.ts +64 -44
- package/src/address-manager/observed-addresses.ts +1 -3
- package/src/address-manager/transport-addresses.ts +7 -9
- package/src/config/connection-gater.browser.ts +8 -24
- package/src/config/connection-gater.ts +1 -12
- package/src/config.ts +3 -25
- package/src/connection-manager/address-sorter.ts +1 -2
- package/src/connection-manager/connection-pruner.ts +8 -3
- package/src/connection-manager/constants.defaults.ts +5 -0
- package/src/connection-manager/dial-queue.ts +12 -27
- package/src/connection-manager/index.ts +60 -45
- package/src/connection-manager/reconnect-queue.ts +1 -1
- package/src/connection-manager/utils.ts +129 -21
- package/src/connection-monitor.ts +3 -4
- package/src/connection.ts +142 -179
- package/src/get-peer.ts +3 -3
- package/src/index.ts +2 -2
- package/src/libp2p.ts +16 -9
- package/src/peer-routing.ts +1 -1
- package/src/random-walk.ts +13 -3
- package/src/registrar.ts +87 -61
- package/src/transport-manager.ts +18 -2
- package/src/upgrader.ts +132 -149
- package/src/utils.ts +31 -0
- package/src/version.ts +1 -1
- package/dist/typedoc-urls.json +0 -24
package/src/connection.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import { connectionSymbol, LimitedConnectionError, ConnectionClosedError,
|
|
1
|
+
import { connectionSymbol, LimitedConnectionError, ConnectionClosedError, TooManyOutboundProtocolStreamsError, TooManyInboundProtocolStreamsError, StreamCloseEvent } from '@libp2p/interface'
|
|
2
2
|
import * as mss from '@libp2p/multistream-select'
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
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'
|
|
5
7
|
import { MuxerUnavailableError } from './errors.ts'
|
|
6
8
|
import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.ts'
|
|
7
|
-
import type { AbortOptions, Logger,
|
|
9
|
+
import type { AbortOptions, Logger, MessageStreamDirection, Connection as ConnectionInterface, Stream, NewStreamOptions, PeerId, ConnectionLimits, StreamMuxer, Metrics, PeerStore, MultiaddrConnection, MessageStreamEvents, MultiaddrConnectionTimeline, ConnectionStatus, MessageStream, StreamMiddleware } from '@libp2p/interface'
|
|
8
10
|
import type { Registrar } from '@libp2p/interface-internal'
|
|
9
11
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
10
12
|
|
|
11
|
-
const CLOSE_TIMEOUT = 500
|
|
12
|
-
|
|
13
13
|
export interface ConnectionComponents {
|
|
14
14
|
peerStore: PeerStore
|
|
15
15
|
registrar: Registrar
|
|
@@ -19,80 +19,74 @@ export interface ConnectionComponents {
|
|
|
19
19
|
export interface ConnectionInit {
|
|
20
20
|
id: string
|
|
21
21
|
maConn: MultiaddrConnection
|
|
22
|
+
stream: MessageStream
|
|
22
23
|
remotePeer: PeerId
|
|
23
|
-
direction?:
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
direction?: MessageStreamDirection
|
|
25
|
+
muxer?: StreamMuxer
|
|
26
|
+
cryptoProtocol?: string
|
|
26
27
|
limits?: ConnectionLimits
|
|
27
28
|
outboundStreamProtocolNegotiationTimeout?: number
|
|
28
29
|
inboundStreamProtocolNegotiationTimeout?: number
|
|
30
|
+
closeTimeout?: number
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
/**
|
|
32
34
|
* An implementation of the js-libp2p connection.
|
|
33
35
|
* Any libp2p transport should use an upgrader to return this connection.
|
|
34
36
|
*/
|
|
35
|
-
export class Connection implements ConnectionInterface {
|
|
37
|
+
export class Connection extends TypedEventEmitter<MessageStreamEvents> implements ConnectionInterface {
|
|
36
38
|
public readonly id: string
|
|
37
39
|
public readonly remoteAddr: Multiaddr
|
|
38
40
|
public readonly remotePeer: PeerId
|
|
39
|
-
public direction:
|
|
40
|
-
public timeline:
|
|
41
|
+
public direction: MessageStreamDirection
|
|
42
|
+
public timeline: MultiaddrConnectionTimeline
|
|
43
|
+
public direct: boolean
|
|
41
44
|
public multiplexer?: string
|
|
42
45
|
public encryption?: string
|
|
43
|
-
public status: ConnectionStatus
|
|
44
46
|
public limits?: ConnectionLimits
|
|
45
47
|
public readonly log: Logger
|
|
46
|
-
public tags: string[]
|
|
47
48
|
|
|
48
49
|
private readonly maConn: MultiaddrConnection
|
|
49
50
|
private readonly muxer?: StreamMuxer
|
|
50
51
|
private readonly components: ConnectionComponents
|
|
51
52
|
private readonly outboundStreamProtocolNegotiationTimeout: number
|
|
52
53
|
private readonly inboundStreamProtocolNegotiationTimeout: number
|
|
54
|
+
private readonly closeTimeout: number
|
|
53
55
|
|
|
54
56
|
constructor (components: ConnectionComponents, init: ConnectionInit) {
|
|
57
|
+
super()
|
|
58
|
+
|
|
55
59
|
this.components = components
|
|
56
60
|
|
|
57
61
|
this.id = init.id
|
|
58
62
|
this.remoteAddr = init.maConn.remoteAddr
|
|
59
63
|
this.remotePeer = init.remotePeer
|
|
60
64
|
this.direction = init.direction ?? 'outbound'
|
|
61
|
-
this.status = 'open'
|
|
62
65
|
this.timeline = init.maConn.timeline
|
|
63
|
-
this.encryption = init.
|
|
66
|
+
this.encryption = init.cryptoProtocol
|
|
64
67
|
this.limits = init.limits
|
|
65
68
|
this.maConn = init.maConn
|
|
66
69
|
this.log = init.maConn.log
|
|
67
70
|
this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT
|
|
68
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)
|
|
69
76
|
|
|
70
|
-
if (this.remoteAddr.
|
|
77
|
+
if (this.remoteAddr.getComponents().find(component => component.code === CODE_P2P) == null) {
|
|
71
78
|
this.remoteAddr = this.remoteAddr.encapsulate(`/p2p/${this.remotePeer}`)
|
|
72
79
|
}
|
|
73
80
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.
|
|
78
|
-
|
|
79
|
-
this.muxer = init.muxerFactory.createStreamMuxer({
|
|
80
|
-
direction: this.direction,
|
|
81
|
-
log: this.log,
|
|
82
|
-
// Run anytime a remote stream is created
|
|
83
|
-
onIncomingStream: (stream) => {
|
|
84
|
-
this.onIncomingStream(stream)
|
|
85
|
-
}
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// Pipe all data through the muxer
|
|
89
|
-
void Promise.all([
|
|
90
|
-
this.muxer.sink(this.maConn.source),
|
|
91
|
-
this.maConn.sink(this.muxer.source)
|
|
92
|
-
]).catch(err => {
|
|
93
|
-
this.log.error('error piping data through muxer - %e', err)
|
|
94
|
-
})
|
|
81
|
+
if (init.muxer != null) {
|
|
82
|
+
this.multiplexer = init.muxer.protocol
|
|
83
|
+
this.muxer = init.muxer
|
|
84
|
+
this.muxer.addEventListener('stream', this.onIncomingStream)
|
|
95
85
|
}
|
|
86
|
+
|
|
87
|
+
this.maConn.addEventListener('close', (evt) => {
|
|
88
|
+
this.dispatchEvent(new StreamCloseEvent(evt.local, evt.error))
|
|
89
|
+
})
|
|
96
90
|
}
|
|
97
91
|
|
|
98
92
|
readonly [Symbol.toStringTag] = 'Connection'
|
|
@@ -103,32 +97,43 @@ export class Connection implements ConnectionInterface {
|
|
|
103
97
|
return this.muxer?.streams ?? []
|
|
104
98
|
}
|
|
105
99
|
|
|
100
|
+
get status (): ConnectionStatus {
|
|
101
|
+
return this.maConn.status
|
|
102
|
+
}
|
|
103
|
+
|
|
106
104
|
/**
|
|
107
105
|
* Create a new stream over this connection
|
|
108
106
|
*/
|
|
109
107
|
newStream = async (protocols: string[], options: NewStreamOptions = {}): Promise<Stream> => {
|
|
110
|
-
if (this.
|
|
111
|
-
throw new
|
|
108
|
+
if (this.muxer == null) {
|
|
109
|
+
throw new MuxerUnavailableError('Connection is not multiplexed')
|
|
112
110
|
}
|
|
113
111
|
|
|
114
|
-
if (this.status
|
|
115
|
-
throw new ConnectionClosedError(
|
|
112
|
+
if (this.muxer.status !== 'open') {
|
|
113
|
+
throw new ConnectionClosedError(`The connection muxer is "${this.muxer.status}" and not "open"`)
|
|
116
114
|
}
|
|
117
115
|
|
|
118
|
-
if (
|
|
119
|
-
|
|
116
|
+
if (this.maConn.status !== 'open') {
|
|
117
|
+
throw new ConnectionClosedError(`The connection is "${this.status}" and not "open"`)
|
|
120
118
|
}
|
|
121
119
|
|
|
122
120
|
if (this.limits != null && options?.runOnLimitedConnection !== true) {
|
|
123
121
|
throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
|
|
124
122
|
}
|
|
125
123
|
|
|
126
|
-
if (
|
|
127
|
-
|
|
124
|
+
if (!Array.isArray(protocols)) {
|
|
125
|
+
protocols = [protocols]
|
|
128
126
|
}
|
|
129
127
|
|
|
130
128
|
this.log.trace('starting new stream for protocols %s', protocols)
|
|
131
|
-
const muxedStream = await this.muxer.
|
|
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
|
+
})
|
|
132
137
|
this.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols)
|
|
133
138
|
|
|
134
139
|
try {
|
|
@@ -144,24 +149,21 @@ export class Connection implements ConnectionInterface {
|
|
|
144
149
|
}
|
|
145
150
|
}
|
|
146
151
|
|
|
147
|
-
muxedStream.
|
|
152
|
+
if (muxedStream.protocol === '') {
|
|
153
|
+
muxedStream.log.trace('selecting protocol from protocols %s', protocols)
|
|
148
154
|
|
|
149
|
-
|
|
150
|
-
stream,
|
|
151
|
-
protocol
|
|
152
|
-
} = await mss.select(muxedStream, protocols, {
|
|
153
|
-
...options,
|
|
154
|
-
log: muxedStream.log,
|
|
155
|
-
yieldBytes: true
|
|
156
|
-
})
|
|
155
|
+
muxedStream.protocol = await mss.select(muxedStream, protocols, options)
|
|
157
156
|
|
|
158
|
-
|
|
157
|
+
muxedStream.log('negotiated protocol %s', muxedStream.protocol)
|
|
158
|
+
} else {
|
|
159
|
+
muxedStream.log('pre-negotiated protocol %s', muxedStream.protocol)
|
|
160
|
+
}
|
|
159
161
|
|
|
160
|
-
const outgoingLimit = findOutgoingStreamLimit(protocol, this.components.registrar, options)
|
|
161
|
-
const streamCount = countStreams(protocol, 'outbound', this)
|
|
162
|
+
const outgoingLimit = findOutgoingStreamLimit(muxedStream.protocol, this.components.registrar, options)
|
|
163
|
+
const streamCount = countStreams(muxedStream.protocol, 'outbound', this)
|
|
162
164
|
|
|
163
|
-
if (streamCount
|
|
164
|
-
const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`)
|
|
165
|
+
if (streamCount > outgoingLimit) {
|
|
166
|
+
const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${muxedStream.protocol}" - ${streamCount}/${outgoingLimit}`)
|
|
165
167
|
muxedStream.abort(err)
|
|
166
168
|
|
|
167
169
|
throw err
|
|
@@ -170,132 +172,120 @@ export class Connection implements ConnectionInterface {
|
|
|
170
172
|
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
171
173
|
// the peer store should ensure that the peer is registered with that protocol
|
|
172
174
|
await this.components.peerStore.merge(this.remotePeer, {
|
|
173
|
-
protocols: [protocol]
|
|
175
|
+
protocols: [muxedStream.protocol]
|
|
174
176
|
})
|
|
175
177
|
|
|
176
|
-
|
|
177
|
-
// the source/sink
|
|
178
|
-
muxedStream.source = stream.source
|
|
179
|
-
muxedStream.sink = stream.sink
|
|
180
|
-
muxedStream.protocol = protocol
|
|
181
|
-
|
|
182
|
-
// allow closing the write end of a not-yet-negotiated stream
|
|
183
|
-
if (stream.closeWrite != null) {
|
|
184
|
-
muxedStream.closeWrite = stream.closeWrite
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// allow closing the read end of a not-yet-negotiated stream
|
|
188
|
-
if (stream.closeRead != null) {
|
|
189
|
-
muxedStream.closeRead = stream.closeRead
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// make sure we don't try to negotiate a stream we are closing
|
|
193
|
-
if (stream.close != null) {
|
|
194
|
-
muxedStream.close = stream.close
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
this.components.metrics?.trackProtocolStream(muxedStream, this)
|
|
178
|
+
this.components.metrics?.trackProtocolStream(muxedStream)
|
|
198
179
|
|
|
199
|
-
|
|
180
|
+
const middleware = this.components.registrar.getMiddleware(muxedStream.protocol)
|
|
200
181
|
|
|
201
|
-
return muxedStream
|
|
182
|
+
return await this.runMiddlewareChain(muxedStream, this, middleware)
|
|
202
183
|
} catch (err: any) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
if (muxedStream.timeline.close == null) {
|
|
184
|
+
if (muxedStream.status === 'open') {
|
|
206
185
|
muxedStream.abort(err)
|
|
186
|
+
} else {
|
|
187
|
+
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)
|
|
207
188
|
}
|
|
208
189
|
|
|
209
190
|
throw err
|
|
210
191
|
}
|
|
211
192
|
}
|
|
212
193
|
|
|
213
|
-
private onIncomingStream (
|
|
194
|
+
private async onIncomingStream (evt: CustomEvent<Stream>): Promise<void> {
|
|
195
|
+
const muxedStream = evt.detail
|
|
196
|
+
|
|
214
197
|
const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout)
|
|
215
198
|
setMaxListeners(Infinity, signal)
|
|
216
199
|
|
|
217
|
-
|
|
218
|
-
|
|
200
|
+
muxedStream.log('start protocol negotiation, timing out after %dms', this.inboundStreamProtocolNegotiationTimeout)
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
if (muxedStream.protocol === '') {
|
|
219
204
|
const protocols = this.components.registrar.getProtocols()
|
|
220
205
|
|
|
221
|
-
|
|
222
|
-
signal,
|
|
223
|
-
log: muxedStream.log,
|
|
224
|
-
yieldBytes: false
|
|
225
|
-
})
|
|
206
|
+
muxedStream.log.trace('selecting protocol from protocols %s', protocols)
|
|
226
207
|
|
|
227
|
-
|
|
208
|
+
muxedStream.protocol = await mss.handle(muxedStream, protocols, {
|
|
209
|
+
signal
|
|
210
|
+
})
|
|
228
211
|
|
|
229
|
-
|
|
230
|
-
|
|
212
|
+
muxedStream.log('negotiated protocol %s', muxedStream.protocol)
|
|
213
|
+
} else {
|
|
214
|
+
muxedStream.log('pre-negotiated protocol %s', muxedStream.protocol)
|
|
215
|
+
}
|
|
231
216
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
muxedStream.abort(err)
|
|
217
|
+
const incomingLimit = findIncomingStreamLimit(muxedStream.protocol, this.components.registrar)
|
|
218
|
+
const streamCount = countStreams(muxedStream.protocol, 'inbound', this)
|
|
235
219
|
|
|
236
|
-
|
|
237
|
-
}
|
|
220
|
+
if (streamCount > incomingLimit) {
|
|
221
|
+
throw new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${muxedStream.protocol}" - limit ${incomingLimit}`)
|
|
222
|
+
}
|
|
238
223
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
muxedStream.
|
|
243
|
-
|
|
224
|
+
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
225
|
+
// the peer store should ensure that the peer is registered with that protocol
|
|
226
|
+
await this.components.peerStore.merge(this.remotePeer, {
|
|
227
|
+
protocols: [muxedStream.protocol]
|
|
228
|
+
}, {
|
|
229
|
+
signal
|
|
230
|
+
})
|
|
244
231
|
|
|
245
|
-
|
|
246
|
-
if (stream.closeWrite != null) {
|
|
247
|
-
muxedStream.closeWrite = stream.closeWrite
|
|
248
|
-
}
|
|
232
|
+
this.components.metrics?.trackProtocolStream(muxedStream)
|
|
249
233
|
|
|
250
|
-
|
|
251
|
-
if (stream.closeRead != null) {
|
|
252
|
-
muxedStream.closeRead = stream.closeRead
|
|
253
|
-
}
|
|
234
|
+
const { handler, options } = this.components.registrar.getHandler(muxedStream.protocol)
|
|
254
235
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}
|
|
236
|
+
if (this.limits != null && options.runOnLimitedConnection !== true) {
|
|
237
|
+
throw new LimitedConnectionError('Cannot open protocol stream on limited connection')
|
|
238
|
+
}
|
|
259
239
|
|
|
260
|
-
|
|
261
|
-
// the peer store should ensure that the peer is registered with that protocol
|
|
262
|
-
await this.components.peerStore.merge(this.remotePeer, {
|
|
263
|
-
protocols: [protocol]
|
|
264
|
-
}, {
|
|
265
|
-
signal
|
|
266
|
-
})
|
|
240
|
+
const middleware = this.components.registrar.getMiddleware(muxedStream.protocol)
|
|
267
241
|
|
|
268
|
-
|
|
242
|
+
middleware.push(async (stream, connection, next) => {
|
|
243
|
+
await handler(stream, connection)
|
|
244
|
+
next(stream, connection)
|
|
245
|
+
})
|
|
269
246
|
|
|
270
|
-
|
|
247
|
+
await this.runMiddlewareChain(muxedStream, this, middleware)
|
|
248
|
+
} catch (err: any) {
|
|
249
|
+
muxedStream.abort(err)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
271
252
|
|
|
272
|
-
|
|
273
|
-
|
|
253
|
+
private async runMiddlewareChain (stream: Stream, connection: ConnectionInterface, middleware: StreamMiddleware[]): Promise<Stream> {
|
|
254
|
+
for (let i = 0; i < middleware.length; i++) {
|
|
255
|
+
const mw = middleware[i]
|
|
256
|
+
stream.log.trace('running middleware', i, mw)
|
|
257
|
+
|
|
258
|
+
// eslint-disable-next-line no-loop-func
|
|
259
|
+
await new Promise<void>((resolve, reject) => {
|
|
260
|
+
try {
|
|
261
|
+
const result = mw(stream, connection, (s, c) => {
|
|
262
|
+
stream = s
|
|
263
|
+
connection = c
|
|
264
|
+
resolve()
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
if (result instanceof Promise) {
|
|
268
|
+
result.catch(reject)
|
|
269
|
+
}
|
|
270
|
+
} catch (err) {
|
|
271
|
+
reject(err)
|
|
274
272
|
}
|
|
275
|
-
|
|
276
|
-
await handler({ connection: this, stream: muxedStream })
|
|
277
273
|
})
|
|
278
|
-
.catch(async err => {
|
|
279
|
-
this.log.error('error handling incoming stream id %s - %e', muxedStream.id, err)
|
|
280
274
|
|
|
281
|
-
|
|
282
|
-
|
|
275
|
+
stream.log.trace('ran middleware', i, mw)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return stream
|
|
283
279
|
}
|
|
284
280
|
|
|
285
281
|
/**
|
|
286
282
|
* Close the connection
|
|
287
283
|
*/
|
|
288
284
|
async close (options: AbortOptions = {}): Promise<void> {
|
|
289
|
-
if (this.status === 'closed' || this.status === 'closing') {
|
|
290
|
-
return
|
|
291
|
-
}
|
|
292
|
-
|
|
293
285
|
this.log('closing connection to %a', this.remoteAddr)
|
|
294
286
|
|
|
295
|
-
this.status = 'closing'
|
|
296
|
-
|
|
297
287
|
if (options.signal == null) {
|
|
298
|
-
const signal = AbortSignal.timeout(
|
|
288
|
+
const signal = AbortSignal.timeout(this.closeTimeout)
|
|
299
289
|
setMaxListeners(Infinity, signal)
|
|
300
290
|
|
|
301
291
|
options = {
|
|
@@ -304,42 +294,13 @@ export class Connection implements ConnectionInterface {
|
|
|
304
294
|
}
|
|
305
295
|
}
|
|
306
296
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
// ensure remaining streams are closed gracefully
|
|
311
|
-
await this.muxer?.close(options)
|
|
312
|
-
|
|
313
|
-
// close the underlying transport
|
|
314
|
-
await this.maConn.close(options)
|
|
315
|
-
|
|
316
|
-
this.log.trace('updating timeline with close time')
|
|
317
|
-
|
|
318
|
-
this.status = 'closed'
|
|
319
|
-
this.timeline.close = Date.now()
|
|
320
|
-
} catch (err: any) {
|
|
321
|
-
this.log.error('error encountered during graceful close of connection to %a', this.remoteAddr, err)
|
|
322
|
-
this.abort(err)
|
|
323
|
-
}
|
|
297
|
+
await this.muxer?.close(options)
|
|
298
|
+
await this.maConn.close(options)
|
|
324
299
|
}
|
|
325
300
|
|
|
326
301
|
abort (err: Error): void {
|
|
327
|
-
if (this.status === 'closed') {
|
|
328
|
-
return
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
this.log.error('aborting connection to %a due to error', this.remoteAddr, err)
|
|
332
|
-
|
|
333
|
-
this.status = 'closing'
|
|
334
|
-
|
|
335
|
-
// ensure remaining streams are aborted
|
|
336
302
|
this.muxer?.abort(err)
|
|
337
|
-
|
|
338
|
-
// abort the underlying transport
|
|
339
303
|
this.maConn.abort(err)
|
|
340
|
-
|
|
341
|
-
this.status = 'closed'
|
|
342
|
-
this.timeline.close = Date.now()
|
|
343
304
|
}
|
|
344
305
|
}
|
|
345
306
|
|
|
@@ -347,11 +308,13 @@ export function createConnection (components: ConnectionComponents, init: Connec
|
|
|
347
308
|
return new Connection(components, init)
|
|
348
309
|
}
|
|
349
310
|
|
|
350
|
-
function findIncomingStreamLimit (protocol: string, registrar: Registrar): number
|
|
311
|
+
function findIncomingStreamLimit (protocol: string, registrar: Registrar): number {
|
|
351
312
|
try {
|
|
352
313
|
const { options } = registrar.getHandler(protocol)
|
|
353
314
|
|
|
354
|
-
|
|
315
|
+
if (options.maxInboundStreams != null) {
|
|
316
|
+
return options.maxInboundStreams
|
|
317
|
+
}
|
|
355
318
|
} catch (err: any) {
|
|
356
319
|
if (err.name !== 'UnhandledProtocolError') {
|
|
357
320
|
throw err
|
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].
|
|
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.
|
|
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 '@
|
|
188
|
-
* import { yamux } from '@
|
|
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'
|
|
@@ -24,7 +24,7 @@ import { userAgent } from './user-agent.js'
|
|
|
24
24
|
import * as pkg from './version.js'
|
|
25
25
|
import type { Components } from './components.js'
|
|
26
26
|
import type { Libp2p as Libp2pInterface, Libp2pInit } from './index.js'
|
|
27
|
-
import type { PeerRouting, ContentRouting, Libp2pEvents, PendingDial, ServiceMap, AbortOptions, ComponentLogger, Logger, Connection, NewStreamOptions, Stream, Metrics, PeerId, PeerInfo, PeerStore, Topology, Libp2pStatus, IsDialableOptions, DialOptions, PublicKey, Ed25519PeerId, Secp256k1PeerId, RSAPublicKey, RSAPeerId, URLPeerId, Ed25519PublicKey, Secp256k1PublicKey, StreamHandler, StreamHandlerOptions } from '@libp2p/interface'
|
|
27
|
+
import type { PeerRouting, ContentRouting, Libp2pEvents, PendingDial, ServiceMap, AbortOptions, ComponentLogger, Logger, Connection, NewStreamOptions, Stream, Metrics, PeerId, PeerInfo, PeerStore, Topology, Libp2pStatus, IsDialableOptions, DialOptions, PublicKey, Ed25519PeerId, Secp256k1PeerId, RSAPublicKey, RSAPeerId, URLPeerId, Ed25519PublicKey, Secp256k1PublicKey, StreamHandler, StreamHandlerOptions, StreamMiddleware } from '@libp2p/interface'
|
|
28
28
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
29
29
|
|
|
30
30
|
export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter<Libp2pEvents> implements Libp2pInterface<T> {
|
|
@@ -119,8 +119,9 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
|
|
|
119
119
|
connectionEncrypters: (init.connectionEncrypters ?? []).map((fn, index) => this.configureComponent(`connection-encryption-${index}`, fn(this.components))),
|
|
120
120
|
streamMuxers: (init.streamMuxers ?? []).map((fn, index) => this.configureComponent(`stream-muxers-${index}`, fn(this.components))),
|
|
121
121
|
inboundUpgradeTimeout: init.connectionManager?.inboundUpgradeTimeout,
|
|
122
|
-
inboundStreamProtocolNegotiationTimeout: init.connectionManager?.inboundStreamProtocolNegotiationTimeout
|
|
123
|
-
outboundStreamProtocolNegotiationTimeout: init.connectionManager?.outboundStreamProtocolNegotiationTimeout
|
|
122
|
+
inboundStreamProtocolNegotiationTimeout: init.connectionManager?.inboundStreamProtocolNegotiationTimeout,
|
|
123
|
+
outboundStreamProtocolNegotiationTimeout: init.connectionManager?.outboundStreamProtocolNegotiationTimeout,
|
|
124
|
+
connectionCloseTimeout: init.connectionManager?.connectionCloseTimeout
|
|
124
125
|
})
|
|
125
126
|
|
|
126
127
|
// Setup the transport manager
|
|
@@ -236,7 +237,7 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
|
|
|
236
237
|
|
|
237
238
|
this.status = 'started'
|
|
238
239
|
this.safeDispatchEvent('start', { detail: this })
|
|
239
|
-
this.log('libp2p has started')
|
|
240
|
+
this.log('libp2p has started with peer id %p', this.peerId)
|
|
240
241
|
} catch (err: any) {
|
|
241
242
|
this.log.error('An error occurred starting libp2p', err)
|
|
242
243
|
// set status to 'started' so this.stop() will stop any running components
|
|
@@ -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
|
-
|
|
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.
|
|
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)
|
|
@@ -402,6 +401,14 @@ export class Libp2p<T extends ServiceMap = ServiceMap> extends TypedEventEmitter
|
|
|
402
401
|
this.components.registrar.unregister(id)
|
|
403
402
|
}
|
|
404
403
|
|
|
404
|
+
use (protocol: string, middleware: StreamMiddleware | StreamMiddleware[]): void {
|
|
405
|
+
this.components.registrar.use(protocol, Array.isArray(middleware) ? middleware : [middleware])
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
unuse (protocol: string): void {
|
|
409
|
+
this.components.registrar.unuse(protocol)
|
|
410
|
+
}
|
|
411
|
+
|
|
405
412
|
async isDialable (multiaddr: Multiaddr, options: IsDialableOptions = {}): Promise<boolean> {
|
|
406
413
|
return this.components.connectionManager.isDialable(multiaddr, options)
|
|
407
414
|
}
|
package/src/peer-routing.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { NotFoundError } from '@libp2p/interface'
|
|
2
|
-
import { createScalableCuckooFilter } from '@libp2p/utils
|
|
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'
|
package/src/random-walk.ts
CHANGED
|
@@ -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 {
|
|
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
|
|
72
|
-
|
|
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--
|