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