1package eu.siacs.conversations.xmpp.jingle;
2
3import android.util.Log;
4import android.util.Pair;
5
6import com.google.common.collect.ArrayListMultimap;
7import com.google.common.collect.ImmutableList;
8
9import java.util.List;
10import java.util.Map;
11
12import eu.siacs.conversations.Config;
13
14public class SessionDescription {
15
16 public final int version;
17 public final String name;
18 public final String connectionData;
19 public final ArrayListMultimap<String, String> attributes;
20 public final List<Media> media;
21
22
23 public SessionDescription(int version, String name, String connectionData, ArrayListMultimap<String, String> attributes, List<Media> media) {
24 this.version = version;
25 this.name = name;
26 this.connectionData = connectionData;
27 this.attributes = attributes;
28 this.media = media;
29 }
30
31 public static SessionDescription parse(final Map<String, JingleRtpConnection.DescriptionTransport> contents) {
32 final SessionDescriptionBuilder sessionDescriptionBuilder = new SessionDescriptionBuilder();
33 return sessionDescriptionBuilder.createSessionDescription();
34 }
35
36 public static SessionDescription parse(final String input) {
37 final SessionDescriptionBuilder sessionDescriptionBuilder = new SessionDescriptionBuilder();
38 MediaBuilder currentMediaBuilder = null;
39 ArrayListMultimap<String, String> attributeMap = ArrayListMultimap.create();
40 ImmutableList.Builder<Media> mediaBuilder = new ImmutableList.Builder<>();
41 for (final String line : input.split("\n")) {
42 final String[] pair = line.trim().split("=", 2);
43 if (pair.length < 2 || pair[0].length() != 1) {
44 Log.d(Config.LOGTAG, "skipping sdp parsing on line " + line);
45 continue;
46 }
47 final char key = pair[0].charAt(0);
48 final String value = pair[1];
49 switch (key) {
50 case 'v':
51 sessionDescriptionBuilder.setVersion(ignorantIntParser(value));
52 break;
53 case 'c':
54 if (currentMediaBuilder != null) {
55 currentMediaBuilder.setConnectionData(value);
56 } else {
57 sessionDescriptionBuilder.setConnectionData(value);
58 }
59 break;
60 case 's':
61 sessionDescriptionBuilder.setName(value);
62 break;
63 case 'a':
64 final Pair<String, String> attribute = parseAttribute(value);
65 attributeMap.put(attribute.first, attribute.second);
66 break;
67 case 'm':
68 if (currentMediaBuilder == null) {
69 sessionDescriptionBuilder.setAttributes(attributeMap);
70 ;
71 } else {
72 currentMediaBuilder.setAttributes(attributeMap);
73 mediaBuilder.add(currentMediaBuilder.createMedia());
74 }
75 attributeMap = ArrayListMultimap.create();
76 currentMediaBuilder = new MediaBuilder();
77 final String[] parts = value.split(" ");
78 if (parts.length >= 3) {
79 currentMediaBuilder.setMedia(parts[0]);
80 currentMediaBuilder.setPort(ignorantIntParser(parts[1]));
81 currentMediaBuilder.setProtocol(parts[2]);
82 ImmutableList.Builder<Integer> formats = new ImmutableList.Builder<>();
83 for (int i = 3; i < parts.length; ++i) {
84 formats.add(ignorantIntParser(parts[i]));
85 }
86 currentMediaBuilder.setFormats(formats.build());
87 } else {
88 Log.d(Config.LOGTAG, "skipping media line " + line);
89 }
90 break;
91 }
92
93 }
94 if (currentMediaBuilder != null) {
95 currentMediaBuilder.setAttributes(attributeMap);
96 mediaBuilder.add(currentMediaBuilder.createMedia());
97 }
98 sessionDescriptionBuilder.setMedia(mediaBuilder.build());
99 return sessionDescriptionBuilder.createSessionDescription();
100 }
101
102 public static int ignorantIntParser(final String input) {
103 try {
104 return Integer.parseInt(input);
105 } catch (NumberFormatException e) {
106 return 0;
107 }
108 }
109
110 public static Pair<String, String> parseAttribute(final String input) {
111 final String[] pair = input.split(":", 2);
112 if (pair.length == 2) {
113 return new Pair<>(pair[0], pair[1]);
114 } else {
115 return new Pair<>(pair[0], "");
116 }
117 }
118
119 public static class Media {
120 public final String media;
121 public final int port;
122 public final String protocol;
123 public final List<Integer> formats;
124 public final String connectionData;
125 public final ArrayListMultimap<String, String> attributes;
126
127 public Media(String media, int port, String protocol, List<Integer> formats, String connectionData, ArrayListMultimap<String, String> attributes) {
128 this.media = media;
129 this.port = port;
130 this.protocol = protocol;
131 this.formats = formats;
132 this.connectionData = connectionData;
133 this.attributes = attributes;
134 }
135 }
136
137}