diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index 4e99ab086..18322453e 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -21,6 +21,7 @@ import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.jingle.JingleConnectionManager; import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection; import eu.siacs.conversations.xmpp.jingle.Media; +import eu.siacs.conversations.xmpp.jingle.stanzas.Reason; import eu.siacs.conversations.xmpp.stanzas.MessagePacket; public class MessageGenerator extends AbstractGenerator { @@ -228,6 +229,20 @@ public class MessageGenerator extends AbstractGenerator { return packet; } + public MessagePacket sessionFinish( + final Jid with, final String sessionId, final Reason reason) { + final MessagePacket packet = new MessagePacket(); + packet.setType(MessagePacket.TYPE_CHAT); + packet.setTo(with); + packet.setId(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX + sessionId); + final Element finish = packet.addChild("finish", Namespace.JINGLE_MESSAGE); + finish.setAttribute("id", sessionId); + final Element reasonElement = finish.addChild("reason", Namespace.JINGLE); + reasonElement.addChild(reason.toString()); + packet.addChild("store", "urn:xmpp:hints"); + return packet; + } + public MessagePacket sessionProposal(final JingleConnectionManager.RtpSessionProposal proposal) { final MessagePacket packet = new MessagePacket(); packet.setType(MessagePacket.TYPE_CHAT); //we want to carbon copy those @@ -238,7 +253,6 @@ public class MessageGenerator extends AbstractGenerator { for (final Media media : proposal.media) { propose.addChild("description", Namespace.JINGLE_APPS_RTP).setAttribute("media", media.toString()); } - packet.addChild("request", "urn:xmpp:receipts"); packet.addChild("store", "urn:xmpp:hints"); return packet; diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index bf3cba178..d20e4dd46 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -53,7 +53,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss", Locale.ENGLISH); private static final List JINGLE_MESSAGE_ELEMENT_NAMES = - Arrays.asList("accept", "propose", "proceed", "reject", "retract", "ringing"); + Arrays.asList("accept", "propose", "proceed", "reject", "retract", "ringing", "finish"); public MessageParser(XmppConnectionService service) { super(service); @@ -913,6 +913,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece Log.d(Config.LOGTAG, "unable to find original rtp session message for received propose"); } + } else if ("finish".equals(action)) { + Log.d(Config.LOGTAG,"received JMI 'finish' during MAM catch-up. Can be used to update success/failure and duration"); } } else { //MAM reloads (non catchups diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java index de39abb51..013a3964a 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java @@ -30,16 +30,19 @@ import com.google.common.util.concurrent.SettableFuture; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.ui.RtpSessionActivity; import eu.siacs.conversations.xmpp.Jid; import eu.siacs.conversations.xmpp.jingle.AbstractJingleConnection; import eu.siacs.conversations.xmpp.jingle.JingleRtpConnection; import eu.siacs.conversations.xmpp.jingle.Media; import eu.siacs.conversations.xmpp.jingle.RtpEndUserState; +import eu.siacs.conversations.xmpp.jingle.stanzas.Reason; import java.util.Collection; import java.util.Collections; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -108,6 +111,9 @@ public class CallIntegrationConnectionService extends ConnectionService { callIntegration = Connection.createFailedConnection( new DisconnectCause(DisconnectCause.ERROR, "contact is offline")); + // we can use a JMI 'finish' message to notify the contact of a call we never + // actually attempted + // sendJingleFinishMessage(service, contact, Reason.CONNECTIVITY_ERROR); } else { final var proposal = service.getJingleConnectionManager() @@ -137,6 +143,12 @@ public class CallIntegrationConnectionService extends ConnectionService { return callIntegration; } + private static void sendJingleFinishMessage( + final XmppConnectionService service, final Contact contact, final Reason reason) { + service.getJingleConnectionManager() + .sendJingleMessageFinish(contact, UUID.randomUUID().toString(), reason); + } + @Override public Connection onCreateOutgoingConnection( final PhoneAccountHandle phoneAccountHandle, final ConnectionRequest request) { 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 e90a35a0c..c07a3b60f 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleConnectionManager.java @@ -746,6 +746,16 @@ public class JingleConnectionManager extends AbstractConnectionManager { } } + public void sendJingleMessageFinish( + final Contact contact, final String sessionId, final Reason reason) { + final var account = contact.getAccount(); + final MessagePacket messagePacket = + mXmppConnectionService + .getMessageGenerator() + .sessionFinish(contact.getJid(), sessionId, reason); + mXmppConnectionService.sendMessagePacket(account, messagePacket); + } + public boolean hasMatchingProposal(final Account account, final Jid with) { synchronized (this.rtpSessionProposals) { for (Map.Entry entry :