@@ -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<Map.Entry<String, RtpContentMap.DescriptionTransport>> 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<String> 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<Content.Senders> 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);
@@ -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<Senders> receiveOnly(final boolean initiator) {
+ return ImmutableSet.of(initiator ? RESPONDER : INITIATOR);
+ }
+
@Override
@NonNull
public String toString() {