Closes the DataChannel when the send buffer is full or on transport errors.
As stated in the spec.
BUG=2645
R=pthatcher@google.com, wu@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/12619004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@6270 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index 048e89a..ef20269 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -164,17 +164,23 @@
// If the queue is non-empty, we're waiting for SignalReadyToSend,
// so just add to the end of the queue and keep waiting.
if (!queued_send_data_.empty()) {
- return QueueSendData(buffer);
+ if (!QueueSendData(buffer)) {
+ if (data_channel_type_ == cricket::DCT_RTP) {
+ return false;
+ }
+ Close();
+ }
+ return true;
}
cricket::SendDataResult send_result;
if (!InternalSendWithoutQueueing(buffer, &send_result)) {
- if (send_result == cricket::SDR_BLOCK) {
- return QueueSendData(buffer);
+ if (data_channel_type_ == cricket::DCT_RTP) {
+ return false;
}
- // Fail for other results.
- // TODO(jiayl): We should close the data channel in this case.
- return false;
+ if (send_result != cricket::SDR_BLOCK || !QueueSendData(buffer)) {
+ Close();
+ }
}
return true;
}
@@ -325,9 +331,8 @@
observer_->OnMessage(*buffer.get());
} else {
if (queued_received_data_.size() > kMaxQueuedReceivedDataPackets) {
- // TODO(jiayl): We should close the data channel in this case.
LOG(LS_ERROR)
- << "Queued received data exceeds the max number of packes.";
+ << "Queued received data exceeds the max number of packets.";
ClearQueuedReceivedData();
}
queued_received_data_.push(buffer.release());
@@ -522,8 +527,8 @@
}
bool DataChannel::QueueSendData(const DataBuffer& buffer) {
- if (queued_send_data_.size() > kMaxQueuedSendDataPackets) {
- LOG(LS_ERROR) << "Can't buffer any more data in the data channel.";
+ if (queued_send_data_.size() >= kMaxQueuedSendDataPackets) {
+ LOG(LS_ERROR) << "Can't buffer any more data for the data channel.";
return false;
}
queued_send_data_.push_back(new DataBuffer(buffer));
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index 1be24e9..e132fb1 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -29,14 +29,24 @@
#include "talk/app/webrtc/sctputils.h"
#include "talk/app/webrtc/test/fakedatachannelprovider.h"
#include "talk/base/gunit.h"
-#include "testing/base/public/gmock.h"
using webrtc::DataChannel;
class FakeDataChannelObserver : public webrtc::DataChannelObserver {
public:
- MOCK_METHOD0(OnStateChange, void());
- MOCK_METHOD1(OnMessage, void(const webrtc::DataBuffer& buffer));
+ FakeDataChannelObserver() : messages_received_(0) {}
+
+ void OnStateChange() {}
+ void OnMessage(const webrtc::DataBuffer& buffer) {
+ ++messages_received_;
+ }
+
+ size_t messages_received() const {
+ return messages_received_;
+ }
+
+ private:
+ size_t messages_received_;
};
class SctpDataChannelTest : public testing::Test {
@@ -233,12 +243,13 @@
SetChannelReady();
AddObserver();
- EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(0);
cricket::ReceiveDataParams params;
params.ssrc = 0;
webrtc::DataBuffer buffer("abcd");
webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
+
+ EXPECT_EQ(0U, observer_->messages_received());
}
// Tests that the incoming messages with right ssrcs are acceted.
@@ -247,13 +258,13 @@
SetChannelReady();
AddObserver();
- EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(1);
cricket::ReceiveDataParams params;
params.ssrc = 1;
webrtc::DataBuffer buffer("abcd");
webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
+ EXPECT_EQ(1U, observer_->messages_received());
}
// Tests that no CONTROL message is sent if the datachannel is negotiated and
@@ -302,3 +313,29 @@
webrtc::InternalDataChannelInit init2(base);
EXPECT_EQ(webrtc::InternalDataChannelInit::kNone, init2.open_handshake_role);
}
+
+// Tests that the DataChannel is closed if the sending buffer is full.
+TEST_F(SctpDataChannelTest, ClosedWhenSendBufferFull) {
+ SetChannelReady();
+ webrtc::DataBuffer buffer("abcd");
+ provider_.set_send_blocked(true);
+
+ for (size_t i = 0; i < 101; ++i) {
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+ }
+
+ EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
+ webrtc_data_channel_->state());
+}
+
+// Tests that the DataChannel is closed on transport errors.
+TEST_F(SctpDataChannelTest, ClosedOnTransportError) {
+ SetChannelReady();
+ webrtc::DataBuffer buffer("abcd");
+ provider_.set_transport_error();
+
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+
+ EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
+ webrtc_data_channel_->state());
+}
diff --git a/talk/app/webrtc/test/fakedatachannelprovider.h b/talk/app/webrtc/test/fakedatachannelprovider.h
index 5b19698..053b3ac 100644
--- a/talk/app/webrtc/test/fakedatachannelprovider.h
+++ b/talk/app/webrtc/test/fakedatachannelprovider.h
@@ -32,7 +32,8 @@
FakeDataChannelProvider()
: send_blocked_(false),
transport_available_(false),
- ready_to_send_(false) {}
+ ready_to_send_(false),
+ transport_error_(false) {}
virtual ~FakeDataChannelProvider() {}
virtual bool SendData(const cricket::SendDataParams& params,
@@ -43,6 +44,12 @@
*result = cricket::SDR_BLOCK;
return false;
}
+
+ if (transport_error_) {
+ *result = cricket::SDR_ERROR;
+ return false;
+ }
+
last_send_data_params_ = params;
return true;
}
@@ -115,6 +122,10 @@
}
}
+ void set_transport_error() {
+ transport_error_ = true;
+ }
+
cricket::SendDataParams last_send_data_params() const {
return last_send_data_params_;
}
@@ -136,6 +147,7 @@
bool send_blocked_;
bool transport_available_;
bool ready_to_send_;
+ bool transport_error_;
std::set<webrtc::DataChannel*> connected_channels_;
std::set<uint32> send_ssrcs_;
std::set<uint32> recv_ssrcs_;