store 'ended call' when ended from proceed

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java | 43 
src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java     |  1 
2 files changed, 43 insertions(+), 1 deletion(-)

Detailed changes

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

@@ -7,6 +7,8 @@ import android.util.Log;
 import com.google.common.base.Function;
 import com.google.common.base.Objects;
 import com.google.common.base.Preconditions;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableSet;
 
@@ -21,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 import eu.siacs.conversations.Config;
 import eu.siacs.conversations.entities.Account;
@@ -49,6 +52,10 @@ public class JingleConnectionManager extends AbstractConnectionManager {
     private final HashMap<RtpSessionProposal, DeviceDiscoveryState> rtpSessionProposals = new HashMap<>();
     private final Map<AbstractJingleConnection.Id, AbstractJingleConnection> connections = new ConcurrentHashMap<>();
 
+    private final Cache<PersistableSessionId, JingleRtpConnection.State> endedSessions = CacheBuilder.newBuilder()
+            .expireAfterWrite(30, TimeUnit.MINUTES)
+            .build();
+
     private HashMap<Jid, JingleCandidate> primaryCandidates = new HashMap<>();
 
     public JingleConnectionManager(XmppConnectionService service) {
@@ -79,7 +86,9 @@ public class JingleConnectionManager extends AbstractConnectionManager {
             if (FileTransferDescription.NAMESPACES.contains(descriptionNamespace)) {
                 connection = new JingleFileTransferConnection(this, id, from);
             } else if (Namespace.JINGLE_APPS_RTP.equals(descriptionNamespace) && !usesTor(account)) {
-                if (isBusy()) {
+                final boolean sessionEnded = this.endedSessions.asMap().containsKey(PersistableSessionId.of(id));
+                if (isBusy() || sessionEnded) {
+                    Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": rejected session with " + id.with + " because busy. sessionEnded=" + sessionEnded);
                     mXmppConnectionService.sendIqPacket(account, packet.generateResponse(IqPacket.TYPE.RESULT), null);
                     final JinglePacket sessionTermination = new JinglePacket(JinglePacket.Action.SESSION_TERMINATE, id.sessionId);
                     sessionTermination.setTo(id.with);
@@ -523,6 +532,38 @@ public class JingleConnectionManager extends AbstractConnectionManager {
         throw new IllegalStateException("JingleConnection has not been registered with connection manager");
     }
 
+    public void endSession(AbstractJingleConnection.Id id, final AbstractJingleConnection.State state) {
+        this.endedSessions.put(PersistableSessionId.of(id), state);
+    }
+
+    private static class PersistableSessionId {
+        private final Jid with;
+        private final String sessionId;
+
+        private PersistableSessionId(Jid with, String sessionId) {
+            this.with = with;
+            this.sessionId = sessionId;
+        }
+
+        public static PersistableSessionId of(AbstractJingleConnection.Id id) {
+            return new PersistableSessionId(id.with, id.sessionId);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            PersistableSessionId that = (PersistableSessionId) o;
+            return Objects.equal(with, that.with) &&
+                    Objects.equal(sessionId, that.sessionId);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(with, sessionId);
+        }
+    }
+
     public enum DeviceDiscoveryState {
         SEARCHING, DISCOVERED, FAILED;
 

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

@@ -819,6 +819,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
         }
         if (isInState(State.PROCEED)) {
             Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": ending call while in state PROCEED just means ending the connection");
+            this.jingleConnectionManager.endSession(id, State.TERMINATED_SUCCESS);
             this.webRTCWrapper.close();
             this.finish();
             transitionOrThrow(State.TERMINATED_SUCCESS); //arguably this wasn't success; but not a real failure either