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.
- package/dist/index.min.js +13 -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 +40 -44
- 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 +3 -9
- package/dist/src/config/connection-gater.browser.js.map +1 -1
- package/dist/src/config.js +1 -1
- 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 +13 -25
- package/dist/src/connection-manager/dial-queue.js.map +1 -1
- package/dist/src/connection-manager/index.d.ts +10 -2
- package/dist/src/connection-manager/index.d.ts.map +1 -1
- package/dist/src/connection-manager/index.js +45 -27
- 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 +62 -0
- package/dist/src/connection.d.ts.map +1 -0
- package/dist/src/connection.js +239 -0
- package/dist/src/connection.js.map +1 -0
- 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.map +1 -1
- package/dist/src/libp2p.js +5 -5
- 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 +3 -3
- package/dist/src/registrar.d.ts.map +1 -1
- package/dist/src/registrar.js +50 -41
- 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 +27 -25
- package/dist/src/upgrader.d.ts.map +1 -1
- package/dist/src/upgrader.js +97 -336
- 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 +26 -30
- package/src/address-manager/dns-mappings.ts +51 -51
- 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 +3 -12
- package/src/config.ts +1 -1
- 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 +14 -29
- package/src/connection-manager/index.ts +62 -29
- 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 +316 -0
- package/src/get-peer.ts +3 -3
- package/src/index.ts +2 -2
- package/src/libp2p.ts +5 -6
- package/src/peer-routing.ts +1 -1
- package/src/random-walk.ts +13 -3
- package/src/registrar.ts +67 -54
- package/src/transport-manager.ts +18 -2
- package/src/upgrader.ts +143 -421
- package/src/utils.ts +31 -0
- package/src/version.ts +1 -1
- package/dist/src/connection/index.d.ts +0 -84
- package/dist/src/connection/index.d.ts.map +0 -1
- package/dist/src/connection/index.js +0 -144
- package/dist/src/connection/index.js.map +0 -1
- package/dist/typedoc-urls.json +0 -24
- package/src/connection/index.ts +0 -199
package/dist/src/upgrader.js
CHANGED
|
@@ -1,50 +1,15 @@
|
|
|
1
|
-
import { InvalidMultiaddrError,
|
|
1
|
+
import { InvalidMultiaddrError, InvalidPeerIdError } from '@libp2p/interface';
|
|
2
2
|
import * as mss from '@libp2p/multistream-select';
|
|
3
3
|
import { peerIdFromString } from '@libp2p/peer-id';
|
|
4
|
-
import { trackedMap } from '@libp2p/utils
|
|
4
|
+
import { trackedMap } from '@libp2p/utils';
|
|
5
|
+
import { CODE_P2P } from '@multiformats/multiaddr';
|
|
5
6
|
import { anySignal } from 'any-signal';
|
|
6
7
|
import { setMaxListeners } from 'main-event';
|
|
7
8
|
import { CustomProgressEvent } from 'progress-events';
|
|
8
9
|
import { raceSignal } from 'race-signal';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
10
|
+
import { PROTOCOL_NEGOTIATION_TIMEOUT, INBOUND_UPGRADE_TIMEOUT, CONNECTION_CLOSE_TIMEOUT } from './connection-manager/constants.js';
|
|
11
|
+
import { createConnection } from './connection.js';
|
|
11
12
|
import { ConnectionDeniedError, ConnectionInterceptedError, EncryptionFailedError, MuxerUnavailableError } from './errors.js';
|
|
12
|
-
import { DEFAULT_MAX_INBOUND_STREAMS, DEFAULT_MAX_OUTBOUND_STREAMS } from './registrar.js';
|
|
13
|
-
function findIncomingStreamLimit(protocol, registrar) {
|
|
14
|
-
try {
|
|
15
|
-
const { options } = registrar.getHandler(protocol);
|
|
16
|
-
return options.maxInboundStreams;
|
|
17
|
-
}
|
|
18
|
-
catch (err) {
|
|
19
|
-
if (err.name !== 'UnhandledProtocolError') {
|
|
20
|
-
throw err;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return DEFAULT_MAX_INBOUND_STREAMS;
|
|
24
|
-
}
|
|
25
|
-
function findOutgoingStreamLimit(protocol, registrar, options = {}) {
|
|
26
|
-
try {
|
|
27
|
-
const { options } = registrar.getHandler(protocol);
|
|
28
|
-
if (options.maxOutboundStreams != null) {
|
|
29
|
-
return options.maxOutboundStreams;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
if (err.name !== 'UnhandledProtocolError') {
|
|
34
|
-
throw err;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return options.maxOutboundStreams ?? DEFAULT_MAX_OUTBOUND_STREAMS;
|
|
38
|
-
}
|
|
39
|
-
function countStreams(protocol, direction, connection) {
|
|
40
|
-
let streamCount = 0;
|
|
41
|
-
connection.streams.forEach(stream => {
|
|
42
|
-
if (stream.direction === direction && stream.protocol === protocol) {
|
|
43
|
-
streamCount++;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
return streamCount;
|
|
47
|
-
}
|
|
48
13
|
export class Upgrader {
|
|
49
14
|
components;
|
|
50
15
|
connectionEncrypters;
|
|
@@ -54,6 +19,7 @@ export class Upgrader {
|
|
|
54
19
|
outboundStreamProtocolNegotiationTimeout;
|
|
55
20
|
events;
|
|
56
21
|
metrics;
|
|
22
|
+
connectionCloseTimeout;
|
|
57
23
|
constructor(components, init) {
|
|
58
24
|
this.components = components;
|
|
59
25
|
this.connectionEncrypters = trackedMap({
|
|
@@ -73,6 +39,7 @@ export class Upgrader {
|
|
|
73
39
|
this.inboundUpgradeTimeout = init.inboundUpgradeTimeout ?? INBOUND_UPGRADE_TIMEOUT;
|
|
74
40
|
this.inboundStreamProtocolNegotiationTimeout = init.inboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT;
|
|
75
41
|
this.outboundStreamProtocolNegotiationTimeout = init.outboundStreamProtocolNegotiationTimeout ?? PROTOCOL_NEGOTIATION_TIMEOUT;
|
|
42
|
+
this.connectionCloseTimeout = init.connectionCloseTimeout ?? CONNECTION_CLOSE_TIMEOUT;
|
|
76
43
|
this.events = components.events;
|
|
77
44
|
this.metrics = {
|
|
78
45
|
dials: components.metrics?.registerCounterGroup('libp2p_connection_manager_dials_total'),
|
|
@@ -100,9 +67,6 @@ export class Upgrader {
|
|
|
100
67
|
setMaxListeners(Infinity, output);
|
|
101
68
|
return output;
|
|
102
69
|
}
|
|
103
|
-
/**
|
|
104
|
-
* Upgrades an inbound connection
|
|
105
|
-
*/
|
|
106
70
|
async upgradeInbound(maConn, opts) {
|
|
107
71
|
let accepted = false;
|
|
108
72
|
// always apply upgrade timeout for incoming upgrades
|
|
@@ -111,7 +75,7 @@ export class Upgrader {
|
|
|
111
75
|
this.metrics.dials?.increment({
|
|
112
76
|
inbound: true
|
|
113
77
|
});
|
|
114
|
-
accepted =
|
|
78
|
+
accepted = this.components.connectionManager.acceptIncomingConnection(maConn);
|
|
115
79
|
if (!accepted) {
|
|
116
80
|
throw new ConnectionDeniedError('Connection denied');
|
|
117
81
|
}
|
|
@@ -137,15 +101,12 @@ export class Upgrader {
|
|
|
137
101
|
}
|
|
138
102
|
}
|
|
139
103
|
}
|
|
140
|
-
/**
|
|
141
|
-
* Upgrades an outbound connection
|
|
142
|
-
*/
|
|
143
104
|
async upgradeOutbound(maConn, opts) {
|
|
144
105
|
try {
|
|
145
106
|
this.metrics.dials?.increment({
|
|
146
107
|
outbound: true
|
|
147
108
|
});
|
|
148
|
-
const idStr = maConn.remoteAddr.
|
|
109
|
+
const idStr = maConn.remoteAddr.getComponents().findLast(c => c.code === CODE_P2P)?.value;
|
|
149
110
|
let remotePeerId;
|
|
150
111
|
if (idStr != null) {
|
|
151
112
|
remotePeerId = peerIdFromString(idStr);
|
|
@@ -169,49 +130,53 @@ export class Upgrader {
|
|
|
169
130
|
}
|
|
170
131
|
}
|
|
171
132
|
async _performUpgrade(maConn, direction, opts) {
|
|
172
|
-
let
|
|
133
|
+
let stream = maConn;
|
|
173
134
|
let remotePeer;
|
|
174
|
-
let upgradedConn;
|
|
175
135
|
let muxerFactory;
|
|
136
|
+
let muxer;
|
|
176
137
|
let cryptoProtocol;
|
|
138
|
+
const id = `${(parseInt(String(Math.random() * 1e9))).toString(36)}${Date.now()}`;
|
|
139
|
+
maConn.log = maConn.log.newScope(`${direction}:${id}`);
|
|
177
140
|
this.components.metrics?.trackMultiaddrConnection(maConn);
|
|
178
141
|
maConn.log.trace('starting the %s connection upgrade', direction);
|
|
179
142
|
// Protect
|
|
180
|
-
let protectedConn = maConn;
|
|
181
143
|
if (opts?.skipProtection !== true) {
|
|
182
144
|
const protector = this.components.connectionProtector;
|
|
183
145
|
if (protector != null) {
|
|
184
146
|
maConn.log('protecting the %s connection', direction);
|
|
185
|
-
|
|
147
|
+
stream = await protector.protect(stream, opts);
|
|
186
148
|
}
|
|
187
149
|
}
|
|
188
150
|
try {
|
|
189
151
|
// Encrypt the connection
|
|
190
|
-
|
|
191
|
-
|
|
152
|
+
if (isEncryptionSkipped(opts)) {
|
|
153
|
+
if (opts.remotePeer == null) {
|
|
154
|
+
throw new InvalidMultiaddrError(`${direction} connection that skipped encryption must have a peer id`);
|
|
155
|
+
}
|
|
156
|
+
cryptoProtocol = 'native';
|
|
157
|
+
remotePeer = opts.remotePeer;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const peerIdString = maConn.remoteAddr.getComponents().findLast(c => c.code === CODE_P2P)?.value;
|
|
161
|
+
let remotePeerFromMultiaddr;
|
|
162
|
+
if (peerIdString != null) {
|
|
163
|
+
remotePeerFromMultiaddr = peerIdFromString(peerIdString);
|
|
164
|
+
}
|
|
192
165
|
opts?.onProgress?.(new CustomProgressEvent(`upgrader:encrypt-${direction}-connection`));
|
|
193
166
|
({
|
|
194
|
-
|
|
167
|
+
connection: stream,
|
|
195
168
|
remotePeer,
|
|
196
169
|
protocol: cryptoProtocol,
|
|
197
170
|
streamMuxer: muxerFactory
|
|
198
171
|
} = await (direction === 'inbound'
|
|
199
|
-
? this._encryptInbound(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
else {
|
|
208
|
-
const idStr = maConn.remoteAddr.getPeerId();
|
|
209
|
-
if (idStr == null) {
|
|
210
|
-
throw new InvalidMultiaddrError(`${direction} connection that skipped encryption must have a peer id`);
|
|
211
|
-
}
|
|
212
|
-
const remotePeerId = peerIdFromString(idStr);
|
|
213
|
-
cryptoProtocol = 'native';
|
|
214
|
-
remotePeer = remotePeerId;
|
|
172
|
+
? this._encryptInbound(stream, {
|
|
173
|
+
...opts,
|
|
174
|
+
remotePeer: remotePeerFromMultiaddr
|
|
175
|
+
})
|
|
176
|
+
: this._encryptOutbound(stream, {
|
|
177
|
+
...opts,
|
|
178
|
+
remotePeer: remotePeerFromMultiaddr
|
|
179
|
+
})));
|
|
215
180
|
}
|
|
216
181
|
// this can happen if we dial a multiaddr without a peer id, we only find
|
|
217
182
|
// out the identity of the remote after the connection is encrypted
|
|
@@ -220,287 +185,84 @@ export class Upgrader {
|
|
|
220
185
|
maConn.abort(err);
|
|
221
186
|
throw err;
|
|
222
187
|
}
|
|
223
|
-
|
|
188
|
+
// stream.pause()
|
|
189
|
+
await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundEncryptedConnection' : 'denyOutboundEncryptedConnection', remotePeer, maConn);
|
|
190
|
+
// stream.resume()
|
|
224
191
|
if (opts?.muxerFactory != null) {
|
|
225
192
|
muxerFactory = opts.muxerFactory;
|
|
226
193
|
}
|
|
227
194
|
else if (muxerFactory == null && this.streamMuxers.size > 0) {
|
|
228
195
|
opts?.onProgress?.(new CustomProgressEvent(`upgrader:multiplex-${direction}-connection`));
|
|
229
196
|
// Multiplex the connection
|
|
230
|
-
|
|
231
|
-
? this._multiplexInbound(
|
|
232
|
-
|
|
233
|
-
...encryptedConn
|
|
234
|
-
}, this.streamMuxers, opts)
|
|
235
|
-
: this._multiplexOutbound({
|
|
236
|
-
...protectedConn,
|
|
237
|
-
...encryptedConn
|
|
238
|
-
}, this.streamMuxers, opts));
|
|
239
|
-
muxerFactory = multiplexed.muxerFactory;
|
|
240
|
-
upgradedConn = multiplexed.stream;
|
|
197
|
+
muxerFactory = await (direction === 'inbound'
|
|
198
|
+
? this._multiplexInbound(stream, this.streamMuxers, opts)
|
|
199
|
+
: this._multiplexOutbound(stream, this.streamMuxers, opts));
|
|
241
200
|
}
|
|
242
201
|
}
|
|
243
202
|
catch (err) {
|
|
244
|
-
maConn.log.error('failed to upgrade
|
|
203
|
+
maConn.log.error('failed to upgrade %s connection %s %a - %e', direction, direction === 'inbound' ? 'from' : 'to', maConn.remoteAddr, err);
|
|
245
204
|
throw err;
|
|
246
205
|
}
|
|
206
|
+
// create the connection muxer if one is configured
|
|
207
|
+
if (muxerFactory != null) {
|
|
208
|
+
maConn.log('create muxer %s', muxerFactory.protocol);
|
|
209
|
+
muxer = muxerFactory.createStreamMuxer(stream);
|
|
210
|
+
}
|
|
211
|
+
// stream.pause()
|
|
247
212
|
await this.shouldBlockConnection(direction === 'inbound' ? 'denyInboundUpgradedConnection' : 'denyOutboundUpgradedConnection', remotePeer, maConn);
|
|
248
|
-
|
|
249
|
-
|
|
213
|
+
const conn = this._createConnection({
|
|
214
|
+
id,
|
|
250
215
|
cryptoProtocol,
|
|
251
216
|
direction,
|
|
252
217
|
maConn,
|
|
253
|
-
|
|
254
|
-
|
|
218
|
+
stream,
|
|
219
|
+
muxer,
|
|
255
220
|
remotePeer,
|
|
256
|
-
limits: opts?.limits
|
|
221
|
+
limits: opts?.limits,
|
|
222
|
+
closeTimeout: this.connectionCloseTimeout
|
|
257
223
|
});
|
|
224
|
+
conn.log('successfully upgraded connection');
|
|
225
|
+
// stream.resume()
|
|
226
|
+
return conn;
|
|
258
227
|
}
|
|
259
228
|
/**
|
|
260
229
|
* A convenience method for generating a new `Connection`
|
|
261
230
|
*/
|
|
262
231
|
_createConnection(opts) {
|
|
263
|
-
const { cryptoProtocol, direction, maConn, upgradedConn, remotePeer, muxerFactory, limits } = opts;
|
|
264
|
-
let muxer;
|
|
265
|
-
let newStream;
|
|
266
|
-
let connection; // eslint-disable-line prefer-const
|
|
267
|
-
if (muxerFactory != null) {
|
|
268
|
-
// Create the muxer
|
|
269
|
-
muxer = muxerFactory.createStreamMuxer({
|
|
270
|
-
direction,
|
|
271
|
-
// Run anytime a remote stream is created
|
|
272
|
-
onIncomingStream: muxedStream => {
|
|
273
|
-
if (connection == null) {
|
|
274
|
-
return;
|
|
275
|
-
}
|
|
276
|
-
const signal = AbortSignal.timeout(this.inboundStreamProtocolNegotiationTimeout);
|
|
277
|
-
setMaxListeners(Infinity, signal);
|
|
278
|
-
void Promise.resolve()
|
|
279
|
-
.then(async () => {
|
|
280
|
-
const protocols = this.components.registrar.getProtocols();
|
|
281
|
-
const { stream, protocol } = await mss.handle(muxedStream, protocols, {
|
|
282
|
-
signal,
|
|
283
|
-
log: muxedStream.log,
|
|
284
|
-
yieldBytes: false
|
|
285
|
-
});
|
|
286
|
-
if (connection == null) {
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
connection.log('incoming stream opened on %s', protocol);
|
|
290
|
-
const incomingLimit = findIncomingStreamLimit(protocol, this.components.registrar);
|
|
291
|
-
const streamCount = countStreams(protocol, 'inbound', connection);
|
|
292
|
-
if (streamCount === incomingLimit) {
|
|
293
|
-
const err = new TooManyInboundProtocolStreamsError(`Too many inbound protocol streams for protocol "${protocol}" - limit ${incomingLimit}`);
|
|
294
|
-
muxedStream.abort(err);
|
|
295
|
-
throw err;
|
|
296
|
-
}
|
|
297
|
-
// after the handshake the returned stream can have early data so override
|
|
298
|
-
// the source/sink
|
|
299
|
-
muxedStream.source = stream.source;
|
|
300
|
-
muxedStream.sink = stream.sink;
|
|
301
|
-
muxedStream.protocol = protocol;
|
|
302
|
-
// allow closing the write end of a not-yet-negotiated stream
|
|
303
|
-
if (stream.closeWrite != null) {
|
|
304
|
-
muxedStream.closeWrite = stream.closeWrite;
|
|
305
|
-
}
|
|
306
|
-
// allow closing the read end of a not-yet-negotiated stream
|
|
307
|
-
if (stream.closeRead != null) {
|
|
308
|
-
muxedStream.closeRead = stream.closeRead;
|
|
309
|
-
}
|
|
310
|
-
// make sure we don't try to negotiate a stream we are closing
|
|
311
|
-
if (stream.close != null) {
|
|
312
|
-
muxedStream.close = stream.close;
|
|
313
|
-
}
|
|
314
|
-
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
315
|
-
// the peer store should ensure that the peer is registered with that protocol
|
|
316
|
-
await this.components.peerStore.merge(remotePeer, {
|
|
317
|
-
protocols: [protocol]
|
|
318
|
-
}, {
|
|
319
|
-
signal
|
|
320
|
-
});
|
|
321
|
-
this.components.metrics?.trackProtocolStream(muxedStream, connection);
|
|
322
|
-
this._onStream({ connection, stream: muxedStream, protocol });
|
|
323
|
-
})
|
|
324
|
-
.catch(async (err) => {
|
|
325
|
-
connection.log.error('error handling incoming stream id %s - %e', muxedStream.id, err);
|
|
326
|
-
if (muxedStream.timeline.close == null) {
|
|
327
|
-
await muxedStream.close({
|
|
328
|
-
signal
|
|
329
|
-
})
|
|
330
|
-
.catch(err => muxedStream.abort(err));
|
|
331
|
-
}
|
|
332
|
-
});
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
newStream = async (protocols, options = {}) => {
|
|
336
|
-
if (muxer == null) {
|
|
337
|
-
throw new MuxerUnavailableError('Connection is not multiplexed');
|
|
338
|
-
}
|
|
339
|
-
connection.log.trace('starting new stream for protocols %s', protocols);
|
|
340
|
-
const muxedStream = await muxer.newStream();
|
|
341
|
-
connection.log.trace('started new stream %s for protocols %s', muxedStream.id, protocols);
|
|
342
|
-
try {
|
|
343
|
-
if (options.signal == null) {
|
|
344
|
-
muxedStream.log('no abort signal was passed while trying to negotiate protocols %s falling back to default timeout', protocols);
|
|
345
|
-
const signal = AbortSignal.timeout(this.outboundStreamProtocolNegotiationTimeout);
|
|
346
|
-
setMaxListeners(Infinity, signal);
|
|
347
|
-
options = {
|
|
348
|
-
...options,
|
|
349
|
-
signal
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
muxedStream.log.trace('selecting protocol from protocols %s', protocols);
|
|
353
|
-
const { stream, protocol } = await mss.select(muxedStream, protocols, {
|
|
354
|
-
...options,
|
|
355
|
-
log: muxedStream.log,
|
|
356
|
-
yieldBytes: true
|
|
357
|
-
});
|
|
358
|
-
muxedStream.log.trace('selected protocol %s', protocol);
|
|
359
|
-
const outgoingLimit = findOutgoingStreamLimit(protocol, this.components.registrar, options);
|
|
360
|
-
const streamCount = countStreams(protocol, 'outbound', connection);
|
|
361
|
-
if (streamCount >= outgoingLimit) {
|
|
362
|
-
const err = new TooManyOutboundProtocolStreamsError(`Too many outbound protocol streams for protocol "${protocol}" - ${streamCount}/${outgoingLimit}`);
|
|
363
|
-
muxedStream.abort(err);
|
|
364
|
-
throw err;
|
|
365
|
-
}
|
|
366
|
-
// If a protocol stream has been successfully negotiated and is to be passed to the application,
|
|
367
|
-
// the peer store should ensure that the peer is registered with that protocol
|
|
368
|
-
await this.components.peerStore.merge(remotePeer, {
|
|
369
|
-
protocols: [protocol]
|
|
370
|
-
});
|
|
371
|
-
// after the handshake the returned stream can have early data so override
|
|
372
|
-
// the source/sink
|
|
373
|
-
muxedStream.source = stream.source;
|
|
374
|
-
muxedStream.sink = stream.sink;
|
|
375
|
-
muxedStream.protocol = protocol;
|
|
376
|
-
// allow closing the write end of a not-yet-negotiated stream
|
|
377
|
-
if (stream.closeWrite != null) {
|
|
378
|
-
muxedStream.closeWrite = stream.closeWrite;
|
|
379
|
-
}
|
|
380
|
-
// allow closing the read end of a not-yet-negotiated stream
|
|
381
|
-
if (stream.closeRead != null) {
|
|
382
|
-
muxedStream.closeRead = stream.closeRead;
|
|
383
|
-
}
|
|
384
|
-
// make sure we don't try to negotiate a stream we are closing
|
|
385
|
-
if (stream.close != null) {
|
|
386
|
-
muxedStream.close = stream.close;
|
|
387
|
-
}
|
|
388
|
-
this.components.metrics?.trackProtocolStream(muxedStream, connection);
|
|
389
|
-
return muxedStream;
|
|
390
|
-
}
|
|
391
|
-
catch (err) {
|
|
392
|
-
connection.log.error('could not create new outbound stream on connection %s %a for protocols %s - %e', direction === 'inbound' ? 'from' : 'to', opts.maConn.remoteAddr, protocols, err);
|
|
393
|
-
if (muxedStream.timeline.close == null) {
|
|
394
|
-
muxedStream.abort(err);
|
|
395
|
-
}
|
|
396
|
-
throw err;
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
// Pipe all data through the muxer
|
|
400
|
-
void Promise.all([
|
|
401
|
-
muxer.sink(upgradedConn.source),
|
|
402
|
-
upgradedConn.sink(muxer.source)
|
|
403
|
-
]).catch(err => {
|
|
404
|
-
connection.log.error('error piping data through muxer - %e', err);
|
|
405
|
-
});
|
|
406
|
-
}
|
|
407
|
-
const _timeline = maConn.timeline;
|
|
408
|
-
maConn.timeline = new Proxy(_timeline, {
|
|
409
|
-
set: (...args) => {
|
|
410
|
-
if (args[1] === 'close' && args[2] != null && _timeline.close == null) {
|
|
411
|
-
// Wait for close to finish before notifying of the closure
|
|
412
|
-
(async () => {
|
|
413
|
-
try {
|
|
414
|
-
if (connection.status === 'open') {
|
|
415
|
-
await connection.close();
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
catch (err) {
|
|
419
|
-
connection.log.error('error closing connection after timeline close %e', err);
|
|
420
|
-
}
|
|
421
|
-
finally {
|
|
422
|
-
this.events.safeDispatchEvent('connection:close', {
|
|
423
|
-
detail: connection
|
|
424
|
-
});
|
|
425
|
-
}
|
|
426
|
-
})().catch(err => {
|
|
427
|
-
connection.log.error('error thrown while dispatching connection:close event %e', err);
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
return Reflect.set(...args);
|
|
431
|
-
}
|
|
432
|
-
});
|
|
433
|
-
maConn.timeline.upgraded = Date.now();
|
|
434
|
-
const errConnectionNotMultiplexed = () => {
|
|
435
|
-
throw new MuxerUnavailableError('Connection is not multiplexed');
|
|
436
|
-
};
|
|
437
232
|
// Create the connection
|
|
438
|
-
connection = createConnection({
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
logger: this.components.logger,
|
|
448
|
-
newStream: newStream ?? errConnectionNotMultiplexed,
|
|
449
|
-
getStreams: () => {
|
|
450
|
-
return muxer?.streams ?? [];
|
|
451
|
-
},
|
|
452
|
-
close: async (options) => {
|
|
453
|
-
// ensure remaining streams are closed gracefully
|
|
454
|
-
await muxer?.close(options);
|
|
455
|
-
// close the underlying transport
|
|
456
|
-
await maConn.close(options);
|
|
457
|
-
},
|
|
458
|
-
abort: (err) => {
|
|
459
|
-
maConn.abort(err);
|
|
460
|
-
// ensure remaining streams are aborted
|
|
461
|
-
muxer?.abort(err);
|
|
462
|
-
}
|
|
233
|
+
const connection = createConnection(this.components, {
|
|
234
|
+
...opts,
|
|
235
|
+
outboundStreamProtocolNegotiationTimeout: this.outboundStreamProtocolNegotiationTimeout,
|
|
236
|
+
inboundStreamProtocolNegotiationTimeout: this.inboundStreamProtocolNegotiationTimeout
|
|
237
|
+
});
|
|
238
|
+
connection.addEventListener('close', () => {
|
|
239
|
+
this.events.safeDispatchEvent('connection:close', {
|
|
240
|
+
detail: connection
|
|
241
|
+
});
|
|
463
242
|
});
|
|
464
243
|
this.events.safeDispatchEvent('connection:open', {
|
|
465
244
|
detail: connection
|
|
466
245
|
});
|
|
467
|
-
// @ts-expect-error nah
|
|
468
|
-
connection.__maConnTimeline = _timeline;
|
|
469
246
|
return connection;
|
|
470
247
|
}
|
|
471
|
-
/**
|
|
472
|
-
* Routes incoming streams to the correct handler
|
|
473
|
-
*/
|
|
474
|
-
_onStream(opts) {
|
|
475
|
-
const { connection, stream, protocol } = opts;
|
|
476
|
-
const { handler, options } = this.components.registrar.getHandler(protocol);
|
|
477
|
-
if (connection.limits != null && options.runOnLimitedConnection !== true) {
|
|
478
|
-
throw new LimitedConnectionError('Cannot open protocol stream on limited connection');
|
|
479
|
-
}
|
|
480
|
-
handler({ connection, stream });
|
|
481
|
-
}
|
|
482
248
|
/**
|
|
483
249
|
* Attempts to encrypt the incoming `connection` with the provided `cryptos`
|
|
484
250
|
*/
|
|
485
251
|
async _encryptInbound(connection, options) {
|
|
486
252
|
const protocols = Array.from(this.connectionEncrypters.keys());
|
|
487
253
|
try {
|
|
488
|
-
const
|
|
489
|
-
...options,
|
|
490
|
-
log: connection.log
|
|
491
|
-
});
|
|
254
|
+
const protocol = await mss.handle(connection, protocols, options);
|
|
492
255
|
const encrypter = this.connectionEncrypters.get(protocol);
|
|
493
256
|
if (encrypter == null) {
|
|
494
257
|
throw new EncryptionFailedError(`no crypto module found for ${protocol}`);
|
|
495
258
|
}
|
|
496
|
-
connection.log('encrypting inbound connection
|
|
259
|
+
connection.log('encrypting inbound connection using %s', protocol);
|
|
497
260
|
return {
|
|
498
|
-
...await encrypter.secureInbound(
|
|
261
|
+
...await encrypter.secureInbound(connection, options),
|
|
499
262
|
protocol
|
|
500
263
|
};
|
|
501
264
|
}
|
|
502
265
|
catch (err) {
|
|
503
|
-
connection.log.error('encrypting inbound connection from %a failed', connection.remoteAddr, err);
|
|
504
266
|
throw new EncryptionFailedError(err.message);
|
|
505
267
|
}
|
|
506
268
|
}
|
|
@@ -512,23 +274,18 @@ export class Upgrader {
|
|
|
512
274
|
const protocols = Array.from(this.connectionEncrypters.keys());
|
|
513
275
|
try {
|
|
514
276
|
connection.log.trace('selecting encrypter from %s', protocols);
|
|
515
|
-
const
|
|
516
|
-
...options,
|
|
517
|
-
log: connection.log,
|
|
518
|
-
yieldBytes: true
|
|
519
|
-
});
|
|
277
|
+
const protocol = await mss.select(connection, protocols, options);
|
|
520
278
|
const encrypter = this.connectionEncrypters.get(protocol);
|
|
521
279
|
if (encrypter == null) {
|
|
522
280
|
throw new EncryptionFailedError(`no crypto module found for ${protocol}`);
|
|
523
281
|
}
|
|
524
|
-
connection.log('encrypting outbound connection
|
|
282
|
+
connection.log('encrypting outbound connection using %s', protocol);
|
|
525
283
|
return {
|
|
526
|
-
...await encrypter.secureOutbound(
|
|
284
|
+
...await encrypter.secureOutbound(connection, options),
|
|
527
285
|
protocol
|
|
528
286
|
};
|
|
529
287
|
}
|
|
530
288
|
catch (err) {
|
|
531
|
-
connection.log.error('encrypting outbound connection to %a failed', connection.remoteAddr, err);
|
|
532
289
|
throw new EncryptionFailedError(err.message);
|
|
533
290
|
}
|
|
534
291
|
}
|
|
@@ -536,22 +293,21 @@ export class Upgrader {
|
|
|
536
293
|
* Selects one of the given muxers via multistream-select. That
|
|
537
294
|
* muxer will be used for all future streams on the connection.
|
|
538
295
|
*/
|
|
539
|
-
async _multiplexOutbound(
|
|
296
|
+
async _multiplexOutbound(maConn, muxers, options) {
|
|
540
297
|
const protocols = Array.from(muxers.keys());
|
|
541
|
-
|
|
298
|
+
maConn.log('outbound selecting muxer %s', protocols);
|
|
542
299
|
try {
|
|
543
|
-
|
|
544
|
-
const
|
|
545
|
-
...options,
|
|
546
|
-
log: connection.log,
|
|
547
|
-
yieldBytes: true
|
|
548
|
-
});
|
|
549
|
-
connection.log('selected %s as muxer protocol', protocol);
|
|
300
|
+
maConn.log.trace('selecting stream muxer from %s', protocols);
|
|
301
|
+
const protocol = await mss.select(maConn, protocols, options);
|
|
550
302
|
const muxerFactory = muxers.get(protocol);
|
|
551
|
-
|
|
303
|
+
if (muxerFactory == null) {
|
|
304
|
+
throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`);
|
|
305
|
+
}
|
|
306
|
+
maConn.log('selected %s as muxer protocol', protocol);
|
|
307
|
+
return muxerFactory;
|
|
552
308
|
}
|
|
553
309
|
catch (err) {
|
|
554
|
-
|
|
310
|
+
maConn.log.error('error multiplexing outbound connection', err);
|
|
555
311
|
throw new MuxerUnavailableError(String(err));
|
|
556
312
|
}
|
|
557
313
|
}
|
|
@@ -559,20 +315,22 @@ export class Upgrader {
|
|
|
559
315
|
* Registers support for one of the given muxers via multistream-select. The
|
|
560
316
|
* selected muxer will be used for all future streams on the connection.
|
|
561
317
|
*/
|
|
562
|
-
async _multiplexInbound(
|
|
318
|
+
async _multiplexInbound(maConn, muxers, options) {
|
|
563
319
|
const protocols = Array.from(muxers.keys());
|
|
564
|
-
|
|
320
|
+
maConn.log('inbound handling muxers %s', protocols);
|
|
565
321
|
try {
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
log: connection.log
|
|
569
|
-
});
|
|
322
|
+
maConn.log.trace('selecting stream muxer from %s', protocols);
|
|
323
|
+
const protocol = await mss.handle(maConn, protocols, options);
|
|
570
324
|
const muxerFactory = muxers.get(protocol);
|
|
571
|
-
|
|
325
|
+
if (muxerFactory == null) {
|
|
326
|
+
throw new MuxerUnavailableError(`No muxer configured for protocol "${protocol}"`);
|
|
327
|
+
}
|
|
328
|
+
maConn.log('selected %s as muxer protocol', protocol);
|
|
329
|
+
return muxerFactory;
|
|
572
330
|
}
|
|
573
331
|
catch (err) {
|
|
574
|
-
|
|
575
|
-
throw
|
|
332
|
+
maConn.log.error('error multiplexing inbound connection', err);
|
|
333
|
+
throw err;
|
|
576
334
|
}
|
|
577
335
|
}
|
|
578
336
|
getConnectionEncrypters() {
|
|
@@ -582,4 +340,7 @@ export class Upgrader {
|
|
|
582
340
|
return this.streamMuxers;
|
|
583
341
|
}
|
|
584
342
|
}
|
|
343
|
+
function isEncryptionSkipped(opts) {
|
|
344
|
+
return opts.skipEncryption === true;
|
|
345
|
+
}
|
|
585
346
|
//# sourceMappingURL=upgrader.js.map
|