~singpolyma/cheogram-android

4e425709a3a606c7c972c762999f23631f7c31be — Daniel Gultsch 4 months ago 8dc854b
upgrade to 'both' upon accepting recvonly content-add
M src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java => src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +44 -15
@@ 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);

M src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java => src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/Content.java +5 -0
@@ 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() {