From 4e425709a3a606c7c972c762999f23631f7c31be Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Wed, 11 Oct 2023 11:38:09 +0200 Subject: [PATCH] upgrade to 'both' upon accepting recvonly content-add --- .../xmpp/jingle/JingleRtpConnection.java | 59 ++++++++++++++----- .../xmpp/jingle/stanzas/Content.java | 5 ++ 2 files changed, 49 insertions(+), 15 deletions(-) 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 5b6c2b215477f480444367ff0e4f735867251506..384ec235fb0f4647611195926be5e9f51631e7a7 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -65,6 +65,7 @@ import eu.siacs.conversations.utils.IP; import eu.siacs.conversations.xml.Element; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; +import eu.siacs.conversations.xmpp.OnIqPacketReceived; import eu.siacs.conversations.xmpp.jingle.stanzas.Content; import eu.siacs.conversations.xmpp.jingle.stanzas.Group; import eu.siacs.conversations.xmpp.jingle.stanzas.IceUdpTransportInfo; @@ -361,23 +362,32 @@ public class JingleRtpConnection extends AbstractJingleConnection final JinglePacket jinglePacket, final RtpContentMap contentMap) { final Set> candidates = contentMap.contents.entrySet(); - if (this.state == State.SESSION_ACCEPTED) { - // zero candidates + modified credentials are an ICE restart offer - if (checkForIceRestart(jinglePacket, contentMap)) { - return; - } + final RtpContentMap remote = getRemoteContentMap(); + final Set remoteContentIds = remote == null ? Collections.emptySet() : remote.contents.keySet(); + if (Collections.disjoint(remoteContentIds, contentMap.contents.keySet())) { + Log.d(Config.LOGTAG,"received transport-info for unknown contents "+contentMap.contents.keySet()+" (known: "+remoteContentIds+")"); respondOk(jinglePacket); - try { - processCandidates(candidates); - } catch (final WebRTCWrapper.PeerConnectionNotInitialized e) { - Log.w( - Config.LOGTAG, - id.account.getJid().asBareJid() - + ": PeerConnection was not initialized when processing transport info. this usually indicates a race condition that can be ignored"); - } - } else { + pendingIceCandidates.addAll(candidates); + return; + } + if (this.state != State.SESSION_ACCEPTED) { + Log.d(Config.LOGTAG,"received transport-info prematurely. adding to backlog"); respondOk(jinglePacket); pendingIceCandidates.addAll(candidates); + return; + } + // zero candidates + modified credentials are an ICE restart offer + if (checkForIceRestart(jinglePacket, contentMap)) { + return; + } + respondOk(jinglePacket); + try { + processCandidates(candidates); + } catch (final WebRTCWrapper.PeerConnectionNotInitialized e) { + Log.w( + Config.LOGTAG, + id.account.getJid().asBareJid() + + ": PeerConnection was not initialized when processing transport info. this usually indicates a race condition that can be ignored"); } } @@ -781,7 +791,23 @@ public class JingleRtpConnection extends AbstractJingleConnection if (contentAddition.equals(ContentAddition.summary(incomingContentAdd))) { this.incomingContentAdd = null; - acceptContentAdd(contentAddition, incomingContentAdd); + final Set senders = incomingContentAdd.getSenders(); + Log.d(Config.LOGTAG,"senders of incoming content-add: "+senders); + if (senders.equals(Content.Senders.receiveOnly(isInitiator()))) { + Log.d(Config.LOGTAG,"content addition is receive only. we want to upgrade to 'both'"); + final RtpContentMap modifiedSenders = incomingContentAdd.modifiedSenders(Content.Senders.BOTH); + final JinglePacket proposedContentModification = modifiedSenders.toStub().toJinglePacket(JinglePacket.Action.CONTENT_MODIFY, id.sessionId); + proposedContentModification.setTo(id.with); + xmppConnectionService.sendIqPacket(id.account, proposedContentModification, (account, response) -> { + if (response.getType() == IqPacket.TYPE.RESULT) { + Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": remote has accepted our upgrade to senders=both"); + acceptContentAdd(ContentAddition.summary(modifiedSenders), modifiedSenders); + } else { + Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": remote has rejected our upgrade to senders=both"); + acceptContentAdd(contentAddition, incomingContentAdd); + } + }); + } } else { throw new IllegalStateException("Accepted content add does not match pending content-add"); } @@ -832,6 +858,9 @@ public class JingleRtpConnection extends AbstractJingleConnection id.getAccount().getJid().asBareJid() + ": sending content-accept " + ContentAddition.summary(contentAcceptMap)); + + addIceCandidatesFromBlackLog(); + modifyLocalContentMap(rtpContentMap); sendContentAccept(contentAcceptMap); this.webRTCWrapper.setIsReadyToReceiveIceCandidates(true); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java index 061cea752cd280c23051c92bbf3d11a96ffa315b..0cca6527abf8b7c38cba68966efd331354efe478 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java @@ -6,6 +6,7 @@ import androidx.annotation.NonNull; import com.google.common.base.Preconditions; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableSet; import java.util.Locale; import java.util.Set; @@ -147,6 +148,10 @@ public class Content extends Element { return BOTH; } + public static Set receiveOnly(final boolean initiator) { + return ImmutableSet.of(initiator ? RESPONDER : INITIATOR); + } + @Override @NonNull public String toString() {