From 3b857e6894df3297496f72ee2df2a51b6111b2b7 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 4 Apr 2020 11:31:53 +0200 Subject: [PATCH] create temporary RtpSessionPropsoal as placeholder before we can create actual session --- .../generator/MessageGenerator.java | 10 +++ .../ui/ConversationFragment.java | 26 +++++--- .../xmpp/jingle/JingleConnectionManager.java | 65 ++++++++++++++++++- .../xmpp/jingle/JingleRtpConnection.java | 8 +-- 4 files changed, 95 insertions(+), 14 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 56445e0d6..423ed9f91 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -18,6 +18,7 @@ import eu.siacs.conversations.services.XmppConnectionService; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.chatstate.ChatState; +import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import rocks.xmpp.addr.Jid; @@ -231,4 +232,13 @@ public class MessageGenerator extends AbstractGenerator { packet.addChild("store", "urn:xmpp:hints"); 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; + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 11f8274eb..bb76d7256 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -199,7 +199,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke private OnClickListener acceptJoin = new OnClickListener() { @Override public void onClick(View v) { - conversation.setAttribute("accept_non_anonymous",true); + conversation.setAttribute("accept_non_anonymous", true); activity.xmppConnectionService.updateConversation(conversation); activity.xmppConnectionService.joinMuc(conversation); } @@ -1127,7 +1127,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke showErrorMessage.setVisible(true); } final String mime = m.isFileOrImage() ? m.getMimeType() : null; - if ((m.isGeoUri() && GeoHelper.openInOsmAnd(getActivity(),m)) || (mime != null && mime.startsWith("audio/"))) { + if ((m.isGeoUri() && GeoHelper.openInOsmAnd(getActivity(), m)) || (mime != null && mime.startsWith("audio/"))) { openWith.setVisible(true); } } @@ -1232,12 +1232,20 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke BlockContactDialog.show((XmppActivity) activity, conversation); } break; + case R.id.action_call: + triggerRtpSession(); + break; default: break; } return super.onOptionsItemSelected(item); } + private void triggerRtpSession() { + final Contact contact = conversation.getContact(); + activity.xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(conversation.getAccount(), contact); + } + private void handleAttachmentSelection(MenuItem item) { switch (item.getItemId()) { case R.id.attach_choose_picture: @@ -1431,7 +1439,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } else if (message.treatAsDownloadable() || message.hasFileOnRemoteHost() || MessageUtils.unInitiatedButKnownSize(message)) { createNewConnection(message); } else { - Log.d(Config.LOGTAG,message.getConversation().getAccount()+": unable to start downloadable"); + Log.d(Config.LOGTAG, message.getConversation().getAccount() + ": unable to start downloadable"); } } @@ -1621,7 +1629,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke private void openWith(final Message message) { if (message.isGeoUri()) { - GeoHelper.view(getActivity(),message); + GeoHelper.view(getActivity(), message); } else { final DownloadableFile file = activity.xmppConnectionService.getFileBackend().getFile(message); ViewUtil.view(activity, file); @@ -1641,8 +1649,8 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } builder.setMessage(displayError); builder.setNegativeButton(R.string.copy_to_clipboard, (dialog, which) -> { - activity.copyTextToClipboard(displayError,R.string.error_message); - Toast.makeText(activity,R.string.error_message_copied_to_clipboard, Toast.LENGTH_SHORT).show(); + activity.copyTextToClipboard(displayError, R.string.error_message); + Toast.makeText(activity, R.string.error_message_copied_to_clipboard, Toast.LENGTH_SHORT).show(); }); builder.setPositiveButton(R.string.confirm, null); builder.create().show(); @@ -2744,10 +2752,10 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke Log.e(Config.LOGTAG, "cleared pending photo uri"); } if (pendingConversationsUuid.clear()) { - Log.e(Config.LOGTAG,"cleared pending conversations uuid"); + Log.e(Config.LOGTAG, "cleared pending conversations uuid"); } if (pendingMediaPreviews.clear()) { - Log.e(Config.LOGTAG,"cleared pending media previews"); + Log.e(Config.LOGTAG, "cleared pending media previews"); } } @@ -2765,7 +2773,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke } final PopupMenu popupMenu = new PopupMenu(getActivity(), v); final Contact contact = message.getContact(); - if (message.getStatus() <= Message.STATUS_RECEIVED && (contact == null || !contact.isSelf())) { + if (message.getStatus() <= Message.STATUS_RECEIVED && (contact == null || !contact.isSelf())) { if (message.getConversation().getMode() == Conversation.MODE_MULTI) { final Jid cp = message.getCounterpart(); if (cp == null || cp.isBareJid()) { diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java index ae951ddfe..146892e82 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -2,15 +2,19 @@ package eu.siacs.conversations.xmpp.jingle; import android.util.Log; +import com.google.common.base.Objects; import com.google.common.base.Preconditions; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.Message; import eu.siacs.conversations.entities.Transferable; 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.JinglePacket; import eu.siacs.conversations.xmpp.stanzas.IqPacket; +import eu.siacs.conversations.xmpp.stanzas.MessagePacket; import rocks.xmpp.addr.Jid; public class JingleConnectionManager extends AbstractConnectionManager { - private Map connections = new ConcurrentHashMap<>(); + private final Set rtpSessionProposals = new HashSet<>(); + private final Map connections = new ConcurrentHashMap<>(); private HashMap primaryCandidates = new HashMap<>(); @@ -95,6 +101,22 @@ public class JingleConnectionManager extends AbstractConnectionManager { } else { 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 { 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() { 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); + } + } } diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index df2fb9823..399688266 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -128,7 +128,7 @@ public class JingleRtpConnection extends AbstractJingleConnection { private void receiveProceed(final Jid from, final Element proceed) { if (from.equals(id.with)) { if (isInitiator()) { - if (transition(State.SESSION_INITIALIZED)) { + if (transition(State.PROCEED)) { this.sendSessionInitiate(); } else { 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() { - + Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": sending session-initiate"); } private void sendSessionAccept() { @@ -167,7 +167,7 @@ public class JingleRtpConnection extends AbstractJingleConnection { final MessagePacket messagePacket = new MessagePacket(); messagePacket.setTo(id.with); //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()); 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)) { throw new IllegalStateException(String.format("Unable to transition from %s to %s", this.state, target)); }