Content.java

  1package eu.siacs.conversations.xmpp.jingle.stanzas;
  2
  3import android.util.Log;
  4
  5import androidx.annotation.NonNull;
  6
  7import com.google.common.base.Preconditions;
  8import com.google.common.base.Strings;
  9
 10import java.util.Locale;
 11import java.util.Set;
 12
 13import eu.siacs.conversations.Config;
 14import eu.siacs.conversations.xml.Element;
 15import eu.siacs.conversations.xml.Namespace;
 16import eu.siacs.conversations.xmpp.jingle.SessionDescription;
 17
 18public class Content extends Element {
 19
 20    public Content(final Creator creator, final Senders senders, final String name) {
 21        super("content", Namespace.JINGLE);
 22        this.setAttribute("creator", creator.toString());
 23        this.setAttribute("name", name);
 24        this.setSenders(senders);
 25    }
 26
 27    private Content() {
 28        super("content", Namespace.JINGLE);
 29    }
 30
 31    public static Content upgrade(final Element element) {
 32        Preconditions.checkArgument("content".equals(element.getName()));
 33        final Content content = new Content();
 34        content.setAttributes(element.getAttributes());
 35        content.setChildren(element.getChildren());
 36        return content;
 37    }
 38
 39    public String getContentName() {
 40        return this.getAttribute("name");
 41    }
 42
 43    public Creator getCreator() {
 44        return Creator.of(getAttribute("creator"));
 45    }
 46
 47    public Senders getSenders() {
 48        final String attribute = getAttribute("senders");
 49        if (Strings.isNullOrEmpty(attribute)) {
 50            return Senders.BOTH;
 51        }
 52        return Senders.of(getAttribute("senders"));
 53    }
 54
 55    public void setSenders(final Senders senders) {
 56        if (senders != null && senders != Senders.BOTH) {
 57            this.setAttribute("senders", senders.toString());
 58        }
 59    }
 60
 61    public GenericDescription getDescription() {
 62        final Element description = this.findChild("description");
 63        if (description == null) {
 64            return null;
 65        }
 66        final String namespace = description.getNamespace();
 67        if (Namespace.JINGLE_APPS_RTP.equals(namespace)) {
 68            return RtpDescription.upgrade(description);
 69        } else {
 70            return GenericDescription.upgrade(description);
 71        }
 72    }
 73
 74    public void setDescription(final GenericDescription description) {
 75        Preconditions.checkNotNull(description);
 76        this.addChild(description);
 77    }
 78
 79    public String getDescriptionNamespace() {
 80        final Element description = this.findChild("description");
 81        return description == null ? null : description.getNamespace();
 82    }
 83
 84    public GenericTransportInfo getTransport() {
 85        final Element transport = this.findChild("transport");
 86        final String namespace = transport == null ? null : transport.getNamespace();
 87        if (Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(namespace)) {
 88            return IceUdpTransportInfo.upgrade(transport);
 89        } else if (transport != null) {
 90            return GenericTransportInfo.upgrade(transport);
 91        } else {
 92            return null;
 93        }
 94    }
 95
 96    public void setTransport(GenericTransportInfo transportInfo) {
 97        this.addChild(transportInfo);
 98    }
 99
100    public enum Creator {
101        INITIATOR,
102        RESPONDER;
103
104        public static Creator of(final String value) {
105            return Creator.valueOf(value.toUpperCase(Locale.ROOT));
106        }
107
108        @Override
109        @NonNull
110        public String toString() {
111            return super.toString().toLowerCase(Locale.ROOT);
112        }
113    }
114
115    public enum Senders {
116        BOTH,
117        INITIATOR,
118        NONE,
119        RESPONDER;
120
121        public static Senders of(final String value) {
122            return Senders.valueOf(value.toUpperCase(Locale.ROOT));
123        }
124
125        public static Senders of(final SessionDescription.Media media, final boolean initiator) {
126            final Set<String> attributes = media.attributes.keySet();
127            if (attributes.contains("sendrecv")) {
128                return BOTH;
129            } else if (attributes.contains("inactive")) {
130                return NONE;
131            } else if (attributes.contains("sendonly")) {
132                return initiator ? INITIATOR : RESPONDER;
133            } else if (attributes.contains("recvonly")) {
134                return initiator ? RESPONDER : INITIATOR;
135            }
136            Log.w(Config.LOGTAG,"assuming default value for senders");
137            // If none of the attributes "sendonly", "recvonly", "inactive", and "sendrecv" is
138            // present, "sendrecv" SHOULD be assumed as the default
139            // https://www.rfc-editor.org/rfc/rfc4566
140            return BOTH;
141        }
142
143        @Override
144        @NonNull
145        public String toString() {
146            return super.toString().toLowerCase(Locale.ROOT);
147        }
148
149        public String asMediaAttribute(final boolean initiator) {
150            final boolean responder = !initiator;
151            if (this == Content.Senders.BOTH) {
152                return "sendrecv";
153            } else if (this == Content.Senders.NONE) {
154                return "inactive";
155            } else if ((initiator && this == Content.Senders.INITIATOR)
156                    || (responder && this == Content.Senders.RESPONDER)) {
157                return "sendonly";
158            } else if ((initiator && this == Content.Senders.RESPONDER)
159                    || (responder && this == Content.Senders.INITIATOR)) {
160                return "recvonly";
161            } else {
162                throw new IllegalStateException(
163                        String.format(
164                                "illegal combination of initiator=%s and %s", initiator, this));
165            }
166        }
167    }
168}