Updated SCTP SDP attributes according to draft-ietf-mmusic-sctp-sdp-07

- SDP sctpmap attribute replaced with fmtp attribute
- SDP sctp-port attribute is newly added

BUG=3592
R=jiayl@webrtc.org, juberti@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/16169004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7087 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc
index 792a091..f4b38c5 100644
--- a/talk/app/webrtc/webrtcsdp.cc
+++ b/talk/app/webrtc/webrtcsdp.cc
@@ -155,6 +155,9 @@
 static const char kAttributeRtcpFb[] = "rtcp-fb";
 static const char kAttributeSendRecv[] = "sendrecv";
 static const char kAttributeInactive[] = "inactive";
+// draft-ietf-mmusic-sctp-sdp-07
+// a=sctp-port
+static const char kAttributeSctpPort[] = "sctp-port";
 
 // Experimental flags
 static const char kAttributeXGoogleFlag[] = "x-google-flag";
@@ -1100,6 +1103,26 @@
   return true;
 }
 
+bool ParseSctpPort(const std::string& line,
+                   int* sctp_port,
+                   SdpParseError* error) {
+  // draft-ietf-mmusic-sctp-sdp-07
+  // a=sctp-port
+  std::vector<std::string> fields;
+  rtc::split(line.substr(kLinePrefixLength),
+                   kSdpDelimiterSpace, &fields);
+  const size_t expected_min_fields = 2;
+  if (fields.size() < expected_min_fields) {
+    return ParseFailedExpectMinFieldNum(line, expected_min_fields, error);
+  }
+  if (!rtc::FromString(fields[1], sctp_port)) {
+    return ParseFailed(line,
+                       "Invalid sctp port value.",
+                       error);
+  }
+  return true;
+}
+
 bool ParseExtmap(const std::string& line, RtpHeaderExtension* extmap,
                  SdpParseError* error) {
   // RFC 5285
@@ -1563,6 +1586,24 @@
   }
 }
 
+bool AddSctpDataCodec(DataContentDescription* media_desc,
+                      int sctp_port) {
+  if (media_desc->HasCodec(cricket::kGoogleSctpDataCodecId)) {
+    return ParseFailed("",
+                       "Can't have multiple sctp port attributes.",
+                       NULL);
+  }
+  // Add the SCTP Port number as a pseudo-codec "port" parameter
+  cricket::DataCodec codec_port(
+      cricket::kGoogleSctpDataCodecId, cricket::kGoogleSctpDataCodecName,
+      0);
+  codec_port.SetParam(cricket::kCodecParamPort, sctp_port);
+  LOG(INFO) << "AddSctpDataCodec: Got SCTP Port Number "
+            << sctp_port;
+  media_desc->AddCodec(codec_port);
+  return true;
+}
+
 bool GetMinValue(const std::vector<int>& values, int* value) {
   if (values.empty()) {
     return false;
@@ -2129,18 +2170,20 @@
 
     // <fmt>
     std::vector<int> codec_preference;
-    for (size_t j = 3 ; j < fields.size(); ++j) {
-      // TODO(wu): Remove when below bug is fixed.
-      // https://bugzilla.mozilla.org/show_bug.cgi?id=996329
-      if (fields[j] == "" && j == fields.size() - 1) {
-        continue;
-      }
+    if (!is_sctp) {
+      for (size_t j = 3 ; j < fields.size(); ++j) {
+        // TODO(wu): Remove when below bug is fixed.
+        // https://bugzilla.mozilla.org/show_bug.cgi?id=996329
+        if (fields[j] == "" && j == fields.size() - 1) {
+          continue;
+        }
 
-      int pl = 0;
-      if (!GetValueFromString(line, fields[j], &pl, error)) {
-        return false;
+        int pl = 0;
+        if (!GetValueFromString(line, fields[j], &pl, error)) {
+          return false;
+        }
+        codec_preference.push_back(pl);
       }
-      codec_preference.push_back(pl);
     }
 
     // Make a temporary TransportDescription based on |session_td|.
@@ -2173,20 +2216,14 @@
                     codec_preference, pos, &content_name,
                     &transport, candidates, error);
 
-      if (desc && protocol == cricket::kMediaProtocolDtlsSctp) {
-        // Add the SCTP Port number as a pseudo-codec "port" parameter
-        cricket::DataCodec codec_port(
-            cricket::kGoogleSctpDataCodecId, cricket::kGoogleSctpDataCodecName,
-            0);
-        codec_port.SetParam(cricket::kCodecParamPort, fields[3]);
-        LOG(INFO) << "ParseMediaDescription: Got SCTP Port Number "
-                  << fields[3];
-        ASSERT(!desc->HasCodec(cricket::kGoogleSctpDataCodecId));
-        desc->AddCodec(codec_port);
+      int p;
+      if (desc && protocol == cricket::kMediaProtocolDtlsSctp &&
+          rtc::FromString(fields[3], &p)) {
+        if (!AddSctpDataCodec(desc, p))
+          return false;
       }
 
       content.reset(desc);
-
       // We should always use the default bandwidth for RTP-based data
       // channels.  Don't allow SDP to set the bandwidth, because that
       // would give JS the opportunity to "break the Internet".
@@ -2518,6 +2555,15 @@
       if (!ParseDtlsSetup(line, &(transport->connection_role), error)) {
         return false;
       }
+    } else if (HasAttribute(line, kAttributeSctpPort)) {
+      int sctp_port;
+      if (!ParseSctpPort(line, &sctp_port, error)) {
+        return false;
+      }
+      if (!AddSctpDataCodec(static_cast<DataContentDescription*>(media_desc),
+                            sctp_port)) {
+        return false;
+      }
     } else if (is_rtp) {
       //
       // RTP specific attrubtes