Fix assertion failure when closing data channel, and add a unit test.

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

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7816 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index 6ff0941..aa540b6 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -441,7 +441,7 @@
   provider_->DisconnectDataChannel(this);
   connected_to_provider_ = false;
 
-  if (data_channel_type_ == cricket::DCT_SCTP) {
+  if (data_channel_type_ == cricket::DCT_SCTP && config_.id >= 0) {
     provider_->RemoveSctpDataStream(config_.id);
   }
 }
diff --git a/talk/app/webrtc/datachannel.h b/talk/app/webrtc/datachannel.h
index 1a455b7..6349cc5 100644
--- a/talk/app/webrtc/datachannel.h
+++ b/talk/app/webrtc/datachannel.h
@@ -54,9 +54,9 @@
   // Disconnects from the transport signals.
   virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
   // Adds the data channel SID to the transport for SCTP.
-  virtual void AddSctpDataStream(uint32 sid) = 0;
+  virtual void AddSctpDataStream(int sid) = 0;
   // Removes the data channel SID from the transport for SCTP.
-  virtual void RemoveSctpDataStream(uint32 sid) = 0;
+  virtual void RemoveSctpDataStream(int sid) = 0;
   // Returns true if the transport channel is ready to send data.
   virtual bool ReadyToSendData() const = 0;
 
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index 84a6935..82f5dc9 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -423,3 +423,10 @@
   EXPECT_EQ(webrtc::DataChannelInterface::kOpen,
             webrtc_data_channel_->state());
 }
+
+// Tests that a channel can be closed without being opened or assigned an sid.
+TEST_F(SctpDataChannelTest, NeverOpened) {
+  provider_.set_transport_available(true);
+  webrtc_data_channel_->OnTransportChannelCreated();
+  webrtc_data_channel_->Close();
+}
diff --git a/talk/app/webrtc/test/fakedatachannelprovider.h b/talk/app/webrtc/test/fakedatachannelprovider.h
index 2e71f94..fa6787a 100644
--- a/talk/app/webrtc/test/fakedatachannelprovider.h
+++ b/talk/app/webrtc/test/fakedatachannelprovider.h
@@ -71,7 +71,8 @@
     connected_channels_.erase(data_channel);
   }
 
-  virtual void AddSctpDataStream(uint32 sid) OVERRIDE {
+  virtual void AddSctpDataStream(int sid) OVERRIDE {
+    ASSERT(sid >= 0);
     if (!transport_available_) {
       return;
     }
@@ -79,7 +80,8 @@
     recv_ssrcs_.insert(sid);
   }
 
-  virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE {
+  virtual void RemoveSctpDataStream(int sid) OVERRIDE {
+    ASSERT(sid >= 0);
     send_ssrcs_.erase(sid);
     recv_ssrcs_.erase(sid);
   }
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index c124237..f651af5 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -1136,7 +1136,7 @@
   data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
 }
 
-void WebRtcSession::AddSctpDataStream(uint32 sid) {
+void WebRtcSession::AddSctpDataStream(int sid) {
   if (!data_channel_.get()) {
     LOG(LS_ERROR) << "AddDataChannelStreams called when data_channel_ is NULL.";
     return;
@@ -1145,8 +1145,8 @@
   data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(sid));
 }
 
-void WebRtcSession::RemoveSctpDataStream(uint32 sid) {
-  mediastream_signaling_->RemoveSctpDataChannel(static_cast<int>(sid));
+void WebRtcSession::RemoveSctpDataStream(int sid) {
+  mediastream_signaling_->RemoveSctpDataChannel(sid);
 
   if (!data_channel_.get()) {
     LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 3db2682..1d8281c 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -203,8 +203,8 @@
                         cricket::SendDataResult* result) OVERRIDE;
   virtual bool ConnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
   virtual void DisconnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
-  virtual void AddSctpDataStream(uint32 sid) OVERRIDE;
-  virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE;
+  virtual void AddSctpDataStream(int sid) OVERRIDE;
+  virtual void RemoveSctpDataStream(int sid) OVERRIDE;
   virtual bool ReadyToSendData() const OVERRIDE;
 
   // Implements DataChannelFactory.