12-05-2026

Перенёс репо
This commit is contained in:
AidarKC 2026-05-12 23:26:27 +03:00
parent a23d090bc1
commit 97d37a2eb6

View File

@ -1,113 +0,0 @@
# Логика установки соединения через сервер
Ниже описан фактический flow звонка в текущей реализации SHiNE с опорой на сообщения, которые проходят через сервер.
## 1) Основные операции и типы сообщений
Клиентские WS-операции:
- `CallInviteBroadcast` — широковещательный входящий вызов пользователю.
- `CallSignalToSession` — точечный сигнал в конкретную сессию.
Серверные события клиенту:
- `IncomingCallInvite` — уведомление о входящем вызове.
- `IncomingCallSignal` — сигнал по активному `callId`.
Коды `type` в `IncomingCallSignal`:
- `100``INVITE`
- `110``RINGING`
- `120``ACCEPT`
- `130``DECLINE_BUSY`
- `140``TIMEOUT`
- `150``HANGUP`
- `200``OFFER`
- `210``ANSWER`
- `220``ICE`
---
## 2) Старт исходящего звонка
1. Инициатор создаёт `callId` и отправляет:
- `CallInviteBroadcast(toLogin, callId, type=100)`.
2. Сервер находит все активные WS-сессии целевого логина и шлёт им `IncomingCallInvite`.
3. На устройствах callee появляется экран входящего вызова.
---
## 3) Ранние статусы до поднятия трубки
Каждое устройство callee может отправить инициатору:
- `RINGING (110)` — «звонок идёт».
Для исходящего звонка инициатор фиксирует выбранную `remoteSessionId`:
- первый валидный `RINGING`/`ACCEPT` выбирает сессию,
- сигналы с тем же `callId`, но от других сессий этого же пользователя, игнорируются.
Это защищает от гонок мультидевайса.
---
## 4) Принятие звонка на одном устройстве callee
1. На выбранном устройстве callee пользователь нажимает «Поднять»:
- отправляется `ACCEPT (120)` в выбранную сессию инициатора.
2. Сервер дополнительно рассылает на **другие** сессии этого же callee:
- `HANGUP (150)` с `data=accepted_on_other_device`.
3. Остальные устройства callee закрывают экран входящего вызова.
Итог: активным остаётся один путь «инициатор ↔ выбранная сессия callee».
---
## 5) Обмен SDP (OFFER/ANSWER)
После `ACCEPT`:
1. Инициатор формирует `RTCPeerConnection`, `createOffer()`, отправляет:
- `OFFER (200)`.
2. Calee применяет `setRemoteDescription(offer)`, делает `createAnswer()`, отправляет:
- `ANSWER (210)`.
3. Инициатор применяет `setRemoteDescription(answer)`.
Защиты:
- повторный `ACCEPT`/повторный старт `offer` игнорируется;
- `ANSWER` обрабатывается только для исходящего звонка;
- `ANSWER` без локального `offer` или дубликат в `stable` игнорируется.
---
## 6) Обмен ICE-кандидатами
`ICE (220)` может приходить раньше SDP. Поэтому:
- если `pc` ещё не создан — ICE кладётся в очередь;
- если `pc` есть, но `remoteDescription` ещё нет — ICE тоже в очередь;
- после установки `remoteDescription` очередь применяется (`addIceCandidate`).
Это устраняет race «remote description was null».
---
## 7) Завершение и ошибки
Нормальное завершение:
- `HANGUP (150)` от одной стороны → вторая завершает звонок.
Неуспех установки:
- сторона, у которой setup не удался, шлёт `HANGUP (150)` с `data=setup_failed:...`,
- вторая сторона сразу закрывает экран ожидания.
Также пишутся `CallDeliveryReport`:
- `call_connected`, `incoming_failed`, `outgoing_failed`, `unknown_error` и расширенная диагностика ICE/SDP.
---
## 8) Почему схема устойчива сейчас
Текущая устойчивость обеспечивается тремя правилами:
1. **Одна выбранная сессия callee** для исходящего звонка.
2. **Принятие на одном устройстве закрывает входящий на остальных** через сервер.
3. **ICE буферизуется до готовности SDP/PC**, а не ломает handshake.
Именно комбинация этих трёх пунктов закрывает основные причины «иногда дозванивается, иногда нет» при мультидевайсе.