Encoding and Decoding of TCP candidates as defined in RFC 6544.

R=juberti@chromium.org, jiayl@webrtc.org, juberti@webrtc.org
BUG=2204

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6857 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/webrtcsdp.cc b/talk/app/webrtc/webrtcsdp.cc
index 4f774a7..64f8e5e 100644
--- a/talk/app/webrtc/webrtcsdp.cc
+++ b/talk/app/webrtc/webrtcsdp.cc
@@ -168,6 +168,7 @@
 // TODO: How to map the prflx with circket candidate type
 // static const char kCandidatePrflx[] = "prflx";
 static const char kCandidateRelay[] = "relay";
+static const char kTcpCandidateType[] = "tcptype";
 
 static const char kSdpDelimiterEqual = '=';
 static const char kSdpDelimiterSpace = ' ';
@@ -1042,6 +1043,25 @@
     ++current_position;
   }
 
+  // If this is a TCP candidate, it has additional extension as defined in
+  // RFC 6544.
+  std::string tcptype;
+  if (fields.size() >= (current_position + 2) &&
+      fields[current_position] == kTcpCandidateType) {
+    tcptype = fields[++current_position];
+    ++current_position;
+
+    if (tcptype != cricket::TCPTYPE_ACTIVE_STR &&
+        tcptype != cricket::TCPTYPE_PASSIVE_STR &&
+        tcptype != cricket::TCPTYPE_SIMOPEN_STR) {
+      return ParseFailed(first_line, "Invalid TCP candidate type.", error);
+    }
+
+    if (protocol != cricket::PROTO_TCP) {
+      return ParseFailed(first_line, "Invalid non-TCP candidate", error);
+    }
+  }
+
   // Extension
   // Empty string as the candidate username and password.
   // Will be updated later with the ice-ufrag and ice-pwd.
@@ -1074,6 +1094,7 @@
       address, priority, username, password, candidate_type, network_name,
       generation, foundation);
   candidate->set_related_address(related_address);
+  candidate->set_tcptype(tcptype);
   return true;
 }
 
@@ -1694,11 +1715,14 @@
 
     InitAttrLine(kAttributeCandidate, &os);
     os << kSdpDelimiterColon
-       << it->foundation() << " " << it->component() << " "
-       << it->protocol() << " " << it->priority() << " "
+       << it->foundation() << " "
+       << it->component() << " "
+       << it->protocol() << " "
+       << it->priority() << " "
        << it->address().ipaddr().ToString() << " "
        << it->address().PortAsString() << " "
-       << kAttributeCandidateTyp << " " << type << " ";
+       << kAttributeCandidateTyp << " "
+       << type << " ";
 
     // Related address
     if (!it->related_address().IsNil()) {
@@ -1708,6 +1732,17 @@
          << it->related_address().PortAsString() << " ";
     }
 
+    if (it->protocol() == cricket::TCP_PROTOCOL_NAME) {
+      // In case of WebRTC, candidate must be always "active" only. That means
+      // it should have port number either 0 or 9.
+      ASSERT(it->address().port() == 0 ||
+             it->address().port() == cricket::DISCARD_PORT);
+      ASSERT(it->tcptype() == cricket::TCPTYPE_ACTIVE_STR);
+      // TODO(mallinath) : Uncomment below line once WebRTCSdp capable of
+      // parsing RFC 6544.
+      // os << kTcpCandidateType << " " << it->tcptype() << " ";
+    }
+
     // Extensions
     os << kAttributeCandidateGeneration << " " << it->generation();