~singpolyma/cheogram-android

f4be142e4d70b90f15bd0793e2870e9ceb13629b — Daniel Gultsch 2 years ago e2f98f6
add helper methods for content modification to RtpContentMap
M src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java => src/main/java/eu/siacs/conversations/xmpp/jingle/RtpContentMap.java +78 -2
@@ 1,7 1,9 @@
package eu.siacs.conversations.xmpp.jingle;

import com.google.common.base.MoreObjects;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;


@@ 236,6 238,23 @@ public class RtpContentMap {
        throw new IllegalStateException("Content map doesn't have distinct DTLS setup");
    }

    private DTLS getDistinctDtls() {
        final Set<DTLS> dtlsSet =
                ImmutableSet.copyOf(
                        Collections2.transform(
                                contents.values(),
                                dt -> {
                                    final IceUdpTransportInfo.Fingerprint fp =
                                            dt.transport.getFingerprint();
                                    return new DTLS(fp.getHash(), fp.getSetup(), fp.getContent());
                                }));
        final DTLS dtls = Iterables.getFirst(dtlsSet, null);
        if (dtlsSet.size() == 1 && dtls != null) {
            return dtls;
        }
        throw new IllegalStateException("Content map doesn't have distinct DTLS setup");
    }

    public boolean emptyCandidates() {
        int count = 0;
        for (DescriptionTransport descriptionTransport : contents.values()) {


@@ 262,12 281,22 @@ public class RtpContentMap {
        return new RtpContentMap(this.group, contentMapBuilder.build());
    }

    public RtpContentMap toContentModification(final Collection<String> modifications) {
        return new RtpContentMap(
                this.group,
                Maps.transformValues(
                        Maps.filterKeys(contents, Predicates.in(modifications)),
                        dt ->
                                new DescriptionTransport(
                                        dt.senders, dt.description, IceUdpTransportInfo.STUB)));
    }

    public Diff diff(final RtpContentMap rtpContentMap) {
        final Set<String> existingContentIds = this.contents.keySet();
        final Set<String> newContentIds = rtpContentMap.contents.keySet();
        return new Diff(
                Sets.difference(newContentIds, existingContentIds),
                Sets.difference(existingContentIds, newContentIds));
                ImmutableSet.copyOf(Sets.difference(newContentIds, existingContentIds)),
                ImmutableSet.copyOf(Sets.difference(existingContentIds, newContentIds)));
    }

    public boolean iceRestart(final RtpContentMap rtpContentMap) {


@@ 278,6 307,26 @@ public class RtpContentMap {
        }
    }

    public RtpContentMap addContent(final RtpContentMap modification) {
        final IceUdpTransportInfo.Credentials credentials = getDistinctCredentials();
        final DTLS dtls = getDistinctDtls();
        final IceUdpTransportInfo iceUdpTransportInfo =
                IceUdpTransportInfo.of(credentials, dtls.setup, dtls.hash, dtls.fingerprint);
        final Map<String, DescriptionTransport> combined =
                new ImmutableMap.Builder<String, DescriptionTransport>()
                        .putAll(contents)
                        .putAll(
                                Maps.transformValues(
                                        modification.contents,
                                        dt ->
                                                new DescriptionTransport(
                                                        dt.senders,
                                                        dt.description,
                                                        iceUdpTransportInfo)))
                        .build();
        return new RtpContentMap(modification.group, combined);
    }

    public static class DescriptionTransport {
        public final Content.Senders senders;
        public final RtpDescription description;


@@ 370,4 419,31 @@ public class RtpContentMap {
                    .toString();
        }
    }

    public static final class DTLS {
        public final String hash;
        public final IceUdpTransportInfo.Setup setup;
        public final String fingerprint;

        private DTLS(String hash, IceUdpTransportInfo.Setup setup, String fingerprint) {
            this.hash = hash;
            this.setup = setup;
            this.fingerprint = fingerprint;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            DTLS dtls = (DTLS) o;
            return Objects.equal(hash, dtls.hash)
                    && setup == dtls.setup
                    && Objects.equal(fingerprint, dtls.fingerprint);
        }

        @Override
        public int hashCode() {
            return Objects.hashCode(hash, setup, fingerprint);
        }
    }
}

M src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java => src/main/java/eu/siacs/conversations/xmpp/jingle/WebRTCWrapper.java +8 -1
@@ 186,15 186,22 @@ public class WebRTCWrapper {
                }

                @Override
                public void onTrack(RtpTransceiver transceiver) {
                public void onTrack(final RtpTransceiver transceiver) {
                    Log.d(
                            EXTENDED_LOGGING_TAG,
                            "onTrack(mid="
                                    + transceiver.getMid()
                                    + ",media="
                                    + transceiver.getMediaType()
                                    + ",direction="
                                    + transceiver.getDirection()
                                    + ")");
                }

                @Override
                public void onRemoveTrack(final RtpReceiver receiver) {
                    Log.d(EXTENDED_LOGGING_TAG, "onRemoveTrack(" + receiver.id() + ")");
                }
            };
    @Nullable private PeerConnectionFactory peerConnectionFactory = null;
    @Nullable private PeerConnection peerConnection = null;

M src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java => src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/IceUdpTransportInfo.java +51 -19
@@ 12,8 12,6 @@ import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;


@@ 28,23 26,29 @@ import eu.siacs.conversations.xmpp.jingle.SessionDescription;

public class IceUdpTransportInfo extends GenericTransportInfo {

    public static final IceUdpTransportInfo STUB = new IceUdpTransportInfo();

    public IceUdpTransportInfo() {
        super("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
    }

    public static IceUdpTransportInfo upgrade(final Element element) {
        Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
        Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
        Preconditions.checkArgument(
                "transport".equals(element.getName()), "Name of provided element is not transport");
        Preconditions.checkArgument(
                Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()),
                "Element does not match ice-udp transport namespace");
        final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
        transportInfo.setAttributes(element.getAttributes());
        transportInfo.setChildren(element.getChildren());
        return transportInfo;
    }

    public static IceUdpTransportInfo of(SessionDescription sessionDescription, SessionDescription.Media media) {
    public static IceUdpTransportInfo of(
            SessionDescription sessionDescription, SessionDescription.Media media) {
        final String ufrag = Iterables.getFirst(media.attributes.get("ice-ufrag"), null);
        final String pwd = Iterables.getFirst(media.attributes.get("ice-pwd"), null);
        IceUdpTransportInfo iceUdpTransportInfo = new IceUdpTransportInfo();
        final IceUdpTransportInfo iceUdpTransportInfo = new IceUdpTransportInfo();
        if (ufrag != null) {
            iceUdpTransportInfo.setAttribute("ufrag", ufrag);
        }


@@ 56,7 60,15 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            iceUdpTransportInfo.addChild(fingerprint);
        }
        return iceUdpTransportInfo;
    }

    public static IceUdpTransportInfo of(
            final Credentials credentials,  final Setup setup, final String hash, final String fingerprint) {
        final IceUdpTransportInfo iceUdpTransportInfo = new IceUdpTransportInfo();
        iceUdpTransportInfo.addChild(Fingerprint.of(setup, hash, fingerprint));
        iceUdpTransportInfo.setAttribute("ufrag", credentials.ufrag);
        iceUdpTransportInfo.setAttribute("pwd", credentials.password);
        return iceUdpTransportInfo;
    }

    public Fingerprint getFingerprint() {


@@ 91,7 103,8 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
        transportInfo.setAttribute("ufrag", credentials.ufrag);
        transportInfo.setAttribute("pwd", credentials.password);
        for (final Element child : getChildren()) {
            if (child.getName().equals("fingerprint") && Namespace.JINGLE_APPS_DTLS.equals(child.getNamespace())) {
            if (child.getName().equals("fingerprint")
                    && Namespace.JINGLE_APPS_DTLS.equals(child.getNamespace())) {
                final Fingerprint fingerprint = new Fingerprint();
                fingerprint.setAttributes(new Hashtable<>(child.getAttributes()));
                fingerprint.setContent(child.getContent());


@@ 231,7 244,7 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            return getAttributeAsInt("rel-port");
        }

        public String getType() { //TODO might be converted to enum
        public String getType() { // TODO might be converted to enum
            return getAttribute("type");
        }



@@ 256,7 269,8 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            checkNotNullNoWhitespace(protocol, "protocol");
            final String transport = protocol.toLowerCase(Locale.ROOT);
            if (!"udp".equals(transport)) {
                throw new IllegalArgumentException(String.format("'%s' is not a supported protocol", transport));
                throw new IllegalArgumentException(
                        String.format("'%s' is not a supported protocol", transport));
            }
            final String priority = this.getAttribute("priority");
            checkNotNullNoWhitespace(priority, "priority");


@@ 284,7 298,15 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            if (ufrag != null) {
                additionalParameter.put("ufrag", ufrag);
            }
            final String parametersString = Joiner.on(' ').join(Collections2.transform(additionalParameter.entrySet(), input -> String.format("%s %s", input.getKey(), input.getValue())));
            final String parametersString =
                    Joiner.on(' ')
                            .join(
                                    Collections2.transform(
                                            additionalParameter.entrySet(),
                                            input ->
                                                    String.format(
                                                            "%s %s",
                                                            input.getKey(), input.getValue())));
            return String.format(
                    "candidate:%s %s %s %s %s %s %s",
                    foundation,


@@ 293,20 315,19 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
                    priority,
                    connectionAddress,
                    port,
                    parametersString

            );
                    parametersString);
        }
    }

    private static void checkNotNullNoWhitespace(final String value, final String name) {
        if (Strings.isNullOrEmpty(value)) {
            throw new IllegalArgumentException(String.format("Parameter %s is missing or empty", name));
            throw new IllegalArgumentException(
                    String.format("Parameter %s is missing or empty", name));
        }
        SessionDescription.checkNoWhitespace(value, String.format("Parameter %s contains white spaces", name));
        SessionDescription.checkNoWhitespace(
                value, String.format("Parameter %s contains white spaces", name));
    }


    public static class Fingerprint extends Element {

        private Fingerprint() {


@@ 340,11 361,20 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            return null;
        }

        public static Fingerprint of(final SessionDescription sessionDescription, final SessionDescription.Media media) {
        public static Fingerprint of(
                final SessionDescription sessionDescription, final SessionDescription.Media media) {
            final Fingerprint fingerprint = of(media.attributes);
            return fingerprint == null ? of(sessionDescription.attributes) : fingerprint;
        }

        private static Fingerprint of(final Setup setup, final String hash, final String content) {
            final Fingerprint fingerprint = new Fingerprint();
            fingerprint.setContent(content);
            fingerprint.setAttribute("hash", hash);
            fingerprint.setAttribute("setup", setup.toString().toLowerCase(Locale.ROOT));
            return fingerprint;
        }

        public String getHash() {
            return this.getAttribute("hash");
        }


@@ 356,7 386,9 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
    }

    public enum Setup {
        ACTPASS, PASSIVE, ACTIVE;
        ACTPASS,
        PASSIVE,
        ACTIVE;

        public static Setup of(String setup) {
            try {


@@ 373,7 405,7 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
            if (this == ACTIVE) {
                return PASSIVE;
            }
            throw new IllegalStateException(this.name()+" can not be flipped");
            throw new IllegalStateException(this.name() + " can not be flipped");
        }
    }
}