@libp2p/webrtc 3.2.6-fdcb801e → 3.2.7
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 +10 -11
- package/dist/src/muxer.d.ts +9 -2
- package/dist/src/muxer.d.ts.map +1 -1
- package/dist/src/muxer.js +32 -21
- package/dist/src/muxer.js.map +1 -1
- package/dist/src/private-to-private/initiate-connection.d.ts +1 -1
- package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
- package/dist/src/private-to-private/initiate-connection.js +4 -6
- package/dist/src/private-to-private/initiate-connection.js.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.d.ts +2 -1
- package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.js +3 -2
- package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
- package/dist/src/private-to-private/transport.d.ts.map +1 -1
- package/dist/src/private-to-private/transport.js +6 -8
- package/dist/src/private-to-private/transport.js.map +1 -1
- package/dist/src/private-to-private/util.d.ts +0 -1
- package/dist/src/private-to-private/util.d.ts.map +1 -1
- package/dist/src/private-to-private/util.js +0 -10
- package/dist/src/private-to-private/util.js.map +1 -1
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +0 -1
- package/dist/src/stream.js.map +1 -1
- package/dist/typedoc-urls.json +8 -0
- package/package.json +9 -9
- package/src/muxer.ts +46 -22
- package/src/private-to-private/initiate-connection.ts +5 -7
- package/src/private-to-private/signaling-stream-handler.ts +4 -3
- package/src/private-to-private/transport.ts +6 -8
- package/src/private-to-private/util.ts +0 -13
- package/src/stream.ts +0 -1
package/src/muxer.ts
CHANGED
|
@@ -32,6 +32,14 @@ export interface DataChannelMuxerFactoryInit {
|
|
|
32
32
|
dataChannelOptions?: DataChannelOptions
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
interface BufferedStream {
|
|
36
|
+
stream: Stream
|
|
37
|
+
channel: RTCDataChannel
|
|
38
|
+
onEnd(err?: Error): void
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let streamIndex = 0
|
|
42
|
+
|
|
35
43
|
export class DataChannelMuxerFactory implements StreamMuxerFactory {
|
|
36
44
|
public readonly protocol: string
|
|
37
45
|
|
|
@@ -39,7 +47,7 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
|
|
|
39
47
|
* WebRTC Peer Connection
|
|
40
48
|
*/
|
|
41
49
|
private readonly peerConnection: RTCPeerConnection
|
|
42
|
-
private
|
|
50
|
+
private bufferedStreams: BufferedStream[] = []
|
|
43
51
|
private readonly metrics?: CounterGroup
|
|
44
52
|
private readonly dataChannelOptions?: DataChannelOptions
|
|
45
53
|
|
|
@@ -51,15 +59,25 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
|
|
|
51
59
|
|
|
52
60
|
// store any datachannels opened before upgrade has been completed
|
|
53
61
|
this.peerConnection.ondatachannel = ({ channel }) => {
|
|
62
|
+
// @ts-expect-error fields are set below
|
|
63
|
+
const bufferedStream: BufferedStream = {}
|
|
64
|
+
|
|
54
65
|
const stream = createStream({
|
|
55
66
|
channel,
|
|
56
67
|
direction: 'inbound',
|
|
57
|
-
onEnd: () => {
|
|
58
|
-
|
|
68
|
+
onEnd: (err) => {
|
|
69
|
+
bufferedStream.onEnd(err)
|
|
59
70
|
},
|
|
60
71
|
...this.dataChannelOptions
|
|
61
72
|
})
|
|
62
|
-
|
|
73
|
+
|
|
74
|
+
bufferedStream.stream = stream
|
|
75
|
+
bufferedStream.channel = channel
|
|
76
|
+
bufferedStream.onEnd = () => {
|
|
77
|
+
this.bufferedStreams = this.bufferedStreams.filter(s => s.stream.id !== stream.id)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.bufferedStreams.push(bufferedStream)
|
|
63
81
|
}
|
|
64
82
|
}
|
|
65
83
|
|
|
@@ -69,14 +87,14 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
|
|
|
69
87
|
peerConnection: this.peerConnection,
|
|
70
88
|
dataChannelOptions: this.dataChannelOptions,
|
|
71
89
|
metrics: this.metrics,
|
|
72
|
-
streams: this.
|
|
90
|
+
streams: this.bufferedStreams,
|
|
73
91
|
protocol: this.protocol
|
|
74
92
|
})
|
|
75
93
|
}
|
|
76
94
|
}
|
|
77
95
|
|
|
78
96
|
export interface DataChannelMuxerInit extends DataChannelMuxerFactoryInit, StreamMuxerInit {
|
|
79
|
-
streams:
|
|
97
|
+
streams: BufferedStream[]
|
|
80
98
|
}
|
|
81
99
|
|
|
82
100
|
/**
|
|
@@ -94,7 +112,7 @@ export class DataChannelMuxer implements StreamMuxer {
|
|
|
94
112
|
private readonly metrics?: CounterGroup
|
|
95
113
|
|
|
96
114
|
constructor (readonly init: DataChannelMuxerInit) {
|
|
97
|
-
this.streams = init.streams
|
|
115
|
+
this.streams = init.streams.map(s => s.stream)
|
|
98
116
|
this.peerConnection = init.peerConnection
|
|
99
117
|
this.protocol = init.protocol ?? PROTOCOL
|
|
100
118
|
this.metrics = init.metrics
|
|
@@ -111,11 +129,7 @@ export class DataChannelMuxer implements StreamMuxer {
|
|
|
111
129
|
channel,
|
|
112
130
|
direction: 'inbound',
|
|
113
131
|
onEnd: () => {
|
|
114
|
-
|
|
115
|
-
drainAndClose(channel, `inbound ${stream.id} ${stream.protocol}`, this.dataChannelOptions.drainTimeout)
|
|
116
|
-
this.streams = this.streams.filter(s => s.id !== stream.id)
|
|
117
|
-
this.metrics?.increment({ stream_end: true })
|
|
118
|
-
init?.onStreamEnd?.(stream)
|
|
132
|
+
this.#onStreamEnd(stream, channel)
|
|
119
133
|
},
|
|
120
134
|
...this.dataChannelOptions
|
|
121
135
|
})
|
|
@@ -125,10 +139,22 @@ export class DataChannelMuxer implements StreamMuxer {
|
|
|
125
139
|
init?.onIncomingStream?.(stream)
|
|
126
140
|
}
|
|
127
141
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
142
|
+
this.init.streams.forEach(bufferedStream => {
|
|
143
|
+
bufferedStream.onEnd = () => {
|
|
144
|
+
this.#onStreamEnd(bufferedStream.stream, bufferedStream.channel)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
this.metrics?.increment({ incoming_stream: true })
|
|
148
|
+
this.init?.onIncomingStream?.(bufferedStream.stream)
|
|
149
|
+
})
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
#onStreamEnd (stream: Stream, channel: RTCDataChannel): void {
|
|
153
|
+
log.trace('stream %s %s %s onEnd', stream.direction, stream.id, stream.protocol)
|
|
154
|
+
drainAndClose(channel, `${stream.direction} ${stream.id} ${stream.protocol}`, this.dataChannelOptions.drainTimeout)
|
|
155
|
+
this.streams = this.streams.filter(s => s.id !== stream.id)
|
|
156
|
+
this.metrics?.increment({ stream_end: true })
|
|
157
|
+
this.init?.onStreamEnd?.(stream)
|
|
132
158
|
}
|
|
133
159
|
|
|
134
160
|
/**
|
|
@@ -164,17 +190,15 @@ export class DataChannelMuxer implements StreamMuxer {
|
|
|
164
190
|
sink: Sink<Source<Uint8Array | Uint8ArrayList>, Promise<void>> = nopSink
|
|
165
191
|
|
|
166
192
|
newStream (): Stream {
|
|
193
|
+
streamIndex++
|
|
194
|
+
|
|
167
195
|
// The spec says the label SHOULD be an empty string: https://github.com/libp2p/specs/blob/master/webrtc/README.md#rtcdatachannel-label
|
|
168
|
-
const channel = this.peerConnection.createDataChannel(
|
|
196
|
+
const channel = this.peerConnection.createDataChannel(`stream-${streamIndex}`)
|
|
169
197
|
const stream = createStream({
|
|
170
198
|
channel,
|
|
171
199
|
direction: 'outbound',
|
|
172
200
|
onEnd: () => {
|
|
173
|
-
|
|
174
|
-
drainAndClose(channel, `outbound ${stream.id} ${stream.protocol}`, this.dataChannelOptions.drainTimeout)
|
|
175
|
-
this.streams = this.streams.filter(s => s.id !== stream.id)
|
|
176
|
-
this.metrics?.increment({ stream_end: true })
|
|
177
|
-
this.init?.onStreamEnd?.(stream)
|
|
201
|
+
this.#onStreamEnd(stream, channel)
|
|
178
202
|
},
|
|
179
203
|
...this.dataChannelOptions
|
|
180
204
|
})
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import { CodeError } from '@libp2p/interface/errors'
|
|
2
2
|
import { logger } from '@libp2p/logger'
|
|
3
3
|
import { peerIdFromString } from '@libp2p/peer-id'
|
|
4
|
-
import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
|
|
5
4
|
import { pbStream } from 'it-protobuf-stream'
|
|
6
5
|
import pDefer, { type DeferredPromise } from 'p-defer'
|
|
7
6
|
import { type RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
|
|
8
7
|
import { Message } from './pb/message.js'
|
|
9
8
|
import { SIGNALING_PROTO_ID, splitAddr, type WebRTCTransportMetrics } from './transport.js'
|
|
10
|
-
import {
|
|
9
|
+
import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
|
|
11
10
|
import type { DataChannelOptions } from '../index.js'
|
|
12
11
|
import type { Connection } from '@libp2p/interface/connection'
|
|
13
12
|
import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
|
|
14
13
|
import type { IncomingStreamData } from '@libp2p/interface-internal/registrar'
|
|
15
14
|
import type { TransportManager } from '@libp2p/interface-internal/transport-manager'
|
|
15
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
16
16
|
|
|
17
17
|
const log = logger('libp2p:webrtc:initiate-connection')
|
|
18
18
|
|
|
@@ -33,7 +33,7 @@ export interface ConnectOptions {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export async function initiateConnection ({ peerConnection, signal, metrics, multiaddr: ma, connectionManager, transportManager }: ConnectOptions): Promise<{ remoteAddress: Multiaddr }> {
|
|
36
|
-
const { baseAddr
|
|
36
|
+
const { baseAddr } = splitAddr(ma)
|
|
37
37
|
|
|
38
38
|
metrics?.dialerEvents.increment({ open: true })
|
|
39
39
|
|
|
@@ -158,12 +158,10 @@ export async function initiateConnection ({ peerConnection, signal, metrics, mul
|
|
|
158
158
|
signal
|
|
159
159
|
})
|
|
160
160
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
log.trace('initiator connected to remote address %s', remoteAddress)
|
|
161
|
+
log.trace('initiator connected to remote address %s', ma)
|
|
164
162
|
|
|
165
163
|
return {
|
|
166
|
-
remoteAddress:
|
|
164
|
+
remoteAddress: ma
|
|
167
165
|
}
|
|
168
166
|
} catch (err: any) {
|
|
169
167
|
peerConnection.close()
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { CodeError } from '@libp2p/interface/errors'
|
|
2
2
|
import { logger } from '@libp2p/logger'
|
|
3
|
+
import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
|
|
3
4
|
import { pbStream } from 'it-protobuf-stream'
|
|
4
5
|
import pDefer, { type DeferredPromise } from 'p-defer'
|
|
5
6
|
import { type RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
|
|
6
7
|
import { Message } from './pb/message.js'
|
|
7
|
-
import {
|
|
8
|
+
import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
|
|
8
9
|
import type { IncomingStreamData } from '@libp2p/interface-internal/registrar'
|
|
9
10
|
|
|
10
11
|
const log = logger('libp2p:webrtc:signaling-stream-handler')
|
|
@@ -14,7 +15,7 @@ export interface IncomingStreamOpts extends IncomingStreamData {
|
|
|
14
15
|
signal: AbortSignal
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
export async function handleIncomingStream ({ peerConnection, stream, signal, connection }: IncomingStreamOpts): Promise<{ remoteAddress:
|
|
18
|
+
export async function handleIncomingStream ({ peerConnection, stream, signal, connection }: IncomingStreamOpts): Promise<{ remoteAddress: Multiaddr }> {
|
|
18
19
|
log.trace('new inbound signaling stream')
|
|
19
20
|
|
|
20
21
|
const messageStream = pbStream(stream).pb(Message)
|
|
@@ -121,7 +122,7 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
|
|
|
121
122
|
}
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
const remoteAddress =
|
|
125
|
+
const remoteAddress = multiaddr(`/webrtc/p2p/${connection.remoteAddr.getPeerId()}`)
|
|
125
126
|
|
|
126
127
|
log.trace('recipient connected to remote address %s', remoteAddress)
|
|
127
128
|
|
|
@@ -121,10 +121,6 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
121
121
|
log.trace('dialing address: %a', ma)
|
|
122
122
|
|
|
123
123
|
const peerConnection = new RTCPeerConnection(this.init.rtcConfiguration)
|
|
124
|
-
const muxerFactory = new DataChannelMuxerFactory({
|
|
125
|
-
peerConnection,
|
|
126
|
-
dataChannelOptions: this.init.dataChannel
|
|
127
|
-
})
|
|
128
124
|
|
|
129
125
|
const { remoteAddress } = await initiateConnection({
|
|
130
126
|
peerConnection,
|
|
@@ -145,7 +141,10 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
145
141
|
const connection = await options.upgrader.upgradeOutbound(webRTCConn, {
|
|
146
142
|
skipProtection: true,
|
|
147
143
|
skipEncryption: true,
|
|
148
|
-
muxerFactory
|
|
144
|
+
muxerFactory: new DataChannelMuxerFactory({
|
|
145
|
+
peerConnection,
|
|
146
|
+
dataChannelOptions: this.init.dataChannel
|
|
147
|
+
})
|
|
149
148
|
})
|
|
150
149
|
|
|
151
150
|
// close the connection on shut down
|
|
@@ -157,7 +156,6 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
157
156
|
async _onProtocol ({ connection, stream }: IncomingStreamData): Promise<void> {
|
|
158
157
|
const signal = AbortSignal.timeout(this.init.inboundConnectionTimeout ?? INBOUND_CONNECTION_TIMEOUT)
|
|
159
158
|
const peerConnection = new RTCPeerConnection(this.init.rtcConfiguration)
|
|
160
|
-
const muxerFactory = new DataChannelMuxerFactory({ peerConnection, dataChannelOptions: this.init.dataChannel })
|
|
161
159
|
|
|
162
160
|
try {
|
|
163
161
|
const { remoteAddress } = await handleIncomingStream({
|
|
@@ -170,7 +168,7 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
170
168
|
const webRTCConn = new WebRTCMultiaddrConnection({
|
|
171
169
|
peerConnection,
|
|
172
170
|
timeline: { open: (new Date()).getTime() },
|
|
173
|
-
remoteAddr:
|
|
171
|
+
remoteAddr: remoteAddress,
|
|
174
172
|
metrics: this.metrics?.listenerEvents
|
|
175
173
|
})
|
|
176
174
|
|
|
@@ -180,7 +178,7 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
180
178
|
await this.components.upgrader.upgradeInbound(webRTCConn, {
|
|
181
179
|
skipEncryption: true,
|
|
182
180
|
skipProtection: true,
|
|
183
|
-
muxerFactory
|
|
181
|
+
muxerFactory: new DataChannelMuxerFactory({ peerConnection, dataChannelOptions: this.init.dataChannel })
|
|
184
182
|
})
|
|
185
183
|
|
|
186
184
|
// close the stream if SDP messages have been exchanged successfully
|
|
@@ -110,16 +110,3 @@ export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredProm
|
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
|
-
|
|
114
|
-
export function parseRemoteAddress (sdp: string): string {
|
|
115
|
-
// 'a=candidate:1746876089 1 udp 2113937151 0614fbad-b...ocal 54882 typ host generation 0 network-cost 999'
|
|
116
|
-
const candidateLine = sdp.split('\r\n').filter(line => line.startsWith('a=candidate')).pop()
|
|
117
|
-
const candidateParts = candidateLine?.split(' ')
|
|
118
|
-
|
|
119
|
-
if (candidateLine == null || candidateParts == null || candidateParts.length < 5) {
|
|
120
|
-
log('could not parse remote address from', candidateLine)
|
|
121
|
-
return '/webrtc'
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return `/dnsaddr/${candidateParts[4]}/${candidateParts[2].toLowerCase()}/${candidateParts[5]}/webrtc`
|
|
125
|
-
}
|
package/src/stream.ts
CHANGED
|
@@ -84,7 +84,6 @@ export class WebRTCStream extends AbstractStream {
|
|
|
84
84
|
*/
|
|
85
85
|
private readonly receiveFinAck: DeferredPromise<void>
|
|
86
86
|
private readonly finAckTimeout: number
|
|
87
|
-
// private sentFinAck: boolean
|
|
88
87
|
|
|
89
88
|
constructor (init: WebRTCStreamInit) {
|
|
90
89
|
// override onEnd to send/receive FIN_ACK before closing the stream
|