1package eu.siacs.conversations.xmpp.jingle;
2
3import androidx.annotation.NonNull;
4
5import com.google.common.base.MoreObjects;
6import com.google.common.base.Objects;
7import com.google.common.base.Preconditions;
8
9import eu.siacs.conversations.entities.Account;
10import eu.siacs.conversations.entities.Contact;
11import eu.siacs.conversations.entities.Message;
12import eu.siacs.conversations.services.XmppConnectionService;
13import eu.siacs.conversations.xmpp.Jid;
14import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
15
16public abstract class AbstractJingleConnection {
17
18 public static final String JINGLE_MESSAGE_PROPOSE_ID_PREFIX = "jm-propose-";
19 public static final String JINGLE_MESSAGE_PROCEED_ID_PREFIX = "jm-proceed-";
20
21 final JingleConnectionManager jingleConnectionManager;
22 protected final XmppConnectionService xmppConnectionService;
23 protected final Id id;
24 private final Jid initiator;
25
26 AbstractJingleConnection(final JingleConnectionManager jingleConnectionManager, final Id id, final Jid initiator) {
27 this.jingleConnectionManager = jingleConnectionManager;
28 this.xmppConnectionService = jingleConnectionManager.getXmppConnectionService();
29 this.id = id;
30 this.initiator = initiator;
31 }
32
33 boolean isInitiator() {
34 return initiator.equals(id.account.getJid());
35 }
36
37 abstract void deliverPacket(JinglePacket jinglePacket);
38
39 public Id getId() {
40 return id;
41 }
42
43 abstract void notifyRebound();
44
45
46 public static class Id implements OngoingRtpSession {
47 public final Account account;
48 public final Jid with;
49 public final String sessionId;
50
51 private Id(final Account account, final Jid with, final String sessionId) {
52 Preconditions.checkNotNull(account);
53 Preconditions.checkNotNull(with);
54 Preconditions.checkNotNull(sessionId);
55 this.account = account;
56 this.with = with;
57 this.sessionId = sessionId;
58 }
59
60 public static Id of(Account account, JinglePacket jinglePacket) {
61 return new Id(account, jinglePacket.getFrom(), jinglePacket.getSessionId());
62 }
63
64 public static Id of(Account account, Jid with, final String sessionId) {
65 return new Id(account, with, sessionId);
66 }
67
68 public static Id of(Account account, Jid with) {
69 return new Id(account, with, JingleConnectionManager.nextRandomId());
70 }
71
72 public static Id of(Message message) {
73 return new Id(
74 message.getConversation().getAccount(),
75 message.getCounterpart(),
76 JingleConnectionManager.nextRandomId()
77 );
78 }
79
80 public Contact getContact() {
81 return account.getRoster().getContact(with);
82 }
83
84 @Override
85 public boolean equals(Object o) {
86 if (this == o) return true;
87 if (o == null || getClass() != o.getClass()) return false;
88 Id id = (Id) o;
89 return Objects.equal(account.getUuid(), id.account.getUuid()) &&
90 Objects.equal(with, id.with) &&
91 Objects.equal(sessionId, id.sessionId);
92 }
93
94 @Override
95 public int hashCode() {
96 return Objects.hashCode(account.getUuid(), with, sessionId);
97 }
98
99 @Override
100 public Account getAccount() {
101 return account;
102 }
103
104 @Override
105 public Jid getWith() {
106 return with;
107 }
108
109 @Override
110 public String getSessionId() {
111 return sessionId;
112 }
113
114 @Override
115 @NonNull
116 public String toString() {
117 return MoreObjects.toStringHelper(this)
118 .add("account", account.getJid())
119 .add("with", with)
120 .add("sessionId", sessionId)
121 .toString();
122 }
123 }
124
125
126 public enum State {
127 NULL, //default value; nothing has been sent or received yet
128 PROPOSED,
129 ACCEPTED,
130 PROCEED,
131 REJECTED,
132 REJECTED_RACED, //used when we want to reject but haven’t received session init yet
133 RETRACTED,
134 RETRACTED_RACED, //used when receiving a retract after we already asked to proceed
135 SESSION_INITIALIZED, //equal to 'PENDING'
136 SESSION_INITIALIZED_PRE_APPROVED,
137 SESSION_ACCEPTED, //equal to 'ACTIVE'
138 TERMINATED_SUCCESS, //equal to 'ENDED' (after successful call) ui will just close
139 TERMINATED_DECLINED_OR_BUSY, //equal to 'ENDED' (after other party declined the call)
140 TERMINATED_CONNECTIVITY_ERROR, //equal to 'ENDED' (but after network failures; ui will display retry button)
141 TERMINATED_CANCEL_OR_TIMEOUT, //more or less the same as retracted; caller pressed end call before session was accepted
142 TERMINATED_APPLICATION_FAILURE,
143 TERMINATED_SECURITY_ERROR
144 }
145}