Fix the SrtpFilter crash caused by two local offers.

BUG=http://crbug.com/421774
R=juberti@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7530 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/session/media/srtpfilter.cc b/talk/session/media/srtpfilter.cc
index c79bf13..5a774db 100644
--- a/talk/session/media/srtpfilter.cc
+++ b/talk/session/media/srtpfilter.cc
@@ -150,7 +150,7 @@
                               const uint8* send_key, int send_key_len,
                               const std::string& recv_cs,
                               const uint8* recv_key, int recv_key_len) {
-  if (state_ == ST_ACTIVE) {
+  if (IsActive()) {
     LOG(LS_ERROR) << "Tried to set SRTP Params when filter already active";
     return false;
   }
@@ -212,6 +212,7 @@
     LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
     return false;
   }
+  ASSERT(send_session_ != NULL);
   return send_session_->ProtectRtp(p, in_len, max_len, out_len);
 }
 
@@ -221,7 +222,7 @@
     LOG(LS_WARNING) << "Failed to ProtectRtp: SRTP not active";
     return false;
   }
-
+  ASSERT(send_session_ != NULL);
   return send_session_->ProtectRtp(p, in_len, max_len, out_len, index);
 }
 
@@ -233,6 +234,7 @@
   if (send_rtcp_session_) {
     return send_rtcp_session_->ProtectRtcp(p, in_len, max_len, out_len);
   } else {
+    ASSERT(send_session_ != NULL);
     return send_session_->ProtectRtcp(p, in_len, max_len, out_len);
   }
 }
@@ -242,6 +244,7 @@
     LOG(LS_WARNING) << "Failed to UnprotectRtp: SRTP not active";
     return false;
   }
+  ASSERT(recv_session_ != NULL);
   return recv_session_->UnprotectRtp(p, in_len, out_len);
 }
 
@@ -253,6 +256,7 @@
   if (recv_rtcp_session_) {
     return recv_rtcp_session_->UnprotectRtcp(p, in_len, out_len);
   } else {
+    ASSERT(recv_session_ != NULL);
     return recv_session_->UnprotectRtcp(p, in_len, out_len);
   }
 }
@@ -263,13 +267,16 @@
     return false;
   }
 
+  ASSERT(send_session_ != NULL);
   return send_session_->GetRtpAuthParams(key, key_len, tag_len);
 }
 
 void SrtpFilter::set_signal_silent_time(uint32 signal_silent_time_in_ms) {
   signal_silent_time_in_ms_ = signal_silent_time_in_ms;
-  if (state_ == ST_ACTIVE) {
+  if (IsActive()) {
+    ASSERT(send_session_ != NULL);
     send_session_->set_signal_silent_time(signal_silent_time_in_ms);
+    ASSERT(recv_session_ != NULL);
     recv_session_->set_signal_silent_time(signal_silent_time_in_ms);
     if (send_rtcp_session_)
       send_rtcp_session_->set_signal_silent_time(signal_silent_time_in_ms);
@@ -292,7 +299,7 @@
   offer_params_ = params;
   if (state_ == ST_INIT) {
     state_ = (source == CS_LOCAL) ? ST_SENTOFFER : ST_RECEIVEDOFFER;
-  } else {  // state >= ST_ACTIVE
+  } else if (state_ == ST_ACTIVE) {
     state_ =
         (source == CS_LOCAL) ? ST_SENTUPDATEDOFFER : ST_RECEIVEDUPDATEDOFFER;
   }
diff --git a/talk/session/media/srtpfilter_unittest.cc b/talk/session/media/srtpfilter_unittest.cc
index 19efa2a..8b859f8 100644
--- a/talk/session/media/srtpfilter_unittest.cc
+++ b/talk/session/media/srtpfilter_unittest.cc
@@ -82,9 +82,12 @@
                      const std::vector<CryptoParams>& params2) {
     EXPECT_TRUE(f1_.SetOffer(params1, CS_LOCAL));
     EXPECT_TRUE(f2_.SetOffer(params1, CS_REMOTE));
+    EXPECT_FALSE(f1_.IsActive());
+    EXPECT_FALSE(f2_.IsActive());
     EXPECT_TRUE(f2_.SetAnswer(params2, CS_LOCAL));
     EXPECT_TRUE(f1_.SetAnswer(params2, CS_REMOTE));
     EXPECT_TRUE(f1_.IsActive());
+    EXPECT_TRUE(f2_.IsActive());
   }
   void TestProtectUnprotect(const std::string& cs1, const std::string& cs2) {
     char rtp_packet[sizeof(kPcmuFrame) + 10];
@@ -139,6 +142,7 @@
 // Test that we can set up the session and keys properly.
 TEST_F(SrtpFilterTest, TestGoodSetupOneCipherSuite) {
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
+  EXPECT_FALSE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
   EXPECT_TRUE(f1_.IsActive());
 }
@@ -153,6 +157,7 @@
   answer[0].tag = 2;
   answer[0].cipher_suite = CS_AES_CM_128_HMAC_SHA1_32;
   EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
+  EXPECT_FALSE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
   EXPECT_TRUE(f1_.IsActive());
 }
@@ -188,6 +193,7 @@
 TEST_F(SrtpFilterTest, TestGoodSetupMultipleOffers) {
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
+  EXPECT_FALSE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams2), CS_REMOTE));
   EXPECT_TRUE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
@@ -196,6 +202,7 @@
 
   EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
   EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
+  EXPECT_FALSE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
   EXPECT_TRUE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_REMOTE));
@@ -206,6 +213,7 @@
 TEST_F(SrtpFilterTest, TestBadSetupMultipleOffers) {
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
   EXPECT_FALSE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
+  EXPECT_FALSE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetAnswer(MakeVector(kTestCryptoParams1), CS_REMOTE));
   EXPECT_TRUE(f1_.IsActive());
   EXPECT_TRUE(f1_.SetOffer(MakeVector(kTestCryptoParams2), CS_LOCAL));
@@ -214,6 +222,7 @@
 
   EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
   EXPECT_FALSE(f2_.SetOffer(MakeVector(kTestCryptoParams1), CS_LOCAL));
+  EXPECT_FALSE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetAnswer(MakeVector(kTestCryptoParams2), CS_LOCAL));
   EXPECT_TRUE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetOffer(MakeVector(kTestCryptoParams2), CS_REMOTE));
@@ -402,6 +411,8 @@
 
   EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
   EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
+  EXPECT_FALSE(f1_.IsActive());
+  EXPECT_FALSE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
   EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
   EXPECT_TRUE(f1_.IsActive());
@@ -425,6 +436,8 @@
 
   EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
   EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
+  EXPECT_FALSE(f1_.IsActive());
+  EXPECT_FALSE(f2_.IsActive());
   EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
   EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
   EXPECT_FALSE(f1_.IsActive());
@@ -438,6 +451,33 @@
   TestProtectUnprotect(CS_AES_CM_128_HMAC_SHA1_80, CS_AES_CM_128_HMAC_SHA1_80);
 }
 
+// Test that if we get a new local offer after a provisional answer
+// with no crypto, that we are in an inactive state.
+TEST_F(SrtpFilterTest, TestLocalOfferAfterProvisionalAnswerWithoutCrypto) {
+  std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));
+  std::vector<CryptoParams> answer;
+
+  EXPECT_TRUE(f1_.SetOffer(offer, CS_LOCAL));
+  EXPECT_TRUE(f2_.SetOffer(offer, CS_REMOTE));
+  EXPECT_TRUE(f1_.SetProvisionalAnswer(answer, CS_REMOTE));
+  EXPECT_TRUE(f2_.SetProvisionalAnswer(answer, CS_LOCAL));
+  EXPECT_FALSE(f1_.IsActive());
+  EXPECT_FALSE(f2_.IsActive());
+  // The calls to set an offer after a provisional answer fail, so the
+  // state doesn't change.
+  EXPECT_FALSE(f1_.SetOffer(offer, CS_LOCAL));
+  EXPECT_FALSE(f2_.SetOffer(offer, CS_REMOTE));
+  EXPECT_FALSE(f1_.IsActive());
+  EXPECT_FALSE(f2_.IsActive());
+
+  answer.push_back(kTestCryptoParams2);
+  EXPECT_TRUE(f2_.SetAnswer(answer, CS_LOCAL));
+  EXPECT_TRUE(f1_.SetAnswer(answer, CS_REMOTE));
+  EXPECT_TRUE(f1_.IsActive());
+  EXPECT_TRUE(f2_.IsActive());
+  TestProtectUnprotect(CS_AES_CM_128_HMAC_SHA1_80, CS_AES_CM_128_HMAC_SHA1_80);
+}
+
 // Test that we can disable encryption.
 TEST_F(SrtpFilterTest, TestDisableEncryption) {
   std::vector<CryptoParams> offer(MakeVector(kTestCryptoParams1));