@libp2p/webrtc 5.2.24-a02cb0461 → 5.2.24-da78fa851
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.
- package/dist/index.min.js +17 -17
- package/dist/index.min.js.map +4 -4
- package/dist/src/constants.d.ts +4 -8
- package/dist/src/constants.d.ts.map +1 -1
- package/dist/src/constants.js +4 -8
- package/dist/src/constants.js.map +1 -1
- package/dist/src/index.d.ts +8 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/muxer.d.ts.map +1 -1
- package/dist/src/muxer.js +7 -12
- package/dist/src/muxer.js.map +1 -1
- package/dist/src/private-to-private/initiate-connection.d.ts +2 -2
- package/dist/src/private-to-private/initiate-connection.d.ts.map +1 -1
- package/dist/src/private-to-private/initiate-connection.js +15 -1
- package/dist/src/private-to-private/initiate-connection.js.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.d.ts.map +1 -1
- package/dist/src/private-to-private/signaling-stream-handler.js +10 -2
- package/dist/src/private-to-private/signaling-stream-handler.js.map +1 -1
- package/dist/src/private-to-private/util.d.ts +0 -1
- package/dist/src/private-to-private/util.d.ts.map +1 -1
- package/dist/src/private-to-private/util.js +11 -11
- package/dist/src/private-to-private/util.js.map +1 -1
- package/dist/src/private-to-public/listener.d.ts.map +1 -1
- package/dist/src/private-to-public/listener.js +20 -14
- package/dist/src/private-to-public/listener.js.map +1 -1
- package/dist/src/private-to-public/transport.d.ts.map +1 -1
- package/dist/src/private-to-public/transport.js +2 -1
- package/dist/src/private-to-public/transport.js.map +1 -1
- package/dist/src/private-to-public/utils/sdp.d.ts.map +1 -1
- package/dist/src/private-to-public/utils/sdp.js +17 -10
- package/dist/src/private-to-public/utils/sdp.js.map +1 -1
- package/dist/src/rtcpeerconnection-to-conn.d.ts.map +1 -1
- package/dist/src/rtcpeerconnection-to-conn.js +3 -0
- package/dist/src/rtcpeerconnection-to-conn.js.map +1 -1
- package/dist/src/stream.d.ts +3 -2
- package/dist/src/stream.d.ts.map +1 -1
- package/dist/src/stream.js +100 -68
- package/dist/src/stream.js.map +1 -1
- package/package.json +12 -12
- package/src/constants.ts +5 -10
- package/src/index.ts +9 -0
- package/src/muxer.ts +6 -13
- package/src/private-to-private/initiate-connection.ts +20 -4
- package/src/private-to-private/signaling-stream-handler.ts +12 -2
- package/src/private-to-private/util.ts +12 -12
- package/src/private-to-public/listener.ts +21 -14
- package/src/private-to-public/transport.ts +2 -1
- package/src/private-to-public/utils/sdp.ts +21 -10
- package/src/rtcpeerconnection-to-conn.ts +4 -0
- package/src/stream.ts +115 -79
package/src/muxer.ts
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import { AbstractStreamMuxer } from '@libp2p/utils'
|
2
|
-
import { pEvent } from 'p-event'
|
3
2
|
import { MUXER_PROTOCOL } from './constants.js'
|
4
3
|
import { createStream, WebRTCStream } from './stream.js'
|
5
4
|
import type { DataChannelOptions } from './index.js'
|
@@ -90,11 +89,12 @@ export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implemen
|
|
90
89
|
* {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/datachannel_event}
|
91
90
|
*/
|
92
91
|
this.peerConnection.ondatachannel = ({ channel }) => {
|
93
|
-
this.log.trace('incoming %s datachannel with channel id %d and status', channel.protocol, channel.id, channel.readyState)
|
92
|
+
this.log.trace('incoming %s datachannel with channel id %d, protocol %s and status %s', channel.protocol, channel.id, channel.protocol, channel.readyState)
|
94
93
|
|
95
|
-
// 'init' channel is only used during connection establishment
|
94
|
+
// 'init' channel is only used during connection establishment, it is
|
95
|
+
// closed by the initiator
|
96
96
|
if (channel.label === 'init') {
|
97
|
-
this.log.trace('closing init channel')
|
97
|
+
this.log.trace('closing init channel %d', channel.id)
|
98
98
|
channel.close()
|
99
99
|
|
100
100
|
return
|
@@ -114,20 +114,13 @@ export class DataChannelMuxer extends AbstractStreamMuxer<WebRTCStream> implemen
|
|
114
114
|
|
115
115
|
async onCreateStream (options?: CreateStreamOptions): Promise<WebRTCStream> {
|
116
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('
|
117
|
+
const channel = this.peerConnection.createDataChannel('', {
|
118
118
|
// TODO: pre-negotiate stream protocol
|
119
|
-
protocol: options?.protocol
|
119
|
+
// protocol: options?.protocol
|
120
120
|
})
|
121
121
|
|
122
122
|
this.log('open channel %d for protocol %s', channel.id, options?.protocol)
|
123
123
|
|
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)
|
127
|
-
|
128
|
-
this.log('channel %d state is now "%s", sending data', channel.id, channel.readyState)
|
129
|
-
}
|
130
|
-
|
131
124
|
const stream = createStream({
|
132
125
|
...options,
|
133
126
|
...this.dataChannelOptions,
|
@@ -10,9 +10,9 @@ import { splitAddr } from './transport.js'
|
|
10
10
|
import { readCandidatesUntilConnected } from './util.js'
|
11
11
|
import type { WebRTCDialEvents, WebRTCTransportMetrics } from './transport.js'
|
12
12
|
import type { DataChannelOptions } from '../index.js'
|
13
|
-
import type { LoggerOptions, Connection, ComponentLogger } from '@libp2p/interface'
|
13
|
+
import type { LoggerOptions, Connection, ComponentLogger, AbortOptions } from '@libp2p/interface'
|
14
14
|
import type { ConnectionManager, TransportManager } from '@libp2p/interface-internal'
|
15
|
-
import type {
|
15
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
16
16
|
import type { ProgressOptions } from 'progress-events'
|
17
17
|
|
18
18
|
export interface IncomingStreamOptions extends AbortOptions {
|
@@ -94,10 +94,20 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
94
94
|
|
95
95
|
// setup callback to write ICE candidates to the remote peer
|
96
96
|
peerConnection.onicecandidate = ({ candidate }) => {
|
97
|
+
if (peerConnection.connectionState === 'connected') {
|
98
|
+
log.trace('ignore new ice candidate as peer connection is already connected')
|
99
|
+
return
|
100
|
+
}
|
101
|
+
|
97
102
|
// a null candidate means end-of-candidates, an empty string candidate
|
98
103
|
// means end-of-candidates for this generation, otherwise this should
|
99
104
|
// be a valid candidate object
|
100
105
|
// see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
|
106
|
+
if (candidate == null || candidate?.candidate === '') {
|
107
|
+
log.trace('initiator detected end of ICE candidates')
|
108
|
+
return
|
109
|
+
}
|
110
|
+
|
101
111
|
const data = JSON.stringify(candidate?.toJSON() ?? null)
|
102
112
|
|
103
113
|
log.trace('initiator sending ICE candidate %o', candidate)
|
@@ -178,10 +188,16 @@ export async function initiateConnection ({ rtcConfiguration, dataChannel, signa
|
|
178
188
|
})
|
179
189
|
}
|
180
190
|
|
181
|
-
log.trace('closing init channel
|
182
|
-
|
191
|
+
log.trace('closing init channel')
|
183
192
|
channel.close()
|
184
193
|
|
194
|
+
// wait for init channel to close before proceeding, otherwise the channel
|
195
|
+
// id can be reused before both sides have seen the channel close
|
196
|
+
log.trace('waiting for init channel to close')
|
197
|
+
await pEvent(channel, 'close', {
|
198
|
+
signal
|
199
|
+
})
|
200
|
+
|
185
201
|
onProgress?.(new CustomProgressEvent('webrtc:close-signaling-stream'))
|
186
202
|
|
187
203
|
log.trace('closing signaling channel')
|
@@ -3,7 +3,7 @@ import { multiaddr } from '@multiformats/multiaddr'
|
|
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 {
|
6
|
+
import { getRemotePeer, readCandidatesUntilConnected } from './util.js'
|
7
7
|
import type { RTCPeerConnection } from '../webrtc/index.js'
|
8
8
|
import type { AbortOptions, Connection, Logger, PeerId, Stream } from '@libp2p/interface'
|
9
9
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
@@ -21,10 +21,20 @@ export async function handleIncomingStream (stream: Stream, connection: Connecti
|
|
21
21
|
try {
|
22
22
|
// candidate callbacks
|
23
23
|
peerConnection.onicecandidate = ({ candidate }) => {
|
24
|
+
if (peerConnection.connectionState === 'connected') {
|
25
|
+
log.trace('ignore new ice candidate as peer connection is already connected')
|
26
|
+
return
|
27
|
+
}
|
28
|
+
|
24
29
|
// a null candidate means end-of-candidates, an empty string candidate
|
25
30
|
// means end-of-candidates for this generation, otherwise this should
|
26
31
|
// be a valid candidate object
|
27
32
|
// see - https://www.w3.org/TR/webrtc/#rtcpeerconnectioniceevent
|
33
|
+
if (candidate == null || candidate?.candidate === '') {
|
34
|
+
log.trace('recipient detected end of ICE candidates')
|
35
|
+
return
|
36
|
+
}
|
37
|
+
|
28
38
|
const data = JSON.stringify(candidate?.toJSON() ?? null)
|
29
39
|
|
30
40
|
log.trace('recipient sending ICE candidate %s', data)
|
@@ -90,7 +100,7 @@ export async function handleIncomingStream (stream: Stream, connection: Connecti
|
|
90
100
|
log
|
91
101
|
})
|
92
102
|
} catch (err: any) {
|
93
|
-
if (
|
103
|
+
if (peerConnection.connectionState !== 'connected') {
|
94
104
|
log.error('error while handling signaling stream from peer %a', connection.remoteAddr, err)
|
95
105
|
|
96
106
|
peerConnection.close()
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import { ConnectionFailedError, InvalidMessageError, InvalidMultiaddrError } from '@libp2p/interface'
|
2
2
|
import { peerIdFromString } from '@libp2p/peer-id'
|
3
3
|
import { CustomProgressEvent } from 'progress-events'
|
4
|
-
import { isFirefox } from '../util.js'
|
5
4
|
import { RTCIceCandidate } from '../webrtc/index.js'
|
6
5
|
import { Message } from './pb/message.js'
|
7
6
|
import type { WebRTCDialEvents } from './transport.js'
|
@@ -28,7 +27,7 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
|
|
28
27
|
connectedPromise.promise,
|
29
28
|
stream.read({
|
30
29
|
signal: options.signal
|
31
|
-
})
|
30
|
+
})
|
32
31
|
])
|
33
32
|
|
34
33
|
// stream ended or we became connected
|
@@ -63,32 +62,33 @@ export const readCandidatesUntilConnected = async (pc: RTCPeerConnection, stream
|
|
63
62
|
options.onProgress?.(new CustomProgressEvent<string>('webrtc:add-ice-candidate', candidate.candidate))
|
64
63
|
await pc.addIceCandidate(candidate)
|
65
64
|
} catch (err) {
|
66
|
-
options.log.error('%s bad candidate received', options.direction, candidateInit, err)
|
65
|
+
options.log.error('%s bad candidate received %o - %e', options.direction, candidateInit, err)
|
67
66
|
}
|
68
67
|
}
|
69
68
|
} catch (err) {
|
70
|
-
options.log.error('%s error parsing ICE candidate', options.direction, err)
|
69
|
+
options.log.error('%s error parsing ICE candidate - %e', options.direction, err)
|
71
70
|
|
72
|
-
if (options.signal?.aborted === true &&
|
71
|
+
if (options.signal?.aborted === true && pc.connectionState !== 'connected') {
|
73
72
|
throw err
|
74
73
|
}
|
75
74
|
}
|
76
75
|
}
|
77
76
|
|
78
|
-
export function getConnectionState (pc: RTCPeerConnection): string {
|
79
|
-
return isFirefox ? pc.iceConnectionState : pc.connectionState
|
80
|
-
}
|
81
|
-
|
82
77
|
function resolveOnConnected (pc: RTCPeerConnection, promise: DeferredPromise<void>): void {
|
83
|
-
pc
|
84
|
-
|
78
|
+
if (pc.connectionState === 'connected') {
|
79
|
+
promise.resolve()
|
80
|
+
return
|
81
|
+
}
|
82
|
+
|
83
|
+
pc.onconnectionstatechange = (_) => {
|
84
|
+
switch (pc.connectionState) {
|
85
85
|
case 'connected':
|
86
86
|
promise.resolve()
|
87
87
|
break
|
88
88
|
case 'failed':
|
89
89
|
case 'disconnected':
|
90
90
|
case 'closed':
|
91
|
-
promise.reject(new ConnectionFailedError(
|
91
|
+
promise.reject(new ConnectionFailedError(`RTCPeerConnection connection state became "${pc.connectionState}"`))
|
92
92
|
break
|
93
93
|
default:
|
94
94
|
break
|
@@ -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'
|
4
|
-
import {
|
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,
|
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 &&
|
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,
|
125
|
+
udpMuxServer = this.startUDPMuxServer(host, port, type === 'ip4' ? 4 : 6)
|
123
126
|
UDP_MUX_LISTENERS.push(udpMuxServer)
|
124
127
|
}
|
125
128
|
|
126
|
-
if (
|
129
|
+
if (type === 'ip4') {
|
127
130
|
udpMuxServer.isIPv4 = true
|
128
|
-
} else if (
|
131
|
+
} else if (type === 'ip6') {
|
129
132
|
udpMuxServer.isIPv6 = true
|
130
133
|
}
|
131
134
|
|
@@ -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
|
244
|
+
const components = ma.getComponents()
|
242
245
|
|
243
|
-
for (let j = 0; j <
|
244
|
-
if (
|
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 (
|
251
|
-
|
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 =
|
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.
|
168
|
+
const remotePeerString = ma.getComponents().findLast(c => c.code === CODE_P2P)?.value
|
168
169
|
if (remotePeerString != null) {
|
169
170
|
theirPeerId = peerIdFromString(remotePeerString)
|
170
171
|
}
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import { InvalidParametersError } from '@libp2p/interface'
|
2
|
-
import {
|
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 {
|
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
|
31
|
-
const certhash =
|
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,
|
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${
|
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${
|
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,
|
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${
|
147
|
+
o=- 0 0 IN IP${type === 'ip4' ? 4 : 6} ${host}
|
137
148
|
s=-
|
138
|
-
c=IN IP${
|
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
|
@@ -24,6 +24,10 @@ class RTCPeerConnectionMultiaddrConnection extends AbstractMultiaddrConnection {
|
|
24
24
|
if (this.peerConnection.connectionState === 'disconnected' || this.peerConnection.connectionState === 'failed' || this.peerConnection.connectionState === 'closed') {
|
25
25
|
// nothing else to do but close the connection
|
26
26
|
this.onTransportClosed()
|
27
|
+
|
28
|
+
// only necessary with node-datachannel
|
29
|
+
// https://github.com/murat-dogan/node-datachannel/issues/366#issuecomment-3228453155
|
30
|
+
this.peerConnection.close()
|
27
31
|
}
|
28
32
|
}
|
29
33
|
}
|