1package eu.siacs.conversations.xmpp.jingle;
2
3import android.util.Log;
4
5import com.google.common.collect.ImmutableList;
6import com.google.common.collect.ImmutableMap;
7
8import java.util.Collection;
9import java.util.Map;
10
11import eu.siacs.conversations.Config;
12import eu.siacs.conversations.xml.Element;
13import eu.siacs.conversations.xml.Namespace;
14import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
15import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
16import rocks.xmpp.addr.Jid;
17
18public class JingleRtpConnection extends AbstractJingleConnection {
19
20 private static final Map<State, Collection<State>> VALID_TRANSITIONS;
21
22 static {
23 final ImmutableMap.Builder<State, Collection<State>> transitionBuilder = new ImmutableMap.Builder<>();
24 transitionBuilder.put(State.NULL, ImmutableList.of(State.PROPOSED, State.SESSION_INITIALIZED));
25 transitionBuilder.put(State.PROPOSED, ImmutableList.of(State.ACCEPTED, State.PROCEED));
26 VALID_TRANSITIONS = transitionBuilder.build();
27 }
28
29 private State state = State.NULL;
30
31
32 public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
33 super(jingleConnectionManager, id, initiator);
34 }
35
36 @Override
37 void deliverPacket(final JinglePacket jinglePacket) {
38 Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": packet delivered to JingleRtpConnection");
39 Log.d(Config.LOGTAG, jinglePacket.toString());
40 }
41
42 void deliveryMessage(final Jid to, final Jid from, final Element message) {
43 Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": delivered message to JingleRtpConnection " + message);
44 final boolean originatedFromMyself = from.asBareJid().equals(id.account.getJid().asBareJid());
45 switch (message.getName()) {
46 case "propose":
47 if (originatedFromMyself) {
48 Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": saw proposal from mysql. ignoring");
49 } else if (transition(State.PROPOSED)) {
50 //TODO start ringing or something
51 pickUpCall();
52 } else {
53 Log.d(Config.LOGTAG, id.account.getJid() + ": ignoring session proposal because already in " + state);
54 }
55 break;
56 default:
57 break;
58 }
59 }
60
61 public void pickUpCall() {
62 switch (this.state) {
63 case PROPOSED:
64 pickupCallFromProposed();
65 break;
66 case SESSION_INITIALIZED:
67 pickupCallFromSessionInitialized();
68 break;
69 default:
70 throw new IllegalStateException("Can not pick up call from " + this.state);
71 }
72 }
73
74 private void pickupCallFromProposed() {
75 transitionOrThrow(State.PROCEED);
76 final MessagePacket messagePacket = new MessagePacket();
77 messagePacket.setTo(id.with);
78 //Note that Movim needs 'accept'
79 messagePacket.addChild("proceed", Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId);
80 Log.d(Config.LOGTAG, messagePacket.toString());
81 xmppConnectionService.sendMessagePacket(id.account, messagePacket);
82 }
83
84 private void pickupCallFromSessionInitialized() {
85
86 }
87
88 private synchronized boolean transition(final State target) {
89 final Collection<State> validTransitions = VALID_TRANSITIONS.get(this.state);
90 if (validTransitions != null && validTransitions.contains(target)) {
91 this.state = target;
92 Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": transitioned into " + target);
93 return true;
94 } else {
95 return false;
96 }
97 }
98
99 private void transitionOrThrow(final State target) {
100 if (!transition(target)) {
101 throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target));
102 }
103 }
104
105}