@live-change/peer-connection-frontend 0.8.34 → 0.8.36
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/build-stats/ssr-srcentryserverjs-outDir-distserver.html +4842 -0
- package/build-stats/ssrManifest-outDir-distclient.html +4842 -0
- package/front/components.d.ts +20 -0
- package/front/public/images/cameraAccess/en.png +0 -0
- package/front/src/App.vue +42 -77
- package/front/src/components/Debugger.vue +68 -177
- package/front/src/components/DevicesSelect.vue +393 -0
- package/front/src/components/Peer.js +167 -252
- package/front/src/components/PeerConnection.js +296 -312
- package/front/src/components/PermissionsDialog.vue +146 -0
- package/front/src/components/mediaStreamsTracks.js +60 -0
- package/front/src/components/userMedia.js +2 -2
- package/front/src/entry-client.js +4 -22
- package/front/src/entry-server.js +5 -4
- package/front/src/router.js +18 -12
- package/front/vite.config.js +8 -107
- package/index.js +14 -0
- package/package-deps.json +41 -0
- package/package.json +21 -20
- package/server/app.config.js +114 -0
- package/server/init.js +10 -2
- package/server/security.config.js +53 -0
- package/server/services.list.js +50 -0
- package/server/start.js +37 -0
- package/server/services.config.js +0 -25
|
@@ -1,329 +1,313 @@
|
|
|
1
|
-
|
|
1
|
+
import { ref, isRef, onUnmounted, getCurrentInstance, unref, reactive, computed, watch } from 'vue'
|
|
2
|
+
import { path, live, actions, api as useApi, inboxReader } from '@live-change/vue3-ssr'
|
|
2
3
|
|
|
3
4
|
const createPeerConnection = (peer, to) => {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const { id, kind, label, muted } = track
|
|
36
|
-
return { id, kind, label, muted, stream: stream.id }
|
|
37
|
-
}),
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
localTracks() {
|
|
41
|
-
return peer.localTracks
|
|
42
|
-
},
|
|
43
|
-
isEnabled() {
|
|
44
|
-
return this.state != 'closed' && this.state != 'created'
|
|
45
|
-
},
|
|
46
|
-
rtcConfiguration() {
|
|
47
|
-
return peer.rtcConfiguration
|
|
48
|
-
},
|
|
49
|
-
clientIp() {
|
|
50
|
-
return peer.clientIp
|
|
51
|
-
},
|
|
52
|
-
isPolite() {
|
|
53
|
-
return peer.peerId < this.to
|
|
5
|
+
const waitingMessages = ref([])
|
|
6
|
+
const state = ref("created")
|
|
7
|
+
const rtc = ref(null)
|
|
8
|
+
const rtcSignalingState = ref("")
|
|
9
|
+
const iceGatheringState = ref("")
|
|
10
|
+
const iceConnectionState = ref("")
|
|
11
|
+
const rtpSenders = ref([])
|
|
12
|
+
const offerOptions = ref(null)
|
|
13
|
+
const answerOptions = ref(null)
|
|
14
|
+
const remoteTracks = ref([])
|
|
15
|
+
const restartOnDisconnect = ref(false) // because could not set rtc configuration(firefox)
|
|
16
|
+
|
|
17
|
+
const localTracks = computed(() => peer.localTracks.value)
|
|
18
|
+
const rtcConfiguration = computed(() => peer.rtcConfiguration.value)
|
|
19
|
+
const clientIp = computed(() => peer.clientIp.value)
|
|
20
|
+
const isPolite = computed(() => peer.peerId < to)
|
|
21
|
+
|
|
22
|
+
const isEnabled = computed(() => state.value !== 'closed' && state.value !== 'created')
|
|
23
|
+
|
|
24
|
+
function synchronizeLocalTracks() {
|
|
25
|
+
console.log("SYNCHRONIZE LOCAL TRACKS")
|
|
26
|
+
const tracks = isEnabled.value ? localTracks.value : []
|
|
27
|
+
let removedSenders = []
|
|
28
|
+
for(const senderInfo of rtpSenders.value) {
|
|
29
|
+
const trackInfo = tracks.find(trackInfo => trackInfo.track === senderInfo.sender.track)
|
|
30
|
+
if(!trackInfo) {
|
|
31
|
+
rtc.value.removeTrack(senderInfo.sender)
|
|
32
|
+
removedSenders.push(senderInfo)
|
|
33
|
+
} else if(senderInfo.stream !== trackInfo.stream) {
|
|
34
|
+
senderInfo.stream = trackInfo.stream
|
|
35
|
+
senderInfo.sender.setStreams(trackInfo.stream)
|
|
54
36
|
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.restartConnection()
|
|
75
|
-
}
|
|
37
|
+
}
|
|
38
|
+
for(const removedSenderInfo of removedSenders) {
|
|
39
|
+
rtpSenders.value.splice(rtpSenders.value.indexOf(removedSenderInfo), 1)
|
|
40
|
+
}
|
|
41
|
+
for(const trackInfo of tracks) {
|
|
42
|
+
if(rtpSenders.value.find(senderInfo => senderInfo.sender.track === trackInfo.track)) continue; // existing track
|
|
43
|
+
const sender = rtc.value.addTrack(trackInfo.track, trackInfo.stream)
|
|
44
|
+
rtpSenders.value.push({ sender, stream: trackInfo.stream })
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
watch(() => isEnabled.value && localTracks.value, () => synchronizeLocalTracks(), { immediate: true, deep: true })
|
|
49
|
+
|
|
50
|
+
watch(rtcConfiguration, configuration => {
|
|
51
|
+
if(rtc.value) {
|
|
52
|
+
if(rtc.value.setConfiguration) {
|
|
53
|
+
rtc.value.setConfiguration(configuration)
|
|
54
|
+
} else {
|
|
55
|
+
restartOnDisconnect.value = true
|
|
76
56
|
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
async function restartConnection() {
|
|
61
|
+
console.log("RESTARTING CONNECTION")
|
|
62
|
+
/*if(false && rtc.value.restartIce) {
|
|
63
|
+
console.log("RESTART ICE!")
|
|
64
|
+
rtc.value.restartIce()
|
|
65
|
+
} else {*/
|
|
66
|
+
console.log("RESTART OFFER!")
|
|
67
|
+
const offer =
|
|
68
|
+
await rtc.value.createOffer({ ...offerOptions.value, iceRestart: true })
|
|
69
|
+
if(rtc.value.signalingState !== "stable") {
|
|
70
|
+
console.log("RTC GOT OUT OF STABLE WHILE CREATING OFFER. IGNORE GENERATED OFFER!")
|
|
71
|
+
return
|
|
72
|
+
}
|
|
73
|
+
await rtc.value.setLocalDescription(offer)
|
|
74
|
+
peer.sendMessage({ to, type: "sdp", data: offer })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
watch(clientIp, ip => {
|
|
78
|
+
if(rtc.value) restartConnection()
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
async function handleNegotiationNeeded(event) {
|
|
82
|
+
console.log("NEGOTIATION NEEDED! IN STATE", rtc.value.signalingState)
|
|
83
|
+
if(!isEnabled.value) return
|
|
84
|
+
if(state.value === 'negotiating') {
|
|
85
|
+
console.log("SKIP NESTED NEGOTIATIONS WITH", to)
|
|
86
|
+
//return
|
|
87
|
+
}
|
|
88
|
+
state.value = 'negotiating'
|
|
89
|
+
// if it's disabled there is no need for offer
|
|
90
|
+
console.log("UPDATING OFFER")
|
|
91
|
+
const offer = await rtc.value.createOffer(offerOptions.value || undefined)
|
|
92
|
+
if(rtc.value.signalingState !== "stable") {
|
|
93
|
+
console.log("RTC GOT OUT OF STABLE WHILE CREATING OFFER. IGNORE GENERATED OFFER!")
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
await rtc.value.setLocalDescription(offer)
|
|
97
|
+
peer.sendMessage({ to, type: "sdp", data: offer })
|
|
98
|
+
console.log("SDP OFFER SET! RTC IN STATE", rtc.value.signalingState)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function handleSignalingStateChange(event) {
|
|
102
|
+
if(state.value === 'closed') return
|
|
103
|
+
console.log("RTC SIGNALING STATE CHANGE", rtc.value.signalingState)
|
|
104
|
+
rtc.valueSignalingState = rtc.value.signalingState
|
|
105
|
+
}
|
|
106
|
+
async function handleIceCandidate(event) {
|
|
107
|
+
if(state.value === 'closed') return
|
|
108
|
+
//console.log("GOT ICE CANDIDATE", event.candidate && event.candidate.candidate)
|
|
109
|
+
peer.sendMessage({ to, type: "ice", data: event.candidate })
|
|
110
|
+
}
|
|
111
|
+
function handleTrack(event) {
|
|
112
|
+
if(state.value === 'closed') return
|
|
113
|
+
const track = event.track
|
|
114
|
+
let stream = event.streams && event.streams[0]
|
|
115
|
+
if(!stream) {
|
|
116
|
+
console.error(`Streamless track ${track.id} ${track.kind} from peer ${to} - something is wrong!`)
|
|
117
|
+
stream = new MediaStream([track])
|
|
118
|
+
}
|
|
119
|
+
const trackInfo = {
|
|
120
|
+
track: event.track,
|
|
121
|
+
stream,
|
|
122
|
+
muted: track.muted,
|
|
123
|
+
removeTrackHandler: () => {
|
|
124
|
+
const trackIndex = remoteTracks.value.findIndex(remoteTrack =>
|
|
125
|
+
remoteTrack.track === track && remoteTrack.stream === stream)
|
|
126
|
+
if(trackIndex !== -1) {
|
|
127
|
+
const trackInfo = remoteTracks.value[trackIndex]
|
|
128
|
+
trackInfo.track.removeEventListener('mute', trackInfo.muteHandler)
|
|
129
|
+
trackInfo.track.removeEventListener('unmute', trackInfo.unmuteHandler)
|
|
130
|
+
remoteTracks.value.splice(trackIndex, 1)
|
|
108
131
|
}
|
|
109
132
|
},
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
133
|
+
muteHandler: () => trackInfo.muted = track.muted,
|
|
134
|
+
unmuteHandler: () => trackInfo.muted = track.muted
|
|
135
|
+
}
|
|
136
|
+
if(stream) {
|
|
137
|
+
stream.addEventListener('removetrack', trackInfo.removeTrackHandler)
|
|
138
|
+
}
|
|
139
|
+
const existingTrackInfo = remoteTracks.value.find(remoteTrack => remoteTrack.track === track)
|
|
140
|
+
if(existingTrackInfo) {
|
|
141
|
+
existingTrackInfo.stream = stream // Track stream changed
|
|
142
|
+
} else {
|
|
143
|
+
trackInfo.track.addEventListener('mute', trackInfo.muteHandler)
|
|
144
|
+
trackInfo.track.addEventListener('unmute', trackInfo.unmuteHandler)
|
|
145
|
+
remoteTracks.value.push(trackInfo)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function handleIceGatheringStateChange(event) {
|
|
149
|
+
if(state.value === 'closed') return
|
|
150
|
+
console.log("ICE GATHERING STATE CHANGED", rtc.value.iceGatheringState)
|
|
151
|
+
iceGatheringState.value = rtc.value.iceGatheringState
|
|
152
|
+
}
|
|
153
|
+
function handleIceConnectionStateChange(event) {
|
|
154
|
+
if(state.value === 'closed') return
|
|
155
|
+
iceConnectionState.value = rtc.value.iceConnectionState
|
|
156
|
+
console.log("ICE GATHERING STATE CHANGED", rtc.value.iceConnectionState)
|
|
157
|
+
if(iceConnectionState.value === 'connected') {
|
|
158
|
+
state.value = 'connected'
|
|
159
|
+
}
|
|
160
|
+
if(iceConnectionState.value === 'failed') {
|
|
161
|
+
state.value = 'failed'
|
|
162
|
+
restartConnection()
|
|
163
|
+
}
|
|
164
|
+
if(iceConnectionState.value === 'disconnected') {
|
|
165
|
+
state.value = 'disconnected'
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async function handleMessage(message) {
|
|
170
|
+
//console.log("PC", to, "HANDLE MESSAGE", message)
|
|
171
|
+
if(state.value === 'created') {
|
|
172
|
+
console.log("ADD MESSAGE TO WAITING QUEUE")
|
|
173
|
+
waitingMessages.value.push(message)
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
if(state.value === 'close') return
|
|
177
|
+
//console.log("DO HANDLE MESSAGE")
|
|
178
|
+
switch(message.type) {
|
|
179
|
+
case "sdp": {
|
|
180
|
+
console.log("RECEIVED SDP", message.data.type, "IN STATE", rtc.value.signalingState)
|
|
181
|
+
if(message.data.type === 'offer') {
|
|
182
|
+
if(rtc.value.signalingState !== "stable") {
|
|
183
|
+
console.log("SDP CONFLICT, RECEIVED OFFER IN UNSTABLE STATE")
|
|
184
|
+
if(isPolite.value) {
|
|
185
|
+
console.log("I AM POLITE SO I WILL ROLLBACK RTC STATE MACHINE")
|
|
186
|
+
await rtc.value.setLocalDescription({ type: "rollback" })
|
|
187
|
+
await rtc.value.setRemoteDescription(message.data)
|
|
188
|
+
console.log("ROLLBACK DONE")
|
|
189
|
+
const answer =
|
|
190
|
+
await rtc.value.createAnswer(answerOptions.value || undefined)
|
|
191
|
+
console.log("GOT RTC ANSWER IN STATE", rtc.value.signalingState)
|
|
192
|
+
await rtc.value.setLocalDescription(answer)
|
|
193
|
+
console.log("LOCAL ANSWER DESCRIPTION SET! SENDING ANSWER!")
|
|
194
|
+
peer.sendMessage({ to, type: "sdp", data: answer })
|
|
147
195
|
} else {
|
|
148
|
-
console.log("
|
|
149
|
-
await this.rtc.setRemoteDescription(message.data)
|
|
150
|
-
}
|
|
151
|
-
} break;
|
|
152
|
-
case "ice": {
|
|
153
|
-
console.log("RECEIVED ICE! IN STATE", this.rtc.signalingState)
|
|
154
|
-
let ice = message.data
|
|
155
|
-
//if(ice && ice.candidate === "") break;
|
|
156
|
-
if(ice && ice.candidate != "") {
|
|
157
|
-
console.log("ADDING ICE CANDIDATE", ice.candidate)
|
|
158
|
-
await this.rtc.addIceCandidate(new RTCIceCandidate(ice))
|
|
159
|
-
} else if(window.RTCPeerConnection.prototype.addIceCandidate.length === 0){
|
|
160
|
-
await this.rtc.addIceCandidate()
|
|
196
|
+
console.log("I AM NOT POLITE SO I WILL IGNORE OFFER")
|
|
161
197
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
console.
|
|
170
|
-
|
|
171
|
-
},
|
|
172
|
-
synchronizeLocalTracks() {
|
|
173
|
-
const tracks = this.isEnabled ? this.localTracks : []
|
|
174
|
-
let removedSenders = []
|
|
175
|
-
let somethingChanged = false
|
|
176
|
-
for(const senderInfo of this.rtpSenders) {
|
|
177
|
-
const trackInfo = tracks.find(trackInfo => trackInfo.track == senderInfo.sender.track)
|
|
178
|
-
if(!trackInfo) {
|
|
179
|
-
this.rtc.removeTrack(senderInfo.sender)
|
|
180
|
-
removedSenders.push(senderInfo)
|
|
181
|
-
somethingChanged = true
|
|
182
|
-
} else if(senderInfo.stream != trackInfo.stream) {
|
|
183
|
-
senderInfo.stream = trackInfo.stream
|
|
184
|
-
senderInfo.sender.setStreams(trackInfo.stream)
|
|
185
|
-
somethingChanged = true
|
|
198
|
+
} else {
|
|
199
|
+
console.log("SDP STATE GOOD!")
|
|
200
|
+
await rtc.value.setRemoteDescription(message.data)
|
|
201
|
+
const answer =
|
|
202
|
+
await rtc.value.createAnswer(answerOptions.value || undefined)
|
|
203
|
+
console.log("GOT RTC ANSWER IN STATE", rtc.value.signalingState)
|
|
204
|
+
await rtc.value.setLocalDescription(answer)
|
|
205
|
+
console.log("LOCAL ANSWER DESCRIPTION SET! SENDING ANSWER!")
|
|
206
|
+
peer.sendMessage({ to, type: "sdp", data: answer })
|
|
186
207
|
}
|
|
187
|
-
}
|
|
188
|
-
for(const removedSenderInfo of removedSenders) {
|
|
189
|
-
this.rtpSenders.splice(this.rtpSenders.indexOf(removedSenderInfo), 1)
|
|
190
|
-
}
|
|
191
|
-
for(const trackInfo of tracks) {
|
|
192
|
-
if(this.rtpSenders.find(senderInfo => senderInfo.sender.track == trackInfo.track)) continue; // existing track
|
|
193
|
-
const sender = this.rtc.addTrack(trackInfo.track, trackInfo.stream)
|
|
194
|
-
this.rtpSenders.push({ sender, stream: trackInfo.stream })
|
|
195
|
-
somethingChanged = true
|
|
196
|
-
}
|
|
197
|
-
if(somethingChanged) {
|
|
198
|
-
//this.updateOffer() // wait for onnegotiationneeded
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
|
-
async handleNegotiationNeeded(event) {
|
|
202
|
-
console.log("NEGOTIATION NEEDED! IN STATE", this.rtc.signalingState)
|
|
203
|
-
if(!this.isEnabled) return
|
|
204
|
-
if(this.state == 'negotiating') {
|
|
205
|
-
console.log("SKIP NESTED NEGOTIATIONS WITH", this.to)
|
|
206
|
-
//return
|
|
207
|
-
}
|
|
208
|
-
this.state = 'negotiating'
|
|
209
|
-
// if it's disabled there is no need for offer
|
|
210
|
-
console.log("UPDATING OFFER")
|
|
211
|
-
const offer = await this.rtc.createOffer(this.offerOptions || undefined)
|
|
212
|
-
if(this.rtc.signalingState != "stable") {
|
|
213
|
-
console.log("RTC GOT OUT OF STABLE WHILE CREATING OFFER. IGNORE GENERATED OFFER!")
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
await this.rtc.setLocalDescription(offer)
|
|
217
|
-
peer.sendMessage({ to, type: "sdp", data: offer })
|
|
218
|
-
console.log("SDP OFFER SET! RTC IN STATE", this.rtc.signalingState)
|
|
219
|
-
|
|
220
|
-
},
|
|
221
|
-
async handleSignalingStateChange(event) {
|
|
222
|
-
if(this.state == 'closed') return;
|
|
223
|
-
console.log("RTC SIGNALING STATE CHANGE", this.rtc.signalingState)
|
|
224
|
-
this.rtcSignalingState = this.rtc.signalingState
|
|
225
|
-
},
|
|
226
|
-
async handleIceCandidate(event) {
|
|
227
|
-
if(this.state == 'closed') return
|
|
228
|
-
//console.log("GOT ICE CANDIDATE", event.candidate && event.candidate.candidate)
|
|
229
|
-
peer.sendMessage({ to, type: "ice", data: event.candidate })
|
|
230
|
-
},
|
|
231
|
-
handleTrack(event) {
|
|
232
|
-
if(this.state == 'closed') return
|
|
233
|
-
const track = event.track
|
|
234
|
-
let stream = event.streams && event.streams[0]
|
|
235
|
-
if(!stream) {
|
|
236
|
-
console.error(`Streamless track ${track.id} ${track.kind} from peer ${to} - something is wrong!`)
|
|
237
|
-
stream = new MediaStream([track])
|
|
238
|
-
}
|
|
239
|
-
const trackInfo = {
|
|
240
|
-
track: event.track,
|
|
241
|
-
stream,
|
|
242
|
-
muted: track.muted,
|
|
243
|
-
removeTrackHandler: () => {
|
|
244
|
-
const trackIndex = this.remoteTracks.findIndex(remoteTrack =>
|
|
245
|
-
remoteTrack.track == track && remoteTrack.stream == stream)
|
|
246
|
-
if(trackIndex != -1) {
|
|
247
|
-
const trackInfo = this.remoteTracks[trackIndex]
|
|
248
|
-
trackInfo.track.removeEventListener('mute', trackInfo.muteHandler)
|
|
249
|
-
trackInfo.track.removeEventListener('unmute', trackInfo.unmuteHandler)
|
|
250
|
-
this.remoteTracks.splice(trackIndex, 1)
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
muteHandler: () => trackInfo.muted = track.muted,
|
|
254
|
-
unmuteHandler: () => trackInfo.muted = track.muted
|
|
255
|
-
}
|
|
256
|
-
if(stream) {
|
|
257
|
-
stream.addEventListener('removetrack', trackInfo.removeTrackHandler)
|
|
258
|
-
}
|
|
259
|
-
const existingTrackInfo = this.remoteTracks.find(remoteTrack => remoteTrack.track == track)
|
|
260
|
-
if(existingTrackInfo) {
|
|
261
|
-
existingTrackInfo.stream = stream // Track stream changed
|
|
262
208
|
} else {
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.remoteTracks.push(trackInfo)
|
|
266
|
-
}
|
|
267
|
-
},
|
|
268
|
-
handleIceGatheringStateChange(event) {
|
|
269
|
-
if(this.state == 'closed') return
|
|
270
|
-
console.log("ICE GATHERING STATE CHANGED", this.rtc.iceGatheringState)
|
|
271
|
-
this.iceGatheringState = this.rtc.iceGatheringState
|
|
272
|
-
},
|
|
273
|
-
handleIceConnectionStateChange(event) {
|
|
274
|
-
if(this.state == 'closed') return
|
|
275
|
-
this.iceConnectionState = this.rtc.iceConnectionState
|
|
276
|
-
console.log("ICE GATHERING STATE CHANGED", this.rtc.iceConnectionState)
|
|
277
|
-
if(this.iceConnectionState == 'connected') {
|
|
278
|
-
this.state = 'connected'
|
|
279
|
-
}
|
|
280
|
-
if(this.iceConnectionState == 'failed') {
|
|
281
|
-
this.state = 'failed'
|
|
282
|
-
this.restartConnection()
|
|
209
|
+
console.log("GOT ANSWER FROM REMOTE PEER")
|
|
210
|
+
await rtc.value.setRemoteDescription(message.data)
|
|
283
211
|
}
|
|
284
|
-
|
|
285
|
-
|
|
212
|
+
} break;
|
|
213
|
+
case "ice": {
|
|
214
|
+
console.log("RECEIVED ICE! IN STATE", rtc.value.signalingState)
|
|
215
|
+
let ice = message.data
|
|
216
|
+
//if(ice && ice.candidate === "") break;
|
|
217
|
+
if(ice && ice.candidate !== "") {
|
|
218
|
+
console.log("ADDING ICE CANDIDATE", ice.candidate)
|
|
219
|
+
await rtc.value.addIceCandidate(new RTCIceCandidate(ice))
|
|
220
|
+
} else if(window.RTCPeerConnection.prototype.addIceCandidate.length === 0){
|
|
221
|
+
await rtc.value.addIceCandidate()
|
|
286
222
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if(this.rtc) {
|
|
318
|
-
this.rtc.removeEventListener('negotiationneeded', this.negotiationNeededHandler)
|
|
319
|
-
this.rtc.removeEventListener('signalingstatechange', this.signalingStateChangeHandler)
|
|
320
|
-
this.rtc.removeEventListener('icecandidate', this.iceCandidateHandler)
|
|
321
|
-
this.rtc.removeEventListener('track', this.trackHandler)
|
|
322
|
-
this.rtc.removeEventListener('icegatheringstatechanged', this.iceGatheringStateChangeHandler)
|
|
323
|
-
this.rtc.removeEventListener('iceconnectionstatechanged', this.iceConnectionStateChangeHandler)
|
|
223
|
+
//console.log("REMOTE ICE CANDIDATE ADDED", ice && ice.candidate)
|
|
224
|
+
} break;
|
|
225
|
+
case "ping": {
|
|
226
|
+
peer.sendMessage({ to, type: "pong", data: message.data})
|
|
227
|
+
} break;
|
|
228
|
+
case "pong": break; // ignore pong
|
|
229
|
+
default:
|
|
230
|
+
console.error("Unknown peer message", message)
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function connect() {
|
|
235
|
+
console.log("PeerConnection connect")
|
|
236
|
+
if(rtc.value) throw new Error("can't connect twice!")
|
|
237
|
+
state.value = 'connecting'
|
|
238
|
+
rtc.value = new RTCPeerConnection(rtcConfiguration.value)
|
|
239
|
+
rtcSignalingState.value = rtc.value.signalingState
|
|
240
|
+
iceGatheringState.value = rtc.value.iceGatheringState
|
|
241
|
+
iceConnectionState.value = rtc.value.iceConnectionState
|
|
242
|
+
rtc.value.addEventListener('negotiationneeded', handleNegotiationNeeded)
|
|
243
|
+
rtc.value.addEventListener('signalingstatechange', handleSignalingStateChange)
|
|
244
|
+
rtc.value.addEventListener('icecandidate', handleIceCandidate)
|
|
245
|
+
rtc.value.addEventListener('track', handleTrack)
|
|
246
|
+
rtc.value.addEventListener('icegatheringstatechange', handleIceGatheringStateChange)
|
|
247
|
+
rtc.value.addEventListener('iceconnectionstatechange', handleIceConnectionStateChange)
|
|
248
|
+
for(const message of waitingMessages.value) {
|
|
249
|
+
try {
|
|
250
|
+
await handleMessage(message)
|
|
251
|
+
} catch(error) {
|
|
252
|
+
console.error("MESSAGE", message, "HANDLING ERROR", error)
|
|
324
253
|
}
|
|
325
254
|
}
|
|
326
|
-
|
|
255
|
+
waitingMessages.value = []
|
|
256
|
+
}
|
|
257
|
+
function close() {
|
|
258
|
+
console.log("PeerConnection close")
|
|
259
|
+
state.value = 'closed'
|
|
260
|
+
if(rtc.value) {
|
|
261
|
+
rtc.value.removeEventListener('negotiationneeded', handleNegotiationNeeded)
|
|
262
|
+
rtc.value.removeEventListener('signalingstatechange', handleSignalingStateChange)
|
|
263
|
+
rtc.value.removeEventListener('icecandidate', handleIceCandidate)
|
|
264
|
+
rtc.value.removeEventListener('track', handleTrack)
|
|
265
|
+
rtc.value.removeEventListener('icegatheringstatechanged', handleIceGatheringStateChange)
|
|
266
|
+
rtc.value.removeEventListener('iceconnectionstatechanged', handleIceConnectionStateChange)
|
|
267
|
+
rtc.value.close()
|
|
268
|
+
rtpSenders.value = []
|
|
269
|
+
rtc.value = null
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function dispose() {
|
|
274
|
+
if(state.value !== 'closed') {
|
|
275
|
+
close()
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const summary = computed(() => ({
|
|
280
|
+
to: to,
|
|
281
|
+
state: state.value,
|
|
282
|
+
isPolite: isPolite.value,
|
|
283
|
+
waitingMessages: waitingMessages.value.length,
|
|
284
|
+
rtpSenders: rtpSenders.value.map(({ sender, stream }) => {
|
|
285
|
+
const { id, kind, label } = sender.track
|
|
286
|
+
return { id, kind, label, stream: stream.id }
|
|
287
|
+
}),
|
|
288
|
+
rtcSignalingState: rtcSignalingState.value,
|
|
289
|
+
iceGatheringState: iceGatheringState.value,
|
|
290
|
+
iceConnectionState: iceConnectionState.value,
|
|
291
|
+
remoteTracks: remoteTracks.value.map(({ track, stream }) => {
|
|
292
|
+
const { id, kind, label, muted } = track
|
|
293
|
+
return { id, kind, label, muted, stream: stream.id }
|
|
294
|
+
}),
|
|
295
|
+
}))
|
|
296
|
+
|
|
297
|
+
return {
|
|
298
|
+
to,
|
|
299
|
+
state,
|
|
300
|
+
isPolite,
|
|
301
|
+
isEnabled,
|
|
302
|
+
summary,
|
|
303
|
+
remoteTracks,
|
|
304
|
+
connect,
|
|
305
|
+
close,
|
|
306
|
+
restartConnection,
|
|
307
|
+
handleMessage,
|
|
308
|
+
dispose,
|
|
309
|
+
}
|
|
310
|
+
|
|
327
311
|
}
|
|
328
312
|
|
|
329
313
|
export { createPeerConnection }
|