@live-change/peer-connection-frontend 0.8.109 → 0.8.110
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/front/src/components/Peer.js +5 -20
- package/front/src/components/PeerConnection.js +107 -42
- package/package.json +16 -16
|
@@ -55,10 +55,10 @@ const createPeer = async ({
|
|
|
55
55
|
|
|
56
56
|
const otherPeers = computed(() => peers.value?.filter(peer => peer.id !== peerId))
|
|
57
57
|
const otherPeersOnline = computed(() => otherPeers.value?.filter(peer => peer.peerState?.online))
|
|
58
|
-
const isConnectionPossible = computed(() => online.value
|
|
58
|
+
const isConnectionPossible = computed(() => online.value /*&& (!!turnConfiguration.value)*/)
|
|
59
59
|
|
|
60
60
|
const rtcConfiguration = computed(() => ({
|
|
61
|
-
iceServers: [ turnConfiguration.value ],
|
|
61
|
+
iceServers: turnConfiguration.value ? [ turnConfiguration.value ] : [],
|
|
62
62
|
iceTransportPolicy: 'all', // 'all' or 'relay',
|
|
63
63
|
bundlePolicy: 'balanced'
|
|
64
64
|
}))
|
|
@@ -132,23 +132,6 @@ const createPeer = async ({
|
|
|
132
132
|
}
|
|
133
133
|
)
|
|
134
134
|
|
|
135
|
-
function sendMessage(message) {
|
|
136
|
-
console.log("SENDING PEER MESSAGE", message)
|
|
137
|
-
message.from = peerId
|
|
138
|
-
message.sent = message.sent || new Date().toISOString()
|
|
139
|
-
message._commandId = message._commandId || api.uid()
|
|
140
|
-
const requestTimeout = 10000
|
|
141
|
-
//console.log("SENDING PEER MESSAGE", message)
|
|
142
|
-
api.requestWithSettings({ requestTimeout }, ['peerConnection', 'postMessage'], message)
|
|
143
|
-
.catch(error => {
|
|
144
|
-
console.log("PEER MESSAGE ERROR", error)
|
|
145
|
-
if(error === 'timeout' && !finished.value) {
|
|
146
|
-
console.log("RETRYING")
|
|
147
|
-
sendMessage(message)
|
|
148
|
-
}
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
|
|
152
135
|
function updateConnections() {
|
|
153
136
|
const peers = isConnectionPossible.value ? otherPeersOnline.value : []
|
|
154
137
|
for(let connectionId = 0; connectionId < connections.value.length; connectionId++) {
|
|
@@ -228,7 +211,9 @@ const createPeer = async ({
|
|
|
228
211
|
...peerPublic,
|
|
229
212
|
rtcConfiguration,
|
|
230
213
|
clientIp,
|
|
231
|
-
|
|
214
|
+
api,
|
|
215
|
+
finished,
|
|
216
|
+
peerId
|
|
232
217
|
}
|
|
233
218
|
|
|
234
219
|
return {
|
|
@@ -57,6 +57,43 @@ const createPeerConnection = (peer, to) => {
|
|
|
57
57
|
}
|
|
58
58
|
})
|
|
59
59
|
|
|
60
|
+
const sendQueue = []
|
|
61
|
+
let sendingPromise = null
|
|
62
|
+
async function sendMessagesQueue() {
|
|
63
|
+
if(!sendingPromise) sendingPromise = (async () => {
|
|
64
|
+
while(sendQueue.length && !peer.finished.value) {
|
|
65
|
+
const messages = sendQueue.slice(0, 23)
|
|
66
|
+
console.log("SENDING PEER MESSAGES", messages)
|
|
67
|
+
const requestTimeout = 10000
|
|
68
|
+
const request = {
|
|
69
|
+
from: peer.peerId,
|
|
70
|
+
to,
|
|
71
|
+
messages,
|
|
72
|
+
_commandId: messages[0]._commandId || api.uid()
|
|
73
|
+
}
|
|
74
|
+
while(true) {
|
|
75
|
+
try {
|
|
76
|
+
await api.requestWithSettings({ requestTimeout }, ['peerConnection', 'postMessages'], request)
|
|
77
|
+
sendQueue.splice(0, messages.length)
|
|
78
|
+
break
|
|
79
|
+
} catch(error) {
|
|
80
|
+
console.error("SENDING PEER MESSAGES ERROR", error)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
sendingPromise = null
|
|
85
|
+
})()
|
|
86
|
+
return sendingPromise
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function sendMessage(message) {
|
|
90
|
+
//console.log("SENDING PEER MESSAGE", message)
|
|
91
|
+
message.sent = message.sent || new Date().toISOString()
|
|
92
|
+
message._commandId = message._commandId || api.uid()
|
|
93
|
+
sendQueue.push(message)
|
|
94
|
+
sendMessagesQueue()
|
|
95
|
+
}
|
|
96
|
+
|
|
60
97
|
async function restartConnection() {
|
|
61
98
|
console.log("RESTARTING CONNECTION")
|
|
62
99
|
/*if(false && rtc.value.restartIce) {
|
|
@@ -64,38 +101,58 @@ const createPeerConnection = (peer, to) => {
|
|
|
64
101
|
rtc.value.restartIce()
|
|
65
102
|
} else {*/
|
|
66
103
|
console.log("RESTART OFFER!")
|
|
67
|
-
|
|
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 })
|
|
104
|
+
createOffer()
|
|
75
105
|
}
|
|
76
106
|
|
|
77
107
|
watch(clientIp, ip => {
|
|
78
108
|
if(rtc.value) restartConnection()
|
|
79
109
|
})
|
|
80
110
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
state.value = 'negotiating'
|
|
89
|
-
// if it's disabled there is no need for offer
|
|
90
|
-
console.log("UPDATING OFFER")
|
|
111
|
+
let lastOfferId = 0
|
|
112
|
+
async function createOffer(){
|
|
113
|
+
if(state.value === 'rollback') return // if it's rollbacked there is no need for offer
|
|
114
|
+
const offerId = ++lastOfferId
|
|
115
|
+
state.value = 'creating-offer'
|
|
116
|
+
console.log("CREATING OFFER")
|
|
91
117
|
const offer = await rtc.value.createOffer(offerOptions.value || undefined)
|
|
92
118
|
if(rtc.value.signalingState !== "stable") {
|
|
93
119
|
console.log("RTC GOT OUT OF STABLE WHILE CREATING OFFER. IGNORE GENERATED OFFER!")
|
|
94
|
-
return
|
|
120
|
+
return
|
|
121
|
+
}
|
|
122
|
+
if(offerId !== lastOfferId) {
|
|
123
|
+
console.log("OFFER ID CHANGED WHILE CREATING OFFER. IGNORE GENERATED OFFER!")
|
|
124
|
+
return
|
|
95
125
|
}
|
|
96
126
|
await rtc.value.setLocalDescription(offer)
|
|
97
|
-
peer.sendMessage({ to, type: "sdp", data: offer })
|
|
98
127
|
console.log("SDP OFFER SET! RTC IN STATE", rtc.value.signalingState)
|
|
128
|
+
sendMessage({ type: "sdp", data: offer })
|
|
129
|
+
state.value = 'sent-offer'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
let lastAnswerId = 0
|
|
133
|
+
async function createAnswer(){
|
|
134
|
+
const answerId = ++lastAnswerId
|
|
135
|
+
state.value = 'creating-answer'
|
|
136
|
+
console.log("CREATING ANSWER")
|
|
137
|
+
const answer = await rtc.value.createAnswer(answerOptions.value || undefined)
|
|
138
|
+
if(rtc.value.signalingState !== "have-remote-offer") {
|
|
139
|
+
console.log("RTC GOT OUT OF HAVE REMOTE OFFER WHILE CREATING ANSWER. IGNORE GENERATED ANSWER!")
|
|
140
|
+
return
|
|
141
|
+
}
|
|
142
|
+
if(answerId !== lastAnswerId) {
|
|
143
|
+
console.log("ANSWER ID CHANGED WHILE CREATING ANSWER. IGNORE GENERATED ANSWER!")
|
|
144
|
+
return
|
|
145
|
+
}
|
|
146
|
+
await rtc.value.setLocalDescription(answer)
|
|
147
|
+
console.log("SDP ANSWER SET! RTC IN STATE", rtc.value.signalingState)
|
|
148
|
+
sendMessage({ type: "sdp", data: answer })
|
|
149
|
+
state.value = 'sent-answer'
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
async function handleNegotiationNeeded(event) {
|
|
153
|
+
console.log("NEGOTIATION NEEDED! IN RTC STATE", rtc.value.signalingState, "STATE", state.value)
|
|
154
|
+
if(!isEnabled.value) return // if it's disabled there is no need for offer
|
|
155
|
+
await createOffer()
|
|
99
156
|
}
|
|
100
157
|
|
|
101
158
|
async function handleSignalingStateChange(event) {
|
|
@@ -106,7 +163,7 @@ const createPeerConnection = (peer, to) => {
|
|
|
106
163
|
async function handleIceCandidate(event) {
|
|
107
164
|
if(state.value === 'closed') return
|
|
108
165
|
//console.log("GOT ICE CANDIDATE", event.candidate && event.candidate.candidate)
|
|
109
|
-
|
|
166
|
+
sendMessage({ type: "ice", data: event.candidate })
|
|
110
167
|
}
|
|
111
168
|
function handleTrack(event) {
|
|
112
169
|
if(state.value === 'closed') return
|
|
@@ -166,7 +223,14 @@ const createPeerConnection = (peer, to) => {
|
|
|
166
223
|
}
|
|
167
224
|
}
|
|
168
225
|
|
|
226
|
+
let lastReceivedMessageSent = ''
|
|
227
|
+
|
|
169
228
|
async function handleMessage(message) {
|
|
229
|
+
if(lastReceivedMessageSent > message.sent) {
|
|
230
|
+
console.error("MESSAGE OUT OF ORDER", message)
|
|
231
|
+
throw new Error("Message sent before last received message - message order broken!")
|
|
232
|
+
}
|
|
233
|
+
lastReceivedMessageSent = message.sent
|
|
170
234
|
//console.log("PC", to, "HANDLE MESSAGE", message)
|
|
171
235
|
if(state.value === 'created') {
|
|
172
236
|
console.log("ADD MESSAGE TO WAITING QUEUE")
|
|
@@ -177,33 +241,29 @@ const createPeerConnection = (peer, to) => {
|
|
|
177
241
|
//console.log("DO HANDLE MESSAGE")
|
|
178
242
|
switch(message.type) {
|
|
179
243
|
case "sdp": {
|
|
180
|
-
console.log("RECEIVED SDP", message.data.type, "IN STATE", rtc.value.signalingState)
|
|
244
|
+
console.log("RECEIVED SDP", message.data.type, "IN RTC STATE", rtc.value.signalingState, "STATE", state.value)
|
|
181
245
|
if(message.data.type === 'offer') {
|
|
182
|
-
if(rtc.value.signalingState !== "stable"
|
|
183
|
-
|
|
246
|
+
if(rtc.value.signalingState !== "stable"
|
|
247
|
+
|| state.value === 'sent-offer' || state.value === 'creating-offer') {
|
|
248
|
+
console.log("SDP CONFLICT, RECEIVED OFFER WHEN CREATING/GOT OFFER")
|
|
184
249
|
if(isPolite.value) {
|
|
185
250
|
console.log("I AM POLITE SO I WILL ROLLBACK RTC STATE MACHINE")
|
|
186
|
-
|
|
251
|
+
lastOfferId ++ // ignore currently creating offer
|
|
252
|
+
state.value = 'rollback'
|
|
253
|
+
if(rtc.value.signalingState !== "stable") {
|
|
254
|
+
console.log("RTC NOT STABLE! ROLLBACK NEEDED!")
|
|
255
|
+
await rtc.value.setLocalDescription({ type: "rollback" })
|
|
256
|
+
console.log("ROLLBACK DONE!")
|
|
257
|
+
}
|
|
187
258
|
await rtc.value.setRemoteDescription(message.data)
|
|
188
|
-
|
|
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 })
|
|
259
|
+
await createAnswer()
|
|
195
260
|
} else {
|
|
196
261
|
console.log("I AM NOT POLITE SO I WILL IGNORE OFFER")
|
|
197
262
|
}
|
|
198
263
|
} else {
|
|
199
264
|
console.log("SDP STATE GOOD!")
|
|
200
265
|
await rtc.value.setRemoteDescription(message.data)
|
|
201
|
-
|
|
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 })
|
|
266
|
+
await createAnswer()
|
|
207
267
|
}
|
|
208
268
|
} else {
|
|
209
269
|
console.log("GOT ANSWER FROM REMOTE PEER")
|
|
@@ -212,22 +272,26 @@ const createPeerConnection = (peer, to) => {
|
|
|
212
272
|
} break;
|
|
213
273
|
case "ice": {
|
|
214
274
|
console.log("RECEIVED ICE! IN STATE", rtc.value.signalingState)
|
|
275
|
+
console.log("ICE TIMESTAMP", message.timestamp, 'SENT', message.sent)
|
|
215
276
|
if(rtc.value.signalingState === "have-local-offer") {
|
|
216
277
|
console.log("IGNORE ICE IN THIS STATE")
|
|
217
278
|
return;
|
|
218
279
|
}
|
|
219
280
|
let ice = message.data
|
|
220
281
|
//if(ice && ice.candidate === "") break;
|
|
221
|
-
if(ice && ice.candidate
|
|
282
|
+
if(ice && ice.candidate) {
|
|
222
283
|
console.log("ADDING ICE CANDIDATE", ice.candidate)
|
|
223
284
|
await rtc.value.addIceCandidate(new RTCIceCandidate(ice))
|
|
224
|
-
} else
|
|
225
|
-
|
|
285
|
+
} else {
|
|
286
|
+
console.log("ICE CANDIDATE WITHOUT CANDIDATE - ICE CANDIDATES END", ice)
|
|
287
|
+
if(window.RTCPeerConnection.prototype.addIceCandidate.length === 0){
|
|
288
|
+
await rtc.value.addIceCandidate()
|
|
289
|
+
}
|
|
226
290
|
}
|
|
227
291
|
//console.log("REMOTE ICE CANDIDATE ADDED", ice && ice.candidate)
|
|
228
292
|
} break;
|
|
229
293
|
case "ping": {
|
|
230
|
-
|
|
294
|
+
sendMessage({ type: "pong", data: message.data})
|
|
231
295
|
} break;
|
|
232
296
|
case "pong": break; // ignore pong
|
|
233
297
|
default:
|
|
@@ -240,6 +304,7 @@ const createPeerConnection = (peer, to) => {
|
|
|
240
304
|
if(rtc.value) throw new Error("can't connect twice!")
|
|
241
305
|
state.value = 'connecting'
|
|
242
306
|
rtc.value = new RTCPeerConnection(rtcConfiguration.value)
|
|
307
|
+
window.rtc = rtc.value
|
|
243
308
|
rtcSignalingState.value = rtc.value.signalingState
|
|
244
309
|
iceGatheringState.value = rtc.value.iceGatheringState
|
|
245
310
|
iceConnectionState.value = rtc.value.iceConnectionState
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@live-change/peer-connection-frontend",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.110",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"memDev": "dotenvx run -- node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
|
|
6
6
|
"localDevInit": "rm tmp.db; dotenvx run -- node server/start.js localDev --enableSessions --initScript ./init.js",
|
|
@@ -22,19 +22,19 @@
|
|
|
22
22
|
},
|
|
23
23
|
"type": "module",
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@live-change/cli": "^0.8.
|
|
26
|
-
"@live-change/dao": "^0.8.
|
|
27
|
-
"@live-change/dao-vue3": "^0.8.
|
|
28
|
-
"@live-change/dao-websocket": "^0.8.
|
|
29
|
-
"@live-change/framework": "^0.8.
|
|
30
|
-
"@live-change/password-authentication-service": "^0.8.
|
|
31
|
-
"@live-change/secret-code-service": "^0.8.
|
|
32
|
-
"@live-change/secret-link-service": "^0.8.
|
|
33
|
-
"@live-change/session-service": "^0.8.
|
|
34
|
-
"@live-change/user-frontend": "^0.8.
|
|
35
|
-
"@live-change/user-service": "^0.8.
|
|
36
|
-
"@live-change/vue3-components": "^0.8.
|
|
37
|
-
"@live-change/vue3-ssr": "^0.8.
|
|
25
|
+
"@live-change/cli": "^0.8.110",
|
|
26
|
+
"@live-change/dao": "^0.8.110",
|
|
27
|
+
"@live-change/dao-vue3": "^0.8.110",
|
|
28
|
+
"@live-change/dao-websocket": "^0.8.110",
|
|
29
|
+
"@live-change/framework": "^0.8.110",
|
|
30
|
+
"@live-change/password-authentication-service": "^0.8.110",
|
|
31
|
+
"@live-change/secret-code-service": "^0.8.110",
|
|
32
|
+
"@live-change/secret-link-service": "^0.8.110",
|
|
33
|
+
"@live-change/session-service": "^0.8.110",
|
|
34
|
+
"@live-change/user-frontend": "^0.8.110",
|
|
35
|
+
"@live-change/user-service": "^0.8.110",
|
|
36
|
+
"@live-change/vue3-components": "^0.8.110",
|
|
37
|
+
"@live-change/vue3-ssr": "^0.8.110",
|
|
38
38
|
"@vueuse/core": "^10.11.0",
|
|
39
39
|
"boxicons": "^2.1.4",
|
|
40
40
|
"codeceptjs-assert": "^0.0.5",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"vue3-scroll-border": "0.1.6"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@live-change/codeceptjs-helper": "^0.8.
|
|
57
|
+
"@live-change/codeceptjs-helper": "^0.8.110",
|
|
58
58
|
"codeceptjs": "^3.6.5",
|
|
59
59
|
"generate-password": "1.7.1",
|
|
60
60
|
"playwright": "^1.41.2",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"author": "Michał Łaszczewski <michal@laszczewski.pl>",
|
|
66
66
|
"license": "BSD-3-Clause",
|
|
67
67
|
"description": "",
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "8af31d640f43b00b2874f2c70fa4d4486541adfe"
|
|
69
69
|
}
|