@libp2p/webrtc 5.2.20 → 5.2.21
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 +12 -12
- package/dist/index.min.js.map +3 -3
- package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
- package/dist/src/private-to-private/initiate-connection.js +99 -125
- package/dist/src/private-to-private/initiate-connection.js.map +1 -1
- package/dist/src/private-to-private/transport.d.ts +2 -2
- package/dist/src/private-to-private/transport.d.ts.map +1 -1
- package/dist/src/private-to-private/transport.js +9 -21
- package/dist/src/private-to-private/transport.js.map +1 -1
- package/package.json +2 -2
- package/src/private-to-private/initiate-connection.ts +106 -132
- package/src/private-to-private/transport.ts +13 -25
@@ -1,5 +1,3 @@
|
|
1
|
-
import { InvalidParametersError } from '@libp2p/interface'
|
2
|
-
import { peerIdFromString } from '@libp2p/peer-id'
|
3
1
|
import { pbStream } from 'it-protobuf-stream'
|
4
2
|
import { CustomProgressEvent } from 'progress-events'
|
5
3
|
import { SIGNALING_PROTOCOL } from '../constants.js'
|
@@ -35,21 +33,14 @@ export interface ConnectOptions extends LoggerOptions, ProgressOptions<WebRTCDia
|
|
35
33
|
}
|
36
34
|
|
37
35
|
export async function initiateConnection ({ rtcConfiguration, dataChannel, signal, metrics, multiaddr: ma, connectionManager, transportManager, log, logger, onProgress }: ConnectOptions): Promise<{ remoteAddress: Multiaddr, peerConnection: RTCPeerConnection, muxerFactory: DataChannelMuxerFactory }> {
|
38
|
-
const {
|
36
|
+
const { circuitAddress, targetPeer } = splitAddr(ma)
|
39
37
|
|
40
38
|
metrics?.dialerEvents.increment({ open: true })
|
41
39
|
|
42
|
-
log.trace('dialing
|
40
|
+
log.trace('dialing circuit address: %a', circuitAddress)
|
43
41
|
|
44
|
-
const
|
45
|
-
|
46
|
-
if (relayPeer == null) {
|
47
|
-
throw new InvalidParametersError('Relay peer was missing')
|
48
|
-
}
|
49
|
-
|
50
|
-
const connections = connectionManager.getConnections(peerIdFromString(relayPeer))
|
42
|
+
const connections = connectionManager.getConnections(targetPeer)
|
51
43
|
let connection: Connection
|
52
|
-
let shouldCloseConnection = false
|
53
44
|
|
54
45
|
if (connections.length === 0) {
|
55
46
|
onProgress?.(new CustomProgressEvent('webrtc:dial-relay'))
|
@@ -57,157 +48,140 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
57
48
|
// use the transport manager to open a connection. Initiating a WebRTC
|
58
49
|
// connection takes place in the context of a dial - if we use the
|
59
50
|
// connection manager instead we can end up joining our own dial context
|
60
|
-
connection = await transportManager.dial(
|
51
|
+
connection = await transportManager.dial(circuitAddress, {
|
61
52
|
signal,
|
62
53
|
onProgress
|
63
54
|
})
|
64
|
-
// this connection is unmanaged by the connection manager so we should
|
65
|
-
// close it when we are done
|
66
|
-
shouldCloseConnection = true
|
67
55
|
} else {
|
68
56
|
onProgress?.(new CustomProgressEvent('webrtc:reuse-relay-connection'))
|
69
57
|
|
70
58
|
connection = connections[0]
|
71
59
|
}
|
72
60
|
|
73
|
-
|
74
|
-
onProgress?.(new CustomProgressEvent('webrtc:open-signaling-stream'))
|
61
|
+
onProgress?.(new CustomProgressEvent('webrtc:open-signaling-stream'))
|
75
62
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
63
|
+
const stream = await connection.newStream(SIGNALING_PROTOCOL, {
|
64
|
+
signal,
|
65
|
+
runOnLimitedConnection: true
|
66
|
+
})
|
80
67
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
68
|
+
const messageStream = pbStream(stream).pb(Message)
|
69
|
+
const peerConnection = new RTCPeerConnection(rtcConfiguration)
|
70
|
+
const muxerFactory = new DataChannelMuxerFactory({
|
71
|
+
logger
|
72
|
+
}, {
|
73
|
+
peerConnection,
|
74
|
+
dataChannelOptions: dataChannel
|
75
|
+
})
|
89
76
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
})
|
112
|
-
.catch(err => {
|
113
|
-
log.error('error sending ICE candidate', err)
|
114
|
-
})
|
115
|
-
}
|
116
|
-
peerConnection.onicecandidateerror = (event) => {
|
117
|
-
log.error('initiator ICE candidate error', event)
|
118
|
-
}
|
119
|
-
|
120
|
-
// create an offer
|
121
|
-
const offerSdp = await peerConnection.createOffer().catch(err => {
|
122
|
-
log.error('could not execute createOffer', err)
|
123
|
-
throw new SDPHandshakeFailedError('Failed to set createOffer')
|
77
|
+
try {
|
78
|
+
// we create the channel so that the RTCPeerConnection has a component for
|
79
|
+
// which to collect candidates. The label is not relevant to connection
|
80
|
+
// initiation but can be useful for debugging
|
81
|
+
const channel = peerConnection.createDataChannel('init')
|
82
|
+
|
83
|
+
// setup callback to write ICE candidates to the remote peer
|
84
|
+
peerConnection.onicecandidate = ({ candidate }) => {
|
85
|
+
// a null candidate means end-of-candidates, an empty string candidate
|
86
|
+
// means end-of-candidates for this generation, otherwise this should
|
87
|
+
// be a valid candidate object
|
88
|
+
// see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
|
89
|
+
const data = JSON.stringify(candidate?.toJSON() ?? null)
|
90
|
+
|
91
|
+
log.trace('initiator sending ICE candidate %o', candidate)
|
92
|
+
|
93
|
+
void messageStream.write({
|
94
|
+
type: Message.Type.ICE_CANDIDATE,
|
95
|
+
data
|
96
|
+
}, {
|
97
|
+
signal
|
124
98
|
})
|
99
|
+
.catch(err => {
|
100
|
+
log.error('error sending ICE candidate', err)
|
101
|
+
})
|
102
|
+
}
|
103
|
+
peerConnection.onicecandidateerror = (event) => {
|
104
|
+
log.error('initiator ICE candidate error', event)
|
105
|
+
}
|
125
106
|
|
126
|
-
|
107
|
+
// create an offer
|
108
|
+
const offerSdp = await peerConnection.createOffer().catch(err => {
|
109
|
+
log.error('could not execute createOffer', err)
|
110
|
+
throw new SDPHandshakeFailedError('Failed to set createOffer')
|
111
|
+
})
|
127
112
|
|
128
|
-
|
113
|
+
log.trace('initiator send SDP offer %s', offerSdp.sdp)
|
129
114
|
|
130
|
-
|
131
|
-
await messageStream.write({ type: Message.Type.SDP_OFFER, data: offerSdp.sdp }, {
|
132
|
-
signal
|
133
|
-
})
|
115
|
+
onProgress?.(new CustomProgressEvent('webrtc:send-sdp-offer'))
|
134
116
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
})
|
117
|
+
// write the offer to the stream
|
118
|
+
await messageStream.write({ type: Message.Type.SDP_OFFER, data: offerSdp.sdp }, {
|
119
|
+
signal
|
120
|
+
})
|
140
121
|
|
141
|
-
|
122
|
+
// set offer as local description
|
123
|
+
await peerConnection.setLocalDescription(offerSdp).catch(err => {
|
124
|
+
log.error('could not execute setLocalDescription', err)
|
125
|
+
throw new SDPHandshakeFailedError('Failed to set localDescription')
|
126
|
+
})
|
142
127
|
|
143
|
-
|
128
|
+
onProgress?.(new CustomProgressEvent('webrtc:read-sdp-answer'))
|
144
129
|
|
145
|
-
|
146
|
-
const answerMessage = await messageStream.read({
|
147
|
-
signal
|
148
|
-
})
|
130
|
+
log.trace('initiator read SDP answer')
|
149
131
|
|
150
|
-
|
151
|
-
|
152
|
-
|
132
|
+
// read answer
|
133
|
+
const answerMessage = await messageStream.read({
|
134
|
+
signal
|
135
|
+
})
|
153
136
|
|
154
|
-
|
137
|
+
if (answerMessage.type !== Message.Type.SDP_ANSWER) {
|
138
|
+
throw new SDPHandshakeFailedError('Remote should send an SDP answer')
|
139
|
+
}
|
155
140
|
|
156
|
-
|
157
|
-
await peerConnection.setRemoteDescription(answerSdp).catch(err => {
|
158
|
-
log.error('could not execute setRemoteDescription', err)
|
159
|
-
throw new SDPHandshakeFailedError('Failed to set remoteDescription')
|
160
|
-
})
|
141
|
+
log.trace('initiator received SDP answer %s', answerMessage.data)
|
161
142
|
|
162
|
-
|
143
|
+
const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data })
|
144
|
+
await peerConnection.setRemoteDescription(answerSdp).catch(err => {
|
145
|
+
log.error('could not execute setRemoteDescription', err)
|
146
|
+
throw new SDPHandshakeFailedError('Failed to set remoteDescription')
|
147
|
+
})
|
163
148
|
|
164
|
-
|
149
|
+
log.trace('initiator read candidates until connected')
|
165
150
|
|
166
|
-
|
167
|
-
direction: 'initiator',
|
168
|
-
signal,
|
169
|
-
log,
|
170
|
-
onProgress
|
171
|
-
})
|
151
|
+
onProgress?.(new CustomProgressEvent('webrtc:read-ice-candidates'))
|
172
152
|
|
173
|
-
|
174
|
-
|
153
|
+
await readCandidatesUntilConnected(peerConnection, messageStream, {
|
154
|
+
direction: 'initiator',
|
155
|
+
signal,
|
156
|
+
log,
|
157
|
+
onProgress
|
158
|
+
})
|
175
159
|
|
176
|
-
|
160
|
+
log.trace('initiator connected, closing init channel')
|
161
|
+
channel.close()
|
177
162
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
163
|
+
onProgress?.(new CustomProgressEvent('webrtc:close-signaling-stream'))
|
164
|
+
|
165
|
+
log.trace('closing signaling channel')
|
166
|
+
await stream.close({
|
167
|
+
signal
|
168
|
+
})
|
169
|
+
|
170
|
+
log.trace('initiator connected to remote address %s', ma)
|
182
171
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
peerConnection,
|
188
|
-
muxerFactory
|
189
|
-
}
|
190
|
-
} catch (err: any) {
|
191
|
-
log.error('outgoing signaling error', err)
|
192
|
-
|
193
|
-
peerConnection.close()
|
194
|
-
stream.abort(err)
|
195
|
-
throw err
|
196
|
-
} finally {
|
197
|
-
peerConnection.onicecandidate = null
|
198
|
-
peerConnection.onicecandidateerror = null
|
172
|
+
return {
|
173
|
+
remoteAddress: ma,
|
174
|
+
peerConnection,
|
175
|
+
muxerFactory
|
199
176
|
}
|
177
|
+
} catch (err: any) {
|
178
|
+
log.error('outgoing signaling error', err)
|
179
|
+
|
180
|
+
peerConnection.close()
|
181
|
+
stream.abort(err)
|
182
|
+
throw err
|
200
183
|
} finally {
|
201
|
-
|
202
|
-
|
203
|
-
if (shouldCloseConnection) {
|
204
|
-
try {
|
205
|
-
await connection.close({
|
206
|
-
signal
|
207
|
-
})
|
208
|
-
} catch (err: any) {
|
209
|
-
connection.abort(err)
|
210
|
-
}
|
211
|
-
}
|
184
|
+
peerConnection.onicecandidate = null
|
185
|
+
peerConnection.onicecandidateerror = null
|
212
186
|
}
|
213
187
|
}
|
@@ -264,32 +264,20 @@ export class WebRTCTransport implements Transport<WebRTCDialEvents>, Startable {
|
|
264
264
|
}
|
265
265
|
}
|
266
266
|
|
267
|
-
export function splitAddr (ma: Multiaddr): {
|
268
|
-
const
|
269
|
-
|
270
|
-
|
267
|
+
export function splitAddr (ma: Multiaddr): { circuitAddress: Multiaddr, targetPeer: PeerId } {
|
268
|
+
const target = ma.getComponents()
|
269
|
+
.filter(({ name }) => name === 'p2p')
|
270
|
+
.map(({ value }) => value)
|
271
|
+
.pop()
|
272
|
+
|
273
|
+
if (target == null) {
|
274
|
+
throw new InvalidParametersError('Destination peer id was missing')
|
271
275
|
}
|
272
276
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
// look for remote peerId
|
278
|
-
let remoteAddr = multiaddr(addrs[0])
|
279
|
-
const destination = multiaddr('/' + addrs[1])
|
280
|
-
|
281
|
-
const destinationIdString = destination.getPeerId()
|
282
|
-
if (destinationIdString == null) {
|
283
|
-
throw new InvalidParametersError('destination peer id was missing')
|
284
|
-
}
|
285
|
-
|
286
|
-
const lastProtoInRemote = remoteAddr.protos().pop()
|
287
|
-
if (lastProtoInRemote === undefined) {
|
288
|
-
throw new InvalidParametersError('invalid multiaddr')
|
289
|
-
}
|
290
|
-
if (lastProtoInRemote.name !== 'p2p') {
|
291
|
-
remoteAddr = remoteAddr.encapsulate(`/p2p/${destinationIdString}`)
|
292
|
-
}
|
277
|
+
const circuitAddress = multiaddr(
|
278
|
+
ma.getComponents()
|
279
|
+
.filter(({ name }) => name !== 'webrtc')
|
280
|
+
)
|
293
281
|
|
294
|
-
return {
|
282
|
+
return { circuitAddress, targetPeer: peerIdFromString(target) }
|
295
283
|
}
|