Update talk to 56092586.
R=jiayl@webrtc.org, mallinath@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/3359004
git-svn-id: http://webrtc.googlecode.com/svn/trunk@5078 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc
index 3a6046e..6f30487 100644
--- a/talk/app/webrtc/datachannel.cc
+++ b/talk/app/webrtc/datachannel.cc
@@ -38,6 +38,10 @@
static size_t kMaxQueuedReceivedDataPackets = 100;
static size_t kMaxQueuedSendDataPackets = 100;
+enum {
+ MSG_CHANNELREADY,
+};
+
talk_base::scoped_refptr<DataChannel> DataChannel::Create(
DataChannelProviderInterface* provider,
cricket::DataChannelType dct,
@@ -95,6 +99,15 @@
// Try to connect to the transport in case the transport channel already
// exists.
OnTransportChannelCreated();
+
+ // Checks if the transport is ready to send because the initial channel
+ // ready signal may have been sent before the DataChannel creation.
+ // This has to be done async because the upper layer objects (e.g.
+ // Chrome glue and WebKit) are not wired up properly until after this
+ // function returns.
+ if (provider_->ReadyToSendData()) {
+ talk_base::Thread::Current()->Post(this, MSG_CHANNELREADY, NULL);
+ }
}
return true;
@@ -217,6 +230,14 @@
UpdateState();
}
+void DataChannel::OnMessage(talk_base::Message* msg) {
+ switch (msg->message_id) {
+ case MSG_CHANNELREADY:
+ OnChannelReady(true);
+ break;
+ }
+}
+
// The underlaying data engine is closing.
// This function makes sure the DataChannel is disconnected and changes state to
// kClosed.
diff --git a/talk/app/webrtc/datachannel.h b/talk/app/webrtc/datachannel.h
index 0d67293..5635e63 100644
--- a/talk/app/webrtc/datachannel.h
+++ b/talk/app/webrtc/datachannel.h
@@ -33,6 +33,7 @@
#include "talk/app/webrtc/datachannelinterface.h"
#include "talk/app/webrtc/proxy.h"
+#include "talk/base/messagehandler.h"
#include "talk/base/scoped_ref_ptr.h"
#include "talk/base/sigslot.h"
#include "talk/media/base/mediachannel.h"
@@ -60,6 +61,8 @@
virtual void RemoveRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) = 0;
// Removes the data channel SID from the transport for SCTP.
virtual void RemoveSctpDataStream(uint32 sid) = 0;
+ // Returns true if the transport channel is ready to send data.
+ virtual bool ReadyToSendData() const = 0;
protected:
virtual ~DataChannelProviderInterface() {}
@@ -81,7 +84,8 @@
// kClosed: Both UpdateReceiveSsrc and UpdateSendSsrc has been called with
// SSRC==0.
class DataChannel : public DataChannelInterface,
- public sigslot::has_slots<> {
+ public sigslot::has_slots<>,
+ public talk_base::MessageHandler {
public:
static talk_base::scoped_refptr<DataChannel> Create(
DataChannelProviderInterface* provider,
@@ -109,6 +113,9 @@
virtual DataState state() const { return state_; }
virtual bool Send(const DataBuffer& buffer);
+ // talk_base::MessageHandler override.
+ virtual void OnMessage(talk_base::Message* msg);
+
// Called if the underlying data engine is closing.
void OnDataEngineClose();
diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc
index 5d29811..dba24a2 100644
--- a/talk/app/webrtc/datachannel_unittest.cc
+++ b/talk/app/webrtc/datachannel_unittest.cc
@@ -39,11 +39,12 @@
}
void SetChannelReady() {
+ provider_.set_transport_available(true);
webrtc_data_channel_->OnTransportChannelCreated();
if (webrtc_data_channel_->id() < 0) {
webrtc_data_channel_->SetSctpSid(0);
}
- webrtc_data_channel_->OnChannelReady(true);
+ provider_.set_ready_to_send(true);
}
webrtc::DataChannelInit init_;
@@ -53,27 +54,28 @@
// Verifies that the data channel is connected to the transport after creation.
TEST_F(SctpDataChannelTest, ConnectedToTransportOnCreated) {
- EXPECT_TRUE(provider_.IsConnected(webrtc_data_channel_.get()));
- // The sid is not set yet, so it should not have added the streams.
- EXPECT_FALSE(provider_.IsSendStreamAdded(webrtc_data_channel_->id()));
- EXPECT_FALSE(provider_.IsRecvStreamAdded(webrtc_data_channel_->id()));
+ provider_.set_transport_available(true);
+ talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
+ &provider_, cricket::DCT_SCTP, "test1", &init_);
- webrtc_data_channel_->SetSctpSid(0);
- EXPECT_TRUE(provider_.IsSendStreamAdded(webrtc_data_channel_->id()));
- EXPECT_TRUE(provider_.IsRecvStreamAdded(webrtc_data_channel_->id()));
+ EXPECT_TRUE(provider_.IsConnected(dc.get()));
+ // The sid is not set yet, so it should not have added the streams.
+ EXPECT_FALSE(provider_.IsSendStreamAdded(dc->id()));
+ EXPECT_FALSE(provider_.IsRecvStreamAdded(dc->id()));
+
+ dc->SetSctpSid(0);
+ EXPECT_TRUE(provider_.IsSendStreamAdded(dc->id()));
+ EXPECT_TRUE(provider_.IsRecvStreamAdded(dc->id()));
}
// Verifies that the data channel is connected to the transport if the transport
// is not available initially and becomes available later.
TEST_F(SctpDataChannelTest, ConnectedAfterTransportBecomesAvailable) {
- provider_.set_transport_available(false);
- talk_base::scoped_refptr<DataChannel> dc = DataChannel::Create(
- &provider_, cricket::DCT_SCTP, "test1", &init_);
- EXPECT_FALSE(provider_.IsConnected(dc.get()));
+ EXPECT_FALSE(provider_.IsConnected(webrtc_data_channel_.get()));
provider_.set_transport_available(true);
- dc->OnTransportChannelCreated();
- EXPECT_TRUE(provider_.IsConnected(dc.get()));
+ webrtc_data_channel_->OnTransportChannelCreated();
+ EXPECT_TRUE(provider_.IsConnected(webrtc_data_channel_.get()));
}
// Tests the state of the data channel.
@@ -81,6 +83,7 @@
EXPECT_EQ(webrtc::DataChannelInterface::kConnecting,
webrtc_data_channel_->state());
SetChannelReady();
+
EXPECT_EQ(webrtc::DataChannelInterface::kOpen, webrtc_data_channel_->state());
webrtc_data_channel_->Close();
EXPECT_EQ(webrtc::DataChannelInterface::kClosed,
@@ -132,3 +135,16 @@
EXPECT_EQ(provider_.last_send_data_params().ssrc,
static_cast<uint32>(webrtc_data_channel_->id()));
}
+
+// Tests that the DataChannel created after transport gets ready can enter OPEN
+// state.
+TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) {
+ SetChannelReady();
+ webrtc::DataChannelInit init;
+ init.id = 1;
+ talk_base::scoped_refptr<DataChannel> dc =
+ DataChannel::Create(&provider_, cricket::DCT_SCTP, "test1", &init);
+ EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, dc->state());
+ EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(),
+ 1000);
+}
diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc
index 91dde24..8d25425 100644
--- a/talk/app/webrtc/mediastreamsignaling.cc
+++ b/talk/app/webrtc/mediastreamsignaling.cc
@@ -276,8 +276,6 @@
}
data_channels_[label] = channel;
stream_observer_->OnAddDataChannel(channel);
- // It's immediately ready to use.
- channel->OnChannelReady(true);
return true;
}
diff --git a/talk/app/webrtc/test/fakedatachannelprovider.h b/talk/app/webrtc/test/fakedatachannelprovider.h
index 3326419..429f4df 100644
--- a/talk/app/webrtc/test/fakedatachannelprovider.h
+++ b/talk/app/webrtc/test/fakedatachannelprovider.h
@@ -30,14 +30,15 @@
class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
public:
FakeDataChannelProvider()
- : id_allocation_should_fail_(false),
- send_blocked_(false),
- transport_available_(true) {}
+ : send_blocked_(false),
+ transport_available_(false),
+ ready_to_send_(false) {}
virtual ~FakeDataChannelProvider() {}
virtual bool SendData(const cricket::SendDataParams& params,
const talk_base::Buffer& payload,
cricket::SendDataResult* result) OVERRIDE {
+ ASSERT(ready_to_send_ && transport_available_);
if (send_blocked_) {
*result = cricket::SDR_BLOCK;
return false;
@@ -45,6 +46,7 @@
last_send_data_params_ = params;
return true;
}
+
virtual bool ConnectDataChannel(webrtc::DataChannel* data_channel) OVERRIDE {
ASSERT(connected_channels_.find(data_channel) == connected_channels_.end());
if (!transport_available_) {
@@ -54,55 +56,98 @@
connected_channels_.insert(data_channel);
return true;
}
+
virtual void DisconnectDataChannel(
webrtc::DataChannel* data_channel) OVERRIDE {
ASSERT(connected_channels_.find(data_channel) != connected_channels_.end());
LOG(LS_INFO) << "DataChannel disconnected " << data_channel;
connected_channels_.erase(data_channel);
}
+
virtual void AddRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) OVERRIDE {
+ if (!transport_available_) {
+ return;
+ }
send_ssrcs_.insert(send_ssrc);
recv_ssrcs_.insert(recv_ssrc);
}
+
virtual void AddSctpDataStream(uint32 sid) OVERRIDE {
+ if (!transport_available_) {
+ return;
+ }
AddRtpDataStream(sid, sid);
}
+
virtual void RemoveRtpDataStream(
uint32 send_ssrc, uint32 recv_ssrc) OVERRIDE {
send_ssrcs_.erase(send_ssrc);
recv_ssrcs_.erase(recv_ssrc);
}
+
virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE {
RemoveRtpDataStream(sid, sid);
}
+ virtual bool ReadyToSendData() const OVERRIDE {
+ return ready_to_send_;
+ }
+
+ // Set true to emulate the SCTP stream being blocked by congestion control.
void set_send_blocked(bool blocked) {
send_blocked_ = blocked;
+ if (!blocked) {
+ std::set<webrtc::DataChannel*>::iterator it;
+ for (it = connected_channels_.begin();
+ it != connected_channels_.end();
+ ++it) {
+ (*it)->OnChannelReady(true);
+ }
+ }
}
- cricket::SendDataParams last_send_data_params() const {
- return last_send_data_params_;
- }
- void set_id_allocaiton_should_fail(bool fail) {
- id_allocation_should_fail_ = fail;
- }
+
+ // Set true to emulate the transport channel creation, e.g. after
+ // setLocalDescription/setRemoteDescription called with data content.
void set_transport_available(bool available) {
transport_available_ = available;
}
+
+ // Set true to emulate the transport ReadyToSendData signal when the transport
+ // becomes writable for the first time.
+ void set_ready_to_send(bool ready) {
+ ASSERT(transport_available_);
+ ready_to_send_ = ready;
+ if (ready) {
+ std::set<webrtc::DataChannel*>::iterator it;
+ for (it = connected_channels_.begin();
+ it != connected_channels_.end();
+ ++it) {
+ (*it)->OnChannelReady(true);
+ }
+ }
+ }
+
+ cricket::SendDataParams last_send_data_params() const {
+ return last_send_data_params_;
+ }
+
bool IsConnected(webrtc::DataChannel* data_channel) const {
return connected_channels_.find(data_channel) != connected_channels_.end();
}
+
bool IsSendStreamAdded(uint32 stream) const {
return send_ssrcs_.find(stream) != send_ssrcs_.end();
}
+
bool IsRecvStreamAdded(uint32 stream) const {
return recv_ssrcs_.find(stream) != recv_ssrcs_.end();
}
private:
cricket::SendDataParams last_send_data_params_;
- bool id_allocation_should_fail_;
bool send_blocked_;
bool transport_available_;
+ bool ready_to_send_;
std::set<webrtc::DataChannel*> connected_channels_;
std::set<uint32> send_ssrcs_;
std::set<uint32> recv_ssrcs_;
diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc
index a96c2da..5935ea0 100644
--- a/talk/app/webrtc/webrtcsession.cc
+++ b/talk/app/webrtc/webrtcsession.cc
@@ -1024,6 +1024,10 @@
RemoveRtpDataStream(sid, sid);
}
+bool WebRtcSession::ReadyToSendData() const {
+ return data_channel_.get() && data_channel_->ready_to_send_data();
+}
+
talk_base::scoped_refptr<DataChannel> WebRtcSession::CreateDataChannel(
const std::string& label,
const DataChannelInit* config) {
diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h
index 893ab3f..4a39a11 100644
--- a/talk/app/webrtc/webrtcsession.h
+++ b/talk/app/webrtc/webrtcsession.h
@@ -194,6 +194,7 @@
virtual void AddSctpDataStream(uint32 sid) OVERRIDE;
virtual void RemoveRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) OVERRIDE;
virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE;
+ virtual bool ReadyToSendData() const OVERRIDE;
talk_base::scoped_refptr<DataChannel> CreateDataChannel(
const std::string& label,
diff --git a/talk/base/common.h b/talk/base/common.h
index 6350baf..d557639 100644
--- a/talk/base/common.h
+++ b/talk/base/common.h
@@ -198,7 +198,7 @@
// TODO(ajm): Hack to avoid multiple definitions until the base/ of webrtc and
// libjingle are merged.
#if !defined(WARN_UNUSED_RESULT)
-#if defined(COMPILER_GCC)
+#if defined(__GNUC__)
#define WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define WARN_UNUSED_RESULT
diff --git a/talk/session/media/channel.cc b/talk/session/media/channel.cc
index 1a3063d..e0aff89 100644
--- a/talk/session/media/channel.cc
+++ b/talk/session/media/channel.cc
@@ -2477,7 +2477,8 @@
bool rtcp)
// MediaEngine is NULL
: BaseChannel(thread, NULL, media_channel, session, content_name, rtcp),
- data_channel_type_(cricket::DCT_NONE) {
+ data_channel_type_(cricket::DCT_NONE),
+ ready_to_send_data_(false) {
}
DataChannel::~DataChannel() {
@@ -2701,7 +2702,8 @@
case MSG_READYTOSENDDATA: {
DataChannelReadyToSendMessageData* data =
static_cast<DataChannelReadyToSendMessageData*>(pmsg->pdata);
- SignalReadyToSendData(data->data());
+ ready_to_send_data_ = data->data();
+ SignalReadyToSendData(ready_to_send_data_);
delete data;
break;
}
diff --git a/talk/session/media/channel.h b/talk/session/media/channel.h
index 51fb575..27a81a6 100644
--- a/talk/session/media/channel.h
+++ b/talk/session/media/channel.h
@@ -610,6 +610,11 @@
void StartMediaMonitor(int cms);
void StopMediaMonitor();
+ // Should be called on the signaling thread only.
+ bool ready_to_send_data() const {
+ return ready_to_send_data_;
+ }
+
sigslot::signal2<DataChannel*, const DataMediaInfo&> SignalMediaMonitor;
sigslot::signal2<DataChannel*, const std::vector<ConnectionInfo>&>
SignalConnectionMonitor;
@@ -714,6 +719,7 @@
// TODO(pthatcher): Make a separate SctpDataChannel and
// RtpDataChannel instead of using this.
DataChannelType data_channel_type_;
+ bool ready_to_send_data_;
};
} // namespace cricket