@libp2p/webtransport 3.0.11 → 3.1.0-6640116d
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 +6 -6
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +65 -53
- package/dist/src/index.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +81 -59
- package/dist/typedoc-urls.json +0 -8
package/dist/src/index.d.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { type Transport } from '@libp2p/interface/transport';
|
|
2
|
+
import type { CounterGroup, Metrics } from '@libp2p/interface/metrics';
|
|
2
3
|
import type { PeerId } from '@libp2p/interface/peer-id';
|
|
3
4
|
export interface WebTransportInit {
|
|
4
5
|
maxInboundStreams?: number;
|
|
5
6
|
}
|
|
6
7
|
export interface WebTransportComponents {
|
|
7
8
|
peerId: PeerId;
|
|
9
|
+
metrics?: Metrics;
|
|
10
|
+
}
|
|
11
|
+
export interface WebTransportMetrics {
|
|
12
|
+
dialerEvents: CounterGroup;
|
|
8
13
|
}
|
|
9
14
|
export declare function webTransport(init?: WebTransportInit): (components: WebTransportComponents) => Transport;
|
|
10
15
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAuE,MAAM,6BAA6B,CAAA;AAQjI,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAWvD,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,SAAS,EAAuE,MAAM,6BAA6B,CAAA;AAQjI,OAAO,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAA;AACtE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAA;AAWvD,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,YAAY,CAAA;CAC3B;AA+SD,wBAAgB,YAAY,CAAE,IAAI,GAAE,gBAAqB,GAAG,CAAC,UAAU,EAAE,sBAAsB,KAAK,SAAS,CAE5G"}
|
package/dist/src/index.js
CHANGED
|
@@ -10,11 +10,20 @@ const log = logger('libp2p:webtransport');
|
|
|
10
10
|
class WebTransportTransport {
|
|
11
11
|
components;
|
|
12
12
|
config;
|
|
13
|
+
metrics;
|
|
13
14
|
constructor(components, init = {}) {
|
|
14
15
|
this.components = components;
|
|
15
16
|
this.config = {
|
|
16
17
|
maxInboundStreams: init.maxInboundStreams ?? 1000
|
|
17
18
|
};
|
|
19
|
+
if (components.metrics != null) {
|
|
20
|
+
this.metrics = {
|
|
21
|
+
dialerEvents: components.metrics.registerCounterGroup('libp2p_webtransport_dialer_events_total', {
|
|
22
|
+
label: 'event',
|
|
23
|
+
help: 'Total count of WebTransport dialer events by type'
|
|
24
|
+
})
|
|
25
|
+
};
|
|
26
|
+
}
|
|
18
27
|
}
|
|
19
28
|
[Symbol.toStringTag] = '@libp2p/webtransport';
|
|
20
29
|
[symbol] = true;
|
|
@@ -36,75 +45,74 @@ class WebTransportTransport {
|
|
|
36
45
|
let abortListener;
|
|
37
46
|
let maConn;
|
|
38
47
|
let cleanUpWTSession = () => { };
|
|
48
|
+
let closed = false;
|
|
49
|
+
let ready = false;
|
|
50
|
+
let authenticated = false;
|
|
39
51
|
try {
|
|
40
|
-
|
|
52
|
+
this.metrics?.dialerEvents.increment({ pending: true });
|
|
41
53
|
const wt = new WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, {
|
|
42
54
|
serverCertificateHashes: certhashes.map(certhash => ({
|
|
43
55
|
algorithm: 'sha-256',
|
|
44
56
|
value: certhash.digest
|
|
45
57
|
}))
|
|
46
58
|
});
|
|
47
|
-
cleanUpWTSession = (
|
|
59
|
+
cleanUpWTSession = (metric) => {
|
|
60
|
+
if (closed) {
|
|
61
|
+
// already closed session
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
48
64
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// already closed session
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
// This is how we specify the connection is closed and shouldn't be used.
|
|
55
|
-
maConn.timeline.close = Date.now();
|
|
56
|
-
}
|
|
57
|
-
if (closed) {
|
|
58
|
-
// already closed session
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
wt.close(closeInfo);
|
|
65
|
+
this.metrics?.dialerEvents.increment({ [metric]: true });
|
|
66
|
+
wt.close();
|
|
62
67
|
}
|
|
63
68
|
catch (err) {
|
|
64
69
|
log.error('error closing wt session', err);
|
|
65
70
|
}
|
|
66
71
|
finally {
|
|
72
|
+
// This is how we specify the connection is closed and shouldn't be used.
|
|
73
|
+
if (maConn != null) {
|
|
74
|
+
maConn.timeline.close = Date.now();
|
|
75
|
+
}
|
|
67
76
|
closed = true;
|
|
68
77
|
}
|
|
69
78
|
};
|
|
70
|
-
// this promise resolves/throws when the session is closed or failed to init
|
|
71
|
-
wt.closed
|
|
72
|
-
.then(async () => {
|
|
73
|
-
await maConn?.close();
|
|
74
|
-
})
|
|
75
|
-
.catch((err) => {
|
|
76
|
-
log.error('error on remote wt session close', err);
|
|
77
|
-
maConn?.abort(err);
|
|
78
|
-
})
|
|
79
|
-
.finally(() => {
|
|
80
|
-
// if we never got as far as creating the maConn, just clean up the session
|
|
81
|
-
if (maConn == null) {
|
|
82
|
-
cleanUpWTSession();
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
79
|
// if the dial is aborted before we are ready, close the WebTransport session
|
|
86
80
|
abortListener = () => {
|
|
87
|
-
if (
|
|
88
|
-
|
|
81
|
+
if (ready) {
|
|
82
|
+
cleanUpWTSession('noise_timeout');
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
cleanUpWTSession('ready_timeout');
|
|
89
86
|
}
|
|
90
|
-
cleanUpWTSession();
|
|
91
87
|
};
|
|
92
|
-
options.signal?.addEventListener('abort', abortListener
|
|
93
|
-
|
|
88
|
+
options.signal?.addEventListener('abort', abortListener, {
|
|
89
|
+
once: true
|
|
90
|
+
});
|
|
91
|
+
await Promise.race([
|
|
92
|
+
wt.closed,
|
|
93
|
+
wt.ready
|
|
94
|
+
]);
|
|
95
|
+
ready = true;
|
|
96
|
+
this.metrics?.dialerEvents.increment({ ready: true });
|
|
97
|
+
// this promise resolves/throws when the session is closed
|
|
98
|
+
wt.closed.catch((err) => {
|
|
99
|
+
log.error('error on remote wt session close', err);
|
|
100
|
+
})
|
|
101
|
+
.finally(() => {
|
|
102
|
+
cleanUpWTSession('remote_close');
|
|
103
|
+
});
|
|
94
104
|
if (!await this.authenticateWebTransport(wt, localPeer, remotePeer, certhashes)) {
|
|
95
105
|
throw new Error('Failed to authenticate webtransport');
|
|
96
106
|
}
|
|
107
|
+
this.metrics?.dialerEvents.increment({ open: true });
|
|
97
108
|
maConn = {
|
|
98
|
-
close: async (
|
|
109
|
+
close: async () => {
|
|
99
110
|
log('Closing webtransport');
|
|
100
|
-
cleanUpWTSession();
|
|
111
|
+
cleanUpWTSession('close');
|
|
101
112
|
},
|
|
102
113
|
abort: (err) => {
|
|
103
114
|
log('aborting webtransport due to passed err', err);
|
|
104
|
-
cleanUpWTSession(
|
|
105
|
-
closeCode: 0,
|
|
106
|
-
reason: err.message
|
|
107
|
-
});
|
|
115
|
+
cleanUpWTSession('abort');
|
|
108
116
|
},
|
|
109
117
|
remoteAddr: ma,
|
|
110
118
|
timeline: {
|
|
@@ -113,15 +121,20 @@ class WebTransportTransport {
|
|
|
113
121
|
// This connection is never used directly since webtransport supports native streams.
|
|
114
122
|
...inertDuplex()
|
|
115
123
|
};
|
|
116
|
-
|
|
117
|
-
return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt
|
|
124
|
+
authenticated = true;
|
|
125
|
+
return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt), skipProtection: true });
|
|
118
126
|
}
|
|
119
127
|
catch (err) {
|
|
120
128
|
log.error('caught wt session err', err);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
129
|
+
if (authenticated) {
|
|
130
|
+
cleanUpWTSession('upgrade_error');
|
|
131
|
+
}
|
|
132
|
+
else if (ready) {
|
|
133
|
+
cleanUpWTSession('noise_error');
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
cleanUpWTSession('ready_error');
|
|
137
|
+
}
|
|
125
138
|
throw err;
|
|
126
139
|
}
|
|
127
140
|
finally {
|
|
@@ -168,7 +181,7 @@ class WebTransportTransport {
|
|
|
168
181
|
}
|
|
169
182
|
return true;
|
|
170
183
|
}
|
|
171
|
-
webtransportMuxer(wt
|
|
184
|
+
webtransportMuxer(wt) {
|
|
172
185
|
let streamIDCounter = 0;
|
|
173
186
|
const config = this.config;
|
|
174
187
|
return {
|
|
@@ -220,14 +233,13 @@ class WebTransportTransport {
|
|
|
220
233
|
*/
|
|
221
234
|
close: async (options) => {
|
|
222
235
|
log('Closing webtransport muxer');
|
|
223
|
-
|
|
236
|
+
await Promise.all(activeStreams.map(async (s) => s.close(options)));
|
|
224
237
|
},
|
|
225
238
|
abort: (err) => {
|
|
226
239
|
log('Aborting webtransport muxer with err:', err);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
});
|
|
240
|
+
for (const stream of activeStreams) {
|
|
241
|
+
stream.abort(err);
|
|
242
|
+
}
|
|
231
243
|
},
|
|
232
244
|
// This stream muxer is webtransport native. Therefore it doesn't plug in with any other duplex.
|
|
233
245
|
...inertDuplex()
|
package/dist/src/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAA;AAC/C,OAAO,EAAkB,MAAM,EAA+D,MAAM,6BAA6B,CAAA;AACjI,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,EAAqC,MAAM,yBAAyB,CAAA;AAC3E,OAAO,EAAE,8BAA8B,EAAE,MAAM,aAAa,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/webtransport",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0-6640116d",
|
|
4
4
|
"description": "JavaScript implementation of the WebTransport module that libp2p uses and that implements the interface-transport spec",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"homepage": "https://github.com/libp2p/js-libp2p/tree/master/packages/transport-webtransport#readme",
|
|
@@ -61,9 +61,9 @@
|
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
63
|
"@chainsafe/libp2p-noise": "^13.0.0",
|
|
64
|
-
"@libp2p/interface": "
|
|
65
|
-
"@libp2p/logger": "
|
|
66
|
-
"@libp2p/peer-id": "
|
|
64
|
+
"@libp2p/interface": "0.1.2-6640116d",
|
|
65
|
+
"@libp2p/logger": "3.0.2-6640116d",
|
|
66
|
+
"@libp2p/peer-id": "3.0.2-6640116d",
|
|
67
67
|
"@multiformats/multiaddr": "^12.1.5",
|
|
68
68
|
"@multiformats/multiaddr-matcher": "^1.0.1",
|
|
69
69
|
"it-stream-types": "^2.0.1",
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
75
|
"aegir": "^40.0.8",
|
|
76
|
-
"libp2p": "
|
|
76
|
+
"libp2p": "0.46.11-6640116d",
|
|
77
77
|
"p-defer": "^4.0.0"
|
|
78
78
|
},
|
|
79
79
|
"browser": {
|
package/src/index.ts
CHANGED
|
@@ -7,13 +7,14 @@ import { inertDuplex } from './utils/inert-duplex.js'
|
|
|
7
7
|
import { isSubset } from './utils/is-subset.js'
|
|
8
8
|
import { parseMultiaddr } from './utils/parse-multiaddr.js'
|
|
9
9
|
import type { Connection, MultiaddrConnection, Stream } from '@libp2p/interface/connection'
|
|
10
|
+
import type { CounterGroup, Metrics } from '@libp2p/interface/metrics'
|
|
10
11
|
import type { PeerId } from '@libp2p/interface/peer-id'
|
|
11
12
|
import type { StreamMuxerFactory, StreamMuxerInit, StreamMuxer } from '@libp2p/interface/stream-muxer'
|
|
12
13
|
import type { Source } from 'it-stream-types'
|
|
13
14
|
import type { MultihashDigest } from 'multiformats/hashes/interface'
|
|
14
15
|
|
|
15
16
|
interface WebTransportSessionCleanup {
|
|
16
|
-
(
|
|
17
|
+
(metric: string): void
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const log = logger('libp2p:webtransport')
|
|
@@ -24,17 +25,32 @@ export interface WebTransportInit {
|
|
|
24
25
|
|
|
25
26
|
export interface WebTransportComponents {
|
|
26
27
|
peerId: PeerId
|
|
28
|
+
metrics?: Metrics
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface WebTransportMetrics {
|
|
32
|
+
dialerEvents: CounterGroup
|
|
27
33
|
}
|
|
28
34
|
|
|
29
35
|
class WebTransportTransport implements Transport {
|
|
30
36
|
private readonly components: WebTransportComponents
|
|
31
37
|
private readonly config: Required<WebTransportInit>
|
|
38
|
+
private readonly metrics?: WebTransportMetrics
|
|
32
39
|
|
|
33
40
|
constructor (components: WebTransportComponents, init: WebTransportInit = {}) {
|
|
34
41
|
this.components = components
|
|
35
42
|
this.config = {
|
|
36
43
|
maxInboundStreams: init.maxInboundStreams ?? 1000
|
|
37
44
|
}
|
|
45
|
+
|
|
46
|
+
if (components.metrics != null) {
|
|
47
|
+
this.metrics = {
|
|
48
|
+
dialerEvents: components.metrics.registerCounterGroup('libp2p_webtransport_dialer_events_total', {
|
|
49
|
+
label: 'event',
|
|
50
|
+
help: 'Total count of WebTransport dialer events by type'
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
}
|
|
38
54
|
}
|
|
39
55
|
|
|
40
56
|
readonly [Symbol.toStringTag] = '@libp2p/webtransport'
|
|
@@ -65,10 +81,15 @@ class WebTransportTransport implements Transport {
|
|
|
65
81
|
let abortListener: (() => void) | undefined
|
|
66
82
|
let maConn: MultiaddrConnection | undefined
|
|
67
83
|
|
|
68
|
-
let cleanUpWTSession:
|
|
84
|
+
let cleanUpWTSession: WebTransportSessionCleanup = () => {}
|
|
85
|
+
|
|
86
|
+
let closed = false
|
|
87
|
+
let ready = false
|
|
88
|
+
let authenticated = false
|
|
69
89
|
|
|
70
90
|
try {
|
|
71
|
-
|
|
91
|
+
this.metrics?.dialerEvents.increment({ pending: true })
|
|
92
|
+
|
|
72
93
|
const wt = new WebTransport(`${url}/.well-known/libp2p-webtransport?type=noise`, {
|
|
73
94
|
serverCertificateHashes: certhashes.map(certhash => ({
|
|
74
95
|
algorithm: 'sha-256',
|
|
@@ -76,74 +97,69 @@ class WebTransportTransport implements Transport {
|
|
|
76
97
|
}))
|
|
77
98
|
})
|
|
78
99
|
|
|
79
|
-
cleanUpWTSession = (
|
|
100
|
+
cleanUpWTSession = (metric: string) => {
|
|
101
|
+
if (closed) {
|
|
102
|
+
// already closed session
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
80
106
|
try {
|
|
107
|
+
this.metrics?.dialerEvents.increment({ [metric]: true })
|
|
108
|
+
wt.close()
|
|
109
|
+
} catch (err) {
|
|
110
|
+
log.error('error closing wt session', err)
|
|
111
|
+
} finally {
|
|
112
|
+
// This is how we specify the connection is closed and shouldn't be used.
|
|
81
113
|
if (maConn != null) {
|
|
82
|
-
if (maConn.timeline.close != null) {
|
|
83
|
-
// already closed session
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// This is how we specify the connection is closed and shouldn't be used.
|
|
88
114
|
maConn.timeline.close = Date.now()
|
|
89
115
|
}
|
|
90
116
|
|
|
91
|
-
if (closed) {
|
|
92
|
-
// already closed session
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
wt.close(closeInfo)
|
|
97
|
-
} catch (err) {
|
|
98
|
-
log.error('error closing wt session', err)
|
|
99
|
-
} finally {
|
|
100
117
|
closed = true
|
|
101
118
|
}
|
|
102
119
|
}
|
|
103
120
|
|
|
104
|
-
// this promise resolves/throws when the session is closed or failed to init
|
|
105
|
-
wt.closed
|
|
106
|
-
.then(async () => {
|
|
107
|
-
await maConn?.close()
|
|
108
|
-
})
|
|
109
|
-
.catch((err: Error) => {
|
|
110
|
-
log.error('error on remote wt session close', err)
|
|
111
|
-
maConn?.abort(err)
|
|
112
|
-
})
|
|
113
|
-
.finally(() => {
|
|
114
|
-
// if we never got as far as creating the maConn, just clean up the session
|
|
115
|
-
if (maConn == null) {
|
|
116
|
-
cleanUpWTSession()
|
|
117
|
-
}
|
|
118
|
-
})
|
|
119
|
-
|
|
120
121
|
// if the dial is aborted before we are ready, close the WebTransport session
|
|
121
122
|
abortListener = () => {
|
|
122
|
-
if (
|
|
123
|
-
|
|
123
|
+
if (ready) {
|
|
124
|
+
cleanUpWTSession('noise_timeout')
|
|
125
|
+
} else {
|
|
126
|
+
cleanUpWTSession('ready_timeout')
|
|
124
127
|
}
|
|
125
|
-
|
|
126
|
-
cleanUpWTSession()
|
|
127
128
|
}
|
|
128
|
-
options.signal?.addEventListener('abort', abortListener
|
|
129
|
+
options.signal?.addEventListener('abort', abortListener, {
|
|
130
|
+
once: true
|
|
131
|
+
})
|
|
129
132
|
|
|
130
|
-
await
|
|
133
|
+
await Promise.race([
|
|
134
|
+
wt.closed,
|
|
135
|
+
wt.ready
|
|
136
|
+
])
|
|
137
|
+
|
|
138
|
+
ready = true
|
|
139
|
+
this.metrics?.dialerEvents.increment({ ready: true })
|
|
140
|
+
|
|
141
|
+
// this promise resolves/throws when the session is closed
|
|
142
|
+
wt.closed.catch((err: Error) => {
|
|
143
|
+
log.error('error on remote wt session close', err)
|
|
144
|
+
})
|
|
145
|
+
.finally(() => {
|
|
146
|
+
cleanUpWTSession('remote_close')
|
|
147
|
+
})
|
|
131
148
|
|
|
132
149
|
if (!await this.authenticateWebTransport(wt, localPeer, remotePeer, certhashes)) {
|
|
133
150
|
throw new Error('Failed to authenticate webtransport')
|
|
134
151
|
}
|
|
135
152
|
|
|
153
|
+
this.metrics?.dialerEvents.increment({ open: true })
|
|
154
|
+
|
|
136
155
|
maConn = {
|
|
137
|
-
close: async (
|
|
156
|
+
close: async () => {
|
|
138
157
|
log('Closing webtransport')
|
|
139
|
-
cleanUpWTSession()
|
|
158
|
+
cleanUpWTSession('close')
|
|
140
159
|
},
|
|
141
160
|
abort: (err: Error) => {
|
|
142
161
|
log('aborting webtransport due to passed err', err)
|
|
143
|
-
cleanUpWTSession(
|
|
144
|
-
closeCode: 0,
|
|
145
|
-
reason: err.message
|
|
146
|
-
})
|
|
162
|
+
cleanUpWTSession('abort')
|
|
147
163
|
},
|
|
148
164
|
remoteAddr: ma,
|
|
149
165
|
timeline: {
|
|
@@ -153,16 +169,19 @@ class WebTransportTransport implements Transport {
|
|
|
153
169
|
...inertDuplex()
|
|
154
170
|
}
|
|
155
171
|
|
|
156
|
-
|
|
172
|
+
authenticated = true
|
|
157
173
|
|
|
158
|
-
return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt
|
|
174
|
+
return await options.upgrader.upgradeOutbound(maConn, { skipEncryption: true, muxerFactory: this.webtransportMuxer(wt), skipProtection: true })
|
|
159
175
|
} catch (err: any) {
|
|
160
176
|
log.error('caught wt session err', err)
|
|
161
177
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
178
|
+
if (authenticated) {
|
|
179
|
+
cleanUpWTSession('upgrade_error')
|
|
180
|
+
} else if (ready) {
|
|
181
|
+
cleanUpWTSession('noise_error')
|
|
182
|
+
} else {
|
|
183
|
+
cleanUpWTSession('ready_error')
|
|
184
|
+
}
|
|
166
185
|
|
|
167
186
|
throw err
|
|
168
187
|
} finally {
|
|
@@ -220,7 +239,7 @@ class WebTransportTransport implements Transport {
|
|
|
220
239
|
return true
|
|
221
240
|
}
|
|
222
241
|
|
|
223
|
-
webtransportMuxer (wt: WebTransport
|
|
242
|
+
webtransportMuxer (wt: WebTransport): StreamMuxerFactory {
|
|
224
243
|
let streamIDCounter = 0
|
|
225
244
|
const config = this.config
|
|
226
245
|
return {
|
|
@@ -281,14 +300,17 @@ class WebTransportTransport implements Transport {
|
|
|
281
300
|
*/
|
|
282
301
|
close: async (options?: AbortOptions) => {
|
|
283
302
|
log('Closing webtransport muxer')
|
|
284
|
-
|
|
303
|
+
|
|
304
|
+
await Promise.all(
|
|
305
|
+
activeStreams.map(async s => s.close(options))
|
|
306
|
+
)
|
|
285
307
|
},
|
|
286
308
|
abort: (err: Error) => {
|
|
287
309
|
log('Aborting webtransport muxer with err:', err)
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
}
|
|
310
|
+
|
|
311
|
+
for (const stream of activeStreams) {
|
|
312
|
+
stream.abort(err)
|
|
313
|
+
}
|
|
292
314
|
},
|
|
293
315
|
// This stream muxer is webtransport native. Therefore it doesn't plug in with any other duplex.
|
|
294
316
|
...inertDuplex()
|
package/dist/typedoc-urls.json
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"WebTransportComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webtransport.WebTransportComponents.html",
|
|
3
|
-
".:WebTransportComponents": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webtransport.WebTransportComponents.html",
|
|
4
|
-
"WebTransportInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webtransport.WebTransportInit.html",
|
|
5
|
-
".:WebTransportInit": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webtransport.WebTransportInit.html",
|
|
6
|
-
"webTransport": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webtransport.webTransport.html",
|
|
7
|
-
".:webTransport": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webtransport.webTransport.html"
|
|
8
|
-
}
|