@libp2p/webrtc 3.2.11 → 4.0.0-06e6d235f

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 (76) hide show
  1. package/README.md +1 -1
  2. package/dist/index.min.js +21 -21
  3. package/dist/src/error.d.ts +2 -2
  4. package/dist/src/error.d.ts.map +1 -1
  5. package/dist/src/error.js +1 -1
  6. package/dist/src/error.js.map +1 -1
  7. package/dist/src/index.d.ts +6 -1
  8. package/dist/src/index.d.ts.map +1 -1
  9. package/dist/src/index.js.map +1 -1
  10. package/dist/src/maconn.d.ts +8 -4
  11. package/dist/src/maconn.d.ts.map +1 -1
  12. package/dist/src/maconn.js +6 -6
  13. package/dist/src/maconn.js.map +1 -1
  14. package/dist/src/muxer.d.ts +13 -5
  15. package/dist/src/muxer.d.ts.map +1 -1
  16. package/dist/src/muxer.js +36 -7
  17. package/dist/src/muxer.js.map +1 -1
  18. package/dist/src/pb/message.js.map +1 -1
  19. package/dist/src/private-to-private/initiate-connection.d.ts +4 -5
  20. package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
  21. package/dist/src/private-to-private/initiate-connection.js +4 -5
  22. package/dist/src/private-to-private/initiate-connection.js.map +1 -1
  23. package/dist/src/private-to-private/listener.d.ts +3 -4
  24. package/dist/src/private-to-private/listener.d.ts.map +1 -1
  25. package/dist/src/private-to-private/listener.js +1 -1
  26. package/dist/src/private-to-private/listener.js.map +1 -1
  27. package/dist/src/private-to-private/pb/message.js.map +1 -1
  28. package/dist/src/private-to-private/signaling-stream-handler.d.ts +4 -2
  29. package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
  30. package/dist/src/private-to-private/signaling-stream-handler.js +4 -5
  31. package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
  32. package/dist/src/private-to-private/transport.d.ts +5 -9
  33. package/dist/src/private-to-private/transport.d.ts.map +1 -1
  34. package/dist/src/private-to-private/transport.js +16 -14
  35. package/dist/src/private-to-private/transport.js.map +1 -1
  36. package/dist/src/private-to-private/util.d.ts +2 -2
  37. package/dist/src/private-to-private/util.d.ts.map +1 -1
  38. package/dist/src/private-to-private/util.js +26 -41
  39. package/dist/src/private-to-private/util.js.map +1 -1
  40. package/dist/src/private-to-public/options.d.ts +1 -1
  41. package/dist/src/private-to-public/options.d.ts.map +1 -1
  42. package/dist/src/private-to-public/sdp.d.ts +2 -1
  43. package/dist/src/private-to-public/sdp.d.ts.map +1 -1
  44. package/dist/src/private-to-public/sdp.js +3 -6
  45. package/dist/src/private-to-public/sdp.js.map +1 -1
  46. package/dist/src/private-to-public/transport.d.ts +4 -5
  47. package/dist/src/private-to-public/transport.d.ts.map +1 -1
  48. package/dist/src/private-to-public/transport.js +26 -15
  49. package/dist/src/private-to-public/transport.js.map +1 -1
  50. package/dist/src/stream.d.ts +10 -4
  51. package/dist/src/stream.d.ts.map +1 -1
  52. package/dist/src/stream.js +19 -33
  53. package/dist/src/stream.js.map +1 -1
  54. package/dist/src/util.d.ts +2 -1
  55. package/dist/src/util.d.ts.map +1 -1
  56. package/dist/src/util.js +4 -6
  57. package/dist/src/util.js.map +1 -1
  58. package/dist/src/webrtc/rtc-data-channel.js.map +1 -1
  59. package/dist/src/webrtc/rtc-ice-candidate.js.map +1 -1
  60. package/dist/src/webrtc/rtc-peer-connection.js.map +1 -1
  61. package/package.json +27 -22
  62. package/src/error.ts +2 -2
  63. package/src/index.ts +7 -1
  64. package/src/maconn.ts +14 -10
  65. package/src/muxer.ts +57 -11
  66. package/src/private-to-private/initiate-connection.ts +7 -11
  67. package/src/private-to-private/listener.ts +3 -4
  68. package/src/private-to-private/signaling-stream-handler.ts +7 -7
  69. package/src/private-to-private/transport.ts +18 -22
  70. package/src/private-to-private/util.ts +30 -46
  71. package/src/private-to-public/options.ts +1 -1
  72. package/src/private-to-public/sdp.ts +4 -8
  73. package/src/private-to-public/transport.ts +27 -19
  74. package/src/stream.ts +27 -39
  75. package/src/util.ts +5 -7
  76. package/dist/typedoc-urls.json +0 -8
package/src/muxer.ts CHANGED
@@ -1,16 +1,11 @@
1
- import { logger } from '@libp2p/logger'
2
1
  import { createStream } from './stream.js'
3
2
  import { drainAndClose, nopSink, nopSource } from './util.js'
4
3
  import type { DataChannelOptions } from './index.js'
5
- import type { Stream } from '@libp2p/interface/connection'
6
- import type { CounterGroup } from '@libp2p/interface/metrics'
7
- import type { StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface/stream-muxer'
4
+ import type { ComponentLogger, Logger, Stream, CounterGroup, StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface'
8
5
  import type { AbortOptions } from '@multiformats/multiaddr'
9
6
  import type { Source, Sink } from 'it-stream-types'
10
7
  import type { Uint8ArrayList } from 'uint8arraylist'
11
8
 
12
- const log = logger('libp2p:webrtc:muxer')
13
-
14
9
  const PROTOCOL = '/webrtc'
15
10
 
16
11
  export interface DataChannelMuxerFactoryInit {
@@ -32,6 +27,10 @@ export interface DataChannelMuxerFactoryInit {
32
27
  dataChannelOptions?: DataChannelOptions
33
28
  }
34
29
 
30
+ export interface DataChannelMuxerFactoryComponents {
31
+ logger: ComponentLogger
32
+ }
33
+
35
34
  interface BufferedStream {
36
35
  stream: Stream
37
36
  channel: RTCDataChannel
@@ -48,15 +47,29 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
48
47
  private bufferedStreams: BufferedStream[] = []
49
48
  private readonly metrics?: CounterGroup
50
49
  private readonly dataChannelOptions?: DataChannelOptions
50
+ private readonly components: DataChannelMuxerFactoryComponents
51
+ private readonly log: Logger
51
52
 
52
- constructor (init: DataChannelMuxerFactoryInit) {
53
+ constructor (components: DataChannelMuxerFactoryComponents, init: DataChannelMuxerFactoryInit) {
54
+ this.components = components
53
55
  this.peerConnection = init.peerConnection
54
56
  this.metrics = init.metrics
55
57
  this.protocol = init.protocol ?? PROTOCOL
56
58
  this.dataChannelOptions = init.dataChannelOptions ?? {}
59
+ this.log = components.logger.forComponent('libp2p:webrtc:datachannelmuxerfactory')
57
60
 
58
61
  // store any datachannels opened before upgrade has been completed
59
62
  this.peerConnection.ondatachannel = ({ channel }) => {
63
+ this.log.trace('incoming early datachannel with channel id %d and label "%s"', channel.id)
64
+
65
+ // 'init' channel is only used during connection establishment
66
+ if (channel.label === 'init') {
67
+ this.log.trace('closing early init channel')
68
+ channel.close()
69
+
70
+ return
71
+ }
72
+
60
73
  // @ts-expect-error fields are set below
61
74
  const bufferedStream: BufferedStream = {}
62
75
 
@@ -66,6 +79,7 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
66
79
  onEnd: (err) => {
67
80
  bufferedStream.onEnd(err)
68
81
  },
82
+ logger: components.logger,
69
83
  ...this.dataChannelOptions
70
84
  })
71
85
 
@@ -80,7 +94,7 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
80
94
  }
81
95
 
82
96
  createStreamMuxer (init?: StreamMuxerInit): StreamMuxer {
83
- return new DataChannelMuxer({
97
+ return new DataChannelMuxer(this.components, {
84
98
  ...init,
85
99
  peerConnection: this.peerConnection,
86
100
  dataChannelOptions: this.dataChannelOptions,
@@ -95,6 +109,10 @@ export interface DataChannelMuxerInit extends DataChannelMuxerFactoryInit, Strea
95
109
  streams: BufferedStream[]
96
110
  }
97
111
 
112
+ export interface DataChannelMuxerComponents {
113
+ logger: ComponentLogger
114
+ }
115
+
98
116
  /**
99
117
  * A libp2p data channel stream muxer
100
118
  */
@@ -105,11 +123,15 @@ export class DataChannelMuxer implements StreamMuxer {
105
123
  public streams: Stream[]
106
124
  public protocol: string
107
125
 
126
+ private readonly log: Logger
108
127
  private readonly peerConnection: RTCPeerConnection
109
128
  private readonly dataChannelOptions: DataChannelOptions
110
129
  private readonly metrics?: CounterGroup
130
+ private readonly logger: ComponentLogger
111
131
 
112
- constructor (readonly init: DataChannelMuxerInit) {
132
+ constructor (components: DataChannelMuxerComponents, readonly init: DataChannelMuxerInit) {
133
+ this.log = components.logger.forComponent('libp2p:webrtc:muxer')
134
+ this.logger = components.logger
113
135
  this.streams = init.streams.map(s => s.stream)
114
136
  this.peerConnection = init.peerConnection
115
137
  this.protocol = init.protocol ?? PROTOCOL
@@ -123,12 +145,24 @@ export class DataChannelMuxer implements StreamMuxer {
123
145
  * {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event}
124
146
  */
125
147
  this.peerConnection.ondatachannel = ({ channel }) => {
148
+ this.log.trace('incoming datachannel with channel id %d', channel.id)
149
+
150
+ // 'init' channel is only used during connection establishment
151
+ if (channel.label === 'init') {
152
+ this.log.trace('closing init channel')
153
+ channel.close()
154
+
155
+ return
156
+ }
157
+
126
158
  const stream = createStream({
127
159
  channel,
128
160
  direction: 'inbound',
129
161
  onEnd: () => {
162
+ this.log('incoming channel %s ended with state %s', channel.id, channel.readyState)
130
163
  this.#onStreamEnd(stream, channel)
131
164
  },
165
+ logger: this.logger,
132
166
  ...this.dataChannelOptions
133
167
  })
134
168
 
@@ -147,6 +181,7 @@ export class DataChannelMuxer implements StreamMuxer {
147
181
  queueMicrotask(() => {
148
182
  this.init.streams.forEach(bufferedStream => {
149
183
  bufferedStream.onEnd = () => {
184
+ this.log('incoming early channel %s ended with state %s', bufferedStream.channel.id, bufferedStream.channel.readyState)
150
185
  this.#onStreamEnd(bufferedStream.stream, bufferedStream.channel)
151
186
  }
152
187
 
@@ -158,8 +193,14 @@ export class DataChannelMuxer implements StreamMuxer {
158
193
  }
159
194
 
160
195
  #onStreamEnd (stream: Stream, channel: RTCDataChannel): void {
161
- log.trace('stream %s %s %s onEnd', stream.direction, stream.id, stream.protocol)
162
- drainAndClose(channel, `${stream.direction} ${stream.id} ${stream.protocol}`, this.dataChannelOptions.drainTimeout)
196
+ this.log.trace('stream %s %s %s onEnd', stream.direction, stream.id, stream.protocol)
197
+ drainAndClose(
198
+ channel,
199
+ `${stream.direction} ${stream.id} ${stream.protocol}`,
200
+ this.dataChannelOptions.drainTimeout, {
201
+ log: this.log
202
+ }
203
+ )
163
204
  this.streams = this.streams.filter(s => s.id !== stream.id)
164
205
  this.metrics?.increment({ stream_end: true })
165
206
  this.init?.onStreamEnd?.(stream)
@@ -200,12 +241,17 @@ export class DataChannelMuxer implements StreamMuxer {
200
241
  newStream (): Stream {
201
242
  // The spec says the label SHOULD be an empty string: https://github.com/libp2p/specs/blob/master/webrtc/README.md#rtcdatachannel-label
202
243
  const channel = this.peerConnection.createDataChannel('')
244
+
245
+ this.log.trace('opened outgoing datachannel with channel id %s', channel.id)
246
+
203
247
  const stream = createStream({
204
248
  channel,
205
249
  direction: 'outbound',
206
250
  onEnd: () => {
251
+ this.log('outgoing channel %s ended with state %s', channel.id, channel.readyState)
207
252
  this.#onStreamEnd(stream, channel)
208
253
  },
254
+ logger: this.logger,
209
255
  ...this.dataChannelOptions
210
256
  })
211
257
  this.streams.push(stream)
@@ -1,5 +1,4 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { logger } from '@libp2p/logger'
1
+ import { CodeError } from '@libp2p/interface'
3
2
  import { peerIdFromString } from '@libp2p/peer-id'
4
3
  import { pbStream } from 'it-protobuf-stream'
5
4
  import pDefer, { type DeferredPromise } from 'p-defer'
@@ -8,21 +7,17 @@ import { Message } from './pb/message.js'
8
7
  import { SIGNALING_PROTO_ID, splitAddr, type WebRTCTransportMetrics } from './transport.js'
9
8
  import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
10
9
  import type { DataChannelOptions } from '../index.js'
11
- import type { Connection } from '@libp2p/interface/connection'
12
- import type { ConnectionManager } from '@libp2p/interface-internal/connection-manager'
13
- import type { IncomingStreamData } from '@libp2p/interface-internal/registrar'
14
- import type { TransportManager } from '@libp2p/interface-internal/transport-manager'
10
+ import type { LoggerOptions, Connection } from '@libp2p/interface'
11
+ import type { ConnectionManager, IncomingStreamData, TransportManager } from '@libp2p/interface-internal'
15
12
  import type { Multiaddr } from '@multiformats/multiaddr'
16
13
 
17
- const log = logger('libp2p:webrtc:initiate-connection')
18
-
19
14
  export interface IncomingStreamOpts extends IncomingStreamData {
20
15
  rtcConfiguration?: RTCConfiguration
21
16
  dataChannelOptions?: Partial<DataChannelOptions>
22
17
  signal: AbortSignal
23
18
  }
24
19
 
25
- export interface ConnectOptions {
20
+ export interface ConnectOptions extends LoggerOptions {
26
21
  peerConnection: RTCPeerConnection
27
22
  multiaddr: Multiaddr
28
23
  connectionManager: ConnectionManager
@@ -32,7 +27,7 @@ export interface ConnectOptions {
32
27
  metrics?: WebRTCTransportMetrics
33
28
  }
34
29
 
35
- export async function initiateConnection ({ peerConnection, signal, metrics, multiaddr: ma, connectionManager, transportManager }: ConnectOptions): Promise<{ remoteAddress: Multiaddr }> {
30
+ export async function initiateConnection ({ peerConnection, signal, metrics, multiaddr: ma, connectionManager, transportManager, log }: ConnectOptions): Promise<{ remoteAddress: Multiaddr }> {
36
31
  const { baseAddr } = splitAddr(ma)
37
32
 
38
33
  metrics?.dialerEvents.increment({ open: true })
@@ -147,7 +142,8 @@ export async function initiateConnection ({ peerConnection, signal, metrics, mul
147
142
 
148
143
  await readCandidatesUntilConnected(connectedPromise, peerConnection, messageStream, {
149
144
  direction: 'initiator',
150
- signal
145
+ signal,
146
+ log
151
147
  })
152
148
 
153
149
  log.trace('initiator connected, closing init channel')
@@ -1,8 +1,7 @@
1
- import { TypedEventEmitter } from '@libp2p/interface/events'
1
+ import { TypedEventEmitter } from '@libp2p/interface'
2
2
  import { Circuit } from '@multiformats/mafmt'
3
- import type { PeerId } from '@libp2p/interface/peer-id'
4
- import type { ListenerEvents, Listener } from '@libp2p/interface/transport'
5
- import type { TransportManager } from '@libp2p/interface-internal/transport-manager'
3
+ import type { PeerId, ListenerEvents, Listener } from '@libp2p/interface'
4
+ import type { TransportManager } from '@libp2p/interface-internal'
6
5
  import type { Multiaddr } from '@multiformats/multiaddr'
7
6
 
8
7
  export interface WebRTCPeerListenerComponents {
@@ -1,21 +1,20 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { logger } from '@libp2p/logger'
1
+ import { CodeError } from '@libp2p/interface'
3
2
  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
7
  import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
9
- import type { IncomingStreamData } from '@libp2p/interface-internal/registrar'
10
-
11
- const log = logger('libp2p:webrtc:signaling-stream-handler')
8
+ import type { Logger } from '@libp2p/interface'
9
+ import type { IncomingStreamData } from '@libp2p/interface-internal'
12
10
 
13
11
  export interface IncomingStreamOpts extends IncomingStreamData {
14
12
  peerConnection: RTCPeerConnection
15
13
  signal: AbortSignal
14
+ log: Logger
16
15
  }
17
16
 
18
- export async function handleIncomingStream ({ peerConnection, stream, signal, connection }: IncomingStreamOpts): Promise<{ remoteAddress: Multiaddr }> {
17
+ export async function handleIncomingStream ({ peerConnection, stream, signal, connection, log }: IncomingStreamOpts): Promise<{ remoteAddress: Multiaddr }> {
19
18
  log.trace('new inbound signaling stream')
20
19
 
21
20
  const messageStream = pbStream(stream).pb(Message)
@@ -104,7 +103,8 @@ export async function handleIncomingStream ({ peerConnection, stream, signal, co
104
103
  // wait until candidates are connected
105
104
  await readCandidatesUntilConnected(connectedPromise, peerConnection, messageStream, {
106
105
  direction: 'recipient',
107
- signal
106
+ signal,
107
+ log
108
108
  })
109
109
 
110
110
  log.trace('recipient connected, closing signaling stream')
@@ -1,6 +1,5 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { type CreateListenerOptions, type DialOptions, symbol, type Transport, type Listener, type Upgrader } from '@libp2p/interface/transport'
3
- import { logger } from '@libp2p/logger'
1
+ import { CodeError } 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'
4
3
  import { peerIdFromString } from '@libp2p/peer-id'
5
4
  import { multiaddr, type Multiaddr } from '@multiformats/multiaddr'
6
5
  import { WebRTC } from '@multiformats/multiaddr-matcher'
@@ -12,15 +11,7 @@ import { initiateConnection } from './initiate-connection.js'
12
11
  import { WebRTCPeerListener } from './listener.js'
13
12
  import { handleIncomingStream } from './signaling-stream-handler.js'
14
13
  import type { DataChannelOptions } from '../index.js'
15
- import type { Connection } from '@libp2p/interface/connection'
16
- import type { PeerId } from '@libp2p/interface/peer-id'
17
- import type { CounterGroup, Metrics } from '@libp2p/interface/src/metrics/index.js'
18
- import type { Startable } from '@libp2p/interface/startable'
19
- import type { IncomingStreamData, Registrar } from '@libp2p/interface-internal/registrar'
20
- import type { ConnectionManager } from '@libp2p/interface-internal/src/connection-manager/index.js'
21
- import type { TransportManager } from '@libp2p/interface-internal/transport-manager'
22
-
23
- const log = logger('libp2p:webrtc:peer')
14
+ import type { IncomingStreamData, Registrar, ConnectionManager, TransportManager } from '@libp2p/interface-internal'
24
15
 
25
16
  const WEBRTC_TRANSPORT = '/webrtc'
26
17
  const CIRCUIT_RELAY_TRANSPORT = '/p2p-circuit'
@@ -45,6 +36,7 @@ export interface WebRTCTransportComponents {
45
36
  transportManager: TransportManager
46
37
  connectionManager: ConnectionManager
47
38
  metrics?: Metrics
39
+ logger: ComponentLogger
48
40
  }
49
41
 
50
42
  export interface WebRTCTransportMetrics {
@@ -53,6 +45,7 @@ export interface WebRTCTransportMetrics {
53
45
  }
54
46
 
55
47
  export class WebRTCTransport implements Transport, Startable {
48
+ private readonly log: Logger
56
49
  private _started = false
57
50
  private readonly metrics?: WebRTCTransportMetrics
58
51
  private readonly shutdownController: AbortController
@@ -61,6 +54,7 @@ export class WebRTCTransport implements Transport, Startable {
61
54
  private readonly components: WebRTCTransportComponents,
62
55
  private readonly init: WebRTCTransportInit = {}
63
56
  ) {
57
+ this.log = components.logger.forComponent('libp2p:webrtc')
64
58
  this.shutdownController = new AbortController()
65
59
 
66
60
  if (components.metrics != null) {
@@ -83,7 +77,7 @@ export class WebRTCTransport implements Transport, Startable {
83
77
 
84
78
  async start (): Promise<void> {
85
79
  await this.components.registrar.handle(SIGNALING_PROTO_ID, (data: IncomingStreamData) => {
86
- this._onProtocol(data).catch(err => { log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) })
80
+ this._onProtocol(data).catch(err => { this.log.error('failed to handle incoming connect from %p', data.connection.remotePeer, err) })
87
81
  }, {
88
82
  runOnTransientConnection: true
89
83
  })
@@ -104,7 +98,7 @@ export class WebRTCTransport implements Transport, Startable {
104
98
 
105
99
  readonly [Symbol.toStringTag] = '@libp2p/webrtc'
106
100
 
107
- readonly [symbol] = true
101
+ readonly [transportSymbol] = true
108
102
 
109
103
  filter (multiaddrs: Multiaddr[]): Multiaddr[] {
110
104
  return multiaddrs.filter(WebRTC.exactMatch)
@@ -118,10 +112,10 @@ export class WebRTCTransport implements Transport, Startable {
118
112
  * <relay address>/p2p/<relay-peer>/p2p-circuit/webrtc/p2p/<destination-peer>
119
113
  */
120
114
  async dial (ma: Multiaddr, options: DialOptions): Promise<Connection> {
121
- log.trace('dialing address: %a', ma)
115
+ this.log.trace('dialing address: %a', ma)
122
116
 
123
117
  const peerConnection = new RTCPeerConnection(this.init.rtcConfiguration)
124
- const muxerFactory = new DataChannelMuxerFactory({
118
+ const muxerFactory = new DataChannelMuxerFactory(this.components, {
125
119
  peerConnection,
126
120
  dataChannelOptions: this.init.dataChannel
127
121
  })
@@ -132,10 +126,11 @@ export class WebRTCTransport implements Transport, Startable {
132
126
  dataChannelOptions: this.init.dataChannel,
133
127
  signal: options.signal,
134
128
  connectionManager: this.components.connectionManager,
135
- transportManager: this.components.transportManager
129
+ transportManager: this.components.transportManager,
130
+ log: this.log
136
131
  })
137
132
 
138
- const webRTCConn = new WebRTCMultiaddrConnection({
133
+ const webRTCConn = new WebRTCMultiaddrConnection(this.components, {
139
134
  peerConnection,
140
135
  timeline: { open: Date.now() },
141
136
  remoteAddr: remoteAddress,
@@ -157,7 +152,7 @@ export class WebRTCTransport implements Transport, Startable {
157
152
  async _onProtocol ({ connection, stream }: IncomingStreamData): Promise<void> {
158
153
  const signal = AbortSignal.timeout(this.init.inboundConnectionTimeout ?? INBOUND_CONNECTION_TIMEOUT)
159
154
  const peerConnection = new RTCPeerConnection(this.init.rtcConfiguration)
160
- const muxerFactory = new DataChannelMuxerFactory({
155
+ const muxerFactory = new DataChannelMuxerFactory(this.components, {
161
156
  peerConnection,
162
157
  dataChannelOptions: this.init.dataChannel
163
158
  })
@@ -167,10 +162,11 @@ export class WebRTCTransport implements Transport, Startable {
167
162
  peerConnection,
168
163
  connection,
169
164
  stream,
170
- signal
165
+ signal,
166
+ log: this.log
171
167
  })
172
168
 
173
- const webRTCConn = new WebRTCMultiaddrConnection({
169
+ const webRTCConn = new WebRTCMultiaddrConnection(this.components, {
174
170
  peerConnection,
175
171
  timeline: { open: (new Date()).getTime() },
176
172
  remoteAddr: remoteAddress,
@@ -201,7 +197,7 @@ export class WebRTCTransport implements Transport, Startable {
201
197
  const shutDownListener = (): void => {
202
198
  webRTCConn.close()
203
199
  .catch(err => {
204
- log.error('could not close WebRTCMultiaddrConnection', err)
200
+ this.log.error('could not close WebRTCMultiaddrConnection', err)
205
201
  })
206
202
  }
207
203
 
@@ -1,19 +1,14 @@
1
- import { CodeError } from '@libp2p/interface/errors'
2
- import { logger } from '@libp2p/logger'
3
- import { abortableSource } from 'abortable-iterator'
1
+ import { CodeError } from '@libp2p/interface'
2
+ import { closeSource } from '@libp2p/utils/close-source'
4
3
  import { anySignal } from 'any-signal'
5
- import * as lp from 'it-length-prefixed'
6
- import { AbortError, raceSignal } from 'race-signal'
7
4
  import { isFirefox } from '../util.js'
8
5
  import { RTCIceCandidate } from '../webrtc/index.js'
9
6
  import { Message } from './pb/message.js'
10
- import type { Stream } from '@libp2p/interface/connection'
7
+ import type { LoggerOptions, Stream } from '@libp2p/interface'
11
8
  import type { AbortOptions, MessageStream } from 'it-protobuf-stream'
12
9
  import type { DeferredPromise } from 'p-defer'
13
10
 
14
- const log = logger('libp2p:webrtc:peer:util')
15
-
16
- export interface ReadCandidatesOptions extends AbortOptions {
11
+ export interface ReadCandidatesOptions extends AbortOptions, LoggerOptions {
17
12
  direction: string
18
13
  }
19
14
 
@@ -31,71 +26,60 @@ export const readCandidatesUntilConnected = async (connectedPromise: DeferredPro
31
26
  options.signal
32
27
  ])
33
28
 
34
- const source = abortableSource(stream.unwrap().unwrap().source, signal, {
35
- returnOnAbort: true
36
- })
29
+ const abortListener = (): void => {
30
+ closeSource(stream.unwrap().unwrap().source, options.log)
31
+ }
32
+
33
+ signal.addEventListener('abort', abortListener)
37
34
 
38
35
  try {
39
36
  // read candidates until we are connected or we reach the end of the stream
40
- for await (const buf of lp.decode(source)) {
41
- const message = Message.decode(buf)
37
+ while (true) {
38
+ const message = await Promise.race([
39
+ connectedPromise.promise,
40
+ stream.read()
41
+ ])
42
+
43
+ // stream ended or we became connected
44
+ if (message == null) {
45
+ break
46
+ }
42
47
 
43
48
  if (message.type !== Message.Type.ICE_CANDIDATE) {
44
49
  throw new CodeError('ICE candidate message expected', 'ERR_NOT_ICE_CANDIDATE')
45
50
  }
46
51
 
47
- let candidateInit = JSON.parse(message.data ?? 'null')
52
+ const candidateInit = JSON.parse(message.data ?? 'null')
48
53
 
49
- if (candidateInit === '') {
50
- log.trace('end-of-candidates for this generation received')
51
- candidateInit = {
52
- candidate: '',
53
- sdpMid: '0',
54
- sdpMLineIndex: 0
55
- }
56
- }
54
+ // an empty string means this generation of candidates is complete, a null
55
+ // candidate means candidate gathering has finished
56
+ // see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
57
+ if (candidateInit === '' || candidateInit === null) {
58
+ options.log.trace('end-of-candidates received')
57
59
 
58
- if (candidateInit === null) {
59
- log.trace('end-of-candidates received')
60
- candidateInit = {
61
- candidate: null,
62
- sdpMid: '0',
63
- sdpMLineIndex: 0
64
- }
60
+ continue
65
61
  }
66
62
 
67
- // a null candidate means end-of-candidates
68
- // see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
69
63
  const candidate = new RTCIceCandidate(candidateInit)
70
64
 
71
- log.trace('%s received new ICE candidate', options.direction, candidate)
65
+ options.log.trace('%s received new ICE candidate', options.direction, candidate)
72
66
 
73
67
  try {
74
68
  await pc.addIceCandidate(candidate)
75
69
  } catch (err) {
76
- log.error('%s bad candidate received', options.direction, err)
70
+ options.log.error('%s bad candidate received', options.direction, candidateInit, err)
77
71
  }
78
72
  }
79
73
  } catch (err) {
80
- log.error('%s error parsing ICE candidate', options.direction, err)
74
+ options.log.error('%s error parsing ICE candidate', options.direction, err)
81
75
  } finally {
76
+ signal.removeEventListener('abort', abortListener)
82
77
  signal.clear()
83
78
  }
84
-
85
- if (options.signal?.aborted === true) {
86
- throw new AbortError('Aborted while reading ICE candidates', 'ERR_ICE_CANDIDATES_READ_ABORTED')
87
- }
88
-
89
- // read all available ICE candidates, wait for connection state change
90
- await raceSignal(connectedPromise.promise, options.signal, {
91
- errorMessage: 'Aborted before connected',
92
- errorCode: 'ERR_ABORTED_BEFORE_CONNECTED'
93
- })
94
79
  }
95
80
 
96
81
  export function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise<void>): void {
97
82
  pc[isFirefox ? 'oniceconnectionstatechange' : 'onconnectionstatechange'] = (_) => {
98
- log.trace('receiver peerConnectionState state change: %s', pc.connectionState)
99
83
  switch (isFirefox ? pc.iceConnectionState : pc.connectionState) {
100
84
  case 'connected':
101
85
  promise.resolve()
@@ -1,4 +1,4 @@
1
- import type { CreateListenerOptions, DialOptions } from '@libp2p/interface/transport'
1
+ import type { CreateListenerOptions, DialOptions } from '@libp2p/interface'
2
2
 
3
3
  export interface WebRTCListenerOptions extends CreateListenerOptions {}
4
4
  export interface WebRTCDialOptions extends DialOptions {}
@@ -1,24 +1,22 @@
1
- import { logger } from '@libp2p/logger'
2
1
  import { bases } from 'multiformats/basics'
3
2
  import * as multihashes from 'multihashes'
4
3
  import { inappropriateMultiaddr, invalidArgument, invalidFingerprint, unsupportedHashAlgorithm } from '../error.js'
5
4
  import { CERTHASH_CODE } from './transport.js'
5
+ import type { LoggerOptions } from '@libp2p/interface'
6
6
  import type { Multiaddr } from '@multiformats/multiaddr'
7
7
  import type { HashCode, HashName } from 'multihashes'
8
8
 
9
- const log = logger('libp2p:webrtc:sdp')
10
-
11
9
  /**
12
10
  * Get base2 | identity decoders
13
11
  */
14
12
  // @ts-expect-error - Not easy to combine these types.
15
13
  export const mbdecoder: any = Object.values(bases).map(b => b.decoder).reduce((d, b) => d.or(b))
16
14
 
17
- export function getLocalFingerprint (pc: RTCPeerConnection): string | undefined {
15
+ export function getLocalFingerprint (pc: RTCPeerConnection, options: LoggerOptions): string | undefined {
18
16
  // try to fetch fingerprint from local certificate
19
17
  const localCert = pc.getConfiguration().certificates?.at(0)
20
18
  if (localCert == null || localCert.getFingerprints == null) {
21
- log.trace('fetching fingerprint from local SDP')
19
+ options.log.trace('fetching fingerprint from local SDP')
22
20
  const localDescription = pc.localDescription
23
21
  if (localDescription == null) {
24
22
  return undefined
@@ -26,7 +24,7 @@ export function getLocalFingerprint (pc: RTCPeerConnection): string | undefined
26
24
  return getFingerprintFromSdp(localDescription.sdp)
27
25
  }
28
26
 
29
- log.trace('fetching fingerprint from local certificate')
27
+ options.log.trace('fetching fingerprint from local certificate')
30
28
 
31
29
  if (localCert.getFingerprints().length === 0) {
32
30
  return undefined
@@ -55,8 +53,6 @@ function ipv (ma: Multiaddr): string {
55
53
  }
56
54
  }
57
55
 
58
- log('Warning: multiaddr does not appear to contain IP4 or IP6, defaulting to IP6', ma)
59
-
60
56
  return 'IP6'
61
57
  }
62
58