RtpCapability.java

  1package eu.siacs.conversations.xmpp.jingle;
  2
  3import com.google.common.base.Strings;
  4import com.google.common.collect.Collections2;
  5
  6import java.util.ArrayList;
  7import java.util.Arrays;
  8import java.util.Collection;
  9import java.util.Collections;
 10import java.util.List;
 11import java.util.Map;
 12
 13import eu.siacs.conversations.entities.Contact;
 14import eu.siacs.conversations.entities.Presence;
 15import eu.siacs.conversations.entities.Presences;
 16import eu.siacs.conversations.entities.ServiceDiscoveryResult;
 17import eu.siacs.conversations.xml.Namespace;
 18import eu.siacs.conversations.xmpp.Jid;
 19
 20public class RtpCapability {
 21
 22    private static final List<String> BASIC_RTP_REQUIREMENTS = Arrays.asList(
 23            Namespace.JINGLE,
 24            Namespace.JINGLE_TRANSPORT_ICE_UDP,
 25            Namespace.JINGLE_APPS_RTP,
 26            Namespace.JINGLE_APPS_DTLS
 27    );
 28    private static final List<String> VIDEO_REQUIREMENTS = Arrays.asList(
 29            Namespace.JINGLE_FEATURE_AUDIO,
 30            Namespace.JINGLE_FEATURE_VIDEO
 31    );
 32
 33    public static Capability check(final Presence presence) {
 34        final ServiceDiscoveryResult disco = presence.getServiceDiscoveryResult();
 35        final List<String> features = disco == null ? Collections.emptyList() : disco.getFeatures();
 36        if (features.containsAll(BASIC_RTP_REQUIREMENTS)) {
 37            if (features.containsAll(VIDEO_REQUIREMENTS)) {
 38                return Capability.VIDEO;
 39            }
 40            if (features.contains(Namespace.JINGLE_FEATURE_AUDIO)) {
 41                return Capability.AUDIO;
 42            }
 43        }
 44        return Capability.NONE;
 45    }
 46
 47    public static String[] filterPresences(final Contact contact, Capability required) {
 48        final Presences presences = contact.getPresences();
 49        final ArrayList<String> resources = new ArrayList<>();
 50        for (final Map.Entry<String, Presence> presence : presences.getPresencesMap().entrySet()) {
 51            final Capability capability = check(presence.getValue());
 52            if (capability == Capability.NONE) {
 53                continue;
 54            }
 55            if (required == Capability.AUDIO || capability == required) {
 56                resources.add(presence.getKey());
 57            }
 58        }
 59        return resources.toArray(new String[0]);
 60    }
 61
 62    public static Capability check(final Contact contact) {
 63        return check(contact, true);
 64    }
 65
 66    public static Capability check(final Contact contact, final boolean allowFallback) {
 67        final Presences presences = contact.getPresences();
 68
 69        if (presences.size() == 0 && allowFallback && contact.getAccount().isEnabled()) {
 70            Contact gateway = contact.getAccount().getRoster().getContact(Jid.of(contact.getJid().getDomain()));
 71            if (gateway.showInRoster() && gateway.getPresences().anyIdentity("gateway", "pstn")) {
 72                return Capability.AUDIO;
 73            }
 74
 75            return contact.getRtpCapability();
 76        }
 77        Capability result = Capability.NONE;
 78        for (final Presence presence : presences.getPresences()) {
 79            Capability capability = check(presence);
 80            if (capability == Capability.VIDEO) {
 81                result = capability;
 82            } else if (capability == Capability.AUDIO && result == Capability.NONE) {
 83                result = capability;
 84            }
 85        }
 86        return result;
 87    }
 88
 89    // do all devices that support Rtp Call also support JMI?
 90    public static boolean jmiSupport(final Contact contact) {
 91        return !Collections2.transform(
 92                Collections2.filter(
 93                        contact.getPresences().getPresences(),
 94                        p -> RtpCapability.check(p) != RtpCapability.Capability.NONE),
 95                p -> {
 96                    ServiceDiscoveryResult disco = p.getServiceDiscoveryResult();
 97                    return disco != null && disco.getFeatures().contains(Namespace.JINGLE_MESSAGE);
 98                }).contains(false);
 99    }
100
101    public enum Capability {
102        NONE, AUDIO, VIDEO;
103
104        public static Capability of(String value) {
105            if (Strings.isNullOrEmpty(value)) {
106                return NONE;
107            }
108            try {
109                return valueOf(value);
110            } catch (IllegalArgumentException e) {
111                return NONE;
112            }
113        }
114    }
115
116}