@libp2p/webrtc 5.2.24-a02cb0461 → 5.2.24-f5932c294

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 (87) hide show
  1. package/README.md +20 -10
  2. package/dist/index.min.js +14 -14
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/constants.d.ts +15 -0
  5. package/dist/src/constants.d.ts.map +1 -1
  6. package/dist/src/constants.js +15 -0
  7. package/dist/src/constants.js.map +1 -1
  8. package/dist/src/index.d.ts +22 -12
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +22 -12
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/maconn.d.ts +58 -0
  13. package/dist/src/maconn.d.ts.map +1 -0
  14. package/dist/src/maconn.js +56 -0
  15. package/dist/src/maconn.js.map +1 -0
  16. package/dist/src/muxer.d.ts +46 -14
  17. package/dist/src/muxer.d.ts.map +1 -1
  18. package/dist/src/muxer.js +135 -32
  19. package/dist/src/muxer.js.map +1 -1
  20. package/dist/src/private-to-private/initiate-connection.d.ts +4 -3
  21. package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
  22. package/dist/src/private-to-private/initiate-connection.js +5 -23
  23. package/dist/src/private-to-private/initiate-connection.js.map +1 -1
  24. package/dist/src/private-to-private/signaling-stream-handler.d.ts +4 -4
  25. package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
  26. package/dist/src/private-to-private/signaling-stream-handler.js +6 -10
  27. package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
  28. package/dist/src/private-to-private/transport.d.ts +2 -2
  29. package/dist/src/private-to-private/transport.d.ts.map +1 -1
  30. package/dist/src/private-to-private/transport.js +15 -30
  31. package/dist/src/private-to-private/transport.js.map +1 -1
  32. package/dist/src/private-to-private/util.d.ts +1 -3
  33. package/dist/src/private-to-private/util.d.ts.map +1 -1
  34. package/dist/src/private-to-private/util.js +3 -15
  35. package/dist/src/private-to-private/util.js.map +1 -1
  36. package/dist/src/private-to-public/listener.js +2 -2
  37. package/dist/src/private-to-public/listener.js.map +1 -1
  38. package/dist/src/private-to-public/transport.js +1 -1
  39. package/dist/src/private-to-public/transport.js.map +1 -1
  40. package/dist/src/private-to-public/utils/connect.d.ts +1 -1
  41. package/dist/src/private-to-public/utils/connect.d.ts.map +1 -1
  42. package/dist/src/private-to-public/utils/connect.js +14 -17
  43. package/dist/src/private-to-public/utils/connect.js.map +1 -1
  44. package/dist/src/private-to-public/utils/get-rtcpeerconnection.d.ts +4 -4
  45. package/dist/src/private-to-public/utils/get-rtcpeerconnection.d.ts.map +1 -1
  46. package/dist/src/private-to-public/utils/get-rtcpeerconnection.js +2 -13
  47. package/dist/src/private-to-public/utils/get-rtcpeerconnection.js.map +1 -1
  48. package/dist/src/private-to-public/utils/sdp.d.ts.map +1 -1
  49. package/dist/src/private-to-public/utils/sdp.js +3 -8
  50. package/dist/src/private-to-public/utils/sdp.js.map +1 -1
  51. package/dist/src/private-to-public/utils/stun-listener.js +1 -1
  52. package/dist/src/private-to-public/utils/stun-listener.js.map +1 -1
  53. package/dist/src/stream.d.ts +26 -13
  54. package/dist/src/stream.d.ts.map +1 -1
  55. package/dist/src/stream.js +166 -64
  56. package/dist/src/stream.js.map +1 -1
  57. package/dist/src/util.d.ts +1 -3
  58. package/dist/src/util.d.ts.map +1 -1
  59. package/dist/src/util.js +0 -19
  60. package/dist/src/util.js.map +1 -1
  61. package/dist/src/webrtc/index.d.ts +1 -1
  62. package/dist/src/webrtc/index.d.ts.map +1 -1
  63. package/dist/src/webrtc/index.js +1 -1
  64. package/dist/src/webrtc/index.js.map +1 -1
  65. package/package.json +29 -26
  66. package/src/constants.ts +18 -0
  67. package/src/index.ts +22 -12
  68. package/src/maconn.ts +101 -0
  69. package/src/muxer.ts +166 -43
  70. package/src/private-to-private/initiate-connection.ts +9 -31
  71. package/src/private-to-private/signaling-stream-handler.ts +9 -12
  72. package/src/private-to-private/transport.ts +17 -33
  73. package/src/private-to-private/util.ts +4 -21
  74. package/src/private-to-public/listener.ts +2 -2
  75. package/src/private-to-public/transport.ts +1 -1
  76. package/src/private-to-public/utils/connect.ts +15 -18
  77. package/src/private-to-public/utils/get-rtcpeerconnection.ts +4 -16
  78. package/src/private-to-public/utils/sdp.ts +3 -8
  79. package/src/private-to-public/utils/stun-listener.ts +1 -1
  80. package/src/stream.ts +194 -74
  81. package/src/util.ts +1 -22
  82. package/src/webrtc/index.ts +1 -1
  83. package/dist/src/rtcpeerconnection-to-conn.d.ts +0 -12
  84. package/dist/src/rtcpeerconnection-to-conn.d.ts.map +0 -1
  85. package/dist/src/rtcpeerconnection-to-conn.js +0 -43
  86. package/dist/src/rtcpeerconnection-to-conn.js.map +0 -1
  87. package/src/rtcpeerconnection-to-conn.ts +0 -62
package/src/index.ts CHANGED
@@ -26,8 +26,8 @@
26
26
  * WebRTC requires use of a relay to connect two nodes. The listener first discovers a relay server and makes a reservation, then the dialer can connect via the relayed address.
27
27
  *
28
28
  * ```TypeScript
29
- * import { noise } from '@libp2p/noise'
30
- * import { yamux } from '@libp2p/yamux'
29
+ * import { noise } from '@chainsafe/libp2p-noise'
30
+ * import { yamux } from '@chainsafe/libp2p-yamux'
31
31
  * import { echo } from '@libp2p/echo'
32
32
  * import { circuitRelayTransport, circuitRelayServer } from '@libp2p/circuit-relay-v2'
33
33
  * import { identify } from '@libp2p/identify'
@@ -35,6 +35,7 @@
35
35
  * import { webSockets } from '@libp2p/websockets'
36
36
  * import { WebRTC } from '@multiformats/multiaddr-matcher'
37
37
  * import delay from 'delay'
38
+ * import { pipe } from 'it-pipe'
38
39
  * import { createLibp2p } from 'libp2p'
39
40
  * import type { Multiaddr } from '@multiformats/multiaddr'
40
41
  *
@@ -133,11 +134,15 @@
133
134
  * await relay.stop()
134
135
  *
135
136
  * // send/receive some data from the remote peer via a direct connection
136
- * stream.send(new TextEncoder().encode('hello world'))
137
- *
138
- * stream.addEventListener('message', (evt) => {
139
- * console.info(new TextDecoder().decode(evt.data.subarray()))
140
- * })
137
+ * await pipe(
138
+ * [new TextEncoder().encode('hello world')],
139
+ * stream,
140
+ * async source => {
141
+ * for await (const buf of source) {
142
+ * console.info(new TextDecoder().decode(buf.subarray()))
143
+ * }
144
+ * }
145
+ * )
141
146
  * ```
142
147
  *
143
148
  * @example WebRTC Direct
@@ -162,6 +167,7 @@
162
167
  * ```TypeScript
163
168
  * import { createLibp2p } from 'libp2p'
164
169
  * import { multiaddr } from '@multiformats/multiaddr'
170
+ * import { pipe } from 'it-pipe'
165
171
  * import { fromString, toString } from 'uint8arrays'
166
172
  * import { webRTCDirect } from '@libp2p/webrtc'
167
173
  *
@@ -190,11 +196,15 @@
190
196
  * signal: AbortSignal.timeout(10_000)
191
197
  * })
192
198
  *
193
- * stream.send(new TextEncoder().encode('hello world'))
194
- *
195
- * stream.addEventListener('message', (evt) => {
196
- * console.info(new TextDecoder().decode(evt.data.subarray()))
197
- * })
199
+ * await pipe(
200
+ * [fromString(`Hello js-libp2p-webrtc\n`)],
201
+ * stream,
202
+ * async function (source) {
203
+ * for await (const buf of source) {
204
+ * console.info(toString(buf.subarray()))
205
+ * }
206
+ * }
207
+ * )
198
208
  * ```
199
209
  *
200
210
  * ## WebRTC Direct certificate hashes
package/src/maconn.ts ADDED
@@ -0,0 +1,101 @@
1
+ import { nopSink, nopSource } from './util.js'
2
+ import type { RTCPeerConnection } from './webrtc/index.js'
3
+ import type { ComponentLogger, Logger, MultiaddrConnection, MultiaddrConnectionTimeline, CounterGroup } from '@libp2p/interface'
4
+ import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
5
+ import type { Source, Sink } from 'it-stream-types'
6
+ import type { Uint8ArrayList } from 'uint8arraylist'
7
+
8
+ interface WebRTCMultiaddrConnectionInit {
9
+ /**
10
+ * WebRTC Peer Connection
11
+ */
12
+ peerConnection: RTCPeerConnection
13
+
14
+ /**
15
+ * The multiaddr address used to communicate with the remote peer
16
+ */
17
+ remoteAddr: Multiaddr
18
+
19
+ /**
20
+ * Holds the relevant events timestamps of the connection
21
+ */
22
+ timeline: MultiaddrConnectionTimeline
23
+
24
+ /**
25
+ * Optional metrics counter group for this connection
26
+ */
27
+ metrics?: CounterGroup
28
+ }
29
+
30
+ export interface WebRTCMultiaddrConnectionComponents {
31
+ logger: ComponentLogger
32
+ }
33
+
34
+ export class WebRTCMultiaddrConnection implements MultiaddrConnection {
35
+ readonly log: Logger
36
+
37
+ /**
38
+ * WebRTC Peer Connection
39
+ */
40
+ readonly peerConnection: RTCPeerConnection
41
+
42
+ /**
43
+ * The multiaddr address used to communicate with the remote peer
44
+ */
45
+ remoteAddr: Multiaddr
46
+
47
+ /**
48
+ * Holds the life cycle times of the connection
49
+ */
50
+ timeline: MultiaddrConnectionTimeline
51
+
52
+ /**
53
+ * Optional metrics counter group for this connection
54
+ */
55
+ metrics?: CounterGroup
56
+
57
+ /**
58
+ * The stream source, a no-op as the transport natively supports multiplexing
59
+ */
60
+ source: AsyncGenerator<Uint8Array, any, unknown> = nopSource()
61
+
62
+ /**
63
+ * The stream destination, a no-op as the transport natively supports multiplexing
64
+ */
65
+ sink: Sink<Source<Uint8Array | Uint8ArrayList>, Promise<void>> = nopSink
66
+
67
+ constructor (components: WebRTCMultiaddrConnectionComponents, init: WebRTCMultiaddrConnectionInit) {
68
+ this.log = components.logger.forComponent('libp2p:webrtc:maconn')
69
+ this.remoteAddr = init.remoteAddr
70
+ this.timeline = init.timeline
71
+ this.peerConnection = init.peerConnection
72
+
73
+ const peerConnection = this.peerConnection
74
+ const initialState = peerConnection.connectionState
75
+
76
+ this.peerConnection.onconnectionstatechange = () => {
77
+ this.log.trace('peer connection state change', peerConnection.connectionState, 'initial state', initialState)
78
+
79
+ if (peerConnection.connectionState === 'disconnected' || peerConnection.connectionState === 'failed' || peerConnection.connectionState === 'closed') {
80
+ // nothing else to do but close the connection
81
+ this.timeline.close = Date.now()
82
+ }
83
+ }
84
+ }
85
+
86
+ async close (options?: AbortOptions): Promise<void> {
87
+ this.log.trace('closing connection')
88
+
89
+ this.peerConnection.close()
90
+ this.timeline.close = Date.now()
91
+ this.metrics?.increment({ close: true })
92
+ }
93
+
94
+ abort (err: Error): void {
95
+ this.log.error('closing connection due to error', err)
96
+
97
+ this.peerConnection.close()
98
+ this.timeline.close = Date.now()
99
+ this.metrics?.increment({ abort: true })
100
+ }
101
+ }
package/src/muxer.ts CHANGED
@@ -1,9 +1,11 @@
1
- import { AbstractStreamMuxer } from '@libp2p/utils'
2
- import { pEvent } from 'p-event'
3
1
  import { MUXER_PROTOCOL } from './constants.js'
4
- import { createStream, WebRTCStream } from './stream.js'
2
+ import { createStream } from './stream.js'
3
+ import { drainAndClose, nopSink, nopSource } from './util.js'
5
4
  import type { DataChannelOptions } from './index.js'
6
- import type { ComponentLogger, CounterGroup, StreamMuxer, StreamMuxerFactory, CreateStreamOptions, MultiaddrConnection } from '@libp2p/interface'
5
+ import type { ComponentLogger, Logger, Stream, CounterGroup, StreamMuxer, StreamMuxerFactory, StreamMuxerInit } from '@libp2p/interface'
6
+ import type { AbortOptions } from '@multiformats/multiaddr'
7
+ import type { Source, Sink } from 'it-stream-types'
8
+ import type { Uint8ArrayList } from 'uint8arraylist'
7
9
 
8
10
  export interface DataChannelMuxerFactoryInit {
9
11
  /**
@@ -21,9 +23,6 @@ export interface DataChannelMuxerFactoryInit {
21
23
  */
22
24
  metrics?: CounterGroup
23
25
 
24
- /**
25
- * Options used to create data channels
26
- */
27
26
  dataChannelOptions?: DataChannelOptions
28
27
  }
29
28
 
@@ -31,6 +30,12 @@ export interface DataChannelMuxerFactoryComponents {
31
30
  logger: ComponentLogger
32
31
  }
33
32
 
33
+ interface BufferedStream {
34
+ stream: Stream
35
+ channel: RTCDataChannel
36
+ onEnd(err?: Error): void
37
+ }
38
+
34
39
  export class DataChannelMuxerFactory implements StreamMuxerFactory {
35
40
  public readonly protocol: string
36
41
 
@@ -38,28 +43,69 @@ export class DataChannelMuxerFactory implements StreamMuxerFactory {
38
43
  * WebRTC Peer Connection
39
44
  */
40
45
  private readonly peerConnection: RTCPeerConnection
46
+ private bufferedStreams: BufferedStream[] = []
41
47
  private readonly metrics?: CounterGroup
42
48
  private readonly dataChannelOptions?: DataChannelOptions
49
+ private readonly components: DataChannelMuxerFactoryComponents
50
+ private readonly log: Logger
43
51
 
44
- constructor (init: DataChannelMuxerFactoryInit) {
52
+ constructor (components: DataChannelMuxerFactoryComponents, init: DataChannelMuxerFactoryInit) {
53
+ this.components = components
45
54
  this.peerConnection = init.peerConnection
46
55
  this.metrics = init.metrics
47
56
  this.protocol = init.protocol ?? MUXER_PROTOCOL
48
57
  this.dataChannelOptions = init.dataChannelOptions ?? {}
58
+ this.log = components.logger.forComponent('libp2p:webrtc:muxerfactory')
59
+
60
+ // store any data channels opened before upgrade has been completed
61
+ this.peerConnection.ondatachannel = ({ channel }) => {
62
+ this.log.trace('incoming early datachannel with channel id %d and label "%s"', channel.id)
63
+
64
+ // 'init' channel is only used during connection establishment
65
+ if (channel.label === 'init') {
66
+ this.log.trace('closing early init channel')
67
+ channel.close()
68
+
69
+ return
70
+ }
71
+
72
+ // @ts-expect-error fields are set below
73
+ const bufferedStream: BufferedStream = {}
74
+
75
+ const stream = createStream({
76
+ channel,
77
+ direction: 'inbound',
78
+ onEnd: (err) => {
79
+ bufferedStream.onEnd(err)
80
+ },
81
+ log: this.log,
82
+ ...this.dataChannelOptions
83
+ })
84
+
85
+ bufferedStream.stream = stream
86
+ bufferedStream.channel = channel
87
+ bufferedStream.onEnd = () => {
88
+ this.bufferedStreams = this.bufferedStreams.filter(s => s.stream.id !== stream.id)
89
+ }
90
+
91
+ this.bufferedStreams.push(bufferedStream)
92
+ }
49
93
  }
50
94
 
51
- createStreamMuxer (maConn: MultiaddrConnection): StreamMuxer {
52
- return new DataChannelMuxer(maConn, {
95
+ createStreamMuxer (init?: StreamMuxerInit): StreamMuxer {
96
+ return new DataChannelMuxer(this.components, {
97
+ ...init,
53
98
  peerConnection: this.peerConnection,
54
99
  dataChannelOptions: this.dataChannelOptions,
55
100
  metrics: this.metrics,
101
+ streams: this.bufferedStreams,
56
102
  protocol: this.protocol
57
103
  })
58
104
  }
59
105
  }
60
106
 
61
- export interface DataChannelMuxerInit extends DataChannelMuxerFactoryInit {
62
- protocol: string
107
+ export interface DataChannelMuxerInit extends DataChannelMuxerFactoryInit, StreamMuxerInit {
108
+ streams: BufferedStream[]
63
109
  }
64
110
 
65
111
  export interface DataChannelMuxerComponents {
@@ -69,18 +115,26 @@ export interface DataChannelMuxerComponents {
69
115
  /**
70
116
  * A libp2p data channel stream muxer
71
117
  */
72
- export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implements StreamMuxer<WebRTCStream> {
118
+ export class DataChannelMuxer implements StreamMuxer {
119
+ /**
120
+ * Array of streams in the data channel
121
+ */
122
+ public streams: Stream[]
123
+ public protocol: string
124
+
125
+ private readonly log: Logger
73
126
  private readonly peerConnection: RTCPeerConnection
74
127
  private readonly dataChannelOptions: DataChannelOptions
128
+ private readonly metrics?: CounterGroup
129
+ private readonly logger: ComponentLogger
75
130
 
76
- constructor (maConn: MultiaddrConnection, init: DataChannelMuxerInit) {
77
- super(maConn, {
78
- ...init,
79
- name: 'muxer'
80
- })
81
-
131
+ constructor (components: DataChannelMuxerComponents, readonly init: DataChannelMuxerInit) {
132
+ this.log = init.log?.newScope('muxer') ?? components.logger.forComponent('libp2p:webrtc:muxer')
133
+ this.logger = components.logger
134
+ this.streams = init.streams.map(s => s.stream)
82
135
  this.peerConnection = init.peerConnection
83
136
  this.protocol = init.protocol ?? MUXER_PROTOCOL
137
+ this.metrics = init.metrics
84
138
  this.dataChannelOptions = init.dataChannelOptions ?? {}
85
139
 
86
140
  /**
@@ -90,7 +144,7 @@ export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implemen
90
144
  * {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event}
91
145
  */
92
146
  this.peerConnection.ondatachannel = ({ channel }) => {
93
- this.log.trace('incoming %s datachannel with channel id %d and status', channel.protocol, channel.id, channel.readyState)
147
+ this.log.trace('incoming datachannel with channel id %d', channel.id)
94
148
 
95
149
  // 'init' channel is only used during connection establishment
96
150
  if (channel.label === 'init') {
@@ -100,46 +154,115 @@ export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implemen
100
154
  return
101
155
  }
102
156
 
157
+ // lib-datachannel throws if `.getId` is called on a closed channel so
158
+ // memoize it
159
+ const id = channel.id
160
+
103
161
  const stream = createStream({
104
- ...this.streamOptions,
105
- ...this.dataChannelOptions,
106
162
  channel,
107
163
  direction: 'inbound',
108
- log: this.log
164
+ onEnd: () => {
165
+ this.#onStreamEnd(stream, channel)
166
+ this.log('incoming channel %s ended', id)
167
+ },
168
+ log: this.log,
169
+ ...this.dataChannelOptions
109
170
  })
110
171
 
111
- this.onRemoteStream(stream)
172
+ this.streams.push(stream)
173
+ this.metrics?.increment({ incoming_stream: true })
174
+ init?.onIncomingStream?.(stream)
112
175
  }
113
- }
114
176
 
115
- async onCreateStream (options?: CreateStreamOptions): Promise<WebRTCStream> {
116
- // The spec says the label MUST be an empty string: https://github.com/libp2p/specs/blob/master/webrtc/README.md#rtcdatachannel-label
117
- const channel = this.peerConnection.createDataChannel('wtf', {
118
- // TODO: pre-negotiate stream protocol
119
- protocol: options?.protocol
120
- })
177
+ // the DataChannelMuxer constructor is called during set up of the
178
+ // connection by the upgrader.
179
+ //
180
+ // If we invoke `init.onIncomingStream` immediately, the connection object
181
+ // will not be set up yet so add a tiny delay before letting the
182
+ // connection know about early streams
183
+ if (this.init.streams.length > 0) {
184
+ queueMicrotask(() => {
185
+ this.init.streams.forEach(bufferedStream => {
186
+ bufferedStream.onEnd = () => {
187
+ this.log('incoming early channel %s ended with state %s', bufferedStream.channel.id, bufferedStream.channel.readyState)
188
+ this.#onStreamEnd(bufferedStream.stream, bufferedStream.channel)
189
+ }
190
+
191
+ this.metrics?.increment({ incoming_stream: true })
192
+ this.init?.onIncomingStream?.(bufferedStream.stream)
193
+ })
194
+ })
195
+ }
196
+ }
121
197
 
122
- this.log('open channel %d for protocol %s', channel.id, options?.protocol)
198
+ #onStreamEnd (stream: Stream, channel: RTCDataChannel): void {
199
+ this.log.trace('stream %s %s %s onEnd', stream.direction, stream.id, stream.protocol)
200
+ drainAndClose(
201
+ channel,
202
+ `${stream.direction} ${stream.id} ${stream.protocol}`,
203
+ this.dataChannelOptions.drainTimeout, {
204
+ log: this.log
205
+ }
206
+ )
207
+ this.streams = this.streams.filter(s => s.id !== stream.id)
208
+ this.metrics?.increment({ stream_end: true })
209
+ this.init?.onStreamEnd?.(stream)
210
+ }
123
211
 
124
- if (channel.readyState !== 'open') {
125
- this.log('channel %d state is "%s" and not "open", waiting for "open" event before sending data', channel.id, channel.readyState)
126
- await pEvent(channel, 'open', options)
212
+ /**
213
+ * Gracefully close all tracked streams and stop the muxer
214
+ */
215
+ async close (options?: AbortOptions): Promise<void> {
216
+ try {
217
+ await Promise.all(
218
+ this.streams.map(async stream => stream.close(options))
219
+ )
220
+ } catch (err: any) {
221
+ this.abort(err)
222
+ }
223
+ }
127
224
 
128
- this.log('channel %d state is now "%s", sending data', channel.id, channel.readyState)
225
+ /**
226
+ * Abort all tracked streams and stop the muxer
227
+ */
228
+ abort (err: Error): void {
229
+ for (const stream of this.streams) {
230
+ stream.abort(err)
129
231
  }
232
+ }
233
+
234
+ /**
235
+ * The stream source, a no-op as the transport natively supports multiplexing
236
+ */
237
+ source: AsyncGenerator<Uint8Array, any, unknown> = nopSource()
238
+
239
+ /**
240
+ * The stream destination, a no-op as the transport natively supports multiplexing
241
+ */
242
+ sink: Sink<Source<Uint8Array | Uint8ArrayList>, Promise<void>> = nopSink
243
+
244
+ newStream (): Stream {
245
+ // The spec says the label MUST be an empty string: https://github.com/libp2p/specs/blob/master/webrtc/README.md#rtcdatachannel-label
246
+ const channel = this.peerConnection.createDataChannel('')
247
+ // lib-datachannel throws if `.getId` is called on a closed channel so
248
+ // memoize it
249
+ const id = channel.id
250
+
251
+ this.log.trace('opened outgoing datachannel with channel id %s', id)
130
252
 
131
253
  const stream = createStream({
132
- ...options,
133
- ...this.dataChannelOptions,
134
254
  channel,
135
255
  direction: 'outbound',
136
- log: this.log
256
+ onEnd: () => {
257
+ this.#onStreamEnd(stream, channel)
258
+ this.log('outgoing channel %s ended', id)
259
+ },
260
+ log: this.log,
261
+ ...this.dataChannelOptions
137
262
  })
263
+ this.streams.push(stream)
264
+ this.metrics?.increment({ outgoing_stream: true })
138
265
 
139
266
  return stream
140
267
  }
141
-
142
- onData (): void {
143
-
144
- }
145
268
  }
@@ -1,5 +1,4 @@
1
- import { pbStream } from '@libp2p/utils'
2
- import { pEvent } from 'p-event'
1
+ import { pbStream } from 'it-protobuf-stream'
3
2
  import { CustomProgressEvent } from 'progress-events'
4
3
  import { SIGNALING_PROTOCOL } from '../constants.js'
5
4
  import { SDPHandshakeFailedError } from '../error.js'
@@ -10,14 +9,15 @@ import { splitAddr } from './transport.js'
10
9
  import { readCandidatesUntilConnected } from './util.js'
11
10
  import type { WebRTCDialEvents, WebRTCTransportMetrics } from './transport.js'
12
11
  import type { DataChannelOptions } from '../index.js'
13
- import type { LoggerOptions, Connection, ComponentLogger } from '@libp2p/interface'
12
+ import type { LoggerOptions, Connection, ComponentLogger, IncomingStreamData } from '@libp2p/interface'
14
13
  import type { ConnectionManager, TransportManager } from '@libp2p/interface-internal'
15
- import type { AbortOptions, Multiaddr } from '@multiformats/multiaddr'
14
+ import type { Multiaddr } from '@multiformats/multiaddr'
16
15
  import type { ProgressOptions } from 'progress-events'
17
16
 
18
- export interface IncomingStreamOptions extends AbortOptions {
17
+ export interface IncomingStreamOpts extends IncomingStreamData {
19
18
  rtcConfiguration?: RTCConfiguration
20
19
  dataChannelOptions?: Partial<DataChannelOptions>
20
+ signal: AbortSignal
21
21
  }
22
22
 
23
23
  export interface ConnectOptions extends LoggerOptions, ProgressOptions<WebRTCDialEvents> {
@@ -67,21 +67,9 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
67
67
 
68
68
  const messageStream = pbStream(stream).pb(Message)
69
69
  const peerConnection = new RTCPeerConnection(rtcConfiguration)
70
-
71
- // make sure C++ peer connection is garbage collected
72
- // https://github.com/murat-dogan/node-datachannel/issues/366#issuecomment-3228453155
73
- peerConnection.addEventListener('connectionstatechange', () => {
74
- switch (peerConnection.connectionState) {
75
- case 'closed':
76
- peerConnection.close()
77
- break
78
- default:
79
- break
80
- }
81
- })
82
-
83
70
  const muxerFactory = new DataChannelMuxerFactory({
84
- // @ts-expect-error https://github.com/murat-dogan/node-datachannel/pull/370
71
+ logger
72
+ }, {
85
73
  peerConnection,
86
74
  dataChannelOptions: dataChannel
87
75
  })
@@ -109,7 +97,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
109
97
  signal
110
98
  })
111
99
  .catch(err => {
112
- log.error('error sending ICE candidate - %e', err)
100
+ log.error('error sending ICE candidate', err)
113
101
  })
114
102
  }
115
103
  peerConnection.onicecandidateerror = (event) => {
@@ -169,17 +157,7 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
169
157
  onProgress
170
158
  })
171
159
 
172
- log.trace('initiator connected')
173
-
174
- if (channel.readyState !== 'open') {
175
- log.trace('wait for init channel to open')
176
- await pEvent(channel, 'open', {
177
- signal
178
- })
179
- }
180
-
181
- log.trace('closing init channel, starting status')
182
-
160
+ log.trace('initiator connected, closing init channel')
183
161
  channel.close()
184
162
 
185
163
  onProgress?.(new CustomProgressEvent('webrtc:close-signaling-stream'))
@@ -1,19 +1,20 @@
1
- import { pbStream } from '@libp2p/utils'
2
1
  import { multiaddr } from '@multiformats/multiaddr'
2
+ import { pbStream } from 'it-protobuf-stream'
3
3
  import { SDPHandshakeFailedError } from '../error.js'
4
4
  import { RTCSessionDescription } from '../webrtc/index.js'
5
5
  import { Message } from './pb/message.js'
6
- import { getConnectionState, getRemotePeer, readCandidatesUntilConnected } from './util.js'
6
+ import { getConnectionState, readCandidatesUntilConnected } from './util.js'
7
7
  import type { RTCPeerConnection } from '../webrtc/index.js'
8
- import type { AbortOptions, Connection, Logger, PeerId, Stream } from '@libp2p/interface'
8
+ import type { Logger, IncomingStreamData } from '@libp2p/interface'
9
9
  import type { Multiaddr } from '@multiformats/multiaddr'
10
10
 
11
- export interface IncomingStreamOptions extends AbortOptions {
11
+ export interface IncomingStreamOpts extends IncomingStreamData {
12
12
  peerConnection: RTCPeerConnection
13
+ signal: AbortSignal
13
14
  log: Logger
14
15
  }
15
16
 
16
- export async function handleIncomingStream (stream: Stream, connection: Connection, { peerConnection, signal, log }: IncomingStreamOptions): Promise<{ remoteAddress: Multiaddr, remotePeer: PeerId }> {
17
+ export async function handleIncomingStream ({ peerConnection, stream, signal, connection, log }: IncomingStreamOpts): Promise<{ remoteAddress: Multiaddr }> {
17
18
  log.trace('new inbound signaling stream')
18
19
 
19
20
  const messageStream = pbStream(stream).pb(Message)
@@ -36,7 +37,7 @@ export async function handleIncomingStream (stream: Stream, connection: Connecti
36
37
  signal
37
38
  })
38
39
  .catch(err => {
39
- log.error('error sending ICE candidate - %e', err)
40
+ log.error('error sending ICE candidate', err)
40
41
  })
41
42
  }
42
43
 
@@ -100,13 +101,9 @@ export async function handleIncomingStream (stream: Stream, connection: Connecti
100
101
  }
101
102
  }
102
103
 
103
- const remotePeer = getRemotePeer(connection.remoteAddr)
104
- const remoteAddress = multiaddr(`/webrtc/p2p/${remotePeer}`)
104
+ const remoteAddress = multiaddr(`/webrtc/p2p/${connection.remoteAddr.getPeerId()}`)
105
105
 
106
106
  log.trace('recipient connected to remote address %s', remoteAddress)
107
107
 
108
- return {
109
- remoteAddress,
110
- remotePeer
111
- }
108
+ return { remoteAddress }
112
109
  }