@live-change/peer-connection-frontend 0.8.109 → 0.8.111

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.
@@ -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 && (!!turnConfiguration.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
- sendMessage
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
- 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 })
104
+ createOffer()
75
105
  }
76
106
 
77
107
  watch(clientIp, ip => {
78
108
  if(rtc.value) restartConnection()
79
109
  })
80
110
 
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")
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
- peer.sendMessage({ to, type: "ice", data: event.candidate })
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
- console.log("SDP CONFLICT, RECEIVED OFFER IN UNSTABLE STATE")
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
- await rtc.value.setLocalDescription({ type: "rollback" })
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
- 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 })
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
- 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 })
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 if(window.RTCPeerConnection.prototype.addIceCandidate.length === 0){
225
- await rtc.value.addIceCandidate()
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
- peer.sendMessage({ to, type: "pong", data: message.data})
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.109",
3
+ "version": "0.8.111",
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.109",
26
- "@live-change/dao": "^0.8.109",
27
- "@live-change/dao-vue3": "^0.8.109",
28
- "@live-change/dao-websocket": "^0.8.109",
29
- "@live-change/framework": "^0.8.109",
30
- "@live-change/password-authentication-service": "^0.8.109",
31
- "@live-change/secret-code-service": "^0.8.109",
32
- "@live-change/secret-link-service": "^0.8.109",
33
- "@live-change/session-service": "^0.8.109",
34
- "@live-change/user-frontend": "^0.8.109",
35
- "@live-change/user-service": "^0.8.109",
36
- "@live-change/vue3-components": "^0.8.109",
37
- "@live-change/vue3-ssr": "^0.8.109",
25
+ "@live-change/cli": "^0.8.111",
26
+ "@live-change/dao": "^0.8.111",
27
+ "@live-change/dao-vue3": "^0.8.111",
28
+ "@live-change/dao-websocket": "^0.8.111",
29
+ "@live-change/framework": "^0.8.111",
30
+ "@live-change/password-authentication-service": "^0.8.111",
31
+ "@live-change/secret-code-service": "^0.8.111",
32
+ "@live-change/secret-link-service": "^0.8.111",
33
+ "@live-change/session-service": "^0.8.111",
34
+ "@live-change/user-frontend": "^0.8.111",
35
+ "@live-change/user-service": "^0.8.111",
36
+ "@live-change/vue3-components": "^0.8.111",
37
+ "@live-change/vue3-ssr": "^0.8.111",
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.109",
57
+ "@live-change/codeceptjs-helper": "^0.8.111",
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": "075bf3759fae6c40fb8e44d77d9f12c5c175e098"
68
+ "gitHead": "9b96afb2fc61ab3d2a5d143924e2c56d411280b4"
69
69
  }