1package eu.siacs.conversations.xmpp.jingle.stanzas;
2
3import com.google.common.base.Preconditions;
4import com.google.common.collect.Iterables;
5import com.google.common.primitives.Ints;
6
7import java.util.Collections;
8import java.util.Hashtable;
9import java.util.List;
10
11import eu.siacs.conversations.xml.Element;
12import eu.siacs.conversations.xml.Namespace;
13import eu.siacs.conversations.xmpp.jingle.SessionDescription;
14import eu.siacs.conversations.xmpp.jingle.transports.Transport;
15
16public class WebRTCDataChannelTransportInfo extends GenericTransportInfo {
17
18 public static final WebRTCDataChannelTransportInfo STUB = new WebRTCDataChannelTransportInfo();
19
20 public WebRTCDataChannelTransportInfo() {
21 super("transport", Namespace.JINGLE_TRANSPORT_WEBRTC_DATA_CHANNEL);
22 }
23
24 public static WebRTCDataChannelTransportInfo upgrade(final Element element) {
25 Preconditions.checkArgument(
26 "transport".equals(element.getName()), "Name of provided element is not transport");
27 Preconditions.checkArgument(
28 Namespace.JINGLE_TRANSPORT_WEBRTC_DATA_CHANNEL.equals(element.getNamespace()),
29 "Element does not match ice-udp transport namespace");
30 final WebRTCDataChannelTransportInfo transportInfo = new WebRTCDataChannelTransportInfo();
31 transportInfo.setAttributes(element.getAttributes());
32 transportInfo.setChildren(element.getChildren());
33 return transportInfo;
34 }
35
36 public IceUdpTransportInfo innerIceUdpTransportInfo() {
37 final var iceUdpTransportInfo =
38 this.findChild("transport", Namespace.JINGLE_TRANSPORT_ICE_UDP);
39 if (iceUdpTransportInfo != null) {
40 return IceUdpTransportInfo.upgrade(iceUdpTransportInfo);
41 }
42 return null;
43 }
44
45 public static Transport.InitialTransportInfo of(final SessionDescription sessionDescription) {
46 final SessionDescription.Media media = Iterables.getOnlyElement(sessionDescription.media);
47 final String id = Iterables.getFirst(media.attributes.get("mid"), null);
48 Preconditions.checkNotNull(id, "media has no mid");
49 final String maxMessageSize =
50 Iterables.getFirst(media.attributes.get("max-message-size"), null);
51 final Integer maxMessageSizeInt =
52 maxMessageSize == null ? null : Ints.tryParse(maxMessageSize);
53 final String sctpPort = Iterables.getFirst(media.attributes.get("sctp-port"), null);
54 final Integer sctpPortInt = sctpPort == null ? null : Ints.tryParse(sctpPort);
55 final WebRTCDataChannelTransportInfo webRTCDataChannelTransportInfo =
56 new WebRTCDataChannelTransportInfo();
57 if (maxMessageSizeInt != null) {
58 webRTCDataChannelTransportInfo.setAttribute("max-message-size", maxMessageSizeInt);
59 }
60 if (sctpPortInt != null) {
61 webRTCDataChannelTransportInfo.setAttribute("sctp-port", sctpPortInt);
62 }
63 webRTCDataChannelTransportInfo.addChild(IceUdpTransportInfo.of(sessionDescription, media));
64
65 final String groupAttribute =
66 Iterables.getFirst(sessionDescription.attributes.get("group"), null);
67 final Group group = groupAttribute == null ? null : Group.ofSdpString(groupAttribute);
68 return new Transport.InitialTransportInfo(id, webRTCDataChannelTransportInfo, group);
69 }
70
71 public Integer getSctpPort() {
72 final var attribute = this.getAttribute("sctp-port");
73 if (attribute == null) {
74 return null;
75 }
76 return Ints.tryParse(attribute);
77 }
78
79 public Integer getMaxMessageSize() {
80 final var attribute = this.getAttribute("max-message-size");
81 if (attribute == null) {
82 return null;
83 }
84 return Ints.tryParse(attribute);
85 }
86
87 public WebRTCDataChannelTransportInfo cloneWrapper() {
88 final var iceUdpTransport = this.innerIceUdpTransportInfo();
89 final WebRTCDataChannelTransportInfo transportInfo = new WebRTCDataChannelTransportInfo();
90 transportInfo.setAttributes(new Hashtable<>(getAttributes()));
91 transportInfo.addChild(iceUdpTransport.cloneWrapper());
92 return transportInfo;
93 }
94
95 public void addCandidate(final IceUdpTransportInfo.Candidate candidate) {
96 this.innerIceUdpTransportInfo().addChild(candidate);
97 }
98
99 public List<IceUdpTransportInfo.Candidate> getCandidates() {
100 final var innerTransportInfo = this.innerIceUdpTransportInfo();
101 if (innerTransportInfo == null) {
102 return Collections.emptyList();
103 }
104 return innerTransportInfo.getCandidates();
105 }
106
107 public IceUdpTransportInfo.Credentials getCredentials() {
108 final var innerTransportInfo = this.innerIceUdpTransportInfo();
109 return innerTransportInfo == null ? null : innerTransportInfo.getCredentials();
110 }
111}