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