Update talk to 54527154.

TBR=wu

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4954 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
index e00ba16..1cb5992 100644
--- a/talk/session/media/channel.cc
+++ b/talk/session/media/channel.cc
@@ -1081,32 +1081,42 @@
   return media_channel()->SetSendBandwidth(true, max_bandwidth);
 }
 
+// |dtls| will be set to true if DTLS is active for transport channel and
+// crypto is empty.
+bool BaseChannel::CheckSrtpConfig(const std::vector<CryptoParams>& cryptos,
+                                  bool* dtls) {
+  *dtls = transport_channel_->IsDtlsActive();
+  if (*dtls && !cryptos.empty()) {
+    LOG(LS_WARNING) << "Cryptos must be empty when DTLS is active.";
+    return false;
+  }
+  return true;
+}
+
 bool BaseChannel::SetSrtp_w(const std::vector<CryptoParams>& cryptos,
                             ContentAction action, ContentSource src) {
   bool ret = false;
+  bool dtls = false;
+  ret = CheckSrtpConfig(cryptos, &dtls);
   switch (action) {
     case CA_OFFER:
-      ret = srtp_filter_.SetOffer(cryptos, src);
+      // If DTLS is already active on the channel, we could be renegotiating
+      // here. We don't update the srtp filter.
+      if (ret && !dtls) {
+        ret = srtp_filter_.SetOffer(cryptos, src);
+      }
       break;
     case CA_PRANSWER:
       // If we're doing DTLS-SRTP, we don't want to update the filter
       // with an answer, because we already have SRTP parameters.
-      if (transport_channel_->IsDtlsActive()) {
-        LOG(LS_INFO) <<
-          "Ignoring SDES answer parameters because we are using DTLS-SRTP";
-        ret = true;
-      } else {
+      if (ret && !dtls) {
         ret = srtp_filter_.SetProvisionalAnswer(cryptos, src);
       }
       break;
     case CA_ANSWER:
       // If we're doing DTLS-SRTP, we don't want to update the filter
       // with an answer, because we already have SRTP parameters.
-      if (transport_channel_->IsDtlsActive()) {
-        LOG(LS_INFO) <<
-          "Ignoring SDES answer parameters because we are using DTLS-SRTP";
-        ret = true;
-      } else {
+      if (ret && !dtls) {
         ret = srtp_filter_.SetAnswer(cryptos, src);
       }
       break;
@@ -2582,6 +2592,9 @@
     ret = UpdateLocalStreams_w(data->streams(), action);
     if (ret) {
       set_local_content_direction(content->direction());
+      // As in SetRemoteContent_w, make sure we set the local SCTP port
+      // number as specified in our DataContentDescription.
+      ret = media_channel()->SetRecvCodecs(data->codecs());
     }
   } else {
     ret = SetBaseLocalContent_w(content, action);
@@ -2620,6 +2633,9 @@
     ret = UpdateRemoteStreams_w(content->streams(), action);
     if (ret) {
       set_remote_content_direction(content->direction());
+      // We send the SCTP port number (not to be confused with the underlying
+      // UDP port number) as a codec parameter.  Make sure it gets there.
+      ret = media_channel()->SetSendCodecs(data->codecs());
     }
   } else {
     // If the remote data doesn't have codecs and isn't an update, it
diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h
index ccfdd07..6ee2e8c 100644
--- a/talk/session/media/channel.h
+++ b/talk/session/media/channel.h
@@ -318,6 +318,7 @@
   virtual bool SetRemoteContent_w(const MediaContentDescription* content,
                                   ContentAction action) = 0;
 
+  bool CheckSrtpConfig(const std::vector<CryptoParams>& cryptos, bool* dtls);
   bool SetSrtp_w(const std::vector<CryptoParams>& params, ContentAction action,
                  ContentSource src);
   bool SetRtcpMux_w(bool enable, ContentAction action, ContentSource src);
diff --git a/talk/session/media/channel_unittest.cc b/talk/session/media/channel_unittest.cc
index fda89b3..24ece06 100644
--- a/talk/session/media/channel_unittest.cc
+++ b/talk/session/media/channel_unittest.cc
@@ -233,6 +233,10 @@
         this, &ChannelTest<T>::OnMediaChannelError);
     channel1_->SignalAutoMuted.connect(
         this, &ChannelTest<T>::OnMediaMuted);
+    if ((flags1 & DTLS) && (flags2 & DTLS)) {
+      flags1 = (flags1 & ~SECURE);
+      flags2 = (flags2 & ~SECURE);
+    }
     CreateContent(flags1, kPcmuCodec, kH264Codec,
                   &local_media_content1_);
     CreateContent(flags2, kPcmuCodec, kH264Codec,
diff --git a/talk/session/media/mediasession.cc b/talk/session/media/mediasession.cc
index 3d1c468..ea23591 100644
--- a/talk/session/media/mediasession.cc
+++ b/talk/session/media/mediasession.cc
@@ -978,6 +978,42 @@
     desc->set_protocol(kMediaProtocolAvpf);
 }
 
+// Gets the TransportInfo of the given |content_name| from the
+// |current_description|. If doesn't exist, returns a new one.
+static const TransportDescription* GetTransportDescription(
+    const std::string& content_name,
+    const SessionDescription* current_description) {
+  const TransportDescription* desc = NULL;
+  if (current_description) {
+    const TransportInfo* info =
+        current_description->GetTransportInfoByName(content_name);
+    if (info) {
+      desc = &info->description;
+    }
+  }
+  return desc;
+}
+
+// Gets the current DTLS state from the transport description.
+static bool IsDtlsActive(
+    const std::string& content_name,
+    const SessionDescription* current_description) {
+  if (!current_description)
+    return false;
+
+  const ContentInfo* content =
+      current_description->GetContentByName(content_name);
+  if (!content)
+    return false;
+
+  const TransportDescription* current_tdesc =
+      GetTransportDescription(content_name, current_description);
+  if (!current_tdesc)
+    return false;
+
+  return current_tdesc->secure();
+}
+
 void MediaSessionOptions::AddStream(MediaType type,
                                     const std::string& id,
                                     const std::string& sync_label) {
@@ -1053,13 +1089,17 @@
 
   // Handle m=audio.
   if (options.has_audio) {
+    cricket::SecurePolicy sdes_policy =
+        IsDtlsActive(CN_AUDIO, current_description) ?
+            cricket::SEC_DISABLED : secure();
+
     scoped_ptr<AudioContentDescription> audio(new AudioContentDescription());
     std::vector<std::string> crypto_suites;
     GetSupportedAudioCryptoSuites(&crypto_suites);
     if (!CreateMediaContentOffer(
             options,
             audio_codecs,
-            secure(),
+            sdes_policy,
             GetCryptos(GetFirstAudioContentDescription(current_description)),
             crypto_suites,
             audio_rtp_extensions,
@@ -1080,13 +1120,17 @@
 
   // Handle m=video.
   if (options.has_video) {
+    cricket::SecurePolicy sdes_policy =
+        IsDtlsActive(CN_VIDEO, current_description) ?
+            cricket::SEC_DISABLED : secure();
+
     scoped_ptr<VideoContentDescription> video(new VideoContentDescription());
     std::vector<std::string> crypto_suites;
     GetSupportedVideoCryptoSuites(&crypto_suites);
     if (!CreateMediaContentOffer(
             options,
             video_codecs,
-            secure(),
+            sdes_policy,
             GetCryptos(GetFirstVideoContentDescription(current_description)),
             crypto_suites,
             video_rtp_extensions,
@@ -1110,8 +1154,10 @@
     scoped_ptr<DataContentDescription> data(new DataContentDescription());
     bool is_sctp = (options.data_channel_type == DCT_SCTP);
 
+    cricket::SecurePolicy sdes_policy =
+        IsDtlsActive(CN_DATA, current_description) ?
+            cricket::SEC_DISABLED : secure();
     std::vector<std::string> crypto_suites;
-    cricket::SecurePolicy sdes_policy = secure();
     if (is_sctp) {
       // SDES doesn't make sense for SCTP, so we disable it, and we only
       // get SDES crypto suites for RTP-based data channels.
@@ -1371,22 +1417,6 @@
   return answer.release();
 }
 
-// Gets the TransportInfo of the given |content_name| from the
-// |current_description|. If doesn't exist, returns a new one.
-static const TransportDescription* GetTransportDescription(
-    const std::string& content_name,
-    const SessionDescription* current_description) {
-  const TransportDescription* desc = NULL;
-  if (current_description) {
-    const TransportInfo* info =
-        current_description->GetTransportInfoByName(content_name);
-    if (info) {
-      desc = &info->description;
-    }
-  }
-  return desc;
-}
-
 void MediaSessionDescriptionFactory::GetCodecsToOffer(
     const SessionDescription* current_description,
     AudioCodecs* audio_codecs,
diff --git a/talk/session/media/mediasession_unittest.cc b/talk/session/media/mediasession_unittest.cc
index f014e78..850d67f 100644
--- a/talk/session/media/mediasession_unittest.cc
+++ b/talk/session/media/mediasession_unittest.cc
@@ -1814,6 +1814,26 @@
   ASSERT_TRUE(video_trans_desc != NULL);
   ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
   ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
+
+  // Try creating offer again. DTLS enabled now, crypto's should be empty
+  // in new offer.
+  offer.reset(f1_.CreateOffer(options, offer.get()));
+  ASSERT_TRUE(offer.get() != NULL);
+  audio_media_desc = static_cast<const cricket::MediaContentDescription*>(
+      offer->GetContentDescriptionByName("audio"));
+  ASSERT_TRUE(audio_media_desc != NULL);
+  video_media_desc = static_cast<const cricket::MediaContentDescription*>(
+      offer->GetContentDescriptionByName("video"));
+  ASSERT_TRUE(video_media_desc != NULL);
+  EXPECT_TRUE(audio_media_desc->cryptos().empty());
+  EXPECT_TRUE(video_media_desc->cryptos().empty());
+
+  audio_trans_desc = offer->GetTransportDescriptionByName("audio");
+  ASSERT_TRUE(audio_trans_desc != NULL);
+  video_trans_desc = offer->GetTransportDescriptionByName("video");
+  ASSERT_TRUE(video_trans_desc != NULL);
+  ASSERT_TRUE(audio_trans_desc->identity_fingerprint.get() != NULL);
+  ASSERT_TRUE(video_trans_desc->identity_fingerprint.get() != NULL);
 }
 
 // Test that an answer can't be created if cryptos are required but the offer is