From db93eace30b504c6596a3ab48f2ad7eedbbd4fb3f51fa4ce9f21b55bac9cffc5 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Fri, 1 May 2026 18:16:01 +0300 Subject: [PATCH] =?UTF-8?q?WebRTC:=20=D1=81=D1=82=D1=80=D0=BE=D0=B3=D0=B0?= =?UTF-8?q?=D1=8F=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=20=D1=81=D0=B8=D0=B3=D0=BD=D0=B0=D0=BB=D0=BE=D0=B2=20(ICE=20?= =?UTF-8?q?=D0=B4=D0=BE=20PC=20=D0=B2=20=D0=BE=D1=87=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D1=8C,=20ANSWER=20=D1=82=D0=BE=D0=BB=D1=8C=D0=BA=D0=BE?= =?UTF-8?q?=20=D0=B4=D0=BB=D1=8F=20outgoing)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION.properties | 2 +- shine-UI/js/services/call-service.js | 58 ++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/VERSION.properties b/VERSION.properties index cea4b5e..a05e542 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.30 +client.version=1.2.32 server.version=1.2.26 diff --git a/shine-UI/js/services/call-service.js b/shine-UI/js/services/call-service.js index 64ac2c3..821c213 100644 --- a/shine-UI/js/services/call-service.js +++ b/shine-UI/js/services/call-service.js @@ -1029,13 +1029,24 @@ async function ensurePeerConnection(call) { } async function onAccept(call) { + if (!call) return; + if (call.initialOfferInProgress || call.initialOfferSent) { + await emitDebug(call, 'warn', 'accept_duplicate_ignored', `phase=${call.phase || ''}`); + return; + } + call.initialOfferInProgress = true; cleanupTimers(call); setStatus(call, 'Соединяем…', 'connecting'); - const pc = await ensurePeerConnection(call); - const offer = await pc.createOffer(); - await pc.setLocalDescription(offer); - await sendSignal(call, TYPES.OFFER, JSON.stringify(offer)); - await emitDebug(call, 'info', 'offer_sent', 'offer created and sent'); + try { + const pc = await ensurePeerConnection(call); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + call.initialOfferSent = true; + await sendSignal(call, TYPES.OFFER, JSON.stringify(offer)); + await emitDebug(call, 'info', 'offer_sent', 'offer created and sent'); + } finally { + call.initialOfferInProgress = false; + } } function ensureIncomingNotification(peerLogin) { @@ -1145,10 +1156,14 @@ export async function startDebugConnectionAsResponder({ runId, callId, peerLogin debugRunId: String(runId || '').trim(), debugRole: 'responder', pendingRemoteIceCandidates: [], + initialOfferInProgress: false, + initialOfferSent: false, }; calls.set(cleanCallId, call); } if (!Array.isArray(call.pendingRemoteIceCandidates)) call.pendingRemoteIceCandidates = []; + if (typeof call.initialOfferInProgress !== 'boolean') call.initialOfferInProgress = false; + if (typeof call.initialOfferSent !== 'boolean') call.initialOfferSent = false; activeCallId = cleanCallId; await emitDebug(call, 'info', 'debug_prepare_responder', `peerSessionId=${cleanPeerSessionId}`); @@ -1180,6 +1195,8 @@ export async function startDebugConnectionAsInitiator({ runId, callId, peerLogin debugRunId: String(runId || '').trim(), debugRole: 'initiator', pendingRemoteIceCandidates: [], + initialOfferInProgress: false, + initialOfferSent: false, }; calls.set(cleanCallId, call); @@ -1225,6 +1242,8 @@ export async function startOutgoingCall(peerLogin) { debugRunId: '', debugRole: '', pendingRemoteIceCandidates: [], + initialOfferInProgress: false, + initialOfferSent: false, }; calls.set(callId, call); activeCallId = callId; @@ -1295,6 +1314,8 @@ export async function handleIncomingCallInvite(evt) { debugRunId: '', debugRole: '', pendingRemoteIceCandidates: [], + initialOfferInProgress: false, + initialOfferSent: false, }; calls.set(callId, call); } @@ -1355,6 +1376,10 @@ export async function handleIncomingCallSignal(evt) { } if (type === TYPES.ACCEPT) { + if (call.direction !== 'out') { + await emitDebug(call, 'warn', 'accept_ignored_for_non_outgoing_call', `direction=${call.direction || ''}`); + return; + } call.phase = 'connecting'; setStatus(call, 'Соединяем…', 'connecting'); await onAccept(call); @@ -1403,7 +1428,20 @@ export async function handleIncomingCallSignal(evt) { if (type === TYPES.ANSWER) { try { - const pc = await ensurePeerConnection(call); + if (call.direction !== 'out') { + await emitDebug(call, 'warn', 'answer_ignored_for_non_outgoing_call', `direction=${call.direction || ''}`); + return; + } + if (!call.pc) { + await emitDebug(call, 'warn', 'answer_ignored_without_pc', 'no local peer connection'); + return; + } + const pc = call.pc; + const localType = String(pc.localDescription?.type || '').trim().toLowerCase(); + if (localType !== 'offer') { + await emitDebug(call, 'warn', 'answer_ignored_without_local_offer', `localType=${localType || 'none'}`); + return; + } if (pc.signalingState === 'stable' && pc.remoteDescription) { await emitDebug(call, 'warn', 'answer_duplicate_ignored', 'remote description already set'); return; @@ -1421,8 +1459,14 @@ export async function handleIncomingCallSignal(evt) { if (type === TYPES.ICE) { try { - const pc = await ensurePeerConnection(call); const candidate = JSON.parse(data); + if (!call.pc) { + if (!Array.isArray(call.pendingRemoteIceCandidates)) call.pendingRemoteIceCandidates = []; + call.pendingRemoteIceCandidates.push(candidate); + await emitDebug(call, 'info', 'ice_queued_before_pc', `queue=${call.pendingRemoteIceCandidates.length}`); + return; + } + const pc = call.pc; if (!pc.remoteDescription) { if (!Array.isArray(call.pendingRemoteIceCandidates)) call.pendingRemoteIceCandidates = []; call.pendingRemoteIceCandidates.push(candidate);