@libp2p/webrtc 4.1.0 → 4.1.1-ce6da9896

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. package/dist/index.min.js +6 -6
  2. package/dist/src/constants.d.ts +7 -0
  3. package/dist/src/constants.d.ts.map +1 -0
  4. package/dist/src/constants.js +17 -0
  5. package/dist/src/constants.js.map +1 -0
  6. package/dist/src/private-to-private/initiate-connection.d.ts +4 -3
  7. package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
  8. package/dist/src/private-to-private/initiate-connection.js +15 -5
  9. package/dist/src/private-to-private/initiate-connection.js.map +1 -1
  10. package/dist/src/private-to-private/transport.d.ts +7 -5
  11. package/dist/src/private-to-private/transport.d.ts.map +1 -1
  12. package/dist/src/private-to-private/transport.js +9 -7
  13. package/dist/src/private-to-private/transport.js.map +1 -1
  14. package/dist/src/private-to-private/util.d.ts +3 -1
  15. package/dist/src/private-to-private/util.d.ts.map +1 -1
  16. package/dist/src/private-to-private/util.js +3 -0
  17. package/dist/src/private-to-private/util.js.map +1 -1
  18. package/dist/src/private-to-public/transport.js +2 -2
  19. package/dist/src/private-to-public/transport.js.map +1 -1
  20. package/dist/src/util.d.ts +1 -0
  21. package/dist/src/util.d.ts.map +1 -1
  22. package/dist/src/util.js +13 -0
  23. package/dist/src/util.js.map +1 -1
  24. package/package.json +14 -13
  25. package/src/constants.ts +16 -0
  26. package/src/private-to-private/initiate-connection.ts +25 -7
  27. package/src/private-to-private/transport.ts +27 -10
  28. package/src/private-to-private/util.ts +6 -1
  29. package/src/private-to-public/transport.ts +2 -2
  30. package/src/util.ts +17 -0
  31. package/dist/typedoc-urls.json +0 -8
@@ -1,15 +1,17 @@
1
1
  import { CodeError } from '@libp2p/interface'
2
2
  import { peerIdFromString } from '@libp2p/peer-id'
3
3
  import { pbStream } from 'it-protobuf-stream'
4
+ import { CustomProgressEvent } from 'progress-events'
4
5
  import { DataChannelMuxerFactory } from '../muxer.js'
5
6
  import { RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
6
7
  import { Message } from './pb/message.js'
7
- import { SIGNALING_PROTO_ID, splitAddr, type WebRTCTransportMetrics } from './transport.js'
8
+ import { SIGNALING_PROTO_ID, splitAddr, type WebRTCDialEvents, type WebRTCTransportMetrics } from './transport.js'
8
9
  import { readCandidatesUntilConnected } from './util.js'
9
10
  import type { DataChannelOptions } from '../index.js'
10
11
  import type { LoggerOptions, Connection, ComponentLogger } from '@libp2p/interface'
11
12
  import type { ConnectionManager, IncomingStreamData, TransportManager } from '@libp2p/interface-internal'
12
13
  import type { Multiaddr } from '@multiformats/multiaddr'
14
+ import type { ProgressOptions } from 'progress-events'
13
15
 
14
16
  export interface IncomingStreamOpts extends IncomingStreamData {
15
17
  rtcConfiguration?: RTCConfiguration
@@ -17,7 +19,7 @@ export interface IncomingStreamOpts extends IncomingStreamData {
17
19
  signal: AbortSignal
18
20
  }
19
21
 
20
- export interface ConnectOptions extends LoggerOptions {
22
+ export interface ConnectOptions extends LoggerOptions, ProgressOptions<WebRTCDialEvents> {
21
23
  rtcConfiguration?: RTCConfiguration
22
24
  dataChannel?: DataChannelOptions
23
25
  multiaddr: Multiaddr
@@ -29,7 +31,7 @@ export interface ConnectOptions extends LoggerOptions {
29
31
  logger: ComponentLogger
30
32
  }
31
33
 
32
- export async function initiateConnection ({ rtcConfiguration, dataChannel, signal, metrics, multiaddr: ma, connectionManager, transportManager, log, logger }: ConnectOptions): Promise<{ remoteAddress: Multiaddr, peerConnection: RTCPeerConnection, muxerFactory: DataChannelMuxerFactory }> {
34
+ export async function initiateConnection ({ rtcConfiguration, dataChannel, signal, metrics, multiaddr: ma, connectionManager, transportManager, log, logger, onProgress }: ConnectOptions): Promise<{ remoteAddress: Multiaddr, peerConnection: RTCPeerConnection, muxerFactory: DataChannelMuxerFactory }> {
33
35
  const { baseAddr } = splitAddr(ma)
34
36
 
35
37
  metrics?.dialerEvents.increment({ open: true })
@@ -47,20 +49,27 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
47
49
  let shouldCloseConnection = false
48
50
 
49
51
  if (connections.length === 0) {
52
+ onProgress?.(new CustomProgressEvent('webrtc:dial-relay'))
53
+
50
54
  // use the transport manager to open a connection. Initiating a WebRTC
51
55
  // connection takes place in the context of a dial - if we use the
52
56
  // connection manager instead we can end up joining our own dial context
53
57
  connection = await transportManager.dial(baseAddr, {
54
- signal
58
+ signal,
59
+ onProgress
55
60
  })
56
61
  // this connection is unmanaged by the connection manager so we should
57
62
  // close it when we are done
58
63
  shouldCloseConnection = true
59
64
  } else {
65
+ onProgress?.(new CustomProgressEvent('webrtc:reuse-relay-connection'))
66
+
60
67
  connection = connections[0]
61
68
  }
62
69
 
63
70
  try {
71
+ onProgress?.(new CustomProgressEvent('webrtc:open-signaling-stream'))
72
+
64
73
  const stream = await connection.newStream(SIGNALING_PROTO_ID, {
65
74
  signal,
66
75
  runOnTransientConnection: true
@@ -113,6 +122,8 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
113
122
 
114
123
  log.trace('initiator send SDP offer %s', offerSdp.sdp)
115
124
 
125
+ onProgress?.(new CustomProgressEvent('webrtc:send-sdp-offer'))
126
+
116
127
  // write the offer to the stream
117
128
  await messageStream.write({ type: Message.Type.SDP_OFFER, data: offerSdp.sdp }, {
118
129
  signal
@@ -124,6 +135,8 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
124
135
  throw new CodeError('Failed to set localDescription', 'ERR_SDP_HANDSHAKE_FAILED')
125
136
  })
126
137
 
138
+ onProgress?.(new CustomProgressEvent('webrtc:read-sdp-answer'))
139
+
127
140
  // read answer
128
141
  const answerMessage = await messageStream.read({
129
142
  signal
@@ -143,16 +156,21 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
143
156
 
144
157
  log.trace('initiator read candidates until connected')
145
158
 
159
+ onProgress?.(new CustomProgressEvent('webrtc:read-ice-candidates'))
160
+
146
161
  await readCandidatesUntilConnected(peerConnection, messageStream, {
147
162
  direction: 'initiator',
148
163
  signal,
149
- log
164
+ log,
165
+ onProgress
150
166
  })
151
167
 
152
168
  log.trace('initiator connected, closing init channel')
153
169
  channel.close()
154
170
 
155
- log.trace('closing signalling channel')
171
+ onProgress?.(new CustomProgressEvent('webrtc:close-signaling-stream'))
172
+
173
+ log.trace('closing signaling channel')
156
174
  await stream.close({
157
175
  signal
158
176
  })
@@ -165,7 +183,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
165
183
  muxerFactory
166
184
  }
167
185
  } catch (err: any) {
168
- log.error('outgoing signalling error', err)
186
+ log.error('outgoing signaling error', err)
169
187
 
170
188
  peerConnection.close()
171
189
  stream.abort(err)
@@ -1,17 +1,19 @@
1
- import { CodeError, serviceCapabilities, serviceDependencies, setMaxListeners } from '@libp2p/interface'
2
- import { type CreateListenerOptions, type DialOptions, transportSymbol, type Transport, type Listener, type Upgrader, type ComponentLogger, type Logger, type Connection, type PeerId, type CounterGroup, type Metrics, type Startable } from '@libp2p/interface'
1
+ import { CodeError, serviceCapabilities, serviceDependencies, setMaxListeners, transportSymbol } from '@libp2p/interface'
3
2
  import { peerIdFromString } from '@libp2p/peer-id'
4
3
  import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
5
4
  import { WebRTC } from '@multiformats/multiaddr-matcher'
6
5
  import { codes } from '../error.js'
7
6
  import { WebRTCMultiaddrConnection } from '../maconn.js'
8
7
  import { DataChannelMuxerFactory } from '../muxer.js'
8
+ import { getRtcConfiguration } from '../util.js'
9
9
  import { RTCPeerConnection } from '../webrtc/index.js'
10
10
  import { initiateConnection } from './initiate-connection.js'
11
11
  import { WebRTCPeerListener } from './listener.js'
12
12
  import { handleIncomingStream } from './signaling-stream-handler.js'
13
13
  import type { DataChannelOptions } from '../index.js'
14
- import type { IncomingStreamData, Registrar, ConnectionManager, TransportManager } from '@libp2p/interface-internal'
14
+ import type { OutboundConnectionUpgradeEvents, CreateListenerOptions, DialOptions, Transport, Listener, Upgrader, ComponentLogger, Logger, Connection, PeerId, CounterGroup, Metrics, Startable } from '@libp2p/interface'
15
+ import type { IncomingStreamData, Registrar, ConnectionManager, TransportManager, OpenConnectionProgressEvents } from '@libp2p/interface-internal'
16
+ import type { ProgressEvent } from 'progress-events'
15
17
 
16
18
  const WEBRTC_TRANSPORT = '/webrtc'
17
19
  const CIRCUIT_RELAY_TRANSPORT = '/p2p-circuit'
@@ -44,7 +46,20 @@ export interface WebRTCTransportMetrics {
44
46
  listenerEvents: CounterGroup
45
47
  }
46
48
 
47
- export class WebRTCTransport implements Transport, Startable {
49
+ export type WebRTCDialEvents =
50
+ OutboundConnectionUpgradeEvents |
51
+ OpenConnectionProgressEvents |
52
+ ProgressEvent<'webrtc:dial-relay'> |
53
+ ProgressEvent<'webrtc:reuse-relay-connection'> |
54
+ ProgressEvent<'webrtc:open-signaling-stream'> |
55
+ ProgressEvent<'webrtc:send-sdp-offer'> |
56
+ ProgressEvent<'webrtc:read-sdp-answer'> |
57
+ ProgressEvent<'webrtc:read-ice-candidates'> |
58
+ ProgressEvent<'webrtc:add-ice-candidate', string> |
59
+ ProgressEvent<'webrtc:end-of-ice-candidates'> |
60
+ ProgressEvent<'webrtc:close-signaling-stream'>
61
+
62
+ export class WebRTCTransport implements Transport<WebRTCDialEvents>, Startable {
48
63
  private readonly log: Logger
49
64
  private _started = false
50
65
  private readonly metrics?: WebRTCTransportMetrics
@@ -130,11 +145,11 @@ export class WebRTCTransport implements Transport, Startable {
130
145
  * For a circuit relay, this will be of the form
131
146
  * <relay address>/p2p/<relay-peer>/p2p-circuit/webrtc/p2p/<destination-peer>
132
147
  */
133
- async dial (ma: Multiaddr, options: DialOptions): Promise<Connection> {
148
+ async dial (ma: Multiaddr, options: DialOptions<WebRTCDialEvents>): Promise<Connection> {
134
149
  this.log.trace('dialing address: %a', ma)
135
150
 
136
151
  const { remoteAddress, peerConnection, muxerFactory } = await initiateConnection({
137
- rtcConfiguration: typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration,
152
+ rtcConfiguration: await getRtcConfiguration(this.init.rtcConfiguration),
138
153
  dataChannel: this.init.dataChannel,
139
154
  multiaddr: ma,
140
155
  dataChannelOptions: this.init.dataChannel,
@@ -142,7 +157,8 @@ export class WebRTCTransport implements Transport, Startable {
142
157
  connectionManager: this.components.connectionManager,
143
158
  transportManager: this.components.transportManager,
144
159
  log: this.log,
145
- logger: this.components.logger
160
+ logger: this.components.logger,
161
+ onProgress: options.onProgress
146
162
  })
147
163
 
148
164
  const webRTCConn = new WebRTCMultiaddrConnection(this.components, {
@@ -155,7 +171,8 @@ export class WebRTCTransport implements Transport, Startable {
155
171
  const connection = await options.upgrader.upgradeOutbound(webRTCConn, {
156
172
  skipProtection: true,
157
173
  skipEncryption: true,
158
- muxerFactory
174
+ muxerFactory,
175
+ onProgress: options.onProgress
159
176
  })
160
177
 
161
178
  // close the connection on shut down
@@ -166,7 +183,7 @@ export class WebRTCTransport implements Transport, Startable {
166
183
 
167
184
  async _onProtocol ({ connection, stream }: IncomingStreamData): Promise<void> {
168
185
  const signal = AbortSignal.timeout(this.init.inboundConnectionTimeout ?? INBOUND_CONNECTION_TIMEOUT)
169
- const peerConnection = new RTCPeerConnection(typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration)
186
+ const peerConnection = new RTCPeerConnection(await getRtcConfiguration(this.init.rtcConfiguration))
170
187
  const muxerFactory = new DataChannelMuxerFactory(this.components, {
171
188
  peerConnection,
172
189
  dataChannelOptions: this.init.dataChannel
@@ -202,7 +219,7 @@ export class WebRTCTransport implements Transport, Startable {
202
219
  // close the connection on shut down
203
220
  this._closeOnShutdown(peerConnection, webRTCConn)
204
221
  } catch (err: any) {
205
- this.log.error('incoming signalling error', err)
222
+ this.log.error('incoming signaling error', err)
206
223
 
207
224
  peerConnection.close()
208
225
  stream.abort(err)
@@ -1,13 +1,16 @@
1
1
  import { CodeError } from '@libp2p/interface'
2
2
  import pDefer from 'p-defer'
3
+ import { CustomProgressEvent } from 'progress-events'
3
4
  import { isFirefox } from '../util.js'
4
5
  import { RTCIceCandidate } from '../webrtc/index.js'
5
6
  import { Message } from './pb/message.js'
7
+ import type { WebRTCDialEvents } from './transport.js'
6
8
  import type { LoggerOptions, Stream } from '@libp2p/interface'
7
9
  import type { AbortOptions, MessageStream } from 'it-protobuf-stream'
8
10
  import type { DeferredPromise } from 'p-defer'
11
+ import type { ProgressOptions } from 'progress-events'
9
12
 
10
- export interface ReadCandidatesOptions extends AbortOptions, LoggerOptions {
13
+ export interface ReadCandidatesOptions extends AbortOptions, LoggerOptions, ProgressOptions<WebRTCDialEvents> {
11
14
  direction: string
12
15
  }
13
16
 
@@ -44,6 +47,7 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
44
47
  // candidate means candidate gathering has finished
45
48
  // see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
46
49
  if (candidateInit === '' || candidateInit === null) {
50
+ options.onProgress?.(new CustomProgressEvent('webrtc:end-of-ice-candidates'))
47
51
  options.log.trace('end-of-candidates received')
48
52
 
49
53
  continue
@@ -54,6 +58,7 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
54
58
  options.log.trace('%s received new ICE candidate %o', options.direction, candidateInit)
55
59
 
56
60
  try {
61
+ options.onProgress?.(new CustomProgressEvent<string>('webrtc:add-ice-candidate', candidate.candidate))
57
62
  await pc.addIceCandidate(candidate)
58
63
  } catch (err) {
59
64
  options.log.error('%s bad candidate received', options.direction, candidateInit, err)
@@ -10,7 +10,7 @@ import { dataChannelError, inappropriateMultiaddr, unimplemented, invalidArgumen
10
10
  import { WebRTCMultiaddrConnection } from '../maconn.js'
11
11
  import { DataChannelMuxerFactory } from '../muxer.js'
12
12
  import { createStream } from '../stream.js'
13
- import { isFirefox } from '../util.js'
13
+ import { getRtcConfiguration, isFirefox } from '../util.js'
14
14
  import { RTCPeerConnection } from '../webrtc/index.js'
15
15
  import * as sdp from './sdp.js'
16
16
  import { genUfrag } from './util.js'
@@ -139,7 +139,7 @@ export class WebRTCDirectTransport implements Transport {
139
139
  } as any)
140
140
 
141
141
  const peerConnection = new RTCPeerConnection({
142
- ...(typeof this.init.rtcConfiguration === 'function' ? await this.init.rtcConfiguration() : this.init.rtcConfiguration ?? {}),
142
+ ...(await getRtcConfiguration(this.init.rtcConfiguration)),
143
143
  certificates: [certificate]
144
144
  })
145
145
 
package/src/util.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { detect } from 'detect-browser'
2
2
  import pDefer from 'p-defer'
3
3
  import pTimeout from 'p-timeout'
4
+ import { DEFAULT_ICE_SERVERS } from './constants.js'
4
5
  import type { LoggerOptions } from '@libp2p/interface'
5
6
 
6
7
  const browser = detect()
@@ -64,3 +65,19 @@ export interface AbortPromiseOptions {
64
65
  signal?: AbortSignal
65
66
  message?: string
66
67
  }
68
+
69
+ export async function getRtcConfiguration (config?: RTCConfiguration | (() => RTCConfiguration | Promise<RTCConfiguration>)): Promise<RTCConfiguration> {
70
+ config = config ?? {}
71
+
72
+ if (typeof config === 'function') {
73
+ config = await config()
74
+ }
75
+
76
+ config.iceServers = config.iceServers ?? DEFAULT_ICE_SERVERS.map(url => ({
77
+ urls: [
78
+ url
79
+ ]
80
+ }))
81
+
82
+ return config
83
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "DataChannelOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webrtc.DataChannelOptions.html",
3
- ".:DataChannelOptions": "https://libp2p.github.io/js-libp2p/interfaces/_libp2p_webrtc.DataChannelOptions.html",
4
- "webRTC": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webrtc.webRTC.html",
5
- ".:webRTC": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webrtc.webRTC.html",
6
- "webRTCDirect": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webrtc.webRTCDirect.html",
7
- ".:webRTCDirect": "https://libp2p.github.io/js-libp2p/functions/_libp2p_webrtc.webRTCDirect.html"
8
- }