@libp2p/webrtc 5.2.23 → 5.2.24-0f07e3df5

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 (90) hide show
  1. package/README.md +10 -20
  2. package/dist/index.min.js +18 -18
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/constants.d.ts +0 -23
  5. package/dist/src/constants.d.ts.map +1 -1
  6. package/dist/src/constants.js +0 -23
  7. package/dist/src/constants.js.map +1 -1
  8. package/dist/src/index.d.ts +12 -22
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +12 -22
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/muxer.d.ts +14 -46
  13. package/dist/src/muxer.d.ts.map +1 -1
  14. package/dist/src/muxer.js +32 -135
  15. package/dist/src/muxer.js.map +1 -1
  16. package/dist/src/private-to-private/initiate-connection.d.ts +2 -3
  17. package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
  18. package/dist/src/private-to-private/initiate-connection.js +23 -5
  19. package/dist/src/private-to-private/initiate-connection.js.map +1 -1
  20. package/dist/src/private-to-private/signaling-stream-handler.d.ts +4 -4
  21. package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
  22. package/dist/src/private-to-private/signaling-stream-handler.js +10 -6
  23. package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
  24. package/dist/src/private-to-private/transport.d.ts +2 -2
  25. package/dist/src/private-to-private/transport.d.ts.map +1 -1
  26. package/dist/src/private-to-private/transport.js +30 -15
  27. package/dist/src/private-to-private/transport.js.map +1 -1
  28. package/dist/src/private-to-private/util.d.ts +3 -1
  29. package/dist/src/private-to-private/util.d.ts.map +1 -1
  30. package/dist/src/private-to-private/util.js +15 -3
  31. package/dist/src/private-to-private/util.js.map +1 -1
  32. package/dist/src/private-to-public/listener.d.ts.map +1 -1
  33. package/dist/src/private-to-public/listener.js +21 -15
  34. package/dist/src/private-to-public/listener.js.map +1 -1
  35. package/dist/src/private-to-public/transport.d.ts.map +1 -1
  36. package/dist/src/private-to-public/transport.js +3 -2
  37. package/dist/src/private-to-public/transport.js.map +1 -1
  38. package/dist/src/private-to-public/utils/connect.d.ts +1 -1
  39. package/dist/src/private-to-public/utils/connect.d.ts.map +1 -1
  40. package/dist/src/private-to-public/utils/connect.js +18 -15
  41. package/dist/src/private-to-public/utils/connect.js.map +1 -1
  42. package/dist/src/private-to-public/utils/get-rtcpeerconnection.d.ts +4 -4
  43. package/dist/src/private-to-public/utils/get-rtcpeerconnection.d.ts.map +1 -1
  44. package/dist/src/private-to-public/utils/get-rtcpeerconnection.js +13 -2
  45. package/dist/src/private-to-public/utils/get-rtcpeerconnection.js.map +1 -1
  46. package/dist/src/private-to-public/utils/sdp.d.ts.map +1 -1
  47. package/dist/src/private-to-public/utils/sdp.js +25 -13
  48. package/dist/src/private-to-public/utils/sdp.js.map +1 -1
  49. package/dist/src/private-to-public/utils/stun-listener.js +1 -1
  50. package/dist/src/private-to-public/utils/stun-listener.js.map +1 -1
  51. package/dist/src/rtcpeerconnection-to-conn.d.ts +12 -0
  52. package/dist/src/rtcpeerconnection-to-conn.d.ts.map +1 -0
  53. package/dist/src/rtcpeerconnection-to-conn.js +43 -0
  54. package/dist/src/rtcpeerconnection-to-conn.js.map +1 -0
  55. package/dist/src/stream.d.ts +16 -26
  56. package/dist/src/stream.d.ts.map +1 -1
  57. package/dist/src/stream.js +65 -167
  58. package/dist/src/stream.js.map +1 -1
  59. package/dist/src/util.d.ts +3 -1
  60. package/dist/src/util.d.ts.map +1 -1
  61. package/dist/src/util.js +19 -0
  62. package/dist/src/util.js.map +1 -1
  63. package/dist/src/webrtc/index.d.ts +1 -1
  64. package/dist/src/webrtc/index.d.ts.map +1 -1
  65. package/dist/src/webrtc/index.js +1 -1
  66. package/dist/src/webrtc/index.js.map +1 -1
  67. package/package.json +26 -29
  68. package/src/constants.ts +0 -28
  69. package/src/index.ts +12 -22
  70. package/src/muxer.ts +43 -166
  71. package/src/private-to-private/initiate-connection.ts +30 -8
  72. package/src/private-to-private/signaling-stream-handler.ts +12 -9
  73. package/src/private-to-private/transport.ts +33 -17
  74. package/src/private-to-private/util.ts +21 -4
  75. package/src/private-to-public/listener.ts +22 -15
  76. package/src/private-to-public/transport.ts +3 -2
  77. package/src/private-to-public/utils/connect.ts +19 -16
  78. package/src/private-to-public/utils/get-rtcpeerconnection.ts +16 -4
  79. package/src/private-to-public/utils/sdp.ts +29 -13
  80. package/src/private-to-public/utils/stun-listener.ts +1 -1
  81. package/src/rtcpeerconnection-to-conn.ts +62 -0
  82. package/src/stream.ts +78 -195
  83. package/src/util.ts +22 -1
  84. package/src/webrtc/index.ts +1 -1
  85. package/dist/src/maconn.d.ts +0 -58
  86. package/dist/src/maconn.d.ts.map +0 -1
  87. package/dist/src/maconn.js +0 -56
  88. package/dist/src/maconn.js.map +0 -1
  89. package/dist/typedoc-urls.json +0 -14
  90. package/src/maconn.ts +0 -101
@@ -1,12 +1,11 @@
1
1
  import { isIPv4 } from '@chainsafe/is-ip'
2
2
  import { InvalidParametersError } from '@libp2p/interface'
3
- import { getThinWaistAddresses } from '@libp2p/utils/get-thin-waist-addresses'
4
- import { multiaddr, fromStringTuples } from '@multiformats/multiaddr'
3
+ import { getNetConfig, getThinWaistAddresses } from '@libp2p/utils'
4
+ import { CODE_CERTHASH, CODE_WEBRTC_DIRECT, multiaddr } from '@multiformats/multiaddr'
5
5
  import { WebRTCDirect } from '@multiformats/multiaddr-matcher'
6
6
  import getPort from 'get-port'
7
7
  import { TypedEventEmitter, setMaxListeners } from 'main-event'
8
8
  import pWaitFor from 'p-wait-for'
9
- import { CODEC_CERTHASH, CODEC_WEBRTC_DIRECT } from '../constants.js'
10
9
  import { connect } from './utils/connect.js'
11
10
  import { createDialerRTCPeerConnection } from './utils/get-rtcpeerconnection.js'
12
11
  import { stunListener } from './utils/stun-listener.js'
@@ -94,7 +93,11 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
94
93
  }
95
94
 
96
95
  async listen (ma: Multiaddr): Promise<void> {
97
- const { host, port, family } = ma.toOptions()
96
+ const { host, port, type, protocol } = getNetConfig(ma)
97
+
98
+ if (port == null || protocol !== 'udp' || (type !== 'ip4' && type !== 'ip6')) {
99
+ throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address or was missing a UDP port`)
100
+ }
98
101
 
99
102
  let udpMuxServer: UDPMuxServer | undefined
100
103
 
@@ -106,7 +109,7 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
106
109
  udpMuxServer = UDP_MUX_LISTENERS.find(s => s.port === port)
107
110
 
108
111
  // make sure the port is free for the given family
109
- if (udpMuxServer != null && ((udpMuxServer.isIPv4 && family === 4) || (udpMuxServer.isIPv6 && family === 6))) {
112
+ if (udpMuxServer != null && ((udpMuxServer.isIPv4 && type === 'ip4') || (udpMuxServer.isIPv6 && type === 'ip6'))) {
110
113
  throw new InvalidParametersError(`There is already a listener for ${host}:${port}`)
111
114
  }
112
115
 
@@ -119,13 +122,13 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
119
122
  // start the mux server if we don't have one already
120
123
  if (udpMuxServer == null) {
121
124
  this.log('starting UDP mux server on %s:%p', host, port)
122
- udpMuxServer = this.startUDPMuxServer(host, port, family)
125
+ udpMuxServer = this.startUDPMuxServer(host, port, type === 'ip4' ? 4 : 6)
123
126
  UDP_MUX_LISTENERS.push(udpMuxServer)
124
127
  }
125
128
 
126
- if (family === 4) {
129
+ if (type === 'ip4') {
127
130
  udpMuxServer.isIPv4 = true
128
- } else if (family === 6) {
131
+ } else if (type === 'ip6') {
129
132
  udpMuxServer.isIPv6 = true
130
133
  }
131
134
 
@@ -205,7 +208,7 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
205
208
  metrics: this.components.metrics,
206
209
  events: this.metrics?.listenerEvents,
207
210
  signal,
208
- remoteAddr: multiaddr(`/ip${isIPv4(remoteHost) ? 4 : 6}/${remoteHost}/udp/${remotePort}`),
211
+ remoteAddr: multiaddr(`/ip${isIPv4(remoteHost) ? 4 : 6}/${remoteHost}/udp/${remotePort}/webrtc-direct`),
209
212
  dataChannel: this.init.dataChannel,
210
213
  upgrader: this.init.upgrader,
211
214
  peerId: this.components.peerId,
@@ -238,19 +241,23 @@ export class WebRTCDirectListener extends TypedEventEmitter<ListenerEvents> impl
238
241
  }
239
242
 
240
243
  // add the certhash if it is missing
241
- const tuples = ma.stringTuples()
244
+ const components = ma.getComponents()
242
245
 
243
- for (let j = 0; j < tuples.length; j++) {
244
- if (tuples[j][0] !== CODEC_WEBRTC_DIRECT) {
246
+ for (let j = 0; j < components.length; j++) {
247
+ if (components[j].code !== CODE_WEBRTC_DIRECT) {
245
248
  continue
246
249
  }
247
250
 
248
251
  const certhashIndex = j + 1
249
252
 
250
- if (tuples[certhashIndex] == null || tuples[certhashIndex][0] !== CODEC_CERTHASH) {
251
- tuples.splice(certhashIndex, 0, [CODEC_CERTHASH, this.certificate?.certhash])
253
+ if (components[certhashIndex] == null || components[certhashIndex].code !== CODE_CERTHASH) {
254
+ components.splice(certhashIndex, 0, {
255
+ code: CODE_CERTHASH,
256
+ name: 'certhash',
257
+ value: this.certificate?.certhash
258
+ })
252
259
 
253
- ma = fromStringTuples(tuples)
260
+ ma = multiaddr(components)
254
261
  multiaddrs[i] = ma
255
262
  }
256
263
  }
@@ -1,6 +1,7 @@
1
1
  import { generateKeyPair, privateKeyToCryptoKeyPair } from '@libp2p/crypto/keys'
2
2
  import { InvalidParametersError, NotFoundError, NotStartedError, serviceCapabilities, transportSymbol } from '@libp2p/interface'
3
3
  import { peerIdFromString } from '@libp2p/peer-id'
4
+ import { CODE_P2P } from '@multiformats/multiaddr'
4
5
  import { WebRTCDirect } from '@multiformats/multiaddr-matcher'
5
6
  import { BasicConstraintsExtension, X509Certificate, X509CertificateGenerator } from '@peculiar/x509'
6
7
  import { Key } from 'interface-datastore'
@@ -164,7 +165,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
164
165
  options.signal.throwIfAborted()
165
166
 
166
167
  let theirPeerId: PeerId | undefined
167
- const remotePeerString = ma.getPeerId()
168
+ const remotePeerString = ma.getComponents().findLast(c => c.code === CODE_P2P)?.value
168
169
  if (remotePeerString != null) {
169
170
  theirPeerId = peerIdFromString(remotePeerString)
170
171
  }
@@ -186,7 +187,7 @@ export class WebRTCDirectTransport implements Transport, Startable {
186
187
  dataChannel: this.init.dataChannel,
187
188
  upgrader: options.upgrader,
188
189
  peerId: this.components.peerId,
189
- remotePeerId: theirPeerId,
190
+ remotePeer: theirPeerId,
190
191
  privateKey: this.components.privateKey
191
192
  })
192
193
  } catch (err) {
@@ -1,8 +1,8 @@
1
- import { noise } from '@chainsafe/libp2p-noise'
2
- import { raceEvent } from 'race-event'
1
+ import { noise } from '@libp2p/noise'
2
+ import { pEvent } from 'p-event'
3
3
  import { WebRTCTransportError } from '../../error.js'
4
- import { WebRTCMultiaddrConnection } from '../../maconn.js'
5
4
  import { DataChannelMuxerFactory } from '../../muxer.js'
5
+ import { toMultiaddrConnection } from '../../rtcpeerconnection-to-conn.ts'
6
6
  import { createStream } from '../../stream.js'
7
7
  import { isFirefox } from '../../util.js'
8
8
  import { generateNoisePrologue } from './generate-noise-prologue.js'
@@ -22,7 +22,7 @@ export interface ConnectOptions {
22
22
  dataChannel?: DataChannelOptions
23
23
  upgrader: Upgrader
24
24
  peerId: PeerId
25
- remotePeerId?: PeerId
25
+ remotePeer?: PeerId
26
26
  signal: AbortSignal
27
27
  privateKey: PrivateKey
28
28
  }
@@ -83,7 +83,7 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
83
83
 
84
84
  if (handshakeDataChannel.readyState !== 'open') {
85
85
  options.log.trace('%s wait for handshake channel to open, starting status %s', options.role, handshakeDataChannel.readyState)
86
- await raceEvent(handshakeDataChannel, 'open', options.signal)
86
+ await pEvent(handshakeDataChannel, 'open', options)
87
87
  }
88
88
 
89
89
  options.log.trace('%s handshake channel opened', options.role)
@@ -116,20 +116,19 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
116
116
  const handshakeStream = createStream({
117
117
  channel: handshakeDataChannel,
118
118
  direction: 'outbound',
119
- handshake: true,
120
- logger: options.logger,
119
+ isHandshake: true,
120
+ log: options.log,
121
121
  ...(options.dataChannel ?? {})
122
122
  })
123
123
 
124
124
  // Creating the connection before completion of the noise
125
125
  // handshake ensures that the stream opening callback is set up
126
- const maConn = new WebRTCMultiaddrConnection(options, {
126
+ const maConn = toMultiaddrConnection({
127
127
  peerConnection,
128
128
  remoteAddr: options.remoteAddr,
129
- timeline: {
130
- open: Date.now()
131
- },
132
- metrics: options.events
129
+ metrics: options.events,
130
+ direction: options.role === 'client' ? 'outbound' : 'inbound',
131
+ log: options.logger.forComponent('libp2p:webrtc-direct:connection')
133
132
  })
134
133
 
135
134
  peerConnection.addEventListener(CONNECTION_STATE_CHANGE_EVENT, () => {
@@ -150,7 +149,8 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
150
149
  // Track opened peer connection
151
150
  options.events?.increment({ peer_connection: true })
152
151
 
153
- const muxerFactory = new DataChannelMuxerFactory(options, {
152
+ const muxerFactory = new DataChannelMuxerFactory({
153
+ // @ts-expect-error https://github.com/murat-dogan/node-datachannel/pull/370
154
154
  peerConnection,
155
155
  metrics: options.events,
156
156
  dataChannelOptions: options.dataChannel
@@ -161,8 +161,8 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
161
161
  // handshake. Therefore, we need to secure an inbound noise connection
162
162
  // from the server.
163
163
  options.log.trace('%s secure inbound', options.role)
164
- await connectionEncrypter.secureInbound(handshakeStream, {
165
- remotePeer: options.remotePeerId,
164
+ const result = await connectionEncrypter.secureInbound(handshakeStream, {
165
+ remotePeer: options.remotePeer,
166
166
  signal: options.signal,
167
167
  skipStreamMuxerNegotiation: true
168
168
  })
@@ -171,6 +171,7 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
171
171
  return await options.upgrader.upgradeOutbound(maConn, {
172
172
  skipProtection: true,
173
173
  skipEncryption: true,
174
+ remotePeer: result.remotePeer,
174
175
  muxerFactory,
175
176
  signal: options.signal
176
177
  })
@@ -181,7 +182,7 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
181
182
  // the client.
182
183
  options.log.trace('%s secure outbound', options.role)
183
184
  const result = await connectionEncrypter.secureOutbound(handshakeStream, {
184
- remotePeer: options.remotePeerId,
185
+ remotePeer: options.remotePeer,
185
186
  signal: options.signal,
186
187
  skipStreamMuxerNegotiation: true
187
188
  })
@@ -193,11 +194,13 @@ export async function connect (peerConnection: DirectRTCPeerConnection, ufrag: s
193
194
  await options.upgrader.upgradeInbound(maConn, {
194
195
  skipProtection: true,
195
196
  skipEncryption: true,
197
+ remotePeer: result.remotePeer,
196
198
  muxerFactory,
197
199
  signal: options.signal
198
200
  })
199
201
  } catch (err) {
200
202
  handshakeDataChannel.close()
203
+ peerConnection.close()
201
204
 
202
205
  throw err
203
206
  }
@@ -1,10 +1,10 @@
1
- import { PeerConnection } from '@ipshipyard/node-datachannel'
2
- import { RTCPeerConnection } from '@ipshipyard/node-datachannel/polyfill'
3
1
  import { Crypto } from '@peculiar/webcrypto'
2
+ import { PeerConnection } from 'node-datachannel'
3
+ import { RTCPeerConnection } from 'node-datachannel/polyfill'
4
4
  import { DEFAULT_ICE_SERVERS, MAX_MESSAGE_SIZE } from '../../constants.js'
5
5
  import { generateTransportCertificate } from './generate-certificates.js'
6
6
  import type { TransportCertificate } from '../../index.js'
7
- import type { CertificateFingerprint } from '@ipshipyard/node-datachannel'
7
+ import type { CertificateFingerprint } from 'node-datachannel'
8
8
 
9
9
  const crypto = new Crypto()
10
10
 
@@ -14,7 +14,7 @@ interface DirectRTCPeerConnectionInit extends RTCConfiguration {
14
14
  }
15
15
 
16
16
  export class DirectRTCPeerConnection extends RTCPeerConnection {
17
- private readonly peerConnection: PeerConnection
17
+ private peerConnection: PeerConnection
18
18
  private readonly ufrag: string
19
19
 
20
20
  constructor (init: DirectRTCPeerConnectionInit) {
@@ -22,6 +22,18 @@ export class DirectRTCPeerConnection extends RTCPeerConnection {
22
22
 
23
23
  this.peerConnection = init.peerConnection
24
24
  this.ufrag = init.ufrag
25
+
26
+ // make sure C++ peer connection is garbage collected
27
+ // https://github.com/murat-dogan/node-datachannel/issues/366#issuecomment-3228453155
28
+ this.addEventListener('connectionstatechange', () => {
29
+ switch (this.connectionState) {
30
+ case 'closed':
31
+ this.peerConnection.close()
32
+ break
33
+ default:
34
+ break
35
+ }
36
+ })
25
37
  }
26
38
 
27
39
  async createOffer (): Promise<globalThis.RTCSessionDescriptionInit | any> {
@@ -1,10 +1,11 @@
1
1
  import { InvalidParametersError } from '@libp2p/interface'
2
- import { multiaddr } from '@multiformats/multiaddr'
2
+ import { getNetConfig } from '@libp2p/utils'
3
+ import { CODE_CERTHASH, multiaddr } from '@multiformats/multiaddr'
3
4
  import { base64url } from 'multiformats/bases/base64'
4
5
  import { bases, digest } from 'multiformats/basics'
5
6
  import * as Digest from 'multiformats/hashes/digest'
6
7
  import { sha256 } from 'multiformats/hashes/sha2'
7
- import { CODEC_CERTHASH, MAX_MESSAGE_SIZE } from '../../constants.js'
8
+ import { MAX_MESSAGE_SIZE } from '../../constants.js'
8
9
  import { InvalidFingerprintError, UnsupportedHashAlgorithmError } from '../../error.js'
9
10
  import type { Multiaddr } from '@multiformats/multiaddr'
10
11
  import type { MultihashDigest } from 'multiformats/hashes/interface'
@@ -27,8 +28,8 @@ export function getFingerprintFromSdp (sdp: string | undefined): string | undefi
27
28
 
28
29
  // Extract the certhash from a multiaddr
29
30
  export function certhash (ma: Multiaddr): string {
30
- const tups = ma.stringTuples()
31
- const certhash = tups.filter((tup) => tup[0] === CODEC_CERTHASH).map((tup) => tup[1])[0]
31
+ const components = ma.getComponents()
32
+ const certhash = components.find(c => c.code === CODE_CERTHASH)?.value
32
33
 
33
34
  if (certhash === undefined || certhash === '') {
34
35
  throw new InvalidParametersError(`Couldn't find a certhash component of multiaddr: ${ma.toString()}`)
@@ -100,15 +101,20 @@ export function toSupportedHashFunction (code: number): 'sha-1' | 'sha-256' | 's
100
101
  * ice-lite mode and DTLS active mode.
101
102
  */
102
103
  export function serverAnswerFromMultiaddr (ma: Multiaddr, ufrag: string): RTCSessionDescriptionInit {
103
- const { host, port, family } = ma.toOptions()
104
+ const { host, port, type } = getNetConfig(ma)
105
+
106
+ if (type !== 'ip4' && type !== 'ip6') {
107
+ throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
108
+ }
109
+
104
110
  const fingerprint = ma2Fingerprint(ma)
105
111
  const sdp = `v=0
106
- o=- 0 0 IN IP${family} ${host}
112
+ o=- 0 0 IN IP${type === 'ip4' ? 4 : 6} ${host}
107
113
  s=-
108
114
  t=0 0
109
115
  a=ice-lite
110
116
  m=application ${port} UDP/DTLS/SCTP webrtc-datachannel
111
- c=IN IP${family} ${host}
117
+ c=IN IP${type === 'ip4' ? 4 : 6} ${host}
112
118
  a=mid:0
113
119
  a=ice-options:ice2
114
120
  a=ice-ufrag:${ufrag}
@@ -131,11 +137,16 @@ a=end-of-candidates
131
137
  * Create an offer SDP message from a multiaddr
132
138
  */
133
139
  export function clientOfferFromMultiAddr (ma: Multiaddr, ufrag: string): RTCSessionDescriptionInit {
134
- const { host, port, family } = ma.toOptions()
140
+ const { host, port, type } = getNetConfig(ma)
141
+
142
+ if (type !== 'ip4' && type !== 'ip6') {
143
+ throw new InvalidParametersError(`Multiaddr ${ma} was not an IPv4 or IPv6 address`)
144
+ }
145
+
135
146
  const sdp = `v=0
136
- o=- 0 0 IN IP${family} ${host}
147
+ o=- 0 0 IN IP${type === 'ip4' ? 4 : 6} ${host}
137
148
  s=-
138
- c=IN IP${family} ${host}
149
+ c=IN IP${type === 'ip4' ? 4 : 6} ${host}
139
150
  t=0 0
140
151
  a=ice-options:ice2,trickle
141
152
  m=application ${port} UDP/DTLS/SCTP webrtc-datachannel
@@ -166,8 +177,13 @@ export function munge (desc: RTCSessionDescriptionInit, ufrag: string): RTCSessi
166
177
 
167
178
  const lineBreak = desc.sdp.includes('\r\n') ? '\r\n' : '\n'
168
179
 
169
- desc.sdp = desc.sdp
170
- .replace(/\na=ice-ufrag:[^\n]*\n/, '\na=ice-ufrag:' + ufrag + lineBreak)
171
- .replace(/\na=ice-pwd:[^\n]*\n/, '\na=ice-pwd:' + ufrag + lineBreak)
180
+ try {
181
+ desc.sdp = desc.sdp
182
+ .replace(/\na=ice-ufrag:[^\n]*\n/, '\na=ice-ufrag:' + ufrag + lineBreak)
183
+ .replace(/\na=ice-pwd:[^\n]*\n/, '\na=ice-pwd:' + ufrag + lineBreak)
184
+ } catch {
185
+ // fails under Node.js
186
+ }
187
+
172
188
  return desc
173
189
  }
@@ -1,5 +1,5 @@
1
1
  import { isIPv4 } from '@chainsafe/is-ip'
2
- import { IceUdpMuxListener } from '@ipshipyard/node-datachannel'
2
+ import { IceUdpMuxListener } from 'node-datachannel'
3
3
  import type { Logger } from '@libp2p/interface'
4
4
  import type { AddressInfo } from 'node:net'
5
5
 
@@ -0,0 +1,62 @@
1
+ import { AbstractMultiaddrConnection } from '@libp2p/utils'
2
+ import type { RTCPeerConnection } from './webrtc/index.js'
3
+ import type { AbortOptions, MultiaddrConnection } from '@libp2p/interface'
4
+ import type { AbstractMultiaddrConnectionInit, SendResult } from '@libp2p/utils'
5
+ import type { Uint8ArrayList } from 'uint8arraylist'
6
+
7
+ export interface RTCPeerConnectionMultiaddrConnectionInit extends Omit<AbstractMultiaddrConnectionInit, 'stream'> {
8
+ peerConnection: RTCPeerConnection
9
+ }
10
+
11
+ class RTCPeerConnectionMultiaddrConnection extends AbstractMultiaddrConnection {
12
+ private peerConnection: RTCPeerConnection
13
+
14
+ constructor (init: RTCPeerConnectionMultiaddrConnectionInit) {
15
+ super(init)
16
+
17
+ this.peerConnection = init.peerConnection
18
+
19
+ const initialState = init.peerConnection.connectionState
20
+
21
+ this.peerConnection.onconnectionstatechange = () => {
22
+ this.log.trace('peer connection state change %s initial state %s', this.peerConnection.connectionState, initialState)
23
+
24
+ if (this.peerConnection.connectionState === 'disconnected' || this.peerConnection.connectionState === 'failed' || this.peerConnection.connectionState === 'closed') {
25
+ // nothing else to do but close the connection
26
+ this.onTransportClosed()
27
+ }
28
+ }
29
+ }
30
+
31
+ sendData (data: Uint8ArrayList): SendResult {
32
+ return {
33
+ sentBytes: data.byteLength,
34
+ canSendMore: true
35
+ }
36
+ }
37
+
38
+ async sendClose (options?: AbortOptions): Promise<void> {
39
+ this.peerConnection.close()
40
+ options?.signal?.throwIfAborted()
41
+ }
42
+
43
+ sendReset (): void {
44
+ this.peerConnection.close()
45
+ }
46
+
47
+ sendPause (): void {
48
+ // TODO: readable backpressure?
49
+ }
50
+
51
+ sendResume (): void {
52
+ // TODO: readable backpressure?
53
+ }
54
+ }
55
+
56
+ /**
57
+ * Convert a RTCPeerConnection into a MultiaddrConnection
58
+ * https://github.com/libp2p/interface-transport#multiaddrconnection
59
+ */
60
+ export const toMultiaddrConnection = (init: RTCPeerConnectionMultiaddrConnectionInit): MultiaddrConnection => {
61
+ return new RTCPeerConnectionMultiaddrConnection(init)
62
+ }