create temporary RtpSessionPropsoal as placeholder before we can create actual session

This commit is contained in:
Daniel Gultsch 2020-04-04 11:31:53 +02:00
parent e2e4390d51
commit 3b857e6894
4 changed files with 95 additions and 14 deletions

View File

@ -18,6 +18,7 @@ import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
@ -231,4 +232,13 @@ public class MessageGenerator extends AbstractGenerator {
packet.addChild("store", "urn:xmpp:hints"); packet.addChild("store", "urn:xmpp:hints");
return packet; return packet;
} }
public MessagePacket sessionProposal(JingleConnectionManager.RtpSessionProposal proposal) {
final MessagePacket packet = new MessagePacket();
packet.setTo(proposal.with);
final Element propose = packet.addChild("propose", Namespace.JINGLE_MESSAGE);
propose.setAttribute("id", proposal.sessionId);
propose.addChild("description", Namespace.JINGLE_APPS_RTP);
return packet;
}
} }

View File

@ -1232,12 +1232,20 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
BlockContactDialog.show((XmppActivity) activity, conversation); BlockContactDialog.show((XmppActivity) activity, conversation);
} }
break; break;
case R.id.action_call:
triggerRtpSession();
break;
default: default:
break; break;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
private void triggerRtpSession() {
final Contact contact = conversation.getContact();
activity.xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(conversation.getAccount(), contact);
}
private void handleAttachmentSelection(MenuItem item) { private void handleAttachmentSelection(MenuItem item) {
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.attach_choose_picture: case R.id.attach_choose_picture:

View File

@ -2,15 +2,19 @@ package eu.siacs.conversations.xmpp.jingle;
import android.util.Log; import android.util.Log;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.Transferable; import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.services.AbstractConnectionManager; import eu.siacs.conversations.services.AbstractConnectionManager;
@ -22,10 +26,12 @@ import eu.siacs.conversations.xmpp.jingle.stanzas.Content;
import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription; import eu.siacs.conversations.xmpp.jingle.stanzas.FileTransferDescription;
import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket; import eu.siacs.conversations.xmpp.jingle.stanzas.JinglePacket;
import eu.siacs.conversations.xmpp.stanzas.IqPacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
public class JingleConnectionManager extends AbstractConnectionManager { public class JingleConnectionManager extends AbstractConnectionManager {
private Map<AbstractJingleConnection.Id, AbstractJingleConnection> connections = new ConcurrentHashMap<>(); private final Set<RtpSessionProposal> rtpSessionProposals = new HashSet<>();
private final Map<AbstractJingleConnection.Id, AbstractJingleConnection> connections = new ConcurrentHashMap<>();
private HashMap<Jid, JingleCandidate> primaryCandidates = new HashMap<>(); private HashMap<Jid, JingleCandidate> primaryCandidates = new HashMap<>();
@ -95,6 +101,22 @@ public class JingleConnectionManager extends AbstractConnectionManager {
} else { } else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to react to proposed " + namespace + " session"); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to react to proposed " + namespace + " session");
} }
} else if ("proceed".equals(message.getName())) {
if (!with.equals(from)) {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": ignore carbon copied proceed");
return;
}
final RtpSessionProposal proposal = new RtpSessionProposal(account, with.asBareJid(), sessionId);
synchronized (rtpSessionProposals) {
if (rtpSessionProposals.remove(proposal)) {
final JingleRtpConnection rtpConnection = new JingleRtpConnection(this, id, account.getJid());
this.connections.put(id, rtpConnection);
rtpConnection.transitionOrThrow(AbstractJingleConnection.State.PROPOSED);
rtpConnection.deliveryMessage(from, message);
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": no rtp session proposal found for " + with);
}
}
} else { } else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": retrieved out of order jingle message"); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": retrieved out of order jingle message");
} }
@ -165,6 +187,16 @@ public class JingleConnectionManager extends AbstractConnectionManager {
} }
} }
public void proposeJingleRtpSession(final Account account, final Contact contact) {
final RtpSessionProposal proposal = RtpSessionProposal.of(account, contact.getJid().asBareJid());
synchronized (this.rtpSessionProposals) {
this.rtpSessionProposals.add(proposal);
final MessagePacket messagePacket = mXmppConnectionService.getMessageGenerator().sessionProposal(proposal);
Log.d(Config.LOGTAG,messagePacket.toString());
mXmppConnectionService.sendMessagePacket(account, messagePacket);
}
}
static String nextRandomId() { static String nextRandomId() {
return UUID.randomUUID().toString(); return UUID.randomUUID().toString();
} }
@ -211,4 +243,35 @@ public class JingleConnectionManager extends AbstractConnectionManager {
}*/ }*/
} }
} }
public static class RtpSessionProposal {
private final Account account;
public final Jid with;
public final String sessionId;
private RtpSessionProposal(Account account, Jid with, String sessionId) {
this.account = account;
this.with = with;
this.sessionId = sessionId;
}
public static RtpSessionProposal of(Account account, Jid with) {
return new RtpSessionProposal(account, with, UUID.randomUUID().toString());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RtpSessionProposal proposal = (RtpSessionProposal) o;
return Objects.equal(account.getJid(), proposal.account.getJid()) &&
Objects.equal(with, proposal.with) &&
Objects.equal(sessionId, proposal.sessionId);
}
@Override
public int hashCode() {
return Objects.hashCode(account.getJid(), with, sessionId);
}
}
} }

View File

@ -128,7 +128,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
private void receiveProceed(final Jid from, final Element proceed) { private void receiveProceed(final Jid from, final Element proceed) {
if (from.equals(id.with)) { if (from.equals(id.with)) {
if (isInitiator()) { if (isInitiator()) {
if (transition(State.SESSION_INITIALIZED)) { if (transition(State.PROCEED)) {
this.sendSessionInitiate(); this.sendSessionInitiate();
} else { } else {
Log.d(Config.LOGTAG, String.format("%s: ignoring proceed because already in %s", id.account.getJid().asBareJid(), this.state)); Log.d(Config.LOGTAG, String.format("%s: ignoring proceed because already in %s", id.account.getJid().asBareJid(), this.state));
@ -142,7 +142,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
} }
private void sendSessionInitiate() { private void sendSessionInitiate() {
Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": sending session-initiate");
} }
private void sendSessionAccept() { private void sendSessionAccept() {
@ -167,7 +167,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
final MessagePacket messagePacket = new MessagePacket(); final MessagePacket messagePacket = new MessagePacket();
messagePacket.setTo(id.with); messagePacket.setTo(id.with);
//Note that Movim needs 'accept', correct is 'proceed' https://github.com/movim/movim/issues/916 //Note that Movim needs 'accept', correct is 'proceed' https://github.com/movim/movim/issues/916
messagePacket.addChild("accept", Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId); messagePacket.addChild("proceed", Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId);
Log.d(Config.LOGTAG, messagePacket.toString()); Log.d(Config.LOGTAG, messagePacket.toString());
xmppConnectionService.sendMessagePacket(id.account, messagePacket); xmppConnectionService.sendMessagePacket(id.account, messagePacket);
} }
@ -187,7 +187,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
} }
} }
private void transitionOrThrow(final State target) { public void transitionOrThrow(final State target) {
if (!transition(target)) { if (!transition(target)) {
throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target)); throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target));
} }