Update libjingle to 50191337.
R=mallinath@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/1885005
git-svn-id: http://webrtc.googlecode.com/svn/trunk@4461 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index 345cd5f..4972424 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -34,7 +34,8 @@
namespace webrtc {
-static size_t kMaxQueuedDataPackets = 100;
+static size_t kMaxQueuedReceivedDataPackets = 100;
+static size_t kMaxQueuedSendDataPackets = 100;
talk_base::scoped_refptr<DataChannel> DataChannel::Create(
WebRtcSession* session,
@@ -95,12 +96,13 @@
}
DataChannel::~DataChannel() {
- ClearQueuedData();
+ ClearQueuedReceivedData();
+ ClearQueuedSendData();
}
void DataChannel::RegisterObserver(DataChannelObserver* observer) {
observer_ = observer;
- DeliverQueuedData();
+ DeliverQueuedReceivedData();
}
void DataChannel::UnregisterObserver() {
@@ -117,7 +119,13 @@
}
uint64 DataChannel::buffered_amount() const {
- return 0;
+ uint64 buffered_amount = 0;
+ for (std::deque<DataBuffer*>::const_iterator it = queued_send_data_.begin();
+ it != queued_send_data_.end();
+ ++it) {
+ buffered_amount += (*it)->size();
+ }
+ return buffered_amount;
}
void DataChannel::Close() {
@@ -133,20 +141,22 @@
if (state_ != kOpen) {
return false;
}
- cricket::SendDataParams send_params;
-
- send_params.ssrc = send_ssrc_;
- if (session_->data_channel_type() == cricket::DCT_SCTP) {
- send_params.ordered = config_.ordered;
- send_params.max_rtx_count = config_.maxRetransmits;
- send_params.max_rtx_ms = config_.maxRetransmitTime;
+ // 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);
}
- send_params.type = buffer.binary ? cricket::DMT_BINARY : cricket::DMT_TEXT;
cricket::SendDataResult send_result;
- // TODO(pthatcher): Use send_result.would_block for buffering.
- return session_->data_channel()->SendData(
- send_params, buffer.data, &send_result);
+ if (!InternalSendWithoutQueueing(buffer, &send_result)) {
+ if (send_result == cricket::SDR_BLOCK) {
+ return QueueSendData(buffer);
+ }
+ // Fail for other results.
+ // TODO(jiayl): We should close the data channel in this case.
+ return false;
+ }
+ return true;
}
void DataChannel::SetReceiveSsrc(uint32 receive_ssrc) {
@@ -183,6 +193,43 @@
DoClose();
}
+void DataChannel::OnDataReceived(cricket::DataChannel* channel,
+ const cricket::ReceiveDataParams& params,
+ const talk_base::Buffer& payload) {
+ if (params.ssrc != receive_ssrc_) {
+ return;
+ }
+
+ bool binary = (params.type == cricket::DMT_BINARY);
+ talk_base::scoped_ptr<DataBuffer> buffer(new DataBuffer(payload, binary));
+ if (was_ever_writable_ && observer_) {
+ 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.";
+ ClearQueuedReceivedData();
+ }
+ queued_received_data_.push(buffer.release());
+ }
+}
+
+void DataChannel::OnChannelReady(bool writable) {
+ if (!writable) {
+ return;
+ }
+ // Update the readyState if the channel is writable for the first time;
+ // otherwise it means the channel was blocked for sending and now unblocked,
+ // so send the queued data now.
+ if (!was_ever_writable_) {
+ was_ever_writable_ = true;
+ UpdateState();
+ } else if (state_ == kOpen) {
+ SendQueuedSendData();
+ }
+}
+
void DataChannel::DoClose() {
receive_ssrc_set_ = false;
send_ssrc_set_ = false;
@@ -201,7 +248,7 @@
SetState(kOpen);
// If we have received buffers before the channel got writable.
// Deliver them now.
- DeliverQueuedData();
+ DeliverQueuedReceivedData();
}
}
break;
@@ -249,47 +296,76 @@
data_session_ = NULL;
}
-void DataChannel::DeliverQueuedData() {
- if (was_ever_writable_ && observer_) {
- while (!queued_data_.empty()) {
- DataBuffer* buffer = queued_data_.front();
- observer_->OnMessage(*buffer);
- queued_data_.pop();
- delete buffer;
- }
+void DataChannel::DeliverQueuedReceivedData() {
+ if (!was_ever_writable_ || !observer_) {
+ return;
}
-}
-void DataChannel::ClearQueuedData() {
- while (!queued_data_.empty()) {
- DataBuffer* buffer = queued_data_.front();
- queued_data_.pop();
+ while (!queued_received_data_.empty()) {
+ DataBuffer* buffer = queued_received_data_.front();
+ observer_->OnMessage(*buffer);
+ queued_received_data_.pop();
delete buffer;
}
}
-void DataChannel::OnDataReceived(cricket::DataChannel* channel,
- const cricket::ReceiveDataParams& params,
- const talk_base::Buffer& payload) {
- if (params.ssrc == receive_ssrc_) {
- bool binary = false;
- talk_base::scoped_ptr<DataBuffer> buffer(new DataBuffer(payload, binary));
- if (was_ever_writable_ && observer_) {
- observer_->OnMessage(*buffer.get());
- } else {
- if (queued_data_.size() > kMaxQueuedDataPackets) {
- ClearQueuedData();
- }
- queued_data_.push(buffer.release());
- }
+void DataChannel::ClearQueuedReceivedData() {
+ while (!queued_received_data_.empty()) {
+ DataBuffer* buffer = queued_received_data_.front();
+ queued_received_data_.pop();
+ delete buffer;
}
}
-void DataChannel::OnChannelReady(bool writable) {
- if (!was_ever_writable_ && writable) {
- was_ever_writable_ = true;
- UpdateState();
+void DataChannel::SendQueuedSendData() {
+ if (!was_ever_writable_) {
+ return;
}
+
+ while (!queued_send_data_.empty()) {
+ DataBuffer* buffer = queued_send_data_.front();
+ cricket::SendDataResult send_result;
+ if (!InternalSendWithoutQueueing(*buffer, &send_result)) {
+ LOG(LS_WARNING) << "SendQueuedSendData aborted due to send_result "
+ << send_result;
+ break;
+ }
+ queued_send_data_.pop_front();
+ delete buffer;
+ }
+}
+
+void DataChannel::ClearQueuedSendData() {
+ while (!queued_received_data_.empty()) {
+ DataBuffer* buffer = queued_received_data_.front();
+ queued_received_data_.pop();
+ delete buffer;
+ }
+}
+
+bool DataChannel::InternalSendWithoutQueueing(
+ const DataBuffer& buffer, cricket::SendDataResult* send_result) {
+ cricket::SendDataParams send_params;
+
+ send_params.ssrc = send_ssrc_;
+ if (session_->data_channel_type() == cricket::DCT_SCTP) {
+ send_params.ordered = config_.ordered;
+ send_params.max_rtx_count = config_.maxRetransmits;
+ send_params.max_rtx_ms = config_.maxRetransmitTime;
+ }
+ send_params.type = buffer.binary ? cricket::DMT_BINARY : cricket::DMT_TEXT;
+
+ return session_->data_channel()->SendData(send_params, buffer.data,
+ send_result);
+}
+
+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.";
+ return false;
+ }
+ queued_send_data_.push_back(new DataBuffer(buffer));
+ return true;
}
} // namespace webrtc
diff --git a/talk/app/webrtc/datachannel.h b/talk/app/webrtc/datachannel.h
index c79c491..440ee15 100644
--- a/talk/app/webrtc/datachannel.h
+++ b/talk/app/webrtc/datachannel.h
@@ -109,8 +109,13 @@
void ConnectToDataSession();
void DisconnectFromDataSession();
bool IsConnectedToDataSession() { return data_session_ != NULL; }
- void DeliverQueuedData();
- void ClearQueuedData();
+ void DeliverQueuedReceivedData();
+ void ClearQueuedReceivedData();
+ void SendQueuedSendData();
+ void ClearQueuedSendData();
+ bool InternalSendWithoutQueueing(const DataBuffer& buffer,
+ cricket::SendDataResult* send_result);
+ bool QueueSendData(const DataBuffer& buffer);
std::string label_;
DataChannelInit config_;
@@ -123,7 +128,8 @@
uint32 send_ssrc_;
bool receive_ssrc_set_;
uint32 receive_ssrc_;
- std::queue<DataBuffer*> queued_data_;
+ std::queue<DataBuffer*> queued_received_data_;
+ std::deque<DataBuffer*> queued_send_data_;
};
class DataChannelFactory {
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
new file mode 100644
index 0000000..d3faf17
--- /dev/null
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -0,0 +1,129 @@
+/*
+ * libjingle
+ * Copyright 2013, Google Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
+ * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "talk/app/webrtc/datachannel.h"
+#include "talk/app/webrtc/mediastreamsignaling.h"
+#include "talk/app/webrtc/test/fakeconstraints.h"
+#include "talk/app/webrtc/webrtcsession.h"
+#include "talk/base/gunit.h"
+#include "talk/media/base/fakemediaengine.h"
+#include "talk/media/devices/fakedevicemanager.h"
+#include "talk/session/media/channelmanager.h"
+
+using webrtc::MediaConstraintsInterface;
+
+const uint32 kFakeSsrc = 1;
+
+class SctpDataChannelTest : public testing::Test {
+ protected:
+ SctpDataChannelTest()
+ : media_engine_(new cricket::FakeMediaEngine),
+ data_engine_(new cricket::FakeDataEngine),
+ channel_manager_(
+ new cricket::ChannelManager(media_engine_,
+ data_engine_,
+ new cricket::FakeDeviceManager(),
+ new cricket::CaptureManager(),
+ talk_base::Thread::Current())),
+ session_(channel_manager_.get(),
+ talk_base::Thread::Current(),
+ talk_base::Thread::Current(),
+ NULL,
+ new webrtc::MediaStreamSignaling(talk_base::Thread::Current(),
+ NULL)),
+ webrtc_data_channel_(NULL) {}
+
+ virtual void SetUp() {
+ if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
+ return;
+ }
+ channel_manager_->Init();
+ webrtc::FakeConstraints constraints;
+ constraints.AddMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
+ constraints.AddMandatory(MediaConstraintsInterface::kEnableSctpDataChannels,
+ true);
+ ASSERT_TRUE(session_.Initialize(&constraints));
+ webrtc::SessionDescriptionInterface* offer = session_.CreateOffer(NULL);
+ ASSERT_TRUE(offer != NULL);
+ ASSERT_TRUE(session_.SetLocalDescription(offer, NULL));
+
+ webrtc_data_channel_ = webrtc::DataChannel::Create(&session_, "test", NULL);
+ // Connect to the media channel.
+ webrtc_data_channel_->SetSendSsrc(kFakeSsrc);
+ webrtc_data_channel_->SetReceiveSsrc(kFakeSsrc);
+
+ session_.data_channel()->SignalReadyToSendData(true);
+ }
+
+ void SetSendBlocked(bool blocked) {
+ bool was_blocked = data_engine_->GetChannel(0)->is_send_blocked();
+ data_engine_->GetChannel(0)->set_send_blocked(blocked);
+ if (!blocked && was_blocked) {
+ session_.data_channel()->SignalReadyToSendData(true);
+ }
+ }
+
+ cricket::FakeMediaEngine* media_engine_;
+ cricket::FakeDataEngine* data_engine_;
+ talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
+ webrtc::WebRtcSession session_;
+ talk_base::scoped_refptr<webrtc::DataChannel> webrtc_data_channel_;
+};
+
+// Tests that DataChannel::buffered_amount() is correct after the channel is
+// blocked.
+TEST_F(SctpDataChannelTest, BufferedAmountWhenBlocked) {
+ if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
+ return;
+ }
+ webrtc::DataBuffer buffer("abcd");
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+
+ EXPECT_EQ(0U, webrtc_data_channel_->buffered_amount());
+
+ SetSendBlocked(true);
+ const int number_of_packets = 3;
+ for (int i = 0; i < number_of_packets; ++i) {
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+ }
+ EXPECT_EQ(buffer.data.length() * number_of_packets,
+ webrtc_data_channel_->buffered_amount());
+}
+
+// Tests that the queued data are sent when the channel transitions from blocked
+// to unblocked.
+TEST_F(SctpDataChannelTest, QueuedDataSentWhenUnblocked) {
+ if (!talk_base::SSLStreamAdapter::HaveDtlsSrtp()) {
+ return;
+ }
+ webrtc::DataBuffer buffer("abcd");
+ SetSendBlocked(true);
+ EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
+
+ SetSendBlocked(false);
+ EXPECT_EQ(0U, webrtc_data_channel_->buffered_amount());
+}
diff --git a/talk/app/webrtc/datachannelinterface.h b/talk/app/webrtc/datachannelinterface.h
index 6054e1b..82d375c 100644
--- a/talk/app/webrtc/datachannelinterface.h
+++ b/talk/app/webrtc/datachannelinterface.h
@@ -75,6 +75,8 @@
: data(text.data(), text.length()),
binary(false) {
}
+ size_t size() const { return data.length(); }
+
talk_base::Buffer data;
// Indicates if the received data contains UTF-8 or binary data.
// Note that the upper layers are left to verify the UTF-8 encoding.
diff --git a/talk/base/host.cc b/talk/base/host.cc
deleted file mode 100644
index 7decc49..0000000
--- a/talk/base/host.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/base/host.h"
-
-#ifdef POSIX
-#include <sys/utsname.h>
-#endif // POSIX
-
-#include <string>
-
-namespace talk_base {
-
-std::string GetHostName() {
- // TODO: fix or get rid of this
-#if 0
- struct utsname nm;
- if (uname(&nm) < 0)
- FatalError("uname", LAST_SYSTEM_ERROR);
- return std::string(nm.nodename);
-#endif
- return "cricket";
-}
-
-} // namespace talk_base
diff --git a/talk/base/host.h b/talk/base/host.h
deleted file mode 100644
index 8528240..0000000
--- a/talk/base/host.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2005, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef TALK_BASE_HOST_H_
-#define TALK_BASE_HOST_H_
-
-#include <string>
-
-namespace talk_base {
-
-// Returns the name of the local host.
-std::string GetHostName();
-
-} // namespace talk_base
-
-#endif // TALK_BASE_HOST_H_
diff --git a/talk/base/host_unittest.cc b/talk/base/host_unittest.cc
deleted file mode 100644
index aba87af..0000000
--- a/talk/base/host_unittest.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * libjingle
- * Copyright 2004--2011, Google Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "talk/base/gunit.h"
-#include "talk/base/host.h"
-
-TEST(Host, GetHostName) {
- EXPECT_NE("", talk_base::GetHostName());
-}
diff --git a/talk/base/httpcommon.cc b/talk/base/httpcommon.cc
index 458f2f9..ec7ffd2 100644
--- a/talk/base/httpcommon.cc
+++ b/talk/base/httpcommon.cc
@@ -528,11 +528,14 @@
HttpError
HttpRequestData::parseLeader(const char* line, size_t len) {
- UNUSED(len);
unsigned int vmajor, vminor;
int vend, dstart, dend;
- if ((sscanf(line, "%*s%n %n%*s%n HTTP/%u.%u", &vend, &dstart, &dend,
- &vmajor, &vminor) != 2)
+ // sscanf isn't safe with strings that aren't null-terminated, and there is
+ // no guarantee that |line| is. Create a local copy that is null-terminated.
+ std::string line_str(line, len);
+ line = line_str.c_str();
+ if ((sscanf(line, "%*s%n %n%*s%n HTTP/%u.%u",
+ &vend, &dstart, &dend, &vmajor, &vminor) != 2)
|| (vmajor != 1)) {
return HE_PROTOCOL;
}
@@ -649,6 +652,10 @@
size_t pos = 0;
unsigned int vmajor, vminor, temp_scode;
int temp_pos;
+ // sscanf isn't safe with strings that aren't null-terminated, and there is
+ // no guarantee that |line| is. Create a local copy that is null-terminated.
+ std::string line_str(line, len);
+ line = line_str.c_str();
if (sscanf(line, "HTTP %u%n",
&temp_scode, &temp_pos) == 1) {
// This server's response has no version. :( NOTE: This happens for every
diff --git a/talk/base/nat_unittest.cc b/talk/base/nat_unittest.cc
index 03170ca..9771235 100644
--- a/talk/base/nat_unittest.cc
+++ b/talk/base/nat_unittest.cc
@@ -28,7 +28,6 @@
#include <string>
#include "talk/base/gunit.h"
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/base/natserver.h"
#include "talk/base/natsocketfactory.h"
diff --git a/talk/base/network.cc b/talk/base/network.cc
index 9351b87..d6367c3 100644
--- a/talk/base/network.cc
+++ b/talk/base/network.cc
@@ -53,7 +53,6 @@
#include <algorithm>
#include <cstdio>
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/socket.h" // includes something that makes windows happy
@@ -174,8 +173,7 @@
}
BasicNetworkManager::BasicNetworkManager()
- : thread_(NULL),
- start_count_(0) {
+ : thread_(NULL), sent_first_update_(false), start_count_(0) {
}
BasicNetworkManager::~BasicNetworkManager() {
diff --git a/talk/base/testclient_unittest.cc b/talk/base/testclient_unittest.cc
index 1269236..c1411f0 100644
--- a/talk/base/testclient_unittest.cc
+++ b/talk/base/testclient_unittest.cc
@@ -26,7 +26,6 @@
*/
#include "talk/base/gunit.h"
-#include "talk/base/host.h"
#include "talk/base/nethelpers.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/testclient.h"
diff --git a/talk/base/thread_unittest.cc b/talk/base/thread_unittest.cc
index 11b493d..246faa4 100644
--- a/talk/base/thread_unittest.cc
+++ b/talk/base/thread_unittest.cc
@@ -28,7 +28,6 @@
#include "talk/base/asyncudpsocket.h"
#include "talk/base/event.h"
#include "talk/base/gunit.h"
-#include "talk/base/host.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/socketaddress.h"
#include "talk/base/thread.h"
diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp
index 09e4316..0944f76 100755
--- a/talk/libjingle.gyp
+++ b/talk/libjingle.gyp
@@ -300,8 +300,6 @@
'base/gunit_prod.h',
'base/helpers.cc',
'base/helpers.h',
- 'base/host.cc',
- 'base/host.h',
'base/httpbase.cc',
'base/httpbase.h',
'base/httpclient.cc',
diff --git a/talk/libjingle_tests.gyp b/talk/libjingle_tests.gyp
index d248750..aba09ed 100755
--- a/talk/libjingle_tests.gyp
+++ b/talk/libjingle_tests.gyp
@@ -121,7 +121,6 @@
'base/filelock_unittest.cc',
'base/fileutils_unittest.cc',
'base/helpers_unittest.cc',
- 'base/host_unittest.cc',
'base/httpbase_unittest.cc',
'base/httpcommon_unittest.cc',
'base/httpserver_unittest.cc',
@@ -376,6 +375,7 @@
],
# TODO(ronghuawu): Reenable below unit tests that require gmock.
'sources': [
+ 'app/webrtc/datachannel_unittest.cc',
'app/webrtc/dtmfsender_unittest.cc',
'app/webrtc/jsepsessiondescription_unittest.cc',
'app/webrtc/localaudiosource_unittest.cc',
diff --git a/talk/media/base/capturemanager.cc b/talk/media/base/capturemanager.cc
index 5705bcd..85bfa54 100644
--- a/talk/media/base/capturemanager.cc
+++ b/talk/media/base/capturemanager.cc
@@ -145,12 +145,19 @@
}
CaptureManager::~CaptureManager() {
- while (!capture_states_.empty()) {
- // There may have been multiple calls to StartVideoCapture which means that
- // an equal number of calls to StopVideoCapture must be made. Note that
- // StopVideoCapture will remove the element from |capture_states_| when a
- // successfull stop has been made.
- UnregisterVideoCapturer(capture_states_.begin()->second);
+ // Since we don't own any of the capturers, all capturers should have been
+ // cleaned up before we get here. In fact, in the normal shutdown sequence,
+ // all capturers *will* be shut down by now, so trying to stop them here
+ // will crash. If we're still tracking any, it's a dangling pointer.
+ if (!capture_states_.empty()) {
+ ASSERT(false &&
+ "CaptureManager destructing while still tracking capturers!");
+ // Delete remaining VideoCapturerStates, but don't touch the capturers.
+ do {
+ CaptureStates::iterator it = capture_states_.begin();
+ delete it->second;
+ capture_states_.erase(it);
+ } while (!capture_states_.empty());
}
}
diff --git a/talk/media/base/capturemanager_unittest.cc b/talk/media/base/capturemanager_unittest.cc
index e9d9cfb..8025e56 100644
--- a/talk/media/base/capturemanager_unittest.cc
+++ b/talk/media/base/capturemanager_unittest.cc
@@ -180,6 +180,10 @@
EXPECT_TRUE(video_capturer_.CaptureFrame());
EXPECT_EQ(1, NumFramesRendered());
EXPECT_TRUE(WasRenderedResolution(format_qvga_));
+ EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
+ format_qvga_));
+ EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
+ format_vga_));
}
// Ensure that the reference counting is working when multiple start and
@@ -230,6 +234,8 @@
EXPECT_TRUE(video_capturer_.CaptureFrame());
EXPECT_EQ(2, NumFramesRendered());
EXPECT_TRUE(WasRenderedResolution(format_vga_));
+ EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
+ format_vga_));
}
TEST_F(CaptureManagerTest, TestRequestRestart) {
@@ -248,4 +254,6 @@
EXPECT_TRUE(video_capturer_.CaptureFrame());
EXPECT_EQ(2, NumFramesRendered());
EXPECT_TRUE(WasRenderedResolution(format_vga_));
+ EXPECT_TRUE(capture_manager_.StopVideoCapture(&video_capturer_,
+ format_qvga_));
}
diff --git a/talk/media/base/fakemediaengine.h b/talk/media/base/fakemediaengine.h
index 7f4c9e3..ded5698 100644
--- a/talk/media/base/fakemediaengine.h
+++ b/talk/media/base/fakemediaengine.h
@@ -599,7 +599,7 @@
class FakeDataMediaChannel : public RtpHelper<DataMediaChannel> {
public:
explicit FakeDataMediaChannel(void* unused)
- : auto_bandwidth_(false), max_bps_(-1) {}
+ : auto_bandwidth_(false), send_blocked_(false), max_bps_(-1) {}
~FakeDataMediaChannel() {}
const std::vector<DataCodec>& recv_codecs() const { return recv_codecs_; }
const std::vector<DataCodec>& send_codecs() const { return send_codecs_; }
@@ -647,13 +647,20 @@
virtual bool SendData(const SendDataParams& params,
const talk_base::Buffer& payload,
SendDataResult* result) {
- last_sent_data_params_ = params;
- last_sent_data_ = std::string(payload.data(), payload.length());
- return true;
+ if (send_blocked_) {
+ *result = SDR_BLOCK;
+ return false;
+ } else {
+ last_sent_data_params_ = params;
+ last_sent_data_ = std::string(payload.data(), payload.length());
+ return true;
+ }
}
SendDataParams last_sent_data_params() { return last_sent_data_params_; }
std::string last_sent_data() { return last_sent_data_; }
+ bool is_send_blocked() { return send_blocked_; }
+ void set_send_blocked(bool blocked) { send_blocked_ = blocked; }
private:
std::vector<DataCodec> recv_codecs_;
@@ -661,6 +668,7 @@
SendDataParams last_sent_data_params_;
std::string last_sent_data_;
bool auto_bandwidth_;
+ bool send_blocked_;
int max_bps_;
};
diff --git a/talk/media/base/mediachannel.h b/talk/media/base/mediachannel.h
index 07d5f90..a9e3778 100644
--- a/talk/media/base/mediachannel.h
+++ b/talk/media/base/mediachannel.h
@@ -957,6 +957,9 @@
// Signal errors from MediaChannel. Arguments are:
// ssrc(uint32), and error(DataMediaChannel::Error).
sigslot::signal2<uint32, DataMediaChannel::Error> SignalMediaError;
+ // Signal when the media channel is ready to send the stream. Arguments are:
+ // writable(bool)
+ sigslot::signal1<bool> SignalReadyToSend;
};
} // namespace cricket
diff --git a/talk/media/sctp/sctpdataengine.cc b/talk/media/sctp/sctpdataengine.cc
index 7fcb239..71ef73c 100644
--- a/talk/media/sctp/sctpdataengine.cc
+++ b/talk/media/sctp/sctpdataengine.cc
@@ -270,7 +270,8 @@
// Subscribe to SCTP event notifications.
int event_types[] = {SCTP_ASSOC_CHANGE,
SCTP_PEER_ADDR_CHANGE,
- SCTP_SEND_FAILED_EVENT};
+ SCTP_SEND_FAILED_EVENT,
+ SCTP_SENDER_DRY_EVENT};
struct sctp_event event = {0};
event.se_assoc_id = SCTP_ALL_ASSOC;
event.se_on = 1;
@@ -479,11 +480,14 @@
static_cast<socklen_t>(sizeof(sndinfo)),
SCTP_SENDV_SNDINFO, 0);
if (res < 0) {
- LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_
- << "SendData->(...): "
- << " usrsctp_sendv: ";
- // TODO(pthatcher): Make result SDR_BLOCK if the error is because
- // it would block.
+ if (errno == EWOULDBLOCK) {
+ *result = SDR_BLOCK;
+ LOG(LS_INFO) << debug_name_ << "->SendData(...): EWOULDBLOCK returned";
+ } else {
+ LOG_ERRNO(LS_ERROR) << "ERROR:" << debug_name_
+ << "->SendData(...): "
+ << " usrsctp_sendv: ";
+ }
return false;
}
if (result) {
@@ -562,8 +566,7 @@
}
}
-void SctpDataMediaChannel::OnNotificationFromSctp(
- talk_base::Buffer* buffer) {
+void SctpDataMediaChannel::OnNotificationFromSctp(talk_base::Buffer* buffer) {
const sctp_notification& notification =
reinterpret_cast<const sctp_notification&>(*buffer->data());
ASSERT(notification.sn_header.sn_length == buffer->length());
@@ -591,6 +594,7 @@
break;
case SCTP_SENDER_DRY_EVENT:
LOG(LS_INFO) << "SCTP_SENDER_DRY_EVENT";
+ SignalReadyToSend(true);
break;
// TODO(ldixon): Unblock after congestion.
case SCTP_NOTIFICATIONS_STOPPED_EVENT:
diff --git a/talk/media/sctp/sctpdataengine_unittest.cc b/talk/media/sctp/sctpdataengine_unittest.cc
index 071fbbb..2b8787f 100644
--- a/talk/media/sctp/sctpdataengine_unittest.cc
+++ b/talk/media/sctp/sctpdataengine_unittest.cc
@@ -137,6 +137,24 @@
cricket::ReceiveDataParams last_params_;
};
+class SignalReadyToSendObserver : public sigslot::has_slots<> {
+ public:
+ SignalReadyToSendObserver() : signaled_(false), writable_(false) {}
+
+ void OnSignaled(bool writable) {
+ signaled_ = true;
+ writable_ = writable;
+ }
+
+ bool IsSignaled(bool writable) {
+ return signaled_ && (writable_ == writable);
+ }
+
+ private:
+ bool signaled_;
+ bool writable_;
+};
+
// SCTP Data Engine testing framework.
class SctpDataMediaChannelTest : public testing::Test {
protected:
@@ -144,6 +162,42 @@
engine_.reset(new cricket::SctpDataEngine());
}
+ void SetupConnectedChannels() {
+ net1_.reset(new SctpFakeNetworkInterface(talk_base::Thread::Current()));
+ net2_.reset(new SctpFakeNetworkInterface(talk_base::Thread::Current()));
+ recv1_.reset(new SctpFakeDataReceiver());
+ recv2_.reset(new SctpFakeDataReceiver());
+ chan1_.reset(CreateChannel(net1_.get(), recv1_.get()));
+ chan1_->set_debug_name("chan1/connector");
+ chan2_.reset(CreateChannel(net2_.get(), recv2_.get()));
+ chan2_->set_debug_name("chan2/listener");
+ // Setup two connected channels ready to send and receive.
+ net1_->SetDestination(chan2_.get());
+ net2_->SetDestination(chan1_.get());
+
+ LOG(LS_VERBOSE) << "Channel setup ----------------------------- ";
+ chan1_->AddSendStream(cricket::StreamParams::CreateLegacy(1));
+ chan2_->AddRecvStream(cricket::StreamParams::CreateLegacy(1));
+
+ chan2_->AddSendStream(cricket::StreamParams::CreateLegacy(2));
+ chan1_->AddRecvStream(cricket::StreamParams::CreateLegacy(2));
+
+ LOG(LS_VERBOSE) << "Connect the channels -----------------------------";
+ // chan1 wants to setup a data connection.
+ chan1_->SetReceive(true);
+ // chan1 will have sent chan2 a request to setup a data connection. After
+ // chan2 accepts the offer, chan2 connects to chan1 with the following.
+ chan2_->SetReceive(true);
+ chan2_->SetSend(true);
+ // Makes sure that network packets are delivered and simulates a
+ // deterministic and realistic small timing delay between the SetSend calls.
+ ProcessMessagesUntilIdle();
+
+ // chan1 and chan2 are now connected so chan1 enables sending to complete
+ // the creation of the connection.
+ chan1_->SetSend(true);
+ }
+
cricket::SctpDataMediaChannel* CreateChannel(
SctpFakeNetworkInterface* net, SctpFakeDataReceiver* recv) {
cricket::SctpDataMediaChannel* channel =
@@ -182,79 +236,78 @@
return !thread->IsQuitting();
}
+ cricket::SctpDataMediaChannel* channel1() { return chan1_.get(); }
+ cricket::SctpDataMediaChannel* channel2() { return chan2_.get(); }
+ SctpFakeDataReceiver* receiver1() { return recv1_.get(); }
+ SctpFakeDataReceiver* receiver2() { return recv2_.get(); }
+
private:
talk_base::scoped_ptr<cricket::SctpDataEngine> engine_;
+ talk_base::scoped_ptr<SctpFakeNetworkInterface> net1_;
+ talk_base::scoped_ptr<SctpFakeNetworkInterface> net2_;
+ talk_base::scoped_ptr<SctpFakeDataReceiver> recv1_;
+ talk_base::scoped_ptr<SctpFakeDataReceiver> recv2_;
+ talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan1_;
+ talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan2_;
};
+// Verifies that SignalReadyToSend is fired.
+TEST_F(SctpDataMediaChannelTest, SignalReadyToSend) {
+ SetupConnectedChannels();
+
+ SignalReadyToSendObserver signal_observer_1;
+ SignalReadyToSendObserver signal_observer_2;
+
+ channel1()->SignalReadyToSend.connect(&signal_observer_1,
+ &SignalReadyToSendObserver::OnSignaled);
+ channel2()->SignalReadyToSend.connect(&signal_observer_2,
+ &SignalReadyToSendObserver::OnSignaled);
+
+ cricket::SendDataResult result;
+ ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
+ EXPECT_EQ(cricket::SDR_SUCCESS, result);
+ EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
+ ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
+ EXPECT_EQ(cricket::SDR_SUCCESS, result);
+ EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
+
+ EXPECT_TRUE_WAIT(signal_observer_1.IsSignaled(true), 1000);
+ EXPECT_TRUE_WAIT(signal_observer_2.IsSignaled(true), 1000);
+}
+
TEST_F(SctpDataMediaChannelTest, SendData) {
- talk_base::scoped_ptr<SctpFakeNetworkInterface> net1(
- new SctpFakeNetworkInterface(talk_base::Thread::Current()));
- talk_base::scoped_ptr<SctpFakeNetworkInterface> net2(
- new SctpFakeNetworkInterface(talk_base::Thread::Current()));
- talk_base::scoped_ptr<SctpFakeDataReceiver> recv1(
- new SctpFakeDataReceiver());
- talk_base::scoped_ptr<SctpFakeDataReceiver> recv2(
- new SctpFakeDataReceiver());
- talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan1(
- CreateChannel(net1.get(), recv1.get()));
- chan1->set_debug_name("chan1/connector");
- talk_base::scoped_ptr<cricket::SctpDataMediaChannel> chan2(
- CreateChannel(net2.get(), recv2.get()));
- chan2->set_debug_name("chan2/listener");
-
- net1->SetDestination(chan2.get());
- net2->SetDestination(chan1.get());
-
- LOG(LS_VERBOSE) << "Channel setup ----------------------------- ";
- chan1->AddSendStream(cricket::StreamParams::CreateLegacy(1));
- chan2->AddRecvStream(cricket::StreamParams::CreateLegacy(1));
-
- chan2->AddSendStream(cricket::StreamParams::CreateLegacy(2));
- chan1->AddRecvStream(cricket::StreamParams::CreateLegacy(2));
-
- LOG(LS_VERBOSE) << "Connect the channels -----------------------------";
- // chan1 wants to setup a data connection.
- chan1->SetReceive(true);
- // chan1 will have sent chan2 a request to setup a data connection. After
- // chan2 accepts the offer, chan2 connects to chan1 with the following.
- chan2->SetReceive(true);
- chan2->SetSend(true);
- // Makes sure that network packets are delivered and simulates a
- // deterministic and realistic small timing delay between the SetSend calls.
- ProcessMessagesUntilIdle();
-
- // chan1 and chan2 are now connected so chan1 enables sending to complete
- // the creation of the connection.
- chan1->SetSend(true);
+ SetupConnectedChannels();
cricket::SendDataResult result;
LOG(LS_VERBOSE) << "chan1 sending: 'hello?' -----------------------------";
- ASSERT_TRUE(SendData(chan1.get(), 1, "hello?", &result));
+ ASSERT_TRUE(SendData(channel1(), 1, "hello?", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
- EXPECT_TRUE_WAIT(ReceivedData(recv2.get(), 1, "hello?"), 1000);
- LOG(LS_VERBOSE) << "recv2.received=" << recv2->received()
- << "recv2.last_params.ssrc=" << recv2->last_params().ssrc
+ EXPECT_TRUE_WAIT(ReceivedData(receiver2(), 1, "hello?"), 1000);
+ LOG(LS_VERBOSE) << "recv2.received=" << receiver2()->received()
+ << "recv2.last_params.ssrc="
+ << receiver2()->last_params().ssrc
<< "recv2.last_params.timestamp="
- << recv2->last_params().ssrc
+ << receiver2()->last_params().ssrc
<< "recv2.last_params.seq_num="
- << recv2->last_params().seq_num
- << "recv2.last_data=" << recv2->last_data();
+ << receiver2()->last_params().seq_num
+ << "recv2.last_data=" << receiver2()->last_data();
LOG(LS_VERBOSE) << "chan2 sending: 'hi chan1' -----------------------------";
- ASSERT_TRUE(SendData(chan2.get(), 2, "hi chan1", &result));
+ ASSERT_TRUE(SendData(channel2(), 2, "hi chan1", &result));
EXPECT_EQ(cricket::SDR_SUCCESS, result);
- EXPECT_TRUE_WAIT(ReceivedData(recv1.get(), 2, "hi chan1"), 1000);
- LOG(LS_VERBOSE) << "recv1.received=" << recv1->received()
- << "recv1.last_params.ssrc=" << recv1->last_params().ssrc
+ EXPECT_TRUE_WAIT(ReceivedData(receiver1(), 2, "hi chan1"), 1000);
+ LOG(LS_VERBOSE) << "recv1.received=" << receiver1()->received()
+ << "recv1.last_params.ssrc="
+ << receiver1()->last_params().ssrc
<< "recv1.last_params.timestamp="
- << recv1->last_params().ssrc
+ << receiver1()->last_params().ssrc
<< "recv1.last_params.seq_num="
- << recv1->last_params().seq_num
- << "recv1.last_data=" << recv1->last_data();
+ << receiver1()->last_params().seq_num
+ << "recv1.last_data=" << receiver1()->last_data();
LOG(LS_VERBOSE) << "Closing down. -----------------------------";
// Disconnects and closes socket, including setting receiving to false.
- chan1->SetSend(false);
- chan2->SetSend(false);
+ channel1()->SetSend(false);
+ channel2()->SetSend(false);
LOG(LS_VERBOSE) << "Cleaning up. -----------------------------";
}
diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc
index 19ccebf..10cdd8e 100644
--- a/talk/media/webrtc/webrtcvideoengine.cc
+++ b/talk/media/webrtc/webrtcvideoengine.cc
@@ -429,7 +429,7 @@
DecoderMap registered_decoders_;
};
-class WebRtcVideoChannelSendInfo {
+class WebRtcVideoChannelSendInfo : public sigslot::has_slots<> {
public:
typedef std::map<int, webrtc::VideoEncoder*> EncoderMap; // key: payload type
WebRtcVideoChannelSendInfo(int channel_id, int capture_id,
@@ -445,9 +445,7 @@
capturer_updated_(false),
interval_(0),
video_adapter_(new CoordinatedVideoAdapter) {
- // TODO(asapersson):
- // video_adapter_->SignalCpuAdaptationUnable.connect(
- // this, &WebRtcVideoChannelSendInfo::OnCpuAdaptationUnable);
+ SignalCpuAdaptationUnable.repeat(video_adapter_->SignalCpuAdaptationUnable);
if (cpu_monitor) {
cpu_monitor->SignalUpdate.connect(
video_adapter_.get(), &CoordinatedVideoAdapter::OnCpuLoadUpdated);
@@ -585,6 +583,8 @@
registered_encoders_.clear();
}
+ sigslot::repeater0<> SignalCpuAdaptationUnable;
+
private:
int channel_id_;
int capture_id_;
@@ -2931,6 +2931,8 @@
external_capture,
engine()->cpu_monitor()));
send_channel->ApplyCpuOptions(options_);
+ send_channel->SignalCpuAdaptationUnable.connect(this,
+ &WebRtcVideoMediaChannel::OnCpuAdaptationUnable);
// Register encoder observer for outgoing framerate and bitrate.
if (engine()->vie()->codec()->RegisterEncoderObserver(
@@ -3404,6 +3406,12 @@
}
}
+void WebRtcVideoMediaChannel::OnCpuAdaptationUnable() {
+ // ssrc is hardcoded to 0. This message is based on a system wide issue,
+ // so finding which ssrc caused it doesn't matter.
+ SignalMediaError(0, VideoMediaChannel::ERROR_REC_CPU_MAX_CANT_DOWNGRADE);
+}
+
void WebRtcVideoMediaChannel::SetNetworkTransmissionState(
bool is_transmitting) {
LOG(LS_INFO) << "SetNetworkTransmissionState: " << is_transmitting;
diff --git a/talk/media/webrtc/webrtcvideoengine.h b/talk/media/webrtc/webrtcvideoengine.h
index 2f0fd3e..f0293bb 100644
--- a/talk/media/webrtc/webrtcvideoengine.h
+++ b/talk/media/webrtc/webrtcvideoengine.h
@@ -396,6 +396,9 @@
const std::vector<RtpHeaderExtension>& extensions,
const char header_extension_uri[]);
+ // Signal when cpu adaptation has no further scope to adapt.
+ void OnCpuAdaptationUnable();
+
// Global state.
WebRtcVideoEngine* engine_;
VoiceMediaChannel* voice_channel_;
diff --git a/talk/media/webrtc/webrtcvideoengine_unittest.cc b/talk/media/webrtc/webrtcvideoengine_unittest.cc
index 376f295..840fcdd 100644
--- a/talk/media/webrtc/webrtcvideoengine_unittest.cc
+++ b/talk/media/webrtc/webrtcvideoengine_unittest.cc
@@ -86,7 +86,9 @@
// Test fixture to test WebRtcVideoEngine with a fake webrtc::VideoEngine.
// Useful for testing failure paths.
-class WebRtcVideoEngineTestFake : public testing::Test {
+class WebRtcVideoEngineTestFake :
+ public testing::Test,
+ public sigslot::has_slots<> {
public:
WebRtcVideoEngineTestFake()
: vie_(kVideoCodecs, ARRAY_SIZE(kVideoCodecs)),
@@ -95,16 +97,22 @@
engine_(NULL, // cricket::WebRtcVoiceEngine
new FakeViEWrapper(&vie_), cpu_monitor_),
channel_(NULL),
- voice_channel_(NULL) {
+ voice_channel_(NULL),
+ last_error_(cricket::VideoMediaChannel::ERROR_NONE) {
}
bool SetupEngine() {
bool result = engine_.Init(talk_base::Thread::Current());
if (result) {
channel_ = engine_.CreateChannel(voice_channel_);
+ channel_->SignalMediaError.connect(this,
+ &WebRtcVideoEngineTestFake::OnMediaError);
result = (channel_ != NULL);
}
return result;
}
+ void OnMediaError(uint32 ssrc, cricket::VideoMediaChannel::Error error) {
+ last_error_ = error;
+ }
bool SendI420Frame(int width, int height) {
if (NULL == channel_) {
return false;
@@ -185,6 +193,7 @@
cricket::WebRtcVideoEngine engine_;
cricket::WebRtcVideoMediaChannel* channel_;
cricket::WebRtcVoiceMediaChannel* voice_channel_;
+ cricket::VideoMediaChannel::Error last_error_;
};
// Test fixtures to test WebRtcVideoEngine with a real webrtc::VideoEngine.
diff --git a/talk/p2p/base/port_unittest.cc b/talk/p2p/base/port_unittest.cc
index 1c6752b..2feeee2 100644
--- a/talk/p2p/base/port_unittest.cc
+++ b/talk/p2p/base/port_unittest.cc
@@ -28,7 +28,6 @@
#include "talk/base/crc32.h"
#include "talk/base/gunit.h"
#include "talk/base/helpers.h"
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/base/natserver.h"
#include "talk/base/natsocketfactory.h"
diff --git a/talk/p2p/base/relayserver_unittest.cc b/talk/p2p/base/relayserver_unittest.cc
index 7580e45..86d2eef 100644
--- a/talk/p2p/base/relayserver_unittest.cc
+++ b/talk/p2p/base/relayserver_unittest.cc
@@ -29,7 +29,6 @@
#include "talk/base/gunit.h"
#include "talk/base/helpers.h"
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/base/physicalsocketserver.h"
#include "talk/base/socketaddress.h"
diff --git a/talk/p2p/base/session_unittest.cc b/talk/p2p/base/session_unittest.cc
index ae0c383..1d072ae 100644
--- a/talk/p2p/base/session_unittest.cc
+++ b/talk/p2p/base/session_unittest.cc
@@ -34,7 +34,6 @@
#include "talk/base/common.h"
#include "talk/base/gunit.h"
#include "talk/base/helpers.h"
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/base/natserver.h"
#include "talk/base/natsocketfactory.h"
diff --git a/talk/p2p/base/stunserver_main.cc b/talk/p2p/base/stunserver_main.cc
index e697728..4467944 100644
--- a/talk/p2p/base/stunserver_main.cc
+++ b/talk/p2p/base/stunserver_main.cc
@@ -31,7 +31,6 @@
#include <iostream>
-#include "talk/base/host.h"
#include "talk/base/thread.h"
#include "talk/p2p/base/stunserver.h"
diff --git a/talk/p2p/client/basicportallocator.cc b/talk/p2p/client/basicportallocator.cc
index 7a61093..a728d98 100644
--- a/talk/p2p/client/basicportallocator.cc
+++ b/talk/p2p/client/basicportallocator.cc
@@ -32,7 +32,6 @@
#include "talk/base/common.h"
#include "talk/base/helpers.h"
-#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/p2p/base/basicpacketsocketfactory.h"
#include "talk/p2p/base/common.h"
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
index 948a02c..379c553 100644
--- a/talk/session/media/channel.cc
+++ b/talk/session/media/channel.cc
@@ -2294,6 +2294,7 @@
SetScreenCaptureFactoryMessageData* data =
static_cast<SetScreenCaptureFactoryMessageData*>(pmsg->pdata);
SetScreenCaptureFactory_w(data->screencapture_factory);
+ break;
}
case MSG_GETSTATS: {
VideoStatsMessageData* data =
@@ -2428,6 +2429,8 @@
this, &DataChannel::OnDataReceived);
media_channel()->SignalMediaError.connect(
this, &DataChannel::OnDataChannelError);
+ media_channel()->SignalReadyToSend.connect(
+ this, &DataChannel::OnDataChannelReadyToSend);
srtp_filter()->SignalSrtpError.connect(
this, &DataChannel::OnSrtpError);
return true;
@@ -2609,7 +2612,7 @@
// Post to trigger SignalReadyToSendData.
signaling_thread()->Post(this, MSG_READYTOSENDDATA,
- new BoolMessageData(send));
+ new DataChannelReadyToSendMessageData(send));
LOG(LS_INFO) << "Changing data state, recv=" << recv << " send=" << send;
}
@@ -2617,7 +2620,8 @@
void DataChannel::OnMessage(talk_base::Message *pmsg) {
switch (pmsg->message_id) {
case MSG_READYTOSENDDATA: {
- BoolMessageData* data = static_cast<BoolMessageData*>(pmsg->pdata);
+ DataChannelReadyToSendMessageData* data =
+ static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
SignalReadyToSendData(data->data());
delete data;
break;
@@ -2690,6 +2694,14 @@
signaling_thread()->Post(this, MSG_CHANNEL_ERROR, data);
}
+void DataChannel::OnDataChannelReadyToSend(bool writable) {
+ // This is usded for congestion control to indicate that the stream is ready
+ // to send by the MediaChannel, as opposed to OnReadyToSend, which indicates
+ // that the transport channel is ready.
+ signaling_thread()->Post(this, MSG_READYTOSENDDATA,
+ new DataChannelReadyToSendMessageData(writable));
+}
+
void DataChannel::OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode,
SrtpFilter::Error error) {
switch (error) {
diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h
index 9bac965..eccadd3 100644
--- a/talk/session/media/channel.h
+++ b/talk/session/media/channel.h
@@ -595,9 +595,9 @@
return static_cast<DataMediaChannel*>(BaseChannel::media_channel());
}
- bool SendData(const SendDataParams& params,
- const talk_base::Buffer& payload,
- SendDataResult* result);
+ virtual bool SendData(const SendDataParams& params,
+ const talk_base::Buffer& payload,
+ SendDataResult* result);
void StartMediaMonitor(int cms);
void StopMediaMonitor();
@@ -612,9 +612,8 @@
const talk_base::Buffer&>
SignalDataReceived;
// Signal for notifying when the channel becomes ready to send data.
- // That occurs when the channel is enabled, the transport is writable and
- // both local and remote descriptions are set.
- // TODO(perkj): Signal this per SSRC stream.
+ // That occurs when the channel is enabled, the transport is writable,
+ // both local and remote descriptions are set, and the channel is unblocked.
sigslot::signal1<bool> SignalReadyToSendData;
private:
@@ -647,6 +646,8 @@
const talk_base::Buffer payload;
};
+ typedef talk_base::TypedMessageData<bool> DataChannelReadyToSendMessageData;
+
// overrides from BaseChannel
virtual const ContentInfo* GetFirstContent(const SessionDescription* sdesc);
// If data_channel_type_ is DCT_NONE, set it. Otherwise, check that
@@ -674,6 +675,7 @@
void OnDataReceived(
const ReceiveDataParams& params, const char* data, size_t len);
void OnDataChannelError(uint32 ssrc, DataMediaChannel::Error error);
+ void OnDataChannelReadyToSend(bool writable);
void OnSrtpError(uint32 ssrc, SrtpFilter::Mode mode, SrtpFilter::Error error);
talk_base::scoped_ptr<DataMediaMonitor> media_monitor_;
diff --git a/talk/session/media/channelmanager.h b/talk/session/media/channelmanager.h
index e5e6e44..b1967bf 100644
--- a/talk/session/media/channelmanager.h
+++ b/talk/session/media/channelmanager.h
@@ -297,8 +297,6 @@
bool capturing_;
bool monitoring_;
- talk_base::scoped_ptr<VideoCapturer> video_capturer_;
-
// String containing currently set device. Note that this string is subtly
// different from camera_device_. E.g. camera_device_ will list unplugged
// but selected devices while this sting will be empty or contain current