@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.
@@ -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 { baseAddr } = splitAddr(ma)
36
+ const { circuitAddress, targetPeer } = splitAddr(ma)
39
37
 
40
38
  metrics?.dialerEvents.increment({ open: true })
41
39
 
42
- log.trace('dialing base address: %a', baseAddr)
40
+ log.trace('dialing circuit address: %a', circuitAddress)
43
41
 
44
- const relayPeer = baseAddr.getPeerId()
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(baseAddr, {
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
- try {
74
- onProgress?.(new CustomProgressEvent('webrtc:open-signaling-stream'))
61
+ onProgress?.(new CustomProgressEvent('webrtc:open-signaling-stream'))
75
62
 
76
- const stream = await connection.newStream(SIGNALING_PROTOCOL, {
77
- signal,
78
- runOnLimitedConnection: true
79
- })
63
+ const stream = await connection.newStream(SIGNALING_PROTOCOL, {
64
+ signal,
65
+ runOnLimitedConnection: true
66
+ })
80
67
 
81
- const messageStream = pbStream(stream).pb(Message)
82
- const peerConnection = new RTCPeerConnection(rtcConfiguration)
83
- const muxerFactory = new DataChannelMuxerFactory({
84
- logger
85
- }, {
86
- peerConnection,
87
- dataChannelOptions: dataChannel
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
- try {
91
- // we create the channel so that the RTCPeerConnection has a component for
92
- // which to collect candidates. The label is not relevant to connection
93
- // initiation but can be useful for debugging
94
- const channel = peerConnection.createDataChannel('init')
95
-
96
- // setup callback to write ICE candidates to the remote peer
97
- peerConnection.onicecandidate = ({ candidate }) => {
98
- // a null candidate means end-of-candidates, an empty string candidate
99
- // means end-of-candidates for this generation, otherwise this should
100
- // be a valid candidate object
101
- // see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
102
- const data = JSON.stringify(candidate?.toJSON() ?? null)
103
-
104
- log.trace('initiator sending ICE candidate %o', candidate)
105
-
106
- void messageStream.write({
107
- type: Message.Type.ICE_CANDIDATE,
108
- data
109
- }, {
110
- signal
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
- log.trace('initiator send SDP offer %s', offerSdp.sdp)
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
- onProgress?.(new CustomProgressEvent('webrtc:send-sdp-offer'))
113
+ log.trace('initiator send SDP offer %s', offerSdp.sdp)
129
114
 
130
- // write the offer to the stream
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
- // set offer as local description
136
- await peerConnection.setLocalDescription(offerSdp).catch(err => {
137
- log.error('could not execute setLocalDescription', err)
138
- throw new SDPHandshakeFailedError('Failed to set localDescription')
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
- onProgress?.(new CustomProgressEvent('webrtc:read-sdp-answer'))
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
- log.trace('initiator read SDP answer')
128
+ onProgress?.(new CustomProgressEvent('webrtc:read-sdp-answer'))
144
129
 
145
- // read answer
146
- const answerMessage = await messageStream.read({
147
- signal
148
- })
130
+ log.trace('initiator read SDP answer')
149
131
 
150
- if (answerMessage.type !== Message.Type.SDP_ANSWER) {
151
- throw new SDPHandshakeFailedError('Remote should send an SDP answer')
152
- }
132
+ // read answer
133
+ const answerMessage = await messageStream.read({
134
+ signal
135
+ })
153
136
 
154
- log.trace('initiator received SDP answer %s', answerMessage.data)
137
+ if (answerMessage.type !== Message.Type.SDP_ANSWER) {
138
+ throw new SDPHandshakeFailedError('Remote should send an SDP answer')
139
+ }
155
140
 
156
- const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data })
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
- log.trace('initiator read candidates until connected')
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
- onProgress?.(new CustomProgressEvent('webrtc:read-ice-candidates'))
149
+ log.trace('initiator read candidates until connected')
165
150
 
166
- await readCandidatesUntilConnected(peerConnection, messageStream, {
167
- direction: 'initiator',
168
- signal,
169
- log,
170
- onProgress
171
- })
151
+ onProgress?.(new CustomProgressEvent('webrtc:read-ice-candidates'))
172
152
 
173
- log.trace('initiator connected, closing init channel')
174
- channel.close()
153
+ await readCandidatesUntilConnected(peerConnection, messageStream, {
154
+ direction: 'initiator',
155
+ signal,
156
+ log,
157
+ onProgress
158
+ })
175
159
 
176
- onProgress?.(new CustomProgressEvent('webrtc:close-signaling-stream'))
160
+ log.trace('initiator connected, closing init channel')
161
+ channel.close()
177
162
 
178
- log.trace('closing signaling channel')
179
- await stream.close({
180
- signal
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
- log.trace('initiator connected to remote address %s', ma)
184
-
185
- return {
186
- remoteAddress: ma,
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
- // if we had to open a connection to perform the SDP handshake
202
- // close it because it's not tracked by the connection manager
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): { baseAddr: Multiaddr, peerId: PeerId } {
268
- const addrs = ma.toString().split('/webrtc/')
269
- if (addrs.length !== 2) {
270
- throw new InvalidParametersError('webrtc protocol was not present in multiaddr')
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
- if (!addrs[0].includes('/p2p-circuit')) {
274
- throw new InvalidParametersError('p2p-circuit protocol was not present in multiaddr')
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 { baseAddr: remoteAddr, peerId: peerIdFromString(destinationIdString) }
282
+ return { circuitAddress, targetPeer: peerIdFromString(target) }
295
283
  }