@libp2p/webrtc 3.0.0 → 3.1.0-c858ca7f
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 -18
- package/dist/src/private-to-private/handler.d.ts +1 -0
- package/dist/src/private-to-private/handler.d.ts.map +1 -1
- package/dist/src/private-to-private/handler.js +102 -85
- package/dist/src/private-to-private/handler.js.map +1 -1
- package/dist/src/private-to-private/transport.d.ts.map +1 -1
- package/dist/src/private-to-private/transport.js +2 -0
- package/dist/src/private-to-private/transport.js.map +1 -1
- package/dist/src/private-to-private/util.d.ts.map +1 -1
- package/dist/src/private-to-private/util.js +1 -0
- package/dist/src/private-to-private/util.js.map +1 -1
- package/dist/src/private-to-public/transport.d.ts.map +1 -1
- package/dist/src/private-to-public/transport.js +98 -91
- package/dist/src/private-to-public/transport.js.map +1 -1
- package/dist/src/webrtc/index.browser.d.ts +15 -0
- package/dist/src/webrtc/index.browser.d.ts.map +1 -0
- package/dist/src/webrtc/index.browser.js +5 -0
- package/dist/src/webrtc/index.browser.js.map +1 -0
- package/dist/src/webrtc/index.d.ts +8 -0
- package/dist/src/webrtc/index.d.ts.map +1 -0
- package/dist/src/webrtc/index.js +11 -0
- package/dist/src/webrtc/index.js.map +1 -0
- package/dist/src/webrtc/rtc-data-channel.d.ts +29 -0
- package/dist/src/webrtc/rtc-data-channel.d.ts.map +1 -0
- package/dist/src/webrtc/rtc-data-channel.js +115 -0
- package/dist/src/webrtc/rtc-data-channel.js.map +1 -0
- package/dist/src/webrtc/rtc-events.d.ts +9 -0
- package/dist/src/webrtc/rtc-events.d.ts.map +1 -0
- package/dist/src/webrtc/rtc-events.js +15 -0
- package/dist/src/webrtc/rtc-events.js.map +1 -0
- package/dist/src/webrtc/rtc-ice-candidate.d.ts +22 -0
- package/dist/src/webrtc/rtc-ice-candidate.d.ts.map +1 -0
- package/dist/src/webrtc/rtc-ice-candidate.js +47 -0
- package/dist/src/webrtc/rtc-ice-candidate.js.map +1 -0
- package/dist/src/webrtc/rtc-peer-connection.d.ts +47 -0
- package/dist/src/webrtc/rtc-peer-connection.d.ts.map +1 -0
- package/dist/src/webrtc/rtc-peer-connection.js +245 -0
- package/dist/src/webrtc/rtc-peer-connection.js.map +1 -0
- package/dist/src/webrtc/rtc-session-description.d.ts +10 -0
- package/dist/src/webrtc/rtc-session-description.d.ts.map +1 -0
- package/dist/src/webrtc/rtc-session-description.js +18 -0
- package/dist/src/webrtc/rtc-session-description.js.map +1 -0
- package/package.json +15 -10
- package/src/private-to-private/handler.ts +120 -102
- package/src/private-to-private/transport.ts +2 -0
- package/src/private-to-private/util.ts +1 -0
- package/src/private-to-public/transport.ts +109 -103
- package/src/webrtc/index.browser.ts +4 -0
- package/src/webrtc/index.ts +12 -0
- package/src/webrtc/rtc-data-channel.ts +140 -0
- package/src/webrtc/rtc-events.ts +19 -0
- package/src/webrtc/rtc-ice-candidate.ts +50 -0
- package/src/webrtc/rtc-peer-connection.ts +306 -0
- package/src/webrtc/rtc-session-description.ts +19 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtc-peer-connection.js","sourceRoot":"","sources":["../../../src/webrtc/rtc-peer-connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://developer.mozilla.org/docs/Web/API/RTCSessionDescription
|
|
3
|
+
*/
|
|
4
|
+
export declare class SessionDescription implements RTCSessionDescription {
|
|
5
|
+
readonly sdp: string;
|
|
6
|
+
readonly type: RTCSdpType;
|
|
7
|
+
constructor(init: RTCSessionDescriptionInit);
|
|
8
|
+
toJSON(): RTCSessionDescriptionInit;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=rtc-session-description.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtc-session-description.d.ts","sourceRoot":"","sources":["../../../src/webrtc/rtc-session-description.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,kBAAmB,YAAW,qBAAqB;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;gBAEZ,IAAI,EAAE,yBAAyB;IAK5C,MAAM,IAAK,yBAAyB;CAMrC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @see https://developer.mozilla.org/docs/Web/API/RTCSessionDescription
|
|
3
|
+
*/
|
|
4
|
+
export class SessionDescription {
|
|
5
|
+
sdp;
|
|
6
|
+
type;
|
|
7
|
+
constructor(init) {
|
|
8
|
+
this.sdp = init.sdp ?? '';
|
|
9
|
+
this.type = init.type;
|
|
10
|
+
}
|
|
11
|
+
toJSON() {
|
|
12
|
+
return {
|
|
13
|
+
sdp: this.sdp,
|
|
14
|
+
type: this.type
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=rtc-session-description.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtc-session-description.js","sourceRoot":"","sources":["../../../src/webrtc/rtc-session-description.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACpB,GAAG,CAAQ;IACX,IAAI,CAAY;IAEzB,YAAa,IAA+B;QAC1C,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,EAAE,CAAA;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAA;IACvB,CAAC;IAED,MAAM;QACJ,OAAO;YACL,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,IAAI,CAAC,IAAI;SAChB,CAAA;IACH,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libp2p/webrtc",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.1.0-c858ca7f",
|
|
4
4
|
"description": "A libp2p transport using WebRTC connections",
|
|
5
5
|
"author": "",
|
|
6
6
|
"license": "Apache-2.0 OR MIT",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"scripts": {
|
|
36
36
|
"generate": "protons src/private-to-private/pb/message.proto src/pb/message.proto",
|
|
37
37
|
"build": "aegir build",
|
|
38
|
-
"test": "aegir test -t browser",
|
|
38
|
+
"test": "aegir test -t node -t browser -t electron-main",
|
|
39
|
+
"test:node": "aegir test -t node --cov",
|
|
39
40
|
"test:chrome": "aegir test -t browser --cov",
|
|
40
41
|
"test:firefox": "aegir test -t browser -- --browser firefox",
|
|
41
42
|
"lint": "aegir lint",
|
|
@@ -45,10 +46,10 @@
|
|
|
45
46
|
},
|
|
46
47
|
"dependencies": {
|
|
47
48
|
"@chainsafe/libp2p-noise": "^12.0.0",
|
|
48
|
-
"@libp2p/interface": "
|
|
49
|
-
"@libp2p/interface-internal": "
|
|
50
|
-
"@libp2p/logger": "
|
|
51
|
-
"@libp2p/peer-id": "
|
|
49
|
+
"@libp2p/interface": "0.1.0-c858ca7f",
|
|
50
|
+
"@libp2p/interface-internal": "0.1.0-c858ca7f",
|
|
51
|
+
"@libp2p/logger": "3.0.0-c858ca7f",
|
|
52
|
+
"@libp2p/peer-id": "3.0.0-c858ca7f",
|
|
52
53
|
"@multiformats/mafmt": "^12.1.2",
|
|
53
54
|
"@multiformats/multiaddr": "^12.1.3",
|
|
54
55
|
"abortable-iterator": "^5.0.1",
|
|
@@ -61,6 +62,7 @@
|
|
|
61
62
|
"it-to-buffer": "^4.0.2",
|
|
62
63
|
"multiformats": "^12.0.1",
|
|
63
64
|
"multihashes": "^4.0.3",
|
|
65
|
+
"node-datachannel": "^0.4.3",
|
|
64
66
|
"p-defer": "^4.0.0",
|
|
65
67
|
"p-event": "^6.0.0",
|
|
66
68
|
"protons-runtime": "^5.0.0",
|
|
@@ -69,18 +71,21 @@
|
|
|
69
71
|
},
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"@chainsafe/libp2p-yamux": "^4.0.0",
|
|
72
|
-
"@libp2p/interface-compliance-tests": "
|
|
73
|
-
"@libp2p/peer-id-factory": "
|
|
74
|
-
"@libp2p/websockets": "
|
|
74
|
+
"@libp2p/interface-compliance-tests": "4.0.0-c858ca7f",
|
|
75
|
+
"@libp2p/peer-id-factory": "3.0.0-c858ca7f",
|
|
76
|
+
"@libp2p/websockets": "7.0.0-c858ca7f",
|
|
75
77
|
"@types/sinon": "^10.0.15",
|
|
76
78
|
"aegir": "^40.0.1",
|
|
77
79
|
"delay": "^6.0.0",
|
|
78
80
|
"it-length": "^3.0.2",
|
|
79
81
|
"it-map": "^3.0.3",
|
|
80
82
|
"it-pair": "^2.0.6",
|
|
81
|
-
"libp2p": "
|
|
83
|
+
"libp2p": "0.46.0-c858ca7f",
|
|
82
84
|
"protons": "^7.0.2",
|
|
83
85
|
"sinon": "^15.1.2",
|
|
84
86
|
"sinon-ts": "^1.0.0"
|
|
87
|
+
},
|
|
88
|
+
"browser": {
|
|
89
|
+
"./dist/src/webrtc/index.js": "./dist/src/webrtc/index.browser.js"
|
|
85
90
|
}
|
|
86
91
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { CodeError } from '@libp2p/interface/errors'
|
|
1
2
|
import { logger } from '@libp2p/logger'
|
|
2
3
|
import { abortableDuplex } from 'abortable-iterator'
|
|
3
4
|
import { pbStream } from 'it-protobuf-stream'
|
|
4
5
|
import pDefer, { type DeferredPromise } from 'p-defer'
|
|
5
6
|
import { DataChannelMuxerFactory } from '../muxer.js'
|
|
7
|
+
import { RTCPeerConnection, RTCSessionDescription } from '../webrtc/index.js'
|
|
6
8
|
import { Message } from './pb/message.js'
|
|
7
9
|
import { readCandidatesUntilConnected, resolveOnConnected } from './util.js'
|
|
8
10
|
import type { DataChannelOpts } from '../stream.js'
|
|
@@ -20,66 +22,75 @@ export async function handleIncomingStream ({ rtcConfiguration, dataChannelOptio
|
|
|
20
22
|
const signal = AbortSignal.timeout(DEFAULT_TIMEOUT)
|
|
21
23
|
const stream = pbStream(abortableDuplex(rawStream, signal)).pb(Message)
|
|
22
24
|
const pc = new RTCPeerConnection(rtcConfiguration)
|
|
23
|
-
const muxerFactory = new DataChannelMuxerFactory({ peerConnection: pc, dataChannelOptions })
|
|
24
|
-
const connectedPromise: DeferredPromise<void> = pDefer()
|
|
25
|
-
const answerSentPromise: DeferredPromise<void> = pDefer()
|
|
26
|
-
|
|
27
|
-
signal.onabort = () => { connectedPromise.reject() }
|
|
28
|
-
// candidate callbacks
|
|
29
|
-
pc.onicecandidate = ({ candidate }) => {
|
|
30
|
-
answerSentPromise.promise.then(
|
|
31
|
-
async () => {
|
|
32
|
-
await stream.write({
|
|
33
|
-
type: Message.Type.ICE_CANDIDATE,
|
|
34
|
-
data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : ''
|
|
35
|
-
})
|
|
36
|
-
},
|
|
37
|
-
(err) => {
|
|
38
|
-
log.error('cannot set candidate since sending answer failed', err)
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
25
|
|
|
43
|
-
|
|
26
|
+
try {
|
|
27
|
+
const muxerFactory = new DataChannelMuxerFactory({ peerConnection: pc, dataChannelOptions })
|
|
28
|
+
const connectedPromise: DeferredPromise<void> = pDefer()
|
|
29
|
+
const answerSentPromise: DeferredPromise<void> = pDefer()
|
|
30
|
+
|
|
31
|
+
signal.onabort = () => {
|
|
32
|
+
connectedPromise.reject(new CodeError('Timed out while trying to connect', 'ERR_TIMEOUT'))
|
|
33
|
+
}
|
|
34
|
+
// candidate callbacks
|
|
35
|
+
pc.onicecandidate = ({ candidate }) => {
|
|
36
|
+
answerSentPromise.promise.then(
|
|
37
|
+
async () => {
|
|
38
|
+
await stream.write({
|
|
39
|
+
type: Message.Type.ICE_CANDIDATE,
|
|
40
|
+
data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : ''
|
|
41
|
+
})
|
|
42
|
+
},
|
|
43
|
+
(err) => {
|
|
44
|
+
log.error('cannot set candidate since sending answer failed', err)
|
|
45
|
+
connectedPromise.reject(err)
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
resolveOnConnected(pc, connectedPromise)
|
|
51
|
+
|
|
52
|
+
// read an SDP offer
|
|
53
|
+
const pbOffer = await stream.read()
|
|
54
|
+
if (pbOffer.type !== Message.Type.SDP_OFFER) {
|
|
55
|
+
throw new Error(`expected message type SDP_OFFER, received: ${pbOffer.type ?? 'undefined'} `)
|
|
56
|
+
}
|
|
57
|
+
const offer = new RTCSessionDescription({
|
|
58
|
+
type: 'offer',
|
|
59
|
+
sdp: pbOffer.data
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
await pc.setRemoteDescription(offer).catch(err => {
|
|
63
|
+
log.error('could not execute setRemoteDescription', err)
|
|
64
|
+
throw new Error('Failed to set remoteDescription')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// create and write an SDP answer
|
|
68
|
+
const answer = await pc.createAnswer().catch(err => {
|
|
69
|
+
log.error('could not execute createAnswer', err)
|
|
70
|
+
answerSentPromise.reject(err)
|
|
71
|
+
throw new Error('Failed to create answer')
|
|
72
|
+
})
|
|
73
|
+
// write the answer to the remote
|
|
74
|
+
await stream.write({ type: Message.Type.SDP_ANSWER, data: answer.sdp })
|
|
75
|
+
|
|
76
|
+
await pc.setLocalDescription(answer).catch(err => {
|
|
77
|
+
log.error('could not execute setLocalDescription', err)
|
|
78
|
+
answerSentPromise.reject(err)
|
|
79
|
+
throw new Error('Failed to set localDescription')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
answerSentPromise.resolve()
|
|
83
|
+
|
|
84
|
+
// wait until candidates are connected
|
|
85
|
+
await readCandidatesUntilConnected(connectedPromise, pc, stream)
|
|
44
86
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
87
|
+
const remoteAddress = parseRemoteAddress(pc.currentRemoteDescription?.sdp ?? '')
|
|
88
|
+
|
|
89
|
+
return { pc, muxerFactory, remoteAddress }
|
|
90
|
+
} catch (err) {
|
|
91
|
+
pc.close()
|
|
92
|
+
throw err
|
|
49
93
|
}
|
|
50
|
-
const offer = new RTCSessionDescription({
|
|
51
|
-
type: 'offer',
|
|
52
|
-
sdp: pbOffer.data
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
await pc.setRemoteDescription(offer).catch(err => {
|
|
56
|
-
log.error('could not execute setRemoteDescription', err)
|
|
57
|
-
throw new Error('Failed to set remoteDescription')
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
// create and write an SDP answer
|
|
61
|
-
const answer = await pc.createAnswer().catch(err => {
|
|
62
|
-
log.error('could not execute createAnswer', err)
|
|
63
|
-
answerSentPromise.reject(err)
|
|
64
|
-
throw new Error('Failed to create answer')
|
|
65
|
-
})
|
|
66
|
-
// write the answer to the remote
|
|
67
|
-
await stream.write({ type: Message.Type.SDP_ANSWER, data: answer.sdp })
|
|
68
|
-
|
|
69
|
-
await pc.setLocalDescription(answer).catch(err => {
|
|
70
|
-
log.error('could not execute setLocalDescription', err)
|
|
71
|
-
answerSentPromise.reject(err)
|
|
72
|
-
throw new Error('Failed to set localDescription')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
answerSentPromise.resolve()
|
|
76
|
-
|
|
77
|
-
// wait until candidates are connected
|
|
78
|
-
await readCandidatesUntilConnected(connectedPromise, pc, stream)
|
|
79
|
-
|
|
80
|
-
const remoteAddress = parseRemoteAddress(pc.currentRemoteDescription?.sdp ?? '')
|
|
81
|
-
|
|
82
|
-
return { pc, muxerFactory, remoteAddress }
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
export interface ConnectOptions {
|
|
@@ -93,56 +104,63 @@ export async function initiateConnection ({ rtcConfiguration, dataChannelOptions
|
|
|
93
104
|
const stream = pbStream(abortableDuplex(rawStream, signal)).pb(Message)
|
|
94
105
|
// setup peer connection
|
|
95
106
|
const pc = new RTCPeerConnection(rtcConfiguration)
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
log.error('error sending ICE candidate', err)
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
const muxerFactory = new DataChannelMuxerFactory({ peerConnection: pc, dataChannelOptions })
|
|
110
|
+
|
|
111
|
+
const connectedPromise: DeferredPromise<void> = pDefer()
|
|
112
|
+
resolveOnConnected(pc, connectedPromise)
|
|
113
|
+
|
|
114
|
+
// reject the connectedPromise if the signal aborts
|
|
115
|
+
signal.onabort = connectedPromise.reject
|
|
116
|
+
// we create the channel so that the peerconnection has a component for which
|
|
117
|
+
// to collect candidates. The label is not relevant to connection initiation
|
|
118
|
+
// but can be useful for debugging
|
|
119
|
+
const channel = pc.createDataChannel('init')
|
|
120
|
+
// setup callback to write ICE candidates to the remote
|
|
121
|
+
// peer
|
|
122
|
+
pc.onicecandidate = ({ candidate }) => {
|
|
123
|
+
void stream.write({
|
|
124
|
+
type: Message.Type.ICE_CANDIDATE,
|
|
125
|
+
data: (candidate != null) ? JSON.stringify(candidate.toJSON()) : ''
|
|
116
126
|
})
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
throw new Error('remote should send an SDP answer')
|
|
132
|
-
}
|
|
127
|
+
.catch(err => {
|
|
128
|
+
log.error('error sending ICE candidate', err)
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// create an offer
|
|
133
|
+
const offerSdp = await pc.createOffer()
|
|
134
|
+
// write the offer to the stream
|
|
135
|
+
await stream.write({ type: Message.Type.SDP_OFFER, data: offerSdp.sdp })
|
|
136
|
+
// set offer as local description
|
|
137
|
+
await pc.setLocalDescription(offerSdp).catch(err => {
|
|
138
|
+
log.error('could not execute setLocalDescription', err)
|
|
139
|
+
throw new Error('Failed to set localDescription')
|
|
140
|
+
})
|
|
133
141
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
142
|
+
// read answer
|
|
143
|
+
const answerMessage = await stream.read()
|
|
144
|
+
if (answerMessage.type !== Message.Type.SDP_ANSWER) {
|
|
145
|
+
throw new Error('remote should send an SDP answer')
|
|
146
|
+
}
|
|
139
147
|
|
|
140
|
-
|
|
141
|
-
|
|
148
|
+
const answerSdp = new RTCSessionDescription({ type: 'answer', sdp: answerMessage.data })
|
|
149
|
+
await pc.setRemoteDescription(answerSdp).catch(err => {
|
|
150
|
+
log.error('could not execute setRemoteDescription', err)
|
|
151
|
+
throw new Error('Failed to set remoteDescription')
|
|
152
|
+
})
|
|
142
153
|
|
|
143
|
-
|
|
154
|
+
await readCandidatesUntilConnected(connectedPromise, pc, stream)
|
|
155
|
+
channel.close()
|
|
144
156
|
|
|
145
|
-
|
|
157
|
+
const remoteAddress = parseRemoteAddress(pc.currentRemoteDescription?.sdp ?? '')
|
|
158
|
+
|
|
159
|
+
return { pc, muxerFactory, remoteAddress }
|
|
160
|
+
} catch (err) {
|
|
161
|
+
pc.close()
|
|
162
|
+
throw err
|
|
163
|
+
}
|
|
146
164
|
}
|
|
147
165
|
|
|
148
166
|
function parseRemoteAddress (sdp: string): string {
|
|
@@ -5,6 +5,7 @@ import { peerIdFromString } from '@libp2p/peer-id'
|
|
|
5
5
|
import { multiaddr, type Multiaddr, protocols } from '@multiformats/multiaddr'
|
|
6
6
|
import { codes } from '../error.js'
|
|
7
7
|
import { WebRTCMultiaddrConnection } from '../maconn.js'
|
|
8
|
+
import { cleanup } from '../webrtc/index.js'
|
|
8
9
|
import { initiateConnection, handleIncomingStream } from './handler.js'
|
|
9
10
|
import { WebRTCPeerListener } from './listener.js'
|
|
10
11
|
import type { DataChannelOpts } from '../stream.js'
|
|
@@ -57,6 +58,7 @@ export class WebRTCTransport implements Transport, Startable {
|
|
|
57
58
|
|
|
58
59
|
async stop (): Promise<void> {
|
|
59
60
|
await this.components.registrar.unhandle(SIGNALING_PROTO_ID)
|
|
61
|
+
cleanup()
|
|
60
62
|
this._started = false
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -11,6 +11,7 @@ import { WebRTCMultiaddrConnection } from '../maconn.js'
|
|
|
11
11
|
import { DataChannelMuxerFactory } from '../muxer.js'
|
|
12
12
|
import { createStream } from '../stream.js'
|
|
13
13
|
import { isFirefox } from '../util.js'
|
|
14
|
+
import { RTCPeerConnection } from '../webrtc/index.js'
|
|
14
15
|
import * as sdp from './sdp.js'
|
|
15
16
|
import { genUfrag } from './util.js'
|
|
16
17
|
import type { WebRTCDialOptions } from './options.js'
|
|
@@ -134,116 +135,121 @@ export class WebRTCDirectTransport implements Transport {
|
|
|
134
135
|
|
|
135
136
|
const peerConnection = new RTCPeerConnection({ certificates: [certificate] })
|
|
136
137
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// ref: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/error_event
|
|
155
|
-
handshakeDataChannel.onerror = (event: Event) => {
|
|
156
|
-
clearTimeout(handshakeTimeout)
|
|
157
|
-
const errorTarget = event.target?.toString() ?? 'not specified'
|
|
158
|
-
const error = `Error opening a data channel for handshaking: ${errorTarget}`
|
|
159
|
-
log.error(error)
|
|
160
|
-
// NOTE: We use unknown error here but this could potentially be considered a reset by some standards.
|
|
161
|
-
this.metrics?.dialerEvents.increment({ unknown_error: true })
|
|
162
|
-
reject(dataChannelError('data', error))
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
const ufrag = 'libp2p+webrtc+v1/' + genUfrag(32)
|
|
167
|
-
|
|
168
|
-
// Create offer and munge sdp with ufrag == pwd. This allows the remote to
|
|
169
|
-
// respond to STUN messages without performing an actual SDP exchange.
|
|
170
|
-
// This is because it can infer the passwd field by reading the USERNAME
|
|
171
|
-
// attribute of the STUN message.
|
|
172
|
-
const offerSdp = await peerConnection.createOffer()
|
|
173
|
-
const mungedOfferSdp = sdp.munge(offerSdp, ufrag)
|
|
174
|
-
await peerConnection.setLocalDescription(mungedOfferSdp)
|
|
175
|
-
|
|
176
|
-
// construct answer sdp from multiaddr and ufrag
|
|
177
|
-
const answerSdp = sdp.fromMultiAddr(ma, ufrag)
|
|
178
|
-
await peerConnection.setRemoteDescription(answerSdp)
|
|
179
|
-
|
|
180
|
-
// wait for peerconnection.onopen to fire, or for the datachannel to open
|
|
181
|
-
const handshakeDataChannel = await dataChannelOpenPromise
|
|
182
|
-
|
|
183
|
-
const myPeerId = this.components.peerId
|
|
184
|
-
|
|
185
|
-
// Do noise handshake.
|
|
186
|
-
// Set the Noise Prologue to libp2p-webrtc-noise:<FINGERPRINTS> before starting the actual Noise handshake.
|
|
187
|
-
// <FINGERPRINTS> is the concatenation of the of the two TLS fingerprints of A and B in their multihash byte representation, sorted in ascending order.
|
|
188
|
-
const fingerprintsPrologue = this.generateNoisePrologue(peerConnection, remoteCerthash.code, ma)
|
|
189
|
-
|
|
190
|
-
// Since we use the default crypto interface and do not use a static key or early data,
|
|
191
|
-
// we pass in undefined for these parameters.
|
|
192
|
-
const noise = Noise({ prologueBytes: fingerprintsPrologue })()
|
|
193
|
-
|
|
194
|
-
const wrappedChannel = createStream({ channel: handshakeDataChannel, direction: 'inbound', dataChannelOptions: this.init.dataChannel })
|
|
195
|
-
const wrappedDuplex = {
|
|
196
|
-
...wrappedChannel,
|
|
197
|
-
sink: wrappedChannel.sink.bind(wrappedChannel),
|
|
198
|
-
source: (async function * () {
|
|
199
|
-
for await (const list of wrappedChannel.source) {
|
|
200
|
-
for (const buf of list) {
|
|
201
|
-
yield buf
|
|
202
|
-
}
|
|
138
|
+
try {
|
|
139
|
+
// create data channel for running the noise handshake. Once the data channel is opened,
|
|
140
|
+
// the remote will initiate the noise handshake. This is used to confirm the identity of
|
|
141
|
+
// the peer.
|
|
142
|
+
const dataChannelOpenPromise = new Promise<RTCDataChannel>((resolve, reject) => {
|
|
143
|
+
const handshakeDataChannel = peerConnection.createDataChannel('', { negotiated: true, id: 0 })
|
|
144
|
+
const handshakeTimeout = setTimeout(() => {
|
|
145
|
+
const error = `Data channel was never opened: state: ${handshakeDataChannel.readyState}`
|
|
146
|
+
log.error(error)
|
|
147
|
+
this.metrics?.dialerEvents.increment({ open_error: true })
|
|
148
|
+
reject(dataChannelError('data', error))
|
|
149
|
+
}, HANDSHAKE_TIMEOUT_MS)
|
|
150
|
+
|
|
151
|
+
handshakeDataChannel.onopen = (_) => {
|
|
152
|
+
clearTimeout(handshakeTimeout)
|
|
153
|
+
resolve(handshakeDataChannel)
|
|
203
154
|
}
|
|
204
|
-
}())
|
|
205
|
-
}
|
|
206
155
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
156
|
+
// ref: https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel/error_event
|
|
157
|
+
handshakeDataChannel.onerror = (event: Event) => {
|
|
158
|
+
clearTimeout(handshakeTimeout)
|
|
159
|
+
const errorTarget = event.target?.toString() ?? 'not specified'
|
|
160
|
+
const error = `Error opening a data channel for handshaking: ${errorTarget}`
|
|
161
|
+
log.error(error)
|
|
162
|
+
// NOTE: We use unknown error here but this could potentially be considered a reset by some standards.
|
|
163
|
+
this.metrics?.dialerEvents.increment({ unknown_error: true })
|
|
164
|
+
reject(dataChannelError('data', error))
|
|
165
|
+
}
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
const ufrag = 'libp2p+webrtc+v1/' + genUfrag(32)
|
|
169
|
+
|
|
170
|
+
// Create offer and munge sdp with ufrag == pwd. This allows the remote to
|
|
171
|
+
// respond to STUN messages without performing an actual SDP exchange.
|
|
172
|
+
// This is because it can infer the passwd field by reading the USERNAME
|
|
173
|
+
// attribute of the STUN message.
|
|
174
|
+
const offerSdp = await peerConnection.createOffer()
|
|
175
|
+
const mungedOfferSdp = sdp.munge(offerSdp, ufrag)
|
|
176
|
+
await peerConnection.setLocalDescription(mungedOfferSdp)
|
|
177
|
+
|
|
178
|
+
// construct answer sdp from multiaddr and ufrag
|
|
179
|
+
const answerSdp = sdp.fromMultiAddr(ma, ufrag)
|
|
180
|
+
await peerConnection.setRemoteDescription(answerSdp)
|
|
181
|
+
|
|
182
|
+
// wait for peerconnection.onopen to fire, or for the datachannel to open
|
|
183
|
+
const handshakeDataChannel = await dataChannelOpenPromise
|
|
184
|
+
|
|
185
|
+
const myPeerId = this.components.peerId
|
|
186
|
+
|
|
187
|
+
// Do noise handshake.
|
|
188
|
+
// Set the Noise Prologue to libp2p-webrtc-noise:<FINGERPRINTS> before starting the actual Noise handshake.
|
|
189
|
+
// <FINGERPRINTS> is the concatenation of the of the two TLS fingerprints of A and B in their multihash byte representation, sorted in ascending order.
|
|
190
|
+
const fingerprintsPrologue = this.generateNoisePrologue(peerConnection, remoteCerthash.code, ma)
|
|
191
|
+
|
|
192
|
+
// Since we use the default crypto interface and do not use a static key or early data,
|
|
193
|
+
// we pass in undefined for these parameters.
|
|
194
|
+
const noise = Noise({ prologueBytes: fingerprintsPrologue })()
|
|
195
|
+
|
|
196
|
+
const wrappedChannel = createStream({ channel: handshakeDataChannel, direction: 'inbound', dataChannelOptions: this.init.dataChannel })
|
|
197
|
+
const wrappedDuplex = {
|
|
198
|
+
...wrappedChannel,
|
|
199
|
+
sink: wrappedChannel.sink.bind(wrappedChannel),
|
|
200
|
+
source: (async function * () {
|
|
201
|
+
for await (const list of wrappedChannel.source) {
|
|
202
|
+
for (const buf of list) {
|
|
203
|
+
yield buf
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}())
|
|
234
207
|
}
|
|
235
|
-
}, { signal })
|
|
236
208
|
|
|
237
|
-
|
|
238
|
-
|
|
209
|
+
// Creating the connection before completion of the noise
|
|
210
|
+
// handshake ensures that the stream opening callback is set up
|
|
211
|
+
const maConn = new WebRTCMultiaddrConnection({
|
|
212
|
+
peerConnection,
|
|
213
|
+
remoteAddr: ma,
|
|
214
|
+
timeline: {
|
|
215
|
+
open: Date.now()
|
|
216
|
+
},
|
|
217
|
+
metrics: this.metrics?.dialerEvents
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
const eventListeningName = isFirefox ? 'iceconnectionstatechange' : 'connectionstatechange'
|
|
221
|
+
|
|
222
|
+
peerConnection.addEventListener(eventListeningName, () => {
|
|
223
|
+
switch (peerConnection.connectionState) {
|
|
224
|
+
case 'failed':
|
|
225
|
+
case 'disconnected':
|
|
226
|
+
case 'closed':
|
|
227
|
+
maConn.close().catch((err) => {
|
|
228
|
+
log.error('error closing connection', err)
|
|
229
|
+
}).finally(() => {
|
|
230
|
+
// Remove the event listener once the connection is closed
|
|
231
|
+
controller.abort()
|
|
232
|
+
})
|
|
233
|
+
break
|
|
234
|
+
default:
|
|
235
|
+
break
|
|
236
|
+
}
|
|
237
|
+
}, { signal })
|
|
239
238
|
|
|
240
|
-
|
|
239
|
+
// Track opened peer connection
|
|
240
|
+
this.metrics?.dialerEvents.increment({ peer_connection: true })
|
|
241
241
|
|
|
242
|
-
|
|
243
|
-
// Therefore, we need to secure an inbound noise connection from the remote.
|
|
244
|
-
await noise.secureInbound(myPeerId, wrappedDuplex, theirPeerId)
|
|
242
|
+
const muxerFactory = new DataChannelMuxerFactory({ peerConnection, metrics: this.metrics?.dialerEvents, dataChannelOptions: this.init.dataChannel })
|
|
245
243
|
|
|
246
|
-
|
|
244
|
+
// For outbound connections, the remote is expected to start the noise handshake.
|
|
245
|
+
// Therefore, we need to secure an inbound noise connection from the remote.
|
|
246
|
+
await noise.secureInbound(myPeerId, wrappedDuplex, theirPeerId)
|
|
247
|
+
|
|
248
|
+
return await options.upgrader.upgradeOutbound(maConn, { skipProtection: true, skipEncryption: true, muxerFactory })
|
|
249
|
+
} catch (err) {
|
|
250
|
+
peerConnection.close()
|
|
251
|
+
throw err
|
|
252
|
+
}
|
|
247
253
|
}
|
|
248
254
|
|
|
249
255
|
/**
|