store peer dtls setup for later use in ice restart

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java | 34 
src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java       |  6 
2 files changed, 30 insertions(+), 10 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java 🔗

@@ -150,6 +150,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
     private Set<Media> proposedMedia;
     private RtpContentMap initiatorRtpContentMap;
     private RtpContentMap responderRtpContentMap;
+    private IceUdpTransportInfo.Setup peerDtlsSetup;
     private final Stopwatch sessionDuration = Stopwatch.createUnstarted();
     private final Queue<PeerConnection.PeerConnectionState> stateHistory = new LinkedList<>();
     private ScheduledFuture<?> ringingTimeoutFuture;
@@ -332,11 +333,18 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
     }
 
     private IceUdpTransportInfo.Setup getPeerDtlsSetup() {
-        final IceUdpTransportInfo.Setup responderSetup = this.responderRtpContentMap.getDtlsSetup();
-        if (responderSetup == null || responderSetup == IceUdpTransportInfo.Setup.ACTPASS) {
-            throw new IllegalStateException("Invalid DTLS setup value in responder content map");
+        final IceUdpTransportInfo.Setup peerSetup = this.peerDtlsSetup;
+        if (peerSetup == null || peerSetup == IceUdpTransportInfo.Setup.ACTPASS) {
+            throw new IllegalStateException("Invalid peer setup");
         }
-        return isInitiator() ? responderSetup : responderSetup.flip();
+        return peerSetup;
+    }
+
+    private void storePeerDtlsSetup(final IceUdpTransportInfo.Setup setup) {
+        if (setup == null || setup == IceUdpTransportInfo.Setup.ACTPASS) {
+            throw new IllegalArgumentException("Trying to store invalid peer dtls setup");
+        }
+        this.peerDtlsSetup = setup;
     }
 
     private boolean applyIceRestart(final JinglePacket jinglePacket, final RtpContentMap restartContentMap, final boolean isOffer) throws ExecutionException, InterruptedException {
@@ -352,11 +360,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
             webRTCWrapper.rollbackLocalDescription().get();
         }
         webRTCWrapper.setRemoteDescription(sdp).get();
-        if (isInitiator()) {
-            this.responderRtpContentMap = restartContentMap;
-        } else {
-            this.initiatorRtpContentMap = restartContentMap;
-        }
+        setRemoteContentMap(restartContentMap);
         if (isOffer) {
             webRTCWrapper.setIsReadyToReceiveIceCandidates(false);
             final SessionDescription localSessionDescription = setLocalSessionDescription();
@@ -364,6 +368,8 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
             //We need to respond OK before sending any candidates
             respondOk(jinglePacket);
             webRTCWrapper.setIsReadyToReceiveIceCandidates(true);
+        } else {
+            storePeerDtlsSetup(restartContentMap.getDtlsSetup());
         }
         return true;
     }
@@ -569,6 +575,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
 
     private void receiveSessionAccept(final RtpContentMap contentMap) {
         this.responderRtpContentMap = contentMap;
+        this.storePeerDtlsSetup(contentMap.getDtlsSetup());
         final SessionDescription sessionDescription;
         try {
             sessionDescription = SessionDescription.of(contentMap);
@@ -663,6 +670,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
         final SessionDescription sessionDescription = SessionDescription.parse(webRTCSessionDescription.description);
         final RtpContentMap respondingRtpContentMap = RtpContentMap.of(sessionDescription);
         this.responderRtpContentMap = respondingRtpContentMap;
+        storePeerDtlsSetup(respondingRtpContentMap.getDtlsSetup().flip());
         webRTCWrapper.setIsReadyToReceiveIceCandidates(true);
         final ListenableFuture<RtpContentMap> outgoingContentMapFuture = prepareOutgoingContentMap(respondingRtpContentMap);
         Futures.addCallback(outgoingContentMapFuture,
@@ -1520,6 +1528,14 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
         }
     }
 
+    private void setRemoteContentMap(final RtpContentMap rtpContentMap) {
+        if (isInitiator()) {
+            this.responderRtpContentMap = rtpContentMap;
+        } else {
+            this.initiatorRtpContentMap = rtpContentMap;
+        }
+    }
+
     private SessionDescription setLocalSessionDescription() throws ExecutionException, InterruptedException {
         final org.webrtc.SessionDescription sessionDescription = this.webRTCWrapper.setLocalDescription().get();
         return SessionDescription.parse(sessionDescription.description);

src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java 🔗

@@ -155,7 +155,11 @@ public class RtpContentMap {
                 contents.values(),
                 dt->dt.transport.getFingerprint().getSetup()
         ));
-        return setups.size() == 1 ? Iterables.getFirst(setups, null) : null;
+        final IceUdpTransportInfo.Setup setup = Iterables.getFirst(setups, null);
+        if (setups.size() == 1 && setup != null) {
+            return setup;
+        }
+        throw new IllegalStateException("Content map doesn't have distinct DTLS setup");
     }
 
     public boolean emptyCandidates() {