Fix a SCTP message reordering issue in datachannel.cc.

Previously DataChannel::SendQueuedDataMessages continues the loop of sending queued messages if the channel is blocked, which will cause message reordering if the channel becomes unblocked during the loop, i.e. messages attempted after the unblocking will be sent earlier than the older messages attempted before the unblocking.

BUG=3979
R=pthatcher@webrtc.org

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

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7690 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
jiayl@webrtc.org
2014-11-12 17:28:40 +00:00
parent ea73ff7267
commit 6ca6190be2
2 changed files with 28 additions and 16 deletions

View File

@@ -215,7 +215,7 @@ bool DataChannel::Send(const DataBuffer& buffer) {
return true; return true;
} }
bool success = SendDataMessage(buffer); bool success = SendDataMessage(buffer, true);
if (data_channel_type_ == cricket::DCT_RTP) { if (data_channel_type_ == cricket::DCT_RTP) {
return success; return success;
} }
@@ -461,17 +461,17 @@ void DataChannel::DeliverQueuedReceivedData() {
void DataChannel::SendQueuedDataMessages() { void DataChannel::SendQueuedDataMessages() {
ASSERT(was_ever_writable_ && state_ == kOpen); ASSERT(was_ever_writable_ && state_ == kOpen);
PacketQueue packet_buffer; while (!queued_send_data_.Empty()) {
packet_buffer.Swap(&queued_send_data_); rtc::scoped_ptr<DataBuffer> buffer(queued_send_data_.Front());
if (!SendDataMessage(*buffer, false)) {
while (!packet_buffer.Empty()) { break;
rtc::scoped_ptr<DataBuffer> buffer(packet_buffer.Front()); }
SendDataMessage(*buffer); queued_send_data_.Pop();
packet_buffer.Pop();
} }
} }
bool DataChannel::SendDataMessage(const DataBuffer& buffer) { bool DataChannel::SendDataMessage(const DataBuffer& buffer,
bool queue_if_blocked) {
cricket::SendDataParams send_params; cricket::SendDataParams send_params;
if (data_channel_type_ == cricket::DCT_SCTP) { if (data_channel_type_ == cricket::DCT_SCTP) {
@@ -494,14 +494,26 @@ bool DataChannel::SendDataMessage(const DataBuffer& buffer) {
cricket::SendDataResult send_result = cricket::SDR_SUCCESS; cricket::SendDataResult send_result = cricket::SDR_SUCCESS;
bool success = provider_->SendData(send_params, buffer.data, &send_result); bool success = provider_->SendData(send_params, buffer.data, &send_result);
if (!success && data_channel_type_ == cricket::DCT_SCTP) { if (success) {
if (send_result != cricket::SDR_BLOCK || !QueueSendDataMessage(buffer)) { return true;
LOG(LS_ERROR) << "Closing the DataChannel due to a failure to send data, " }
<< "send_result = " << send_result;
Close(); if (data_channel_type_ != cricket::DCT_SCTP) {
return false;
}
if (send_result == cricket::SDR_BLOCK) {
if (!queue_if_blocked || QueueSendDataMessage(buffer)) {
return false;
} }
} }
return success; // Close the channel if the error is not SDR_BLOCK, or if queuing the
// message failed.
LOG(LS_ERROR) << "Closing the DataChannel due to a failure to send data, "
<< "send_result = " << send_result;
Close();
return false;
} }
bool DataChannel::QueueSendDataMessage(const DataBuffer& buffer) { bool DataChannel::QueueSendDataMessage(const DataBuffer& buffer) {

View File

@@ -213,7 +213,7 @@ class DataChannel : public DataChannelInterface,
void DeliverQueuedReceivedData(); void DeliverQueuedReceivedData();
void SendQueuedDataMessages(); void SendQueuedDataMessages();
bool SendDataMessage(const DataBuffer& buffer); bool SendDataMessage(const DataBuffer& buffer, bool queue_if_blocked);
bool QueueSendDataMessage(const DataBuffer& buffer); bool QueueSendDataMessage(const DataBuffer& buffer);
void SendQueuedControlMessages(); void SendQueuedControlMessages();