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
This commit is contained in:
@ -164,18 +164,24 @@ bool DataChannel::Send(const DataBuffer& buffer) {
|
|||||||
// If the queue is non-empty, we're waiting for SignalReadyToSend,
|
// If the queue is non-empty, we're waiting for SignalReadyToSend,
|
||||||
// so just add to the end of the queue and keep waiting.
|
// so just add to the end of the queue and keep waiting.
|
||||||
if (!queued_send_data_.empty()) {
|
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;
|
cricket::SendDataResult send_result;
|
||||||
if (!InternalSendWithoutQueueing(buffer, &send_result)) {
|
if (!InternalSendWithoutQueueing(buffer, &send_result)) {
|
||||||
if (send_result == cricket::SDR_BLOCK) {
|
if (data_channel_type_ == cricket::DCT_RTP) {
|
||||||
return QueueSendData(buffer);
|
|
||||||
}
|
|
||||||
// Fail for other results.
|
|
||||||
// TODO(jiayl): We should close the data channel in this case.
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (send_result != cricket::SDR_BLOCK || !QueueSendData(buffer)) {
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -325,9 +331,8 @@ void DataChannel::OnDataReceived(cricket::DataChannel* channel,
|
|||||||
observer_->OnMessage(*buffer.get());
|
observer_->OnMessage(*buffer.get());
|
||||||
} else {
|
} else {
|
||||||
if (queued_received_data_.size() > kMaxQueuedReceivedDataPackets) {
|
if (queued_received_data_.size() > kMaxQueuedReceivedDataPackets) {
|
||||||
// TODO(jiayl): We should close the data channel in this case.
|
|
||||||
LOG(LS_ERROR)
|
LOG(LS_ERROR)
|
||||||
<< "Queued received data exceeds the max number of packes.";
|
<< "Queued received data exceeds the max number of packets.";
|
||||||
ClearQueuedReceivedData();
|
ClearQueuedReceivedData();
|
||||||
}
|
}
|
||||||
queued_received_data_.push(buffer.release());
|
queued_received_data_.push(buffer.release());
|
||||||
@ -522,8 +527,8 @@ bool DataChannel::InternalSendWithoutQueueing(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DataChannel::QueueSendData(const DataBuffer& buffer) {
|
bool DataChannel::QueueSendData(const DataBuffer& buffer) {
|
||||||
if (queued_send_data_.size() > kMaxQueuedSendDataPackets) {
|
if (queued_send_data_.size() >= kMaxQueuedSendDataPackets) {
|
||||||
LOG(LS_ERROR) << "Can't buffer any more data in the data channel.";
|
LOG(LS_ERROR) << "Can't buffer any more data for the data channel.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
queued_send_data_.push_back(new DataBuffer(buffer));
|
queued_send_data_.push_back(new DataBuffer(buffer));
|
||||||
|
@ -29,14 +29,24 @@
|
|||||||
#include "talk/app/webrtc/sctputils.h"
|
#include "talk/app/webrtc/sctputils.h"
|
||||||
#include "talk/app/webrtc/test/fakedatachannelprovider.h"
|
#include "talk/app/webrtc/test/fakedatachannelprovider.h"
|
||||||
#include "talk/base/gunit.h"
|
#include "talk/base/gunit.h"
|
||||||
#include "testing/base/public/gmock.h"
|
|
||||||
|
|
||||||
using webrtc::DataChannel;
|
using webrtc::DataChannel;
|
||||||
|
|
||||||
class FakeDataChannelObserver : public webrtc::DataChannelObserver {
|
class FakeDataChannelObserver : public webrtc::DataChannelObserver {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD0(OnStateChange, void());
|
FakeDataChannelObserver() : messages_received_(0) {}
|
||||||
MOCK_METHOD1(OnMessage, void(const webrtc::DataBuffer& buffer));
|
|
||||||
|
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 {
|
class SctpDataChannelTest : public testing::Test {
|
||||||
@ -233,12 +243,13 @@ TEST_F(SctpDataChannelTest, ReceiveDataWithInvalidSsrc) {
|
|||||||
SetChannelReady();
|
SetChannelReady();
|
||||||
|
|
||||||
AddObserver();
|
AddObserver();
|
||||||
EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(0);
|
|
||||||
|
|
||||||
cricket::ReceiveDataParams params;
|
cricket::ReceiveDataParams params;
|
||||||
params.ssrc = 0;
|
params.ssrc = 0;
|
||||||
webrtc::DataBuffer buffer("abcd");
|
webrtc::DataBuffer buffer("abcd");
|
||||||
webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
|
webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
|
||||||
|
|
||||||
|
EXPECT_EQ(0U, observer_->messages_received());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that the incoming messages with right ssrcs are acceted.
|
// Tests that the incoming messages with right ssrcs are acceted.
|
||||||
@ -247,13 +258,13 @@ TEST_F(SctpDataChannelTest, ReceiveDataWithValidSsrc) {
|
|||||||
SetChannelReady();
|
SetChannelReady();
|
||||||
|
|
||||||
AddObserver();
|
AddObserver();
|
||||||
EXPECT_CALL(*(observer_.get()), OnMessage(testing::_)).Times(1);
|
|
||||||
|
|
||||||
cricket::ReceiveDataParams params;
|
cricket::ReceiveDataParams params;
|
||||||
params.ssrc = 1;
|
params.ssrc = 1;
|
||||||
webrtc::DataBuffer buffer("abcd");
|
webrtc::DataBuffer buffer("abcd");
|
||||||
|
|
||||||
webrtc_data_channel_->OnDataReceived(NULL, params, buffer.data);
|
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
|
// Tests that no CONTROL message is sent if the datachannel is negotiated and
|
||||||
@ -302,3 +313,29 @@ TEST_F(SctpDataChannelTest, OpenAckRoleInitialization) {
|
|||||||
webrtc::InternalDataChannelInit init2(base);
|
webrtc::InternalDataChannelInit init2(base);
|
||||||
EXPECT_EQ(webrtc::InternalDataChannelInit::kNone, init2.open_handshake_role);
|
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());
|
||||||
|
}
|
||||||
|
@ -32,7 +32,8 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
|
|||||||
FakeDataChannelProvider()
|
FakeDataChannelProvider()
|
||||||
: send_blocked_(false),
|
: send_blocked_(false),
|
||||||
transport_available_(false),
|
transport_available_(false),
|
||||||
ready_to_send_(false) {}
|
ready_to_send_(false),
|
||||||
|
transport_error_(false) {}
|
||||||
virtual ~FakeDataChannelProvider() {}
|
virtual ~FakeDataChannelProvider() {}
|
||||||
|
|
||||||
virtual bool SendData(const cricket::SendDataParams& params,
|
virtual bool SendData(const cricket::SendDataParams& params,
|
||||||
@ -43,6 +44,12 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
|
|||||||
*result = cricket::SDR_BLOCK;
|
*result = cricket::SDR_BLOCK;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (transport_error_) {
|
||||||
|
*result = cricket::SDR_ERROR;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
last_send_data_params_ = params;
|
last_send_data_params_ = params;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -115,6 +122,10 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_transport_error() {
|
||||||
|
transport_error_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
cricket::SendDataParams last_send_data_params() const {
|
cricket::SendDataParams last_send_data_params() const {
|
||||||
return last_send_data_params_;
|
return last_send_data_params_;
|
||||||
}
|
}
|
||||||
@ -136,6 +147,7 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
|
|||||||
bool send_blocked_;
|
bool send_blocked_;
|
||||||
bool transport_available_;
|
bool transport_available_;
|
||||||
bool ready_to_send_;
|
bool ready_to_send_;
|
||||||
|
bool transport_error_;
|
||||||
std::set<webrtc::DataChannel*> connected_channels_;
|
std::set<webrtc::DataChannel*> connected_channels_;
|
||||||
std::set<uint32> send_ssrcs_;
|
std::set<uint32> send_ssrcs_;
|
||||||
std::set<uint32> recv_ssrcs_;
|
std::set<uint32> recv_ssrcs_;
|
||||||
|
@ -393,7 +393,7 @@
|
|||||||
],
|
],
|
||||||
# TODO(ronghuawu): Reenable below unit tests that require gmock.
|
# TODO(ronghuawu): Reenable below unit tests that require gmock.
|
||||||
'sources': [
|
'sources': [
|
||||||
# 'app/webrtc/datachannel_unittest.cc',
|
'app/webrtc/datachannel_unittest.cc',
|
||||||
'app/webrtc/dtmfsender_unittest.cc',
|
'app/webrtc/dtmfsender_unittest.cc',
|
||||||
'app/webrtc/jsepsessiondescription_unittest.cc',
|
'app/webrtc/jsepsessiondescription_unittest.cc',
|
||||||
'app/webrtc/localaudiosource_unittest.cc',
|
'app/webrtc/localaudiosource_unittest.cc',
|
||||||
|
Reference in New Issue
Block a user