@libp2p/webrtc 4.1.0 → 4.1.1-ce6da9896

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.
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
- }