Fail call gracefully on turn server network error.

This commit is contained in:
Cody Henthorne 2020-10-29 13:51:30 -04:00 committed by GitHub
parent b5d6cb2a8d
commit 6933f1d818
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 76 additions and 16 deletions

View File

@ -151,6 +151,7 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
public static final String ACTION_MESSAGE_SENT_ERROR = "MESSAGE_SENT_ERROR";
public static final String ACTION_CAMERA_SWITCH_COMPLETED = "CAMERA_FLIP_COMPLETE";
public static final String ACTION_TURN_SERVER_UPDATE = "TURN_SERVER_UPDATE";
public static final String ACTION_SETUP_FAILURE = "SETUP_FAILURE";
public static final int BUSY_TONE_LENGTH = 2000;
@ -333,17 +334,28 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
}
public void retrieveTurnServers(@NonNull RemotePeer remotePeer) {
retrieveTurnServers().addListener(new SuccessOnlyListener<TurnServerInfoParcel>(remotePeer.getState(), remotePeer.getCallId()) {
retrieveTurnServers().addListener(new FutureTaskListener<TurnServerInfoParcel>() {
@Override
public void onSuccessContinue(@Nullable TurnServerInfoParcel turnServerInfoParcel) {
public void onSuccess(@Nullable TurnServerInfoParcel result) {
boolean isAlwaysTurn = TextSecurePreferences.isTurnOnly(WebRtcCallService.this);
Intent intent = new Intent(WebRtcCallService.this, WebRtcCallService.class);
intent.setAction(ACTION_TURN_SERVER_UPDATE)
.putExtra(EXTRA_IS_ALWAYS_TURN, isAlwaysTurn)
.putExtra(EXTRA_TURN_SERVER_INFO, turnServerInfoParcel);
.putExtra(EXTRA_TURN_SERVER_INFO, result);
WebRtcCallService.this.startService(intent);
startService(intent);
}
@Override
public void onFailure(@NonNull ExecutionException exception) {
Log.w(TAG, "Unable to retrieve turn servers: ", exception);
Intent intent = new Intent(WebRtcCallService.this, WebRtcCallService.class);
intent.setAction(ACTION_SETUP_FAILURE)
.putExtra(EXTRA_CALL_ID, remotePeer.getCallId().longValue());
startService(intent);
}
});
}
@ -543,18 +555,6 @@ public class WebRtcCallService extends Service implements CallManager.Observer,
public abstract void onFailureContinue(@Nullable Throwable throwable);
}
private abstract class SuccessOnlyListener<V> extends StateAwareListener<V> {
SuccessOnlyListener(@NonNull CallState expectedState, @NonNull CallId expectedCallId) {
super(expectedState, expectedCallId);
}
@Override
public void onFailureContinue(@Nullable Throwable throwable) {
Log.w(TAG, throwable);
throw new AssertionError(throwable);
}
}
private class SendCallMessageListener<V> extends StateAwareListener<V> {
SendCallMessageListener(@NonNull RemotePeer expectedRemotePeer) {
super(expectedRemotePeer.getState(), expectedRemotePeer.getCallId());

View File

@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallId;
import org.signal.ringrtc.IceCandidate;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.events.CallParticipant;
@ -246,4 +247,38 @@ public class ActiveCallActionProcessorDelegate extends WebRtcActionProcessor {
return terminate(currentState, remotePeer);
}
@Override
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
Log.i(tag, "handleSetupFailure(): call_id: " + callId);
RemotePeer activePeer = currentState.getCallInfoState().getActivePeer();
if (activePeer != null && activePeer.getCallId().equals(callId)) {
try {
if (activePeer.getState() == CallState.DIALING || activePeer.getState() == CallState.REMOTE_RINGING) {
webRtcInteractor.getCallManager().hangup();
} else {
webRtcInteractor.getCallManager().drop(callId);
}
} catch (CallException e) {
return callFailure(currentState, "Unable to drop call due to setup failure", e);
}
currentState = currentState.builder()
.changeCallInfoState()
.callState(WebRtcViewModel.State.NETWORK_FAILURE)
.build();
webRtcInteractor.sendMessage(currentState);
if (activePeer.getState() == CallState.ANSWERING || activePeer.getState() == CallState.LOCAL_RINGING) {
webRtcInteractor.insertMissedCall(activePeer, true, activePeer.getCallStartTimestamp());
}
return terminate(currentState, activePeer);
}
return currentState;
}
}

View File

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallId;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.events.CallParticipant;
@ -204,6 +205,11 @@ public class IncomingCallActionProcessor extends DeviceAwareActionProcessor {
return activeCallDelegate.handleEnded(currentState, action, remotePeer);
}
@Override
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
return activeCallDelegate.handleSetupFailure(currentState, callId);
}
@Override
protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) {
return activeCallDelegate.handleCallConcluded(currentState, remotePeer);

View File

@ -7,6 +7,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.signal.ringrtc.CallException;
import org.signal.ringrtc.CallId;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.events.CallParticipant;
@ -204,6 +205,11 @@ public class OutgoingCallActionProcessor extends DeviceAwareActionProcessor {
return activeCallDelegate.handleEnded(currentState, action, remotePeer);
}
@Override
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
return activeCallDelegate.handleSetupFailure(currentState, callId);
}
@Override
protected @NonNull WebRtcServiceState handleCallConcluded(@NonNull WebRtcServiceState currentState, @NonNull RemotePeer remotePeer) {
return activeCallDelegate.handleCallConcluded(currentState, remotePeer);

View File

@ -80,6 +80,7 @@ import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_B
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_HANGUP;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_ICE_CANDIDATES;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SEND_OFFER;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SETUP_FAILURE;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_AUDIO_BLUETOOTH;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_AUDIO_SPEAKER;
import static org.thoughtcrime.securesms.service.WebRtcCallService.ACTION_SET_ENABLE_VIDEO;
@ -204,6 +205,9 @@ public abstract class WebRtcActionProcessor {
case ACTION_ENDED_INTERNAL_FAILURE:
case ACTION_ENDED_SIGNALING_FAILURE:
case ACTION_ENDED_CONNECTION_FAILURE: return handleEnded(currentState, action, getRemotePeerFromMap(intent, currentState));
// Local Call Failure Actions
case ACTION_SETUP_FAILURE: return handleSetupFailure(currentState, getCallId(intent));
}
return currentState;
@ -574,6 +578,15 @@ public abstract class WebRtcActionProcessor {
//endregion
//region Local call failure
protected @NonNull WebRtcServiceState handleSetupFailure(@NonNull WebRtcServiceState currentState, @NonNull CallId callId) {
Log.i(tag, "handleSetupFailure not processed");
return currentState;
}
//endregion
//region Global call operations
public @NonNull WebRtcServiceState callFailure(@NonNull WebRtcServiceState currentState,