5.3 KiB
Логика установки соединения через сервер
Ниже описан фактический flow звонка в текущей реализации SHiNE с опорой на сообщения, которые проходят через сервер.
1) Основные операции и типы сообщений
Клиентские WS-операции:
CallInviteBroadcast— широковещательный входящий вызов пользователю.CallSignalToSession— точечный сигнал в конкретную сессию.
Серверные события клиенту:
IncomingCallInvite— уведомление о входящем вызове.IncomingCallSignal— сигнал по активномуcallId.
Коды type в IncomingCallSignal:
100—INVITE110—RINGING120—ACCEPT130—DECLINE_BUSY140—TIMEOUT150—HANGUP200—OFFER210—ANSWER220—ICE
2) Старт исходящего звонка
- Инициатор создаёт
callIdи отправляет:CallInviteBroadcast(toLogin, callId, type=100).
- Сервер находит все активные WS-сессии целевого логина и шлёт им
IncomingCallInvite. - На устройствах callee появляется экран входящего вызова.
3) Ранние статусы до поднятия трубки
Каждое устройство callee может отправить инициатору:
RINGING (110)— «звонок идёт».
Для исходящего звонка инициатор фиксирует выбранную remoteSessionId:
- первый валидный
RINGING/ACCEPTвыбирает сессию, - сигналы с тем же
callId, но от других сессий этого же пользователя, игнорируются.
Это защищает от гонок мультидевайса.
4) Принятие звонка на одном устройстве callee
- На выбранном устройстве callee пользователь нажимает «Поднять»:
- отправляется
ACCEPT (120)в выбранную сессию инициатора.
- отправляется
- Сервер дополнительно рассылает на другие сессии этого же callee:
HANGUP (150)сdata=accepted_on_other_device.
- Остальные устройства callee закрывают экран входящего вызова.
Итог: активным остаётся один путь «инициатор ↔ выбранная сессия callee».
5) Обмен SDP (OFFER/ANSWER)
После ACCEPT:
- Инициатор формирует
RTCPeerConnection,createOffer(), отправляет:OFFER (200).
- Calee применяет
setRemoteDescription(offer), делаетcreateAnswer(), отправляет:ANSWER (210).
- Инициатор применяет
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) Почему схема устойчива сейчас
Текущая устойчивость обеспечивается тремя правилами:
- Одна выбранная сессия callee для исходящего звонка.
- Принятие на одном устройстве закрывает входящий на остальных через сервер.
- ICE буферизуется до готовности SDP/PC, а не ломает handshake.
Именно комбинация этих трёх пунктов закрывает основные причины «иногда дозванивается, иногда нет» при мультидевайсе.