IceUdpTransportInfo.java

  1package eu.siacs.conversations.xmpp.jingle.stanzas;
  2
  3import android.util.Log;
  4
  5import com.google.common.base.Preconditions;
  6import com.google.common.collect.ArrayListMultimap;
  7import com.google.common.collect.ImmutableList;
  8import com.google.common.collect.Iterables;
  9
 10import java.util.HashMap;
 11import java.util.Hashtable;
 12import java.util.List;
 13
 14import eu.siacs.conversations.Config;
 15import eu.siacs.conversations.xml.Element;
 16import eu.siacs.conversations.xml.Namespace;
 17import eu.siacs.conversations.xmpp.jingle.SessionDescription;
 18
 19public class IceUdpTransportInfo extends GenericTransportInfo {
 20
 21    private IceUdpTransportInfo() {
 22        super("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
 23    }
 24
 25    public Fingerprint getFingerprint() {
 26        final Element fingerprint = this.findChild("fingerprint", Namespace.JINGLE_APPS_DTLS);
 27        return fingerprint == null ? null : Fingerprint.upgrade(fingerprint);
 28    }
 29
 30    public List<Candidate> getCandidates() {
 31        final ImmutableList.Builder<Candidate> builder = new ImmutableList.Builder<>();
 32        for (final Element child : getChildren()) {
 33            if ("candidate".equals(child.getName())) {
 34                builder.add(Candidate.upgrade(child));
 35            }
 36        }
 37        return builder.build();
 38    }
 39
 40    public static IceUdpTransportInfo upgrade(final Element element) {
 41        Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
 42        Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
 43        final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
 44        transportInfo.setAttributes(element.getAttributes());
 45        transportInfo.setChildren(element.getChildren());
 46        return transportInfo;
 47    }
 48
 49    public IceUdpTransportInfo cloneWrapper() {
 50        final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
 51        transportInfo.setAttributes(new Hashtable<>(getAttributes()));
 52        return transportInfo;
 53    }
 54
 55    public static IceUdpTransportInfo of(SessionDescription sessionDescription, SessionDescription.Media media) {
 56        final String ufrag = Iterables.getFirst(media.attributes.get("ice-ufrag"), null);
 57        final String pwd = Iterables.getFirst(media.attributes.get("ice-pwd"), null);
 58        IceUdpTransportInfo iceUdpTransportInfo = new IceUdpTransportInfo();
 59        if (ufrag != null) {
 60            iceUdpTransportInfo.setAttribute("ufrag", ufrag);
 61        }
 62        if (pwd != null) {
 63            iceUdpTransportInfo.setAttribute("pwd", pwd);
 64        }
 65        final Fingerprint fingerprint = Fingerprint.of(sessionDescription, media);
 66        if (fingerprint != null) {
 67            iceUdpTransportInfo.addChild(fingerprint);
 68        }
 69        return iceUdpTransportInfo;
 70
 71    }
 72
 73    public static class Candidate extends Element {
 74
 75        private Candidate() {
 76            super("candidate");
 77        }
 78
 79        public int getComponent() {
 80            return getAttributeAsInt("component");
 81        }
 82
 83        public int getFoundation() {
 84            return getAttributeAsInt("foundation");
 85        }
 86
 87        public int getGeneration() {
 88            return getAttributeAsInt("generation");
 89        }
 90
 91        public String getId() {
 92            return getAttribute("id");
 93        }
 94
 95        public String getIp() {
 96            return getAttribute("ip");
 97        }
 98
 99        public int getNetwork() {
100            return getAttributeAsInt("network");
101        }
102
103        public int getPort() {
104            return getAttributeAsInt("port");
105        }
106
107        public int getPriority() {
108            return getAttributeAsInt("priority");
109        }
110
111        public String getProtocol() {
112            return getAttribute("protocol");
113        }
114
115        public String getRelAddr() {
116            return getAttribute("rel-addr");
117        }
118
119        public int getRelPort() {
120            return getAttributeAsInt("rel-port");
121        }
122
123        public String getType() { //TODO might be converted to enum
124            return getAttribute("type");
125        }
126
127        private int getAttributeAsInt(final String name) {
128            final String value = this.getAttribute(name);
129            if (value == null) {
130                return 0;
131            }
132            try {
133                return Integer.parseInt(value);
134            } catch (NumberFormatException e) {
135                return 0;
136            }
137        }
138
139        public static Candidate upgrade(final Element element) {
140            Preconditions.checkArgument("candidate".equals(element.getName()));
141            final Candidate candidate = new Candidate();
142            candidate.setAttributes(element.getAttributes());
143            candidate.setChildren(element.getChildren());
144            return candidate;
145        }
146
147        // https://tools.ietf.org/html/draft-ietf-mmusic-ice-sip-sdp-39#section-5.1
148        public static Candidate fromSdpAttribute(final String attribute) {
149            final String[] pair = attribute.split(":", 2);
150            if (pair.length == 2 && "candidate".equals(pair[0])) {
151                final String[] segments = pair[1].split(" ");
152                if (segments.length >= 6) {
153                    final String foundation = segments[0];
154                    final String component = segments[1];
155                    final String transport = segments[2];
156                    final String priority = segments[3];
157                    final String connectionAddress = segments[4];
158                    final String port = segments[5];
159                    final HashMap<String, String> additional = new HashMap<>();
160                    for (int i = 6; i < segments.length - 1; i = i + 2) {
161                        additional.put(segments[i], segments[i + 1]);
162                    }
163                    final Candidate candidate = new Candidate();
164                    candidate.setAttribute("component", component);
165                    candidate.setAttribute("foundation", foundation);
166                    candidate.setAttribute("generation", additional.get("generation"));
167                    candidate.setAttribute("ip", connectionAddress);
168                    candidate.setAttribute("port", port);
169                    candidate.setAttribute("priority", priority);
170                    candidate.setAttribute("protocol", transport);
171                    candidate.setAttribute("type", additional.get("typ"));
172                    return candidate;
173                }
174            }
175            return null;
176        }
177    }
178
179
180    public static class Fingerprint extends Element {
181
182        public String getHash() {
183            return this.getAttribute("hash");
184        }
185
186        public String getSetup() {
187            return this.getAttribute("setup");
188        }
189
190        private Fingerprint() {
191            super("fingerprint", Namespace.JINGLE_APPS_DTLS);
192        }
193
194        public static Fingerprint upgrade(final Element element) {
195            Preconditions.checkArgument("fingerprint".equals(element.getName()));
196            Preconditions.checkArgument(Namespace.JINGLE_APPS_DTLS.equals(element.getNamespace()));
197            final Fingerprint fingerprint = new Fingerprint();
198            fingerprint.setAttributes(element.getAttributes());
199            fingerprint.setContent(element.getContent());
200            return fingerprint;
201        }
202
203        private static Fingerprint of(ArrayListMultimap<String, String> attributes) {
204            final String fingerprint = Iterables.getFirst(attributes.get("fingerprint"), null);
205            final String setup = Iterables.getFirst(attributes.get("setup"), null);
206            if (setup != null && fingerprint != null) {
207                final String[] fingerprintParts = fingerprint.split(" ", 2);
208                if (fingerprintParts.length == 2) {
209                    final String hash = fingerprintParts[0];
210                    final String actualFingerprint = fingerprintParts[1];
211                    final Fingerprint element = new Fingerprint();
212                    element.setAttribute("hash", hash);
213                    element.setAttribute("setup", setup);
214                    element.setContent(actualFingerprint);
215                    return element;
216                }
217            }
218            return null;
219        }
220
221        public static Fingerprint of(final SessionDescription sessionDescription, final SessionDescription.Media media) {
222            final Fingerprint fingerprint = of(media.attributes);
223            return fingerprint == null ? of(sessionDescription.attributes) : fingerprint;
224        }
225    }
226}