Enable DTLS for peerconnection example. If it's a loopback test, then we recreate another peerconnection with DTLS off.

BUG=3872
TEST=Manual Test
R=jiayl@webrtc.org, tommi@webrtc.org

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

Cr-Commit-Position: refs/heads/master@{#8193}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8193 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/examples/peerconnection/client/conductor.cc b/talk/examples/peerconnection/client/conductor.cc
index a3ea99f..3fca758 100644
--- a/talk/examples/peerconnection/client/conductor.cc
+++ b/talk/examples/peerconnection/client/conductor.cc
@@ -32,6 +32,7 @@
 #include "talk/app/webrtc/videosourceinterface.h"
 #include "talk/examples/peerconnection/client/defaults.h"
 #include "talk/media/devices/devicemanager.h"
+#include "talk/app/webrtc/test/fakeconstraints.h"
 #include "webrtc/base/common.h"
 #include "webrtc/base/json.h"
 #include "webrtc/base/logging.h"
@@ -45,6 +46,9 @@
 const char kSessionDescriptionTypeName[] = "type";
 const char kSessionDescriptionSdpName[] = "sdp";
 
+#define DTLS_ON  true
+#define DTLS_OFF false
+
 class DummySetSessionDescriptionObserver
     : public webrtc::SetSessionDescriptionObserver {
  public:
@@ -66,6 +70,7 @@
 
 Conductor::Conductor(PeerConnectionClient* client, MainWindow* main_wnd)
   : peer_id_(-1),
+    loopback_(false),
     client_(client),
     main_wnd_(main_wnd) {
   client_->RegisterObserver(this);
@@ -98,16 +103,7 @@
     return false;
   }
 
-  webrtc::PeerConnectionInterface::IceServers servers;
-  webrtc::PeerConnectionInterface::IceServer server;
-  server.uri = GetPeerConnectionString();
-  servers.push_back(server);
-  peer_connection_ = peer_connection_factory_->CreatePeerConnection(servers,
-                                                                    NULL,
-                                                                    NULL,
-                                                                    NULL,
-                                                                    this);
-  if (!peer_connection_.get()) {
+ if (!CreatePeerConnection(DTLS_ON)) {
     main_wnd_->MessageBox("Error",
         "CreatePeerConnection failed", true);
     DeletePeerConnection();
@@ -116,6 +112,43 @@
   return peer_connection_.get() != NULL;
 }
 
+bool Conductor::ReinitializePeerConnectionForLoopback() {
+  loopback_ = true;

+  rtc::scoped_refptr<webrtc::StreamCollectionInterface> streams(

+      peer_connection_->local_streams());

+  peer_connection_ = NULL;

+  if (CreatePeerConnection(DTLS_OFF)) {
+    for (size_t i = 0; i < streams->count(); ++i)

+      peer_connection_->AddStream(streams->at(i));

+    peer_connection_->CreateOffer(this, NULL);

+  }
+  return peer_connection_.get() != NULL;
+}
+
+bool Conductor::CreatePeerConnection(bool dtls) {
+  ASSERT(peer_connection_factory_.get() != NULL);
+  ASSERT(peer_connection_.get() == NULL);
+
+  webrtc::PeerConnectionInterface::IceServers servers;

+  webrtc::PeerConnectionInterface::IceServer server;

+  server.uri = GetPeerConnectionString();

+  servers.push_back(server);

+

+  webrtc::FakeConstraints constraints;
+  if (dtls) {
+    constraints.AddOptional(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,

+                            "true");

+  }

+

+  peer_connection_ =

+      peer_connection_factory_->CreatePeerConnection(servers,

+                                                     &constraints,

+                                                     NULL,

+                                                     NULL,

+                                                     this);

+  return peer_connection_.get() != NULL;
+}
+
 void Conductor::DeletePeerConnection() {
   peer_connection_ = NULL;
   active_streams_.clear();
@@ -123,6 +156,7 @@
   main_wnd_->StopRemoteRenderer();
   peer_connection_factory_ = NULL;
   peer_id_ = -1;
+  loopback_ = false;
 }
 
 void Conductor::EnsureStreamingUI() {
@@ -155,6 +189,14 @@
 
 void Conductor::OnIceCandidate(const webrtc::IceCandidateInterface* candidate) {
   LOG(INFO) << __FUNCTION__ << " " << candidate->sdp_mline_index();
+  // For loopback test. To save some connecting delay.

+  if (loopback_) {

+    if (!peer_connection_->AddIceCandidate(candidate)) {

+      LOG(WARNING) << "Failed to apply the received candidate";

+    }

+    return;

+  }
+
   Json::StyledWriter writer;
   Json::Value jmessage;
 
@@ -237,6 +279,17 @@
 
   GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName, &type);
   if (!type.empty()) {
+    if (type == "offer-loopback") {

+      // This is a loopback call.

+      // Recreate the peerconnection with DTLS disabled.

+      if (!ReinitializePeerConnectionForLoopback()) {

+        LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
+        DeletePeerConnection();
+        client_->SignOut();

+      }

+      return;

+    }
+
     std::string sdp;
     if (!GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName, &sdp)) {
       LOG(WARNING) << "Can't parse received session description message.";
@@ -465,13 +518,25 @@
 }
 
 void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
-  peer_connection_->SetLocalDescription(
-      DummySetSessionDescriptionObserver::Create(), desc);
+  peer_connection_->SetLocalDescription(

+      DummySetSessionDescriptionObserver::Create(), desc);

+

+  std::string sdp;
+  desc->ToString(&sdp);

+

+  // For loopback test. To save some connecting delay.

+  if (loopback_) {

+    // Replace message type from "offer" to "answer"

+    webrtc::SessionDescriptionInterface* session_description(

+        webrtc::CreateSessionDescription("answer", sdp));

+    peer_connection_->SetRemoteDescription(

+        DummySetSessionDescriptionObserver::Create(), session_description);

+    return;

+  }

+
   Json::StyledWriter writer;
   Json::Value jmessage;
   jmessage[kSessionDescriptionTypeName] = desc->type();
-  std::string sdp;
-  desc->ToString(&sdp);
   jmessage[kSessionDescriptionSdpName] = sdp;
   SendMessage(writer.write(jmessage));
 }
diff --git a/talk/examples/peerconnection/client/conductor.h b/talk/examples/peerconnection/client/conductor.h
index 1ce3e50..d99c98a 100644
--- a/talk/examples/peerconnection/client/conductor.h
+++ b/talk/examples/peerconnection/client/conductor.h
@@ -71,6 +71,8 @@
  protected:
   ~Conductor();
   bool InitializePeerConnection();
+  bool ReinitializePeerConnectionForLoopback();
+  bool CreatePeerConnection(bool dtls);
   void DeletePeerConnection();
   void EnsureStreamingUI();
   void AddStreams();
@@ -129,6 +131,7 @@
   void SendMessage(const std::string& json_object);
 
   int peer_id_;
+  bool loopback_;
   rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
   rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface>
       peer_connection_factory_;
diff --git a/talk/examples/peerconnection/server/server_test.html b/talk/examples/peerconnection/server/server_test.html
index 0155917..0a165f1 100644
--- a/talk/examples/peerconnection/server/server_test.html
+++ b/talk/examples/peerconnection/server/server_test.html
@@ -33,28 +33,12 @@
   trace(str);
   if (document.getElementById("loopback").checked) {
     if (data.search("offer") != -1) {
-      // In loopback mode, replace the offer with an answer.
-      data = data.replace("offer", "answer");
-      // Keep only the first crypto line for each m line in the answer.
-      var mlines = data.split("m=");
-      // Start from 1 because the first item in the array is not a m line.
-      for (var i = 1; i < mlines.length; ++i) {
-        var mline = mlines[i];
-        var cryptoBegin = mline.indexOf("a=crypto:", 0);
-        if (cryptoBegin == -1) {
-          // No crypto line found.
-          continue;
-        }
-        // Skip the first crypto line.
-        cryptoBegin = mline.indexOf("a=crypto:", cryptoBegin + 1);
-        while (cryptoBegin != -1) {
-          var cryptoEnd = mline.indexOf("\\n", cryptoBegin);
-          var crypto = mline.substring(cryptoBegin, cryptoEnd + 2);
-          data = data.replace(crypto, "");
-          // Search for the the next crypto line.
-          cryptoBegin = mline.indexOf("a=crypto:", cryptoBegin + 1);
-        }
-      }
+      // In loopback mode, if DTLS is enabled, notify the client to disable it.
+      // Otherwise replace the offer with an answer.
+      if (data.search("fingerprint") != -1)
+        data = data.replace("offer", "offer-loopback");
+      else
+        data = data.replace("offer", "answer");
     }
     sendToPeer(peer_id, data);
   }