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 d16d3ca3e..d54c42bb4 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -7,12 +7,14 @@ import androidx.annotation.Nullable; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.base.Predicates; import com.google.common.base.Stopwatch; import com.google.common.base.Strings; import com.google.common.base.Throwables; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; import com.google.common.util.concurrent.FutureCallback; @@ -499,6 +501,10 @@ public class JingleRtpConnection extends AbstractJingleConnection return isInitiator() ? this.responderRtpContentMap : this.initiatorRtpContentMap; } + private RtpContentMap getLocalContentMap() { + return isInitiator() ? this.initiatorRtpContentMap : this.responderRtpContentMap; + } + private List toIdentificationTags(final RtpContentMap rtpContentMap) { final Group originalGroup = rtpContentMap.group; final List identificationTags = @@ -1906,11 +1912,11 @@ public class JingleRtpConnection extends AbstractJingleConnection @Override public void onRenegotiationNeeded() { - this.webRTCWrapper.execute(this::initiateIceRestart); + this.webRTCWrapper.execute(this::renegotiate); } - private void initiateIceRestart() { - // TODO discover new TURN/STUN credentials + private void renegotiate() { + //TODO needs to be called only for ice restarts; maybe in the call to restartICe() this.stateHistory.clear(); this.webRTCWrapper.setIsReadyToReceiveIceCandidates(false); final SessionDescription sessionDescription; @@ -1919,10 +1925,41 @@ public class JingleRtpConnection extends AbstractJingleConnection } catch (final Exception e) { final Throwable cause = Throwables.getRootCause(e); Log.d(Config.LOGTAG, "failed to renegotiate", cause); + webRTCWrapper.close(); sendSessionTerminate(Reason.FAILED_APPLICATION, cause.getMessage()); return; } final RtpContentMap rtpContentMap = RtpContentMap.of(sessionDescription, isInitiator()); + final RtpContentMap currentContentMap = getLocalContentMap(); + final boolean iceRestart = currentContentMap.iceRestart(rtpContentMap); + final RtpContentMap.Diff diff = currentContentMap.diff(rtpContentMap); + + Log.d( + Config.LOGTAG, + id.getAccount().getJid().asBareJid() + + ": renegotiate. iceRestart=" + + iceRestart + + " content id diff=" + + diff); + + if (diff.hasModifications() && iceRestart) { + webRTCWrapper.close(); + sendSessionTerminate(Reason.FAILED_APPLICATION, "WebRTC unexpectedly tried to modify content and transport at once"); + return; + } + + if (iceRestart) { + initiateIceRestart(rtpContentMap); + return; + } + + if (diff.added.size() > 0) { + sendContentAdd(rtpContentMap); + } + + } + + private void initiateIceRestart(final RtpContentMap rtpContentMap) { final RtpContentMap transportInfo = rtpContentMap.transportInfo(); final JinglePacket jinglePacket = transportInfo.toJinglePacket(JinglePacket.Action.TRANSPORT_INFO, id.sessionId); @@ -1952,6 +1989,10 @@ public class JingleRtpConnection extends AbstractJingleConnection }); } + private void sendContentAdd(final RtpContentMap rtpContentMap) { + + } + private void setLocalContentMap(final RtpContentMap rtpContentMap) { if (isInitiator()) { this.initiatorRtpContentMap = rtpContentMap;