mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-23 08:33:09 +00:00
ui: reconnect call (#7711)
* Update Call.hs * Update Internal.hs * add reconnecting string * Update WebRTC.kt * desktop: show reconnecting state, keep call duration * android keep connection time correct wiith adding reconnecting * Update CallTypes.swift add reconnecting status on IOS * Update WebRTC.swift add reconnecting * add reconnecting and make sure call duration is correct * Update call.ts * core: regenerate call.js from call.ts * Update Call.hs revert call status change minimization * Update Internal.hs rever to minimize changes * Update CallTypes.swift minimize changes * Update WebRTC.kt minimize changes * Update CallView.desktop.kt desktop shows reconnecting without sending to core * Update CallView.android.kt show reconnecting without sending it to the core * Update ActiveCallView.swift show reconnecting to ui without sending to core * Update CallView.desktop.kt add reconnecting sound on reconnect * Update CallView.android.kt add reconnecting sound * Update ActiveCallView.swift play reconnecting sound when reconnecting * Update RecAndPlay.desktop.kt * rebuild * refactor * build * android, desktop: restart ICE to reconnect calls * ios: restart ICE to reconnect calls * webrtc: add call reconnection e2e tests * android, desktop: fix lost call commands --------- Co-authored-by: GuavaGoat <320862384+GuavaGoat@users.noreply.github.com> Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com> Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
This commit is contained in:
27 files changed
+1247
-136
No files matched your search
@@ -99,6 +99,7 @@ Both platforms share a common signaling flow through the Haskell core API.
|
||||
```
|
||||
Outgoing: WaitCapabilities -> InvitationSent -> OfferSent -> AnswerReceived -> Negotiated -> Connected -> Ended
|
||||
Incoming: InvitationAccepted -> OfferReceived -> Negotiated -> Connected -> Ended
|
||||
Reconnection: Connected -> Reconnecting -> Connected | Ended
|
||||
```
|
||||
|
||||
| State | Description |
|
||||
@@ -111,8 +112,17 @@ Incoming: InvitationAccepted -> OfferReceived -> Negotiated -> Connected -> Ende
|
||||
| `AnswerReceived` | Caller received SDP answer |
|
||||
| `Negotiated` | ICE negotiation complete |
|
||||
| `Connected` | Media flowing |
|
||||
| `Reconnecting` | Connection lost, waiting for ICE restart |
|
||||
| `Ended` | Call terminated |
|
||||
|
||||
### 3.1 Reconnection
|
||||
|
||||
1. A connected call loses its WebRTC connection, e.g. when the device switches between Wi-Fi and mobile network.
|
||||
2. The WebRTC engine reports `"reconnecting"` connection state; the app shows "reconnecting…" and plays the connecting sound. This state is not reported to the core, and `connectedAt` is kept, so call duration continues.
|
||||
3. The callee's WebRTC engine (the party that sent the initial offer) restarts ICE every 10 seconds, sending the new offer in `WCallResponse.Ice` with `session` via `apiSendCallExtraInfo`. The caller answers the same way.
|
||||
4. When the connection is restored, the call returns to `Connected` and the sound stops.
|
||||
5. If the connection is not restored in 30 seconds, the call ends as disconnected. Clients without ICE restart support ignore the restart offer, so the call ends in this case.
|
||||
|
||||
---
|
||||
|
||||
## 4. Ending a Call
|
||||
@@ -184,7 +194,7 @@ Incoming: InvitationAccepted -> OfferReceived -> Negotiated -> Connected -> Ende
|
||||
| `apiRejectCall(rh, contact)` | Reject incoming call |
|
||||
| `apiSendCallOffer(rh, contact, rtcSession, rtcIceCandidates, media, capabilities)` | Send SDP offer |
|
||||
| `apiSendCallAnswer(rh, contact, rtcSession, rtcIceCandidates)` | Send SDP answer |
|
||||
| `apiSendCallExtraInfo(rh, contact, rtcIceCandidates)` | Send additional ICE candidates |
|
||||
| `apiSendCallExtraInfo(rh, contact, rtcSession, rtcIceCandidates)` | Send additional ICE candidates, or ICE restart offer/answer |
|
||||
| `apiEndCall(rh, contact)` | End active call |
|
||||
| `apiCallStatus(rh, contact, status)` | Report WebRTC connection status |
|
||||
|
||||
|
||||
@@ -71,8 +71,8 @@ Sound: `SoundPlayer.start()` plays ringtone while banner is visible (unless call
|
||||
| 1. Capabilities | `WCallResponse.Capabilities` | Local capabilities reported; `apiSendCallInvitation()` called |
|
||||
| 2. Offer | `WCallResponse.Offer` | SDP offer + ICE candidates sent via `apiSendCallOffer()` |
|
||||
| 3. Answer | `WCallResponse.Answer` | SDP answer + ICE candidates sent via `apiSendCallAnswer()` |
|
||||
| 4. ICE | `WCallResponse.Ice` | Additional ICE candidates exchanged via `apiSendCallExtraInfo()` |
|
||||
| 5. Connection | `WCallResponse.Connection` | WebRTC connection state changes; `CallState.Connected` set on success |
|
||||
| 4. ICE | `WCallResponse.Ice` | Additional ICE candidates, and ICE restart offer/answer in `session`, exchanged via `apiSendCallExtraInfo()` |
|
||||
| 5. Connection | `WCallResponse.Connection` | WebRTC connection state changes; `CallState.Connected` set on success, `CallState.Reconnecting` when a connected call loses connection |
|
||||
| 6. Connected | `WCallResponse.Connected` | Connection info (relay/direct) stored in `call.connectionInfo` |
|
||||
| 7. PeerMedia | `WCallResponse.PeerMedia` | Remote party media source changes (mic, camera, screen) |
|
||||
| 8. Media control | `WCallCommand.Media` | Toggle local media sources (mic, camera, screen audio/video) |
|
||||
@@ -90,14 +90,15 @@ Sound: `SoundPlayer.start()` plays ringtone while banner is visible (unless call
|
||||
| `OfferReceived` | Callee received SDP offer |
|
||||
| `AnswerReceived` | Caller received SDP answer |
|
||||
| `Negotiated` | ICE negotiation complete |
|
||||
| `Connected` | WebRTC media flowing; `connectedAt` timestamp set |
|
||||
| `Connected` | WebRTC media flowing; `connectedAt` timestamp set on the first connection |
|
||||
| `Reconnecting` | Connection lost; "reconnecting…" shown while ICE restarts, call ends after 30 seconds without connection |
|
||||
| `Ended` | Call terminated |
|
||||
|
||||
### Call Sounds
|
||||
|
||||
| Sound | Trigger |
|
||||
|---|---|
|
||||
| Connecting sound | `CallSoundsPlayer.startConnectingCallSound()` after invitation sent |
|
||||
| Connecting sound | `CallSoundsPlayer.startConnectingCallSound()` after invitation sent, and while reconnecting |
|
||||
| In-call sound | `CallSoundsPlayer.startInCallSound()` when delivery receipt received |
|
||||
| Ringtone | `SoundPlayer.start()` for incoming calls |
|
||||
| End vibration | `CallSoundsPlayer.vibrate()` on call end (if was connected) |
|
||||
|
||||
Reference in new issue
Block a user