diff --git a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java index abe5d161f..c3a3b1532 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java @@ -54,7 +54,6 @@ import javax.net.ssl.X509TrustManager; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; -import eu.siacs.conversations.crypto.DomainHostnameVerifier; import eu.siacs.conversations.crypto.XmppDomainVerifier; import eu.siacs.conversations.crypto.axolotl.AxolotlService; import eu.siacs.conversations.crypto.sasl.Anonymous; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 5c474a754..66cf5c23b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -311,7 +311,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web restartContentMap = existing.modifiedCredentials(newCredentials, IceUdpTransportInfo.Setup.ACTPASS); } else { final IceUdpTransportInfo.Setup setup = getPeerDtlsSetup(); - Log.d(Config.LOGTAG, "received confirmation of ICE restart" + newCredentials.values()+" peer_setup="+setup); + Log.d(Config.LOGTAG, "received confirmation of ICE restart" + newCredentials.values() + " peer_setup=" + setup); // DTLS setup attribute needs to be rewritten to reflect current peer state // https://groups.google.com/g/discuss-webrtc/c/DfpIMwvUfeM restartContentMap = existing.modifiedCredentials(newCredentials, setup); @@ -319,12 +319,18 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web if (applyIceRestart(jinglePacket, restartContentMap, isOffer)) { return isOffer; } else { + Log.d(Config.LOGTAG,"ignored ice restart. offer="+isOffer); respondWithTieBreak(jinglePacket); return true; } } catch (final Exception exception) { respondOk(jinglePacket); final Throwable rootCause = Throwables.getRootCause(exception); + if (rootCause instanceof WebRTCWrapper.PeerConnectionNotInitialized) { + Log.d(Config.LOGTAG,"ignoring PeerConnectionNotInitialized"); + //TODO don’t respond OK but respond with out-of-order + return true; + } Log.d(Config.LOGTAG, "failure to apply ICE restart", rootCause); webRTCWrapper.close(); sendSessionTerminate(Reason.ofThrowable(rootCause), rootCause.getMessage()); @@ -1466,21 +1472,18 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web } final boolean neverConnected = !this.stateHistory.contains(PeerConnection.PeerConnectionState.CONNECTED); - final boolean failedOrDisconnected = Arrays.asList( - PeerConnection.PeerConnectionState.FAILED, - PeerConnection.PeerConnectionState.DISCONNECTED - ).contains(newState); - - if (neverConnected && failedOrDisconnected) { - if (isTerminated()) { - Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state); + if (newState == PeerConnection.PeerConnectionState.FAILED) { + if (neverConnected) { + if (isTerminated()) { + Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": not sending session-terminate after connectivity error because session is already in state " + this.state); + return; + } + webRTCWrapper.execute(this::closeWebRTCSessionAfterFailedConnection); return; + } else { + webRTCWrapper.restartIce(); } - webRTCWrapper.execute(this::closeWebRTCSessionAfterFailedConnection); - } else if (newState == PeerConnection.PeerConnectionState.FAILED) { - Log.d(Config.LOGTAG, "attempting to restart ICE"); - webRTCWrapper.restartIce(); } updateEndUserState(); } @@ -1491,6 +1494,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web } private void initiateIceRestart() { + this.stateHistory.clear(); this.webRTCWrapper.setIsReadyToReceiveIceCandidates(false); final SessionDescription sessionDescription; try { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java index 13b695b0e..0712fa900 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java @@ -431,7 +431,7 @@ public class WebRTCWrapper { videoTrack.setEnabled(enabled); } - ListenableFuture setLocalDescription() { + synchronized ListenableFuture setLocalDescription() { return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> { final SettableFuture future = SettableFuture.create(); peerConnection.setLocalDescription(new SetSdpObserver() { @@ -458,7 +458,7 @@ public class WebRTCWrapper { } } - ListenableFuture setRemoteDescription(final SessionDescription sessionDescription) { + synchronized ListenableFuture setRemoteDescription(final SessionDescription sessionDescription) { Log.d(EXTENDED_LOGGING_TAG, "setting remote description:"); logDescription(sessionDescription); return Futures.transformAsync(getPeerConnectionFuture(), peerConnection -> { @@ -482,12 +482,20 @@ public class WebRTCWrapper { private ListenableFuture getPeerConnectionFuture() { final PeerConnection peerConnection = this.peerConnection; if (peerConnection == null) { - return Futures.immediateFailedFuture(new IllegalStateException("initialize PeerConnection first")); + return Futures.immediateFailedFuture(new PeerConnectionNotInitialized()); } else { return Futures.immediateFuture(peerConnection); } } + private PeerConnection requirePeerConnection() { + final PeerConnection peerConnection = this.peerConnection; + if (peerConnection == null) { + throw new PeerConnectionNotInitialized(); + } + return peerConnection; + } + void addIceCandidate(IceCandidate iceCandidate) { requirePeerConnection().addIceCandidate(iceCandidate); } @@ -512,10 +520,15 @@ public class WebRTCWrapper { } } - public PeerConnection.PeerConnectionState getState() { + PeerConnection.PeerConnectionState getState() { return requirePeerConnection().connectionState(); } + public PeerConnection.SignalingState getSignalingState() { + return requirePeerConnection().signalingState(); + } + + EglBase.Context getEglBaseContext() { return this.eglBase.getEglBaseContext(); } @@ -528,14 +541,6 @@ public class WebRTCWrapper { return Optional.fromNullable(this.remoteVideoTrack); } - private PeerConnection requirePeerConnection() { - final PeerConnection peerConnection = this.peerConnection; - if (peerConnection == null) { - throw new PeerConnectionNotInitialized(); - } - return peerConnection; - } - private Context requireContext() { final Context context = this.context; if (context == null) { @@ -552,10 +557,6 @@ public class WebRTCWrapper { executorService.execute(command); } - public PeerConnection.SignalingState getSignalingState() { - return requirePeerConnection().signalingState(); - } - public interface EventCallback { void onIceCandidate(IceCandidate iceCandidate);