be more liberal in 0167 payload-type parameter parsing

Daniel Gultsch created

some implementations will transform the following SDP coming from Firefox

m=audio 12346 RTP/AVP 101
a=rtpmap:101 telephone-event/8000
a=fmtp:101 0-15

to

<payload-type channels="1" name="telephone-event" clockrate="8000" id="101">
  <parameter value="0-15" xmlns="urn:xmpp:jingle:apps:rtp:1"/>
</payload-type>

While a missing name attribute is not legal according to the XEP; and 0-15 are
technically not just one value the following commit will accept it if there is
just one paramater.

Change summary

src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java     |  6 
src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java | 19 
2 files changed, 20 insertions(+), 5 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java 🔗

@@ -168,8 +168,10 @@ public class SessionDescription {
                 }
                 formatBuilder.add(payloadType.getIntId());
                 mediaAttributes.put("rtpmap", payloadType.toSdpAttribute());
-                List<RtpDescription.Parameter> parameters = payloadType.getParameters();
-                if (parameters.size() > 0) {
+                final List<RtpDescription.Parameter> parameters = payloadType.getParameters();
+                if (parameters.size() == 1) {
+                    mediaAttributes.put("fmtp", RtpDescription.Parameter.toSdpString(id, parameters.get(0)));
+                } else if (parameters.size() > 0) {
                     mediaAttributes.put("fmtp", RtpDescription.Parameter.toSdpString(id, parameters));
                 }
                 for (RtpDescription.FeedbackNegotiation feedbackNegotiation : payloadType.getFeedbackNegotiations()) {

src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java 🔗

@@ -3,6 +3,7 @@ package eu.siacs.conversations.xmpp.jingle.stanzas;
 import android.util.Pair;
 
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ImmutableList;
 
@@ -369,7 +370,7 @@ public class RtpDescription extends GenericDescription {
             final StringBuilder stringBuilder = new StringBuilder();
             stringBuilder.append(id).append(' ');
             for (int i = 0; i < parameters.size(); ++i) {
-                Parameter p = parameters.get(i);
+                final Parameter p = parameters.get(i);
                 final String name = p.getParameterName();
                 Preconditions.checkArgument(name != null, String.format("parameter for %s must have a name", id));
                 SessionDescription.checkNoWhitespace(name, String.format("parameter names for %s must not contain whitespaces", id));
@@ -386,11 +387,23 @@ public class RtpDescription extends GenericDescription {
             return stringBuilder.toString();
         }
 
-        public static Pair<String, List<Parameter>> ofSdpString(final String sdp) {
+        public static String toSdpString(final String id, final Parameter parameter) {
+            final String name = parameter.getParameterName();
+            final String value = parameter.getParameterValue();
+            Preconditions.checkArgument(value != null, String.format("parameter for %s must have a value", id));
+            SessionDescription.checkNoWhitespace(value, String.format("parameter values for %s must not contain whitespaces", id));
+            if (Strings.isNullOrEmpty(name)) {
+                return String.format("%s %s", id, value);
+            } else {
+                return String.format("%s %s=%s", id, name, value);
+            }
+        }
+
+        static Pair<String, List<Parameter>> ofSdpString(final String sdp) {
             final String[] pair = sdp.split(" ");
             if (pair.length == 2) {
                 final String id = pair[0];
-                ImmutableList.Builder<Parameter> builder = new ImmutableList.Builder<>();
+                final ImmutableList.Builder<Parameter> builder = new ImmutableList.Builder<>();
                 for (final String parameter : pair[1].split(";")) {
                     final String[] parts = parameter.split("=", 2);
                     if (parts.length == 2) {