@@ -72,4 +72,15 @@ public abstract class AbstractJingleConnection {
return Objects.hashCode(account.getJid(), with, sessionId);
}
}
+
+
+ public enum State {
+ NULL, //default value; nothing has been sent or received yet
+ PROPOSED,
+ ACCEPTED,
+ PROCEED,
+ SESSION_INITIALIZED, //equal to 'PENDING'
+ SESSION_ACCEPTED, //equal to 'ACTIVE'
+ TERMINATED //equal to 'ENDED'
+ }
}
@@ -2,13 +2,32 @@ package eu.siacs.conversations.xmpp.jingle;
import android.util.Log;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Collection;
+import java.util.Map;
+
import eu.siacs.conversations.Config;
import eu.siacs.conversations.xml.Element;
+import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
+import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid;
public class JingleRtpConnection extends AbstractJingleConnection {
+ private static final Map<State, Collection<State>> VALID_TRANSITIONS;
+
+ static {
+ final ImmutableMap.Builder<State, Collection<State>> transitionBuilder = new ImmutableMap.Builder<>();
+ transitionBuilder.put(State.NULL, ImmutableList.of(State.PROPOSED, State.SESSION_INITIALIZED));
+ transitionBuilder.put(State.PROPOSED, ImmutableList.of(State.ACCEPTED, State.PROCEED));
+ VALID_TRANSITIONS = transitionBuilder.build();
+ }
+
+ private State state = State.NULL;
+
public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id) {
super(jingleConnectionManager, id);
@@ -17,9 +36,70 @@ public class JingleRtpConnection extends AbstractJingleConnection {
@Override
void deliverPacket(final JinglePacket jinglePacket) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": packet delivered to JingleRtpConnection");
+ Log.d(Config.LOGTAG, jinglePacket.toString());
}
- void deliveryMessage(final Jid to, Jid from, Element message) {
+ void deliveryMessage(final Jid to, final Jid from, final Element message) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": delivered message to JingleRtpConnection " + message);
+ final boolean originatedFromMyself = from.asBareJid().equals(id.account.getJid().asBareJid());
+ switch (message.getName()) {
+ case "propose":
+ if (originatedFromMyself) {
+ Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": saw proposal from mysql. ignoring");
+ } else if (transition(State.PROPOSED)) {
+ //TODO start ringing or something
+ pickUpCall();
+ } else {
+ Log.d(Config.LOGTAG, id.account.getJid() + ": ignoring session proposal because already in " + state);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ public void pickUpCall() {
+ switch (this.state) {
+ case PROPOSED:
+ pickupCallFromProposed();
+ break;
+ case SESSION_INITIALIZED:
+ pickupCallFromSessionInitialized();
+ break;
+ default:
+ throw new IllegalStateException("Can not pick up call from " + this.state);
+ }
+ }
+
+ private void pickupCallFromProposed() {
+ transitionOrThrow(State.PROCEED);
+ final MessagePacket messagePacket = new MessagePacket();
+ messagePacket.setTo(id.with);
+ //Note that Movim needs 'accept'
+ messagePacket.addChild("proceed", Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId);
+ Log.d(Config.LOGTAG, messagePacket.toString());
+ xmppConnectionService.sendMessagePacket(id.account, messagePacket);
}
+
+ private void pickupCallFromSessionInitialized() {
+
+ }
+
+ private synchronized boolean transition(final State target) {
+ final Collection<State> validTransitions = VALID_TRANSITIONS.get(this.state);
+ if (validTransitions != null && validTransitions.contains(target)) {
+ this.state = target;
+ Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": transitioned into " + target);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private void transitionOrThrow(final State target) {
+ if (!transition(target)) {
+ throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target));
+ }
+ }
+
}
@@ -11,6 +11,8 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class JinglePacket extends IqPacket {
+ //TODO add support for groups: https://xmpp.org/extensions/xep-0338.html
+
private JinglePacket() {
super();
}
@@ -30,6 +32,7 @@ public class JinglePacket extends IqPacket {
return jinglePacket;
}
+ //TODO can have multiple contents
public Content getJingleContent() {
final Element content = getJingleChild("content");
return content == null ? null : Content.upgrade(content);