Update talk to 56619788
R=wu@webrtc.org Review URL: https://webrtc-codereview.appspot.com/3839005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@5120 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
e8722856f9
commit
a23f0ca4ba
@ -248,7 +248,9 @@ void DataChannel::OnDataEngineClose() {
|
||||
void DataChannel::OnDataReceived(cricket::DataChannel* channel,
|
||||
const cricket::ReceiveDataParams& params,
|
||||
const talk_base::Buffer& payload) {
|
||||
if (params.ssrc != receive_ssrc_) {
|
||||
uint32 expected_ssrc =
|
||||
(data_channel_type_ == cricket::DCT_RTP) ? receive_ssrc_ : config_.id;
|
||||
if (params.ssrc != expected_ssrc) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -307,7 +309,6 @@ void DataChannel::UpdateState() {
|
||||
if (send_ssrc_set_ == receive_ssrc_set_) {
|
||||
if (data_channel_type_ == cricket::DCT_RTP && !connected_to_provider_) {
|
||||
connected_to_provider_ = provider_->ConnectDataChannel(this);
|
||||
provider_->AddRtpDataStream(send_ssrc_, receive_ssrc_);
|
||||
}
|
||||
if (was_ever_writable_) {
|
||||
// TODO(jiayl): Do not transition to kOpen if we failed to send the
|
||||
@ -351,9 +352,7 @@ void DataChannel::DisconnectFromTransport() {
|
||||
provider_->DisconnectDataChannel(this);
|
||||
connected_to_provider_ = false;
|
||||
|
||||
if (data_channel_type_ == cricket::DCT_RTP) {
|
||||
provider_->RemoveRtpDataStream(send_ssrc_, receive_ssrc_);
|
||||
} else {
|
||||
if (data_channel_type_ == cricket::DCT_SCTP) {
|
||||
provider_->RemoveSctpDataStream(config_.id);
|
||||
}
|
||||
}
|
||||
@ -429,11 +428,13 @@ bool DataChannel::InternalSendWithoutQueueing(
|
||||
const DataBuffer& buffer, cricket::SendDataResult* send_result) {
|
||||
cricket::SendDataParams send_params;
|
||||
|
||||
send_params.ssrc = send_ssrc_;
|
||||
if (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.ssrc = config_.id;
|
||||
} else {
|
||||
send_params.ssrc = send_ssrc_;
|
||||
}
|
||||
send_params.type = buffer.binary ? cricket::DMT_BINARY : cricket::DMT_TEXT;
|
||||
|
||||
|
@ -53,12 +53,8 @@ class DataChannelProviderInterface {
|
||||
virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
|
||||
// Disconnects from the transport signals.
|
||||
virtual void DisconnectDataChannel(DataChannel* data_channel) = 0;
|
||||
// Adds the send and receive stream ssrc to the transport for RTP.
|
||||
virtual void AddRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) = 0;
|
||||
// Adds the data channel SID to the transport for SCTP.
|
||||
virtual void AddSctpDataStream(uint32 sid) = 0;
|
||||
// Removes the data channel ssrcs from the transport for RTP.
|
||||
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.
|
||||
@ -149,6 +145,10 @@ class DataChannel : public DataChannelInterface,
|
||||
// underlying data engine.
|
||||
void SetReceiveSsrc(uint32 receive_ssrc);
|
||||
|
||||
cricket::DataChannelType data_channel_type() const {
|
||||
return data_channel_type_;
|
||||
}
|
||||
|
||||
protected:
|
||||
DataChannel(DataChannelProviderInterface* client,
|
||||
cricket::DataChannelType dct,
|
||||
|
@ -28,9 +28,16 @@
|
||||
#include "talk/app/webrtc/datachannel.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));
|
||||
};
|
||||
|
||||
class SctpDataChannelTest : public testing::Test {
|
||||
protected:
|
||||
SctpDataChannelTest()
|
||||
@ -47,8 +54,14 @@ class SctpDataChannelTest : public testing::Test {
|
||||
provider_.set_ready_to_send(true);
|
||||
}
|
||||
|
||||
void AddObserver() {
|
||||
observer_.reset(new FakeDataChannelObserver());
|
||||
webrtc_data_channel_->RegisterObserver(observer_.get());
|
||||
}
|
||||
|
||||
webrtc::DataChannelInit init_;
|
||||
FakeDataChannelProvider provider_;
|
||||
talk_base::scoped_ptr<FakeDataChannelObserver> observer_;
|
||||
talk_base::scoped_refptr<DataChannel> webrtc_data_channel_;
|
||||
};
|
||||
|
||||
@ -148,3 +161,41 @@ TEST_F(SctpDataChannelTest, LateCreatedChannelTransitionToOpen) {
|
||||
EXPECT_TRUE_WAIT(webrtc::DataChannelInterface::kOpen == dc->state(),
|
||||
1000);
|
||||
}
|
||||
|
||||
// Tests that messages are sent with the right ssrc.
|
||||
TEST_F(SctpDataChannelTest, SendDataSsrc) {
|
||||
webrtc_data_channel_->SetSctpSid(1);
|
||||
SetChannelReady();
|
||||
webrtc::DataBuffer buffer("data");
|
||||
EXPECT_TRUE(webrtc_data_channel_->Send(buffer));
|
||||
EXPECT_EQ(1U, provider_.last_send_data_params().ssrc);
|
||||
}
|
||||
|
||||
// Tests that the incoming messages with wrong ssrcs are rejected.
|
||||
TEST_F(SctpDataChannelTest, ReceiveDataWithInvalidSsrc) {
|
||||
webrtc_data_channel_->SetSctpSid(1);
|
||||
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);
|
||||
}
|
||||
|
||||
// Tests that the incoming messages with right ssrcs are acceted.
|
||||
TEST_F(SctpDataChannelTest, ReceiveDataWithValidSsrc) {
|
||||
webrtc_data_channel_->SetSctpSid(1);
|
||||
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);
|
||||
}
|
||||
|
@ -208,10 +208,10 @@ void MediaStreamSignaling::TearDown() {
|
||||
bool MediaStreamSignaling::IsSctpSidAvailable(int sid) const {
|
||||
if (sid < 0 || sid > static_cast<int>(cricket::kMaxSctpSid))
|
||||
return false;
|
||||
for (DataChannels::const_iterator iter = data_channels_.begin();
|
||||
iter != data_channels_.end();
|
||||
for (SctpDataChannels::const_iterator iter = sctp_data_channels_.begin();
|
||||
iter != sctp_data_channels_.end();
|
||||
++iter) {
|
||||
if (iter->second->id() == sid) {
|
||||
if ((*iter)->id() == sid) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -240,17 +240,23 @@ bool MediaStreamSignaling::AllocateSctpSid(talk_base::SSLRole role, int* sid) {
|
||||
}
|
||||
|
||||
bool MediaStreamSignaling::HasDataChannels() const {
|
||||
return !data_channels_.empty();
|
||||
return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
|
||||
}
|
||||
|
||||
bool MediaStreamSignaling::AddDataChannel(DataChannel* data_channel) {
|
||||
ASSERT(data_channel != NULL);
|
||||
if (data_channels_.find(data_channel->label()) != data_channels_.end()) {
|
||||
LOG(LS_ERROR) << "DataChannel with label " << data_channel->label()
|
||||
<< " already exists.";
|
||||
return false;
|
||||
if (data_channel->data_channel_type() == cricket::DCT_RTP) {
|
||||
if (rtp_data_channels_.find(data_channel->label()) !=
|
||||
rtp_data_channels_.end()) {
|
||||
LOG(LS_ERROR) << "DataChannel with label " << data_channel->label()
|
||||
<< " already exists.";
|
||||
return false;
|
||||
}
|
||||
rtp_data_channels_[data_channel->label()] = data_channel;
|
||||
} else {
|
||||
ASSERT(data_channel->data_channel_type() == cricket::DCT_SCTP);
|
||||
sctp_data_channels_.push_back(data_channel);
|
||||
}
|
||||
data_channels_[data_channel->label()] = data_channel;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -262,19 +268,13 @@ bool MediaStreamSignaling::AddDataChannelFromOpenMessage(
|
||||
<< "are not supported.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data_channels_.find(label) != data_channels_.end()) {
|
||||
LOG(LS_ERROR) << "DataChannel with label " << label
|
||||
<< " already exists.";
|
||||
return false;
|
||||
}
|
||||
scoped_refptr<DataChannel> channel(
|
||||
data_channel_factory_->CreateDataChannel(label, &config));
|
||||
if (!channel.get()) {
|
||||
LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
|
||||
return false;
|
||||
}
|
||||
data_channels_[label] = channel;
|
||||
sctp_data_channels_.push_back(channel);
|
||||
stream_observer_->OnAddDataChannel(channel);
|
||||
return true;
|
||||
}
|
||||
@ -464,10 +464,13 @@ void MediaStreamSignaling::OnVideoChannelClose() {
|
||||
}
|
||||
|
||||
void MediaStreamSignaling::OnDataChannelClose() {
|
||||
DataChannels::iterator it = data_channels_.begin();
|
||||
for (; it != data_channels_.end(); ++it) {
|
||||
DataChannel* data_channel = it->second;
|
||||
data_channel->OnDataEngineClose();
|
||||
RtpDataChannels::iterator it1 = rtp_data_channels_.begin();
|
||||
for (; it1 != rtp_data_channels_.end(); ++it1) {
|
||||
it1->second->OnDataEngineClose();
|
||||
}
|
||||
SctpDataChannels::iterator it2 = sctp_data_channels_.begin();
|
||||
for (; it2 != sctp_data_channels_.end(); ++it2) {
|
||||
(*it2)->OnDataEngineClose();
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,8 +528,8 @@ void MediaStreamSignaling::UpdateSessionOptions() {
|
||||
}
|
||||
|
||||
// Check for data channels.
|
||||
DataChannels::const_iterator data_channel_it = data_channels_.begin();
|
||||
for (; data_channel_it != data_channels_.end(); ++data_channel_it) {
|
||||
RtpDataChannels::const_iterator data_channel_it = rtp_data_channels_.begin();
|
||||
for (; data_channel_it != rtp_data_channels_.end(); ++data_channel_it) {
|
||||
const DataChannel* channel = data_channel_it->second;
|
||||
if (channel->state() == DataChannel::kConnecting ||
|
||||
channel->state() == DataChannel::kOpen) {
|
||||
@ -843,8 +846,9 @@ void MediaStreamSignaling::UpdateLocalRtpDataChannels(
|
||||
// For MediaStreams, the sync_label is the MediaStream label and the
|
||||
// track label is the same as |streamid|.
|
||||
const std::string& channel_label = it->sync_label;
|
||||
DataChannels::iterator data_channel_it = data_channels_.find(channel_label);
|
||||
if (!VERIFY(data_channel_it != data_channels_.end())) {
|
||||
RtpDataChannels::iterator data_channel_it =
|
||||
rtp_data_channels_.find(channel_label);
|
||||
if (!VERIFY(data_channel_it != rtp_data_channels_.end())) {
|
||||
continue;
|
||||
}
|
||||
// Set the SSRC the data channel should use for sending.
|
||||
@ -866,9 +870,9 @@ void MediaStreamSignaling::UpdateRemoteRtpDataChannels(
|
||||
// does not exist. Ex a=ssrc:444330170 mslabel:test1.
|
||||
std::string label = it->sync_label.empty() ?
|
||||
talk_base::ToString(it->first_ssrc()) : it->sync_label;
|
||||
DataChannels::iterator data_channel_it =
|
||||
data_channels_.find(label);
|
||||
if (data_channel_it == data_channels_.end()) {
|
||||
RtpDataChannels::iterator data_channel_it =
|
||||
rtp_data_channels_.find(label);
|
||||
if (data_channel_it == rtp_data_channels_.end()) {
|
||||
// This is a new data channel.
|
||||
CreateRemoteDataChannel(label, it->first_ssrc());
|
||||
} else {
|
||||
@ -882,8 +886,8 @@ void MediaStreamSignaling::UpdateRemoteRtpDataChannels(
|
||||
|
||||
void MediaStreamSignaling::UpdateClosingDataChannels(
|
||||
const std::vector<std::string>& active_channels, bool is_local_update) {
|
||||
DataChannels::iterator it = data_channels_.begin();
|
||||
while (it != data_channels_.end()) {
|
||||
RtpDataChannels::iterator it = rtp_data_channels_.begin();
|
||||
while (it != rtp_data_channels_.end()) {
|
||||
DataChannel* data_channel = it->second;
|
||||
if (std::find(active_channels.begin(), active_channels.end(),
|
||||
data_channel->label()) != active_channels.end()) {
|
||||
@ -897,8 +901,8 @@ void MediaStreamSignaling::UpdateClosingDataChannels(
|
||||
data_channel->RemotePeerRequestClose();
|
||||
|
||||
if (data_channel->state() == DataChannel::kClosed) {
|
||||
data_channels_.erase(it);
|
||||
it = data_channels_.begin();
|
||||
rtp_data_channels_.erase(it);
|
||||
it = rtp_data_channels_.begin();
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
@ -914,29 +918,32 @@ void MediaStreamSignaling::CreateRemoteDataChannel(const std::string& label,
|
||||
}
|
||||
scoped_refptr<DataChannel> channel(
|
||||
data_channel_factory_->CreateDataChannel(label, NULL));
|
||||
if (!channel.get()) {
|
||||
LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
|
||||
<< "CreateDataChannel failed.";
|
||||
return;
|
||||
}
|
||||
channel->SetReceiveSsrc(remote_ssrc);
|
||||
stream_observer_->OnAddDataChannel(channel);
|
||||
}
|
||||
|
||||
void MediaStreamSignaling::OnDataTransportCreatedForSctp() {
|
||||
DataChannels::iterator it = data_channels_.begin();
|
||||
for (; it != data_channels_.end(); ++it) {
|
||||
DataChannel* data_channel = it->second;
|
||||
data_channel->OnTransportChannelCreated();
|
||||
SctpDataChannels::iterator it = sctp_data_channels_.begin();
|
||||
for (; it != sctp_data_channels_.end(); ++it) {
|
||||
(*it)->OnTransportChannelCreated();
|
||||
}
|
||||
}
|
||||
|
||||
void MediaStreamSignaling::OnDtlsRoleReadyForSctp(talk_base::SSLRole role) {
|
||||
DataChannels::iterator it = data_channels_.begin();
|
||||
for (; it != data_channels_.end(); ++it) {
|
||||
DataChannel* data_channel = it->second;
|
||||
if (data_channel->id() < 0) {
|
||||
SctpDataChannels::iterator it = sctp_data_channels_.begin();
|
||||
for (; it != sctp_data_channels_.end(); ++it) {
|
||||
if ((*it)->id() < 0) {
|
||||
int sid;
|
||||
if (!AllocateSctpSid(role, &sid)) {
|
||||
LOG(LS_ERROR) << "Failed to allocate SCTP sid.";
|
||||
continue;
|
||||
}
|
||||
data_channel->SetSctpSid(sid);
|
||||
(*it)->SetSctpSid(sid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -384,8 +384,10 @@ class MediaStreamSignaling {
|
||||
int last_allocated_sctp_odd_sid_;
|
||||
|
||||
typedef std::map<std::string, talk_base::scoped_refptr<DataChannel> >
|
||||
DataChannels;
|
||||
DataChannels data_channels_;
|
||||
RtpDataChannels;
|
||||
typedef std::vector<talk_base::scoped_refptr<DataChannel> > SctpDataChannels;
|
||||
RtpDataChannels rtp_data_channels_;
|
||||
SctpDataChannels sctp_data_channels_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -238,6 +238,23 @@ static bool CompareStreamCollections(StreamCollectionInterface* s1,
|
||||
return true;
|
||||
}
|
||||
|
||||
class FakeDataChannelFactory : public webrtc::DataChannelFactory {
|
||||
public:
|
||||
FakeDataChannelFactory(FakeDataChannelProvider* provider,
|
||||
cricket::DataChannelType dct)
|
||||
: provider_(provider), type_(dct) {}
|
||||
|
||||
virtual talk_base::scoped_refptr<webrtc::DataChannel> CreateDataChannel(
|
||||
const std::string& label,
|
||||
const webrtc::DataChannelInit* config) {
|
||||
return webrtc::DataChannel::Create(provider_, type_, label, config);
|
||||
}
|
||||
|
||||
private:
|
||||
FakeDataChannelProvider* provider_;
|
||||
cricket::DataChannelType type_;
|
||||
};
|
||||
|
||||
class MockSignalingObserver : public webrtc::MediaStreamSignalingObserver {
|
||||
public:
|
||||
MockSignalingObserver()
|
||||
@ -418,6 +435,7 @@ class MediaStreamSignalingTest: public testing::Test {
|
||||
talk_base::Thread::Current()));
|
||||
signaling_.reset(new MediaStreamSignalingForTest(observer_.get(),
|
||||
channel_manager_.get()));
|
||||
data_channel_provider_.reset(new FakeDataChannelProvider());
|
||||
}
|
||||
|
||||
// Create a collection of streams.
|
||||
@ -508,12 +526,25 @@ class MediaStreamSignalingTest: public testing::Test {
|
||||
ASSERT_TRUE(stream->AddTrack(video_track));
|
||||
}
|
||||
|
||||
talk_base::scoped_refptr<webrtc::DataChannel> AddDataChannel(
|
||||
cricket::DataChannelType type, const std::string& label, int id) {
|
||||
webrtc::DataChannelInit config;
|
||||
config.id = id;
|
||||
talk_base::scoped_refptr<webrtc::DataChannel> data_channel(
|
||||
webrtc::DataChannel::Create(
|
||||
data_channel_provider_.get(), type, label, &config));
|
||||
EXPECT_TRUE(data_channel.get() != NULL);
|
||||
EXPECT_TRUE(signaling_->AddDataChannel(data_channel.get()));
|
||||
return data_channel;
|
||||
}
|
||||
|
||||
// ChannelManager is used by VideoSource, so it should be released after all
|
||||
// the video tracks. Put it as the first private variable should ensure that.
|
||||
talk_base::scoped_ptr<cricket::ChannelManager> channel_manager_;
|
||||
talk_base::scoped_refptr<StreamCollection> reference_collection_;
|
||||
talk_base::scoped_ptr<MockSignalingObserver> observer_;
|
||||
talk_base::scoped_ptr<MediaStreamSignalingForTest> signaling_;
|
||||
talk_base::scoped_ptr<FakeDataChannelProvider> data_channel_provider_;
|
||||
};
|
||||
|
||||
// Test that a MediaSessionOptions is created for an offer if
|
||||
@ -1029,27 +1060,46 @@ TEST_F(MediaStreamSignalingTest, SctpIdAllocationBasedOnRole) {
|
||||
|
||||
// Verifies that SCTP ids of existing DataChannels are not reused.
|
||||
TEST_F(MediaStreamSignalingTest, SctpIdAllocationNoReuse) {
|
||||
talk_base::scoped_ptr<FakeDataChannelProvider> provider(
|
||||
new FakeDataChannelProvider());
|
||||
// Creates a DataChannel with id 1.
|
||||
webrtc::DataChannelInit config;
|
||||
config.id = 1;
|
||||
talk_base::scoped_refptr<webrtc::DataChannel> data_channel(
|
||||
webrtc::DataChannel::Create(
|
||||
provider.get(), cricket::DCT_SCTP, "a", &config));
|
||||
ASSERT_TRUE(data_channel.get() != NULL);
|
||||
ASSERT_TRUE(signaling_->AddDataChannel(data_channel.get()));
|
||||
int old_id = 1;
|
||||
AddDataChannel(cricket::DCT_SCTP, "a", old_id);
|
||||
|
||||
int new_id;
|
||||
ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_SERVER, &new_id));
|
||||
EXPECT_NE(config.id, new_id);
|
||||
EXPECT_NE(old_id, new_id);
|
||||
|
||||
// Creates a DataChannel with id 0.
|
||||
config.id = 0;
|
||||
data_channel = webrtc::DataChannel::Create(
|
||||
provider.get(), cricket::DCT_SCTP, "b", &config);
|
||||
ASSERT_TRUE(data_channel.get() != NULL);
|
||||
ASSERT_TRUE(signaling_->AddDataChannel(data_channel.get()));
|
||||
old_id = 0;
|
||||
AddDataChannel(cricket::DCT_SCTP, "a", old_id);
|
||||
ASSERT_TRUE(signaling_->AllocateSctpSid(talk_base::SSL_CLIENT, &new_id));
|
||||
EXPECT_NE(config.id, new_id);
|
||||
EXPECT_NE(old_id, new_id);
|
||||
}
|
||||
|
||||
// Verifies that duplicated label is not allowed for RTP data channel.
|
||||
TEST_F(MediaStreamSignalingTest, RtpDuplicatedLabelNotAllowed) {
|
||||
AddDataChannel(cricket::DCT_RTP, "a", -1);
|
||||
|
||||
webrtc::DataChannelInit config;
|
||||
talk_base::scoped_refptr<webrtc::DataChannel> data_channel =
|
||||
webrtc::DataChannel::Create(
|
||||
data_channel_provider_.get(), cricket::DCT_RTP, "a", &config);
|
||||
ASSERT_TRUE(data_channel.get() != NULL);
|
||||
EXPECT_FALSE(signaling_->AddDataChannel(data_channel.get()));
|
||||
}
|
||||
|
||||
// Verifies that duplicated label is allowed for SCTP data channel.
|
||||
TEST_F(MediaStreamSignalingTest, SctpDuplicatedLabelAllowed) {
|
||||
AddDataChannel(cricket::DCT_SCTP, "a", -1);
|
||||
AddDataChannel(cricket::DCT_SCTP, "a", -1);
|
||||
}
|
||||
|
||||
// Verifies that duplicated label from OPEN message is allowed.
|
||||
TEST_F(MediaStreamSignalingTest, DuplicatedLabelFromOpenMessageAllowed) {
|
||||
AddDataChannel(cricket::DCT_SCTP, "a", -1);
|
||||
|
||||
FakeDataChannelFactory fake_factory(data_channel_provider_.get(),
|
||||
cricket::DCT_SCTP);
|
||||
signaling_->SetDataChannelFactory(&fake_factory);
|
||||
webrtc::DataChannelInit config;
|
||||
config.id = 0;
|
||||
EXPECT_TRUE(signaling_->AddDataChannelFromOpenMessage("a", config));
|
||||
}
|
||||
|
@ -42,8 +42,6 @@ namespace {
|
||||
|
||||
using webrtc::PeerConnectionInterface;
|
||||
|
||||
// The min number of tokens in the ice uri.
|
||||
static const size_t kMinIceUriTokens = 2;
|
||||
// The min number of tokens must present in Turn host uri.
|
||||
// e.g. user@turn.example.org
|
||||
static const size_t kTurnHostTokensNum = 2;
|
||||
@ -103,6 +101,73 @@ struct GetStatsMsg : public talk_base::MessageData {
|
||||
talk_base::scoped_refptr<webrtc::StatsObserver> observer;
|
||||
};
|
||||
|
||||
// |in_str| should be of format
|
||||
// stunURI = scheme ":" stun-host [ ":" stun-port ]
|
||||
// scheme = "stun" / "stuns"
|
||||
// stun-host = IP-literal / IPv4address / reg-name
|
||||
// stun-port = *DIGIT
|
||||
|
||||
// draft-petithuguenin-behave-turn-uris-01
|
||||
// turnURI = scheme ":" turn-host [ ":" turn-port ]
|
||||
// turn-host = username@IP-literal / IPv4address / reg-name
|
||||
bool GetServiceTypeAndHostnameFromUri(const std::string& in_str,
|
||||
ServiceType* service_type,
|
||||
std::string* hostname) {
|
||||
std::string::size_type colonpos = in_str.find(':');
|
||||
if (colonpos == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
std::string type = in_str.substr(0, colonpos);
|
||||
for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
|
||||
if (type.compare(kValidIceServiceTypes[i]) == 0) {
|
||||
*service_type = static_cast<ServiceType>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*service_type == INVALID) {
|
||||
return false;
|
||||
}
|
||||
*hostname = in_str.substr(colonpos + 1, std::string::npos);
|
||||
return true;
|
||||
}
|
||||
|
||||
// This method parses IPv6 and IPv4 literal strings, along with hostnames in
|
||||
// standard hostname:port format.
|
||||
// Consider following formats as correct.
|
||||
// |hostname:port|, |[IPV6 address]:port|, |IPv4 address|:port,
|
||||
// |hostname|, |[IPv6 address]|, |IPv4 address|
|
||||
bool ParseHostnameAndPortFromString(const std::string& in_str,
|
||||
std::string* host,
|
||||
int* port) {
|
||||
if (in_str.at(0) == '[') {
|
||||
std::string::size_type closebracket = in_str.rfind(']');
|
||||
if (closebracket != std::string::npos) {
|
||||
*host = in_str.substr(1, closebracket - 1);
|
||||
std::string::size_type colonpos = in_str.find(':', closebracket);
|
||||
if (std::string::npos != colonpos) {
|
||||
if (!talk_base::FromString(
|
||||
in_str.substr(closebracket + 2, std::string::npos), port)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
std::string::size_type colonpos = in_str.find(':');
|
||||
if (std::string::npos != colonpos) {
|
||||
*host = in_str.substr(0, colonpos);
|
||||
if (!talk_base::FromString(
|
||||
in_str.substr(colonpos + 1, std::string::npos), port)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
*host = in_str;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef webrtc::PortAllocatorFactoryInterface::StunConfiguration
|
||||
StunConfiguration;
|
||||
typedef webrtc::PortAllocatorFactoryInterface::TurnConfiguration
|
||||
@ -125,8 +190,6 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
|
||||
// transport-ext = 1*unreserved
|
||||
// turn-host = IP-literal / IPv4address / reg-name
|
||||
// turn-port = *DIGIT
|
||||
|
||||
// TODO(ronghuawu): Handle IPV6 address
|
||||
for (size_t i = 0; i < configuration.size(); ++i) {
|
||||
webrtc::PeerConnectionInterface::IceServer server = configuration[i];
|
||||
if (server.uri.empty()) {
|
||||
@ -152,41 +215,40 @@ bool ParseIceServers(const PeerConnectionInterface::IceServers& configuration,
|
||||
}
|
||||
}
|
||||
|
||||
tokens.clear();
|
||||
talk_base::tokenize(uri_without_transport, ':', &tokens);
|
||||
if (tokens.size() < kMinIceUriTokens) {
|
||||
LOG(WARNING) << "Invalid uri: " << server.uri;
|
||||
continue;
|
||||
}
|
||||
std::string hoststring;
|
||||
ServiceType service_type = INVALID;
|
||||
const std::string& type = tokens[0];
|
||||
for (size_t i = 0; i < ARRAY_SIZE(kValidIceServiceTypes); ++i) {
|
||||
if (type.compare(kValidIceServiceTypes[i]) == 0) {
|
||||
service_type = static_cast<ServiceType>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (service_type == INVALID) {
|
||||
LOG(WARNING) << "Invalid service type: " << type;
|
||||
if (!GetServiceTypeAndHostnameFromUri(uri_without_transport,
|
||||
&service_type,
|
||||
&hoststring)) {
|
||||
LOG(LS_WARNING) << "Invalid transport parameter in ICE URI: "
|
||||
<< uri_without_transport;
|
||||
continue;
|
||||
}
|
||||
std::string address = tokens[1];
|
||||
|
||||
// Let's break hostname.
|
||||
tokens.clear();
|
||||
talk_base::tokenize(hoststring, '@', &tokens);
|
||||
hoststring = tokens[0];
|
||||
if (tokens.size() == kTurnHostTokensNum) {
|
||||
server.username = talk_base::s_url_decode(tokens[0]);
|
||||
hoststring = tokens[1];
|
||||
}
|
||||
|
||||
int port = kDefaultStunPort;
|
||||
std::string address;
|
||||
if (!ParseHostnameAndPortFromString(hoststring, &address, &port)) {
|
||||
LOG(WARNING) << "Invalid Hostname format: " << uri_without_transport;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (service_type == TURNS) {
|
||||
port = kDefaultStunTlsPort;
|
||||
turn_transport_type = kTcpTransportType;
|
||||
}
|
||||
|
||||
if (tokens.size() > kMinIceUriTokens) {
|
||||
if (!talk_base::FromString(tokens[2], &port)) {
|
||||
LOG(LS_WARNING) << "Failed to parse port string: " << tokens[2];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (port <= 0 || port > 0xffff) {
|
||||
LOG(WARNING) << "Invalid port: " << port;
|
||||
continue;
|
||||
}
|
||||
if (port <= 0 || port > 0xffff) {
|
||||
LOG(WARNING) << "Invalid port: " << port;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (service_type) {
|
||||
|
@ -69,6 +69,15 @@ static const char kTurnPassword[] = "turnpassword";
|
||||
static const int kDefaultStunPort = 3478;
|
||||
static const int kDefaultStunTlsPort = 5349;
|
||||
static const char kTurnUsername[] = "test";
|
||||
static const char kStunIceServerWithIPv4Address[] = "stun:1.2.3.4:1234";
|
||||
static const char kStunIceServerWithIPv4AddressWithoutPort[] = "stun:1.2.3.4";
|
||||
static const char kStunIceServerWithIPv6Address[] = "stun:[2401:fa00:4::]:1234";
|
||||
static const char kStunIceServerWithIPv6AddressWithoutPort[] =
|
||||
"stun:[2401:fa00:4::]";
|
||||
static const char kStunIceServerWithInvalidIPv6Address[] =
|
||||
"stun:[2401:fa00:4:::3478";
|
||||
static const char kTurnIceServerWithIPv6Address[] =
|
||||
"turn:test@[2401:fa00:4::]:1234";
|
||||
|
||||
class NullPeerConnectionObserver : public PeerConnectionObserver {
|
||||
public:
|
||||
@ -265,6 +274,51 @@ TEST_F(PeerConnectionFactoryTest, CreatePCUsingSecureTurnUrl) {
|
||||
VerifyTurnConfigurations(turn_configs);
|
||||
}
|
||||
|
||||
TEST_F(PeerConnectionFactoryTest, CreatePCUsingIPLiteralAddress) {
|
||||
webrtc::PeerConnectionInterface::IceServers ice_servers;
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.uri = kStunIceServerWithIPv4Address;
|
||||
ice_servers.push_back(ice_server);
|
||||
ice_server.uri = kStunIceServerWithIPv4AddressWithoutPort;
|
||||
ice_servers.push_back(ice_server);
|
||||
ice_server.uri = kStunIceServerWithIPv6Address;
|
||||
ice_servers.push_back(ice_server);
|
||||
ice_server.uri = kStunIceServerWithIPv6AddressWithoutPort;
|
||||
ice_servers.push_back(ice_server);
|
||||
ice_server.uri = kStunIceServerWithInvalidIPv6Address;
|
||||
ice_servers.push_back(ice_server);
|
||||
ice_server.uri = kTurnIceServerWithIPv6Address;
|
||||
ice_server.password = kTurnPassword;
|
||||
ice_servers.push_back(ice_server);
|
||||
talk_base::scoped_refptr<PeerConnectionInterface> pc(
|
||||
factory_->CreatePeerConnection(ice_servers, NULL,
|
||||
allocator_factory_.get(),
|
||||
NULL,
|
||||
&observer_));
|
||||
EXPECT_TRUE(pc.get() != NULL);
|
||||
StunConfigurations stun_configs;
|
||||
webrtc::PortAllocatorFactoryInterface::StunConfiguration stun1(
|
||||
"1.2.3.4", 1234);
|
||||
stun_configs.push_back(stun1);
|
||||
webrtc::PortAllocatorFactoryInterface::StunConfiguration stun2(
|
||||
"1.2.3.4", 3478);
|
||||
stun_configs.push_back(stun2); // Default port
|
||||
webrtc::PortAllocatorFactoryInterface::StunConfiguration stun3(
|
||||
"2401:fa00:4::", 1234);
|
||||
stun_configs.push_back(stun3);
|
||||
webrtc::PortAllocatorFactoryInterface::StunConfiguration stun4(
|
||||
"2401:fa00:4::", 3478);
|
||||
stun_configs.push_back(stun4); // Default port
|
||||
// Turn Address has the same host information as |stun3|.
|
||||
stun_configs.push_back(stun3);
|
||||
VerifyStunConfigurations(stun_configs);
|
||||
TurnConfigurations turn_configs;
|
||||
webrtc::PortAllocatorFactoryInterface::TurnConfiguration turn1(
|
||||
"2401:fa00:4::", 1234, "test", kTurnPassword, "udp", false);
|
||||
turn_configs.push_back(turn1);
|
||||
VerifyTurnConfigurations(turn_configs);
|
||||
}
|
||||
|
||||
// This test verifies the captured stream is rendered locally using a
|
||||
// local video track.
|
||||
TEST_F(PeerConnectionFactoryTest, LocalRendering) {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "talk/app/webrtc/videosource.h"
|
||||
#include "talk/base/gunit.h"
|
||||
#include "talk/base/scoped_ptr.h"
|
||||
#include "talk/base/ssladapter.h"
|
||||
#include "talk/base/sslstreamadapter.h"
|
||||
#include "talk/base/stringutils.h"
|
||||
#include "talk/base/thread.h"
|
||||
@ -227,12 +228,17 @@ class MockPeerConnectionObserver : public PeerConnectionObserver {
|
||||
class PeerConnectionInterfaceTest : public testing::Test {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
talk_base::InitializeSSL(NULL);
|
||||
pc_factory_ = webrtc::CreatePeerConnectionFactory(
|
||||
talk_base::Thread::Current(), talk_base::Thread::Current(), NULL, NULL,
|
||||
NULL);
|
||||
ASSERT_TRUE(pc_factory_.get() != NULL);
|
||||
}
|
||||
|
||||
virtual void TearDown() {
|
||||
talk_base::CleanupSSL();
|
||||
}
|
||||
|
||||
void CreatePeerConnection() {
|
||||
CreatePeerConnection("", "", NULL);
|
||||
}
|
||||
@ -1070,9 +1076,7 @@ TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
|
||||
// Test that we can create a session description from an SDP string from
|
||||
// FireFox, use it as a remote session description, generate an answer and use
|
||||
// the answer as a local description.
|
||||
// TODO(mallinath): re-enable per
|
||||
// https://code.google.com/p/webrtc/issues/detail?id=2574
|
||||
TEST_F(PeerConnectionInterfaceTest, DISABLED_ReceiveFireFoxOffer) {
|
||||
TEST_F(PeerConnectionInterfaceTest, ReceiveFireFoxOffer) {
|
||||
MAYBE_SKIP_TEST(talk_base::SSLStreamAdapter::HaveDtlsSrtp);
|
||||
FakeConstraints constraints;
|
||||
constraints.AddMandatory(webrtc::MediaConstraintsInterface::kEnableDtlsSrtp,
|
||||
@ -1096,11 +1100,12 @@ TEST_F(PeerConnectionInterfaceTest, DISABLED_ReceiveFireFoxOffer) {
|
||||
cricket::GetFirstVideoContent(pc_->local_description()->description());
|
||||
ASSERT_TRUE(content != NULL);
|
||||
EXPECT_FALSE(content->rejected);
|
||||
|
||||
#ifdef HAVE_SCTP
|
||||
content =
|
||||
cricket::GetFirstDataContent(pc_->local_description()->description());
|
||||
ASSERT_TRUE(content != NULL);
|
||||
EXPECT_TRUE(content->rejected);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Test that we can create an audio only offer and receive an answer with a
|
||||
|
@ -64,29 +64,17 @@ class FakeDataChannelProvider : public webrtc::DataChannelProviderInterface {
|
||||
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);
|
||||
send_ssrcs_.insert(sid);
|
||||
recv_ssrcs_.insert(sid);
|
||||
}
|
||||
|
||||
virtual void RemoveSctpDataStream(uint32 sid) OVERRIDE {
|
||||
RemoveRtpDataStream(sid, sid);
|
||||
send_ssrcs_.erase(sid);
|
||||
recv_ssrcs_.erase(sid);
|
||||
}
|
||||
|
||||
virtual bool ReadyToSendData() const OVERRIDE {
|
||||
|
@ -75,6 +75,7 @@ static const char kFireFoxSdpOffer[] =
|
||||
"a=candidate:4 2 UDP 2113667326 10.0.254.2 58890 typ host\r\n"
|
||||
"a=candidate:5 2 UDP 1694302206 74.95.2.170 33611 typ srflx raddr"
|
||||
" 10.0.254.2 rport 58890\r\n"
|
||||
#ifdef HAVE_SCTP
|
||||
"m=application 45536 SCTP/DTLS 5000\r\n"
|
||||
"c=IN IP4 74.95.2.170\r\n"
|
||||
"a=fmtp:5000 protocol=webrtc-datachannel;streams=16\r\n"
|
||||
@ -88,7 +89,9 @@ static const char kFireFoxSdpOffer[] =
|
||||
"a=candidate:2 2 UDP 2112487678 172.16.131.1 59635 typ host\r\n"
|
||||
"a=candidate:4 2 UDP 2113667326 10.0.254.2 61232 typ host\r\n"
|
||||
"a=candidate:5 2 UDP 1694302206 74.95.2.170 45468 typ srflx raddr"
|
||||
" 10.0.254.2 rport 61232\r\n";
|
||||
" 10.0.254.2 rport 61232\r\n"
|
||||
#endif
|
||||
;
|
||||
|
||||
// Audio SDP with a limited set of audio codecs.
|
||||
static const char kAudioSdp[] =
|
||||
|
@ -997,31 +997,23 @@ void WebRtcSession::DisconnectDataChannel(DataChannel* webrtc_data_channel) {
|
||||
data_channel_->SignalDataReceived.disconnect(webrtc_data_channel);
|
||||
}
|
||||
|
||||
void WebRtcSession::AddRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) {
|
||||
void WebRtcSession::AddSctpDataStream(uint32 sid) {
|
||||
if (!data_channel_.get()) {
|
||||
LOG(LS_ERROR) << "AddDataChannelStreams called when data_channel_ is NULL.";
|
||||
return;
|
||||
}
|
||||
data_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(recv_ssrc));
|
||||
data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(send_ssrc));
|
||||
data_channel_->AddRecvStream(cricket::StreamParams::CreateLegacy(sid));
|
||||
data_channel_->AddSendStream(cricket::StreamParams::CreateLegacy(sid));
|
||||
}
|
||||
|
||||
void WebRtcSession::AddSctpDataStream(uint32 sid) {
|
||||
AddRtpDataStream(sid, sid);
|
||||
}
|
||||
|
||||
void WebRtcSession::RemoveRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) {
|
||||
void WebRtcSession::RemoveSctpDataStream(uint32 sid) {
|
||||
if (!data_channel_.get()) {
|
||||
LOG(LS_ERROR) << "RemoveDataChannelStreams called when data_channel_ is "
|
||||
<< "NULL.";
|
||||
return;
|
||||
}
|
||||
data_channel_->RemoveRecvStream(recv_ssrc);
|
||||
data_channel_->RemoveSendStream(send_ssrc);
|
||||
}
|
||||
|
||||
void WebRtcSession::RemoveSctpDataStream(uint32 sid) {
|
||||
RemoveRtpDataStream(sid, sid);
|
||||
data_channel_->RemoveRecvStream(sid);
|
||||
data_channel_->RemoveSendStream(sid);
|
||||
}
|
||||
|
||||
bool WebRtcSession::ReadyToSendData() const {
|
||||
|
@ -190,9 +190,7 @@ class WebRtcSession : public cricket::BaseSession,
|
||||
cricket::SendDataResult* result) OVERRIDE;
|
||||
virtual bool ConnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
|
||||
virtual void DisconnectDataChannel(DataChannel* webrtc_data_channel) OVERRIDE;
|
||||
virtual void AddRtpDataStream(uint32 send_ssrc, uint32 recv_ssrc) OVERRIDE;
|
||||
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;
|
||||
|
||||
|
64
talk/base/asyncresolverinterface.h
Normal file
64
talk/base/asyncresolverinterface.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef TALK_BASE_ASYNCRESOLVERINTERFACE_H_
|
||||
#define TALK_BASE_ASYNCRESOLVERINTERFACE_H_
|
||||
|
||||
#include "talk/base/sigslot.h"
|
||||
#include "talk/base/socketaddress.h"
|
||||
|
||||
namespace talk_base {
|
||||
|
||||
// This interface defines the methods to resolve the address asynchronously.
|
||||
class AsyncResolverInterface {
|
||||
public:
|
||||
AsyncResolverInterface() {}
|
||||
virtual ~AsyncResolverInterface() {}
|
||||
|
||||
// Start address resolve process.
|
||||
virtual void Start(const SocketAddress& addr) = 0;
|
||||
// Returns top most resolved address of |family|
|
||||
virtual bool GetResolvedAddress(int family, SocketAddress* addr) const = 0;
|
||||
// Returns error from resolver.
|
||||
virtual int GetError() const = 0;
|
||||
// Delete the resolver.
|
||||
virtual void Destroy(bool wait) = 0;
|
||||
// Returns top most resolved IPv4 address if address is resolved successfully.
|
||||
// Otherwise returns address set in SetAddress.
|
||||
SocketAddress address() const {
|
||||
SocketAddress addr;
|
||||
GetResolvedAddress(AF_INET, &addr);
|
||||
return addr;
|
||||
}
|
||||
|
||||
// This signal is fired when address resolve process is completed.
|
||||
sigslot::signal1<AsyncResolverInterface*> SignalDone;
|
||||
};
|
||||
|
||||
} // namespace talk_base
|
||||
|
||||
#endif
|
@ -82,7 +82,10 @@ void AutoDetectProxy::DoWork() {
|
||||
}
|
||||
|
||||
void AutoDetectProxy::OnMessage(Message *msg) {
|
||||
if (MSG_TIMEOUT == msg->message_id) {
|
||||
if (MSG_UNRESOLVABLE == msg->message_id) {
|
||||
// If we can't resolve the proxy, skip straight to failure.
|
||||
Complete(PROXY_UNKNOWN);
|
||||
} else if (MSG_TIMEOUT == msg->message_id) {
|
||||
OnCloseEvent(socket_, ETIMEDOUT);
|
||||
} else {
|
||||
// This must be the ST_MSG_WORKER_DONE message that deletes the
|
||||
@ -136,22 +139,24 @@ void AutoDetectProxy::OnMessage(Message *msg) {
|
||||
}
|
||||
}
|
||||
|
||||
void AutoDetectProxy::OnResolveResult(SignalThread* thread) {
|
||||
if (thread != resolver_) {
|
||||
void AutoDetectProxy::OnResolveResult(AsyncResolverInterface* resolver) {
|
||||
if (resolver != resolver_) {
|
||||
return;
|
||||
}
|
||||
int error = resolver_->error();
|
||||
int error = resolver_->GetError();
|
||||
if (error == 0) {
|
||||
LOG(LS_VERBOSE) << "Resolved " << proxy_.address << " to "
|
||||
<< resolver_->address();
|
||||
proxy_.address = resolver_->address();
|
||||
DoConnect();
|
||||
if (!DoConnect()) {
|
||||
Thread::Current()->Post(this, MSG_TIMEOUT);
|
||||
}
|
||||
} else {
|
||||
LOG(LS_INFO) << "Failed to resolve " << resolver_->address();
|
||||
resolver_->Destroy(false);
|
||||
resolver_ = NULL;
|
||||
proxy_.address = SocketAddress();
|
||||
Thread::Current()->Post(this, MSG_TIMEOUT);
|
||||
Thread::Current()->Post(this, MSG_UNRESOLVABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,6 +171,7 @@ void AutoDetectProxy::Next() {
|
||||
|
||||
if (socket_) {
|
||||
Thread::Current()->Clear(this, MSG_TIMEOUT);
|
||||
Thread::Current()->Clear(this, MSG_UNRESOLVABLE);
|
||||
socket_->Close();
|
||||
Thread::Current()->Dispose(socket_);
|
||||
socket_ = NULL;
|
||||
@ -177,17 +183,18 @@ void AutoDetectProxy::Next() {
|
||||
if (!resolver_) {
|
||||
resolver_ = new AsyncResolver();
|
||||
}
|
||||
resolver_->set_address(proxy_.address);
|
||||
resolver_->SignalWorkDone.connect(this,
|
||||
&AutoDetectProxy::OnResolveResult);
|
||||
resolver_->Start();
|
||||
resolver_->SignalDone.connect(this, &AutoDetectProxy::OnResolveResult);
|
||||
resolver_->Start(proxy_.address);
|
||||
} else {
|
||||
DoConnect();
|
||||
if (!DoConnect()) {
|
||||
Thread::Current()->Post(this, MSG_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
Thread::Current()->PostDelayed(timeout, this, MSG_TIMEOUT);
|
||||
}
|
||||
|
||||
void AutoDetectProxy::DoConnect() {
|
||||
bool AutoDetectProxy::DoConnect() {
|
||||
if (resolver_) {
|
||||
resolver_->Destroy(false);
|
||||
resolver_ = NULL;
|
||||
@ -197,16 +204,18 @@ void AutoDetectProxy::DoConnect() {
|
||||
proxy_.address.family(), SOCK_STREAM);
|
||||
if (!socket_) {
|
||||
LOG(LS_VERBOSE) << "Unable to create socket for " << proxy_.address;
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
socket_->SignalConnectEvent.connect(this, &AutoDetectProxy::OnConnectEvent);
|
||||
socket_->SignalReadEvent.connect(this, &AutoDetectProxy::OnReadEvent);
|
||||
socket_->SignalCloseEvent.connect(this, &AutoDetectProxy::OnCloseEvent);
|
||||
socket_->Connect(proxy_.address);
|
||||
return true;
|
||||
}
|
||||
|
||||
void AutoDetectProxy::Complete(ProxyType type) {
|
||||
Thread::Current()->Clear(this, MSG_TIMEOUT);
|
||||
Thread::Current()->Clear(this, MSG_UNRESOLVABLE);
|
||||
if (socket_) {
|
||||
socket_->Close();
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace talk_base {
|
||||
// AutoDetectProxy
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AsyncResolver;
|
||||
class AsyncResolverInterface;
|
||||
class AsyncSocket;
|
||||
|
||||
class AutoDetectProxy : public SignalThread {
|
||||
@ -72,6 +72,7 @@ class AutoDetectProxy : public SignalThread {
|
||||
return GetProxySettingsForUrl(agent, url, proxy, true);
|
||||
}
|
||||
enum { MSG_TIMEOUT = SignalThread::ST_MSG_FIRST_AVAILABLE,
|
||||
MSG_UNRESOLVABLE,
|
||||
ADP_MSG_FIRST_AVAILABLE};
|
||||
|
||||
protected:
|
||||
@ -87,14 +88,14 @@ class AutoDetectProxy : public SignalThread {
|
||||
void OnConnectEvent(AsyncSocket * socket);
|
||||
void OnReadEvent(AsyncSocket * socket);
|
||||
void OnCloseEvent(AsyncSocket * socket, int error);
|
||||
void OnResolveResult(SignalThread* thread);
|
||||
void DoConnect();
|
||||
void OnResolveResult(AsyncResolverInterface* resolver);
|
||||
bool DoConnect();
|
||||
|
||||
private:
|
||||
std::string agent_;
|
||||
std::string server_url_;
|
||||
ProxyInfo proxy_;
|
||||
AsyncResolver* resolver_;
|
||||
AsyncResolverInterface* resolver_;
|
||||
AsyncSocket* socket_;
|
||||
int next_;
|
||||
|
||||
|
@ -37,9 +37,16 @@ static const char kPath[] = "/";
|
||||
static const char kHost[] = "relay.google.com";
|
||||
static const uint16 kPort = 443;
|
||||
static const bool kSecure = true;
|
||||
// Each of the two stages in AutoDetectProxy has a 2-second time-out, so 5
|
||||
// seconds total should be enough.
|
||||
static const int kTimeoutMs = 5000;
|
||||
// At most, AutoDetectProxy should take ~6 seconds. Each connect step is
|
||||
// allotted 2 seconds, with the initial resolution + connect given an
|
||||
// extra 2 seconds. The slowest case is:
|
||||
// 1) Resolution + HTTPS takes full 4 seconds and fails (but resolution
|
||||
// succeeds).
|
||||
// 2) SOCKS5 takes the full 2 seconds.
|
||||
// Socket creation time seems unbounded, and has been observed to take >1 second
|
||||
// on a linux machine under load. As such, we allow for 10 seconds for timeout,
|
||||
// though could still end up with some flakiness.
|
||||
static const int kTimeoutMs = 10000;
|
||||
|
||||
class AutoDetectProxyTest : public testing::Test, public sigslot::has_slots<> {
|
||||
public:
|
||||
|
@ -316,11 +316,11 @@ void HttpClient::reset() {
|
||||
base_.abort(HE_OPERATION_CANCELLED);
|
||||
}
|
||||
|
||||
void HttpClient::OnResolveResult(SignalThread* thread) {
|
||||
if (thread != resolver_) {
|
||||
void HttpClient::OnResolveResult(AsyncResolverInterface* resolver) {
|
||||
if (resolver != resolver_) {
|
||||
return;
|
||||
}
|
||||
int error = resolver_->error();
|
||||
int error = resolver_->GetError();
|
||||
server_ = resolver_->address();
|
||||
resolver_->Destroy(false);
|
||||
resolver_ = NULL;
|
||||
@ -335,9 +335,8 @@ void HttpClient::OnResolveResult(SignalThread* thread) {
|
||||
|
||||
void HttpClient::StartDNSLookup() {
|
||||
resolver_ = new AsyncResolver();
|
||||
resolver_->set_address(server_);
|
||||
resolver_->SignalWorkDone.connect(this, &HttpClient::OnResolveResult);
|
||||
resolver_->Start();
|
||||
resolver_->SignalDone.connect(this, &HttpClient::OnResolveResult);
|
||||
resolver_->Start(server_);
|
||||
}
|
||||
|
||||
void HttpClient::set_server(const SocketAddress& address) {
|
||||
|
@ -175,7 +175,7 @@ protected:
|
||||
HttpError OnHeaderAvailable(bool ignore_data, bool chunked, size_t data_size);
|
||||
|
||||
void StartDNSLookup();
|
||||
void OnResolveResult(SignalThread* thread);
|
||||
void OnResolveResult(AsyncResolverInterface* resolver);
|
||||
|
||||
// IHttpNotify Interface
|
||||
virtual HttpError onHttpHeaderComplete(bool chunked, size_t& data_size);
|
||||
@ -199,7 +199,7 @@ private:
|
||||
scoped_ptr<HttpAuthContext> context_;
|
||||
DiskCache* cache_;
|
||||
CacheState cache_state_;
|
||||
AsyncResolver* resolver_;
|
||||
AsyncResolverInterface* resolver_;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@ -109,7 +109,23 @@ bool LateBindingSymbolTable::LoadFromPath(const char *dll_path) {
|
||||
}
|
||||
|
||||
#ifdef POSIX
|
||||
handle_ = dlopen(dll_path, RTLD_NOW);
|
||||
handle_ = dlopen(dll_path,
|
||||
// RTLD_NOW front-loads symbol resolution so that errors are
|
||||
// caught early instead of causing a process abort later.
|
||||
// RTLD_LOCAL prevents other modules from automatically
|
||||
// seeing symbol definitions in the newly-loaded tree. This
|
||||
// is necessary for same-named symbols in different ABI
|
||||
// versions of the same library to not explode.
|
||||
RTLD_NOW|RTLD_LOCAL
|
||||
#ifdef LINUX
|
||||
// RTLD_DEEPBIND makes symbol dependencies in the
|
||||
// newly-loaded tree prefer to resolve to definitions within
|
||||
// that tree (the default on OS X). This is necessary for
|
||||
// same-named symbols in different ABI versions of the same
|
||||
// library to not explode.
|
||||
|RTLD_DEEPBIND
|
||||
#endif
|
||||
); // NOLINT
|
||||
#else
|
||||
#error Not implemented
|
||||
#endif
|
||||
|
@ -33,7 +33,7 @@ namespace talk_base {
|
||||
|
||||
#define LATE_BINDING_SYMBOL_TABLE_CLASS_NAME LIBDBUS_GLIB_CLASS_NAME
|
||||
#define LATE_BINDING_SYMBOL_TABLE_SYMBOLS_LIST LIBDBUS_GLIB_SYMBOLS_LIST
|
||||
#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so"
|
||||
#define LATE_BINDING_SYMBOL_TABLE_DLL_NAME "libdbus-glib-1.so.2"
|
||||
#include "talk/base/latebindingsymboltable.cc.def"
|
||||
|
||||
} // namespace talk_base
|
||||
|
@ -87,7 +87,7 @@ void MacAsyncSocket::OnResolveResult(SignalThread* thread) {
|
||||
if (thread != resolver_) {
|
||||
return;
|
||||
}
|
||||
int error = resolver_->error();
|
||||
int error = resolver_->GetError();
|
||||
if (error == 0) {
|
||||
error = DoConnect(resolver_->address());
|
||||
} else {
|
||||
@ -109,10 +109,9 @@ int MacAsyncSocket::Connect(const SocketAddress& addr) {
|
||||
if (addr.IsUnresolved()) {
|
||||
LOG(LS_VERBOSE) << "Resolving addr in MacAsyncSocket::Connect";
|
||||
resolver_ = new AsyncResolver();
|
||||
resolver_->set_address(addr);
|
||||
resolver_->SignalWorkDone.connect(this,
|
||||
&MacAsyncSocket::OnResolveResult);
|
||||
resolver_->Start();
|
||||
resolver_->Start(addr);
|
||||
state_ = CS_CONNECTING;
|
||||
return 0;
|
||||
}
|
||||
|
@ -67,7 +67,27 @@ int ResolveHostname(const std::string& hostname, int family,
|
||||
}
|
||||
|
||||
// AsyncResolver
|
||||
AsyncResolver::AsyncResolver() : error_(0) {
|
||||
AsyncResolver::AsyncResolver() : error_(-1) {
|
||||
}
|
||||
|
||||
void AsyncResolver::Start(const SocketAddress& addr) {
|
||||
addr_ = addr;
|
||||
// SignalThred Start will kickoff the resolve process.
|
||||
SignalThread::Start();
|
||||
}
|
||||
|
||||
bool AsyncResolver::GetResolvedAddress(int family, SocketAddress* addr) const {
|
||||
if (error_ != 0 || addresses_.empty())
|
||||
return false;
|
||||
|
||||
*addr = addr_;
|
||||
for (size_t i = 0; i < addresses_.size(); ++i) {
|
||||
if (family == addresses_[i].family()) {
|
||||
addr->SetIP(addresses_[i]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AsyncResolver::DoWork() {
|
||||
@ -76,9 +96,7 @@ void AsyncResolver::DoWork() {
|
||||
}
|
||||
|
||||
void AsyncResolver::OnWorkDone() {
|
||||
if (addresses_.size() > 0) {
|
||||
addr_.SetIP(addresses_[0]);
|
||||
}
|
||||
SignalDone(this);
|
||||
}
|
||||
|
||||
const char* inet_ntop(int af, const void *src, char* dst, socklen_t size) {
|
||||
|
@ -37,25 +37,30 @@
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "talk/base/asyncresolverinterface.h"
|
||||
#include "talk/base/signalthread.h"
|
||||
#include "talk/base/sigslot.h"
|
||||
#include "talk/base/socketaddress.h"
|
||||
|
||||
namespace talk_base {
|
||||
|
||||
class AsyncResolverTest;
|
||||
|
||||
// AsyncResolver will perform async DNS resolution, signaling the result on
|
||||
// the inherited SignalWorkDone when the operation completes.
|
||||
class AsyncResolver : public SignalThread {
|
||||
// the SignalDone from AsyncResolverInterface when the operation completes.
|
||||
class AsyncResolver : public SignalThread, public AsyncResolverInterface {
|
||||
public:
|
||||
AsyncResolver();
|
||||
virtual ~AsyncResolver() {}
|
||||
|
||||
virtual void Start(const SocketAddress& addr);
|
||||
virtual bool GetResolvedAddress(int family, SocketAddress* addr) const;
|
||||
virtual int GetError() const { return error_; }
|
||||
virtual void Destroy(bool wait) { SignalThread::Destroy(wait); }
|
||||
|
||||
const SocketAddress& address() const { return addr_; }
|
||||
const std::vector<IPAddress>& addresses() const { return addresses_; }
|
||||
void set_address(const SocketAddress& addr) { addr_ = addr; }
|
||||
int error() const { return error_; }
|
||||
void set_error(int error) { error_ = error; }
|
||||
|
||||
|
||||
protected:
|
||||
virtual void DoWork();
|
||||
virtual void OnWorkDone();
|
||||
|
@ -200,9 +200,8 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
|
||||
if (addr.IsUnresolved()) {
|
||||
LOG(LS_VERBOSE) << "Resolving addr in PhysicalSocket::Connect";
|
||||
resolver_ = new AsyncResolver();
|
||||
resolver_->set_address(addr);
|
||||
resolver_->SignalWorkDone.connect(this, &PhysicalSocket::OnResolveResult);
|
||||
resolver_->Start();
|
||||
resolver_->SignalDone.connect(this, &PhysicalSocket::OnResolveResult);
|
||||
resolver_->Start(addr);
|
||||
state_ = CS_CONNECTING;
|
||||
return 0;
|
||||
}
|
||||
@ -476,12 +475,12 @@ class PhysicalSocket : public AsyncSocket, public sigslot::has_slots<> {
|
||||
SocketServer* socketserver() { return ss_; }
|
||||
|
||||
protected:
|
||||
void OnResolveResult(SignalThread* thread) {
|
||||
if (thread != resolver_) {
|
||||
void OnResolveResult(AsyncResolverInterface* resolver) {
|
||||
if (resolver != resolver_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int error = resolver_->error();
|
||||
int error = resolver_->GetError();
|
||||
if (error == 0) {
|
||||
error = DoConnect(resolver_->address());
|
||||
} else {
|
||||
|
@ -134,17 +134,16 @@ void PeerConnectionClient::Connect(const std::string& server, int port,
|
||||
if (server_address_.IsUnresolved()) {
|
||||
state_ = RESOLVING;
|
||||
resolver_ = new talk_base::AsyncResolver();
|
||||
resolver_->SignalWorkDone.connect(this,
|
||||
&PeerConnectionClient::OnResolveResult);
|
||||
resolver_->set_address(server_address_);
|
||||
resolver_->Start();
|
||||
resolver_->SignalDone.connect(this, &PeerConnectionClient::OnResolveResult);
|
||||
resolver_->Start(server_address_);
|
||||
} else {
|
||||
DoConnect();
|
||||
}
|
||||
}
|
||||
|
||||
void PeerConnectionClient::OnResolveResult(talk_base::SignalThread *t) {
|
||||
if (resolver_->error() != 0) {
|
||||
void PeerConnectionClient::OnResolveResult(
|
||||
talk_base::AsyncResolverInterface* resolver) {
|
||||
if (resolver_->GetError() != 0) {
|
||||
callback_->OnServerConnectionFailure();
|
||||
resolver_->Destroy(false);
|
||||
resolver_ = NULL;
|
||||
|
@ -121,7 +121,7 @@ class PeerConnectionClient : public sigslot::has_slots<>,
|
||||
|
||||
void OnClose(talk_base::AsyncSocket* socket, int err);
|
||||
|
||||
void OnResolveResult(talk_base::SignalThread *t);
|
||||
void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
|
||||
|
||||
PeerConnectionClientObserver* callback_;
|
||||
talk_base::SocketAddress server_address_;
|
||||
|
@ -257,6 +257,7 @@
|
||||
'base/asynchttprequest.cc',
|
||||
'base/asynchttprequest.h',
|
||||
'base/asyncpacketsocket.h',
|
||||
'base/asyncresolverinterface.h',
|
||||
'base/asyncsocket.cc',
|
||||
'base/asyncsocket.h',
|
||||
'base/asynctcpsocket.cc',
|
||||
|
@ -42,7 +42,8 @@ namespace cricket {
|
||||
#undef LATE_BINDING_SYMBOL_TABLE_DLL_NAME
|
||||
|
||||
bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0) {
|
||||
talk_base::DllHandle libudev_1 = dlopen("libudev.so.1", RTLD_NOW|RTLD_NOLOAD);
|
||||
talk_base::DllHandle libudev_1 = dlopen("libudev.so.1",
|
||||
RTLD_NOW|RTLD_LOCAL|RTLD_NOLOAD);
|
||||
bool unsafe_symlink = (libudev_0 == libudev_1);
|
||||
if (unsafe_symlink) {
|
||||
// .0 and .1 are distinct ABIs, so if they point to the same thing then one
|
||||
@ -55,7 +56,8 @@ bool IsWrongLibUDevAbiVersion(talk_base::DllHandle libudev_0) {
|
||||
// system library loaded the new ABI separately. This is not a problem for
|
||||
// LateBindingSymbolTable because its symbol look-ups are restricted to its
|
||||
// DllHandle, but having libudev.so.0 resident may cause problems for that
|
||||
// system library because symbol names are not namespaced by DLL.
|
||||
// system library because symbol names are not namespaced by DLL. (Although
|
||||
// our use of RTLD_LOCAL should avoid most problems.)
|
||||
LOG(LS_WARNING)
|
||||
<< "libudev.so.1 is resident but distinct from libudev.so.0";
|
||||
}
|
||||
|
@ -3219,7 +3219,8 @@ bool WebRtcVideoMediaChannel::SetNackFec(int channel_id,
|
||||
LOG_RTCERR1(SetNACKStatus, channel_id);
|
||||
return false;
|
||||
}
|
||||
LOG(LS_INFO) << "NACK enabled for channel " << channel_id;
|
||||
std::string enabled = nack_enabled ? "enabled" : "disabled";
|
||||
LOG(LS_INFO) << "NACK " << enabled << " for channel " << channel_id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3065,9 +3065,12 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) {
|
||||
static_cast<float>(ns.currentExpandRate) / (1 << 14);
|
||||
}
|
||||
if (engine()->voe()->sync()) {
|
||||
int jitter_buffer_delay_ms = 0;
|
||||
int playout_buffer_delay_ms = 0;
|
||||
engine()->voe()->sync()->GetDelayEstimate(
|
||||
*it, &rinfo.delay_estimate_ms, &playout_buffer_delay_ms);
|
||||
*it, &jitter_buffer_delay_ms, &playout_buffer_delay_ms);
|
||||
rinfo.delay_estimate_ms = jitter_buffer_delay_ms +
|
||||
playout_buffer_delay_ms;
|
||||
}
|
||||
|
||||
// Get speech level.
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include "talk/base/asyncudpsocket.h"
|
||||
#include "talk/base/asynctcpsocket.h"
|
||||
#include "talk/base/logging.h"
|
||||
#include "talk/base/nethelpers.h"
|
||||
#include "talk/base/physicalsocketserver.h"
|
||||
#include "talk/base/scoped_ptr.h"
|
||||
#include "talk/base/socketadapters.h"
|
||||
#include "talk/base/thread.h"
|
||||
#include "talk/p2p/base/asyncstuntcpsocket.h"
|
||||
@ -174,6 +177,10 @@ AsyncPacketSocket* BasicPacketSocketFactory::CreateClientTcpSocket(
|
||||
return tcp_socket;
|
||||
}
|
||||
|
||||
AsyncResolverInterface* BasicPacketSocketFactory::CreateAsyncResolver() {
|
||||
return new talk_base::AsyncResolver();
|
||||
}
|
||||
|
||||
int BasicPacketSocketFactory::BindSocket(
|
||||
AsyncSocket* socket, const SocketAddress& local_address,
|
||||
int min_port, int max_port) {
|
||||
|
@ -51,6 +51,8 @@ class BasicPacketSocketFactory : public PacketSocketFactory {
|
||||
const SocketAddress& local_address, const SocketAddress& remote_address,
|
||||
const ProxyInfo& proxy_info, const std::string& user_agent, int opts);
|
||||
|
||||
virtual AsyncResolverInterface* CreateAsyncResolver();
|
||||
|
||||
private:
|
||||
int BindSocket(AsyncSocket* socket, const SocketAddress& local_address,
|
||||
int min_port, int max_port);
|
||||
|
@ -33,6 +33,7 @@
|
||||
namespace talk_base {
|
||||
|
||||
class AsyncPacketSocket;
|
||||
class AsyncResolverInterface;
|
||||
|
||||
class PacketSocketFactory {
|
||||
public:
|
||||
@ -57,6 +58,8 @@ class PacketSocketFactory {
|
||||
const SocketAddress& local_address, const SocketAddress& remote_address,
|
||||
const ProxyInfo& proxy_info, const std::string& user_agent, int opts) = 0;
|
||||
|
||||
virtual AsyncResolverInterface* CreateAsyncResolver() = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(PacketSocketFactory);
|
||||
};
|
||||
|
@ -162,11 +162,11 @@ static std::string ComputeFoundation(
|
||||
return talk_base::ToString<uint32>(talk_base::ComputeCrc32(ost.str()));
|
||||
}
|
||||
|
||||
Port::Port(talk_base::Thread* thread, talk_base::Network* network,
|
||||
const talk_base::IPAddress& ip,
|
||||
Port::Port(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network, const talk_base::IPAddress& ip,
|
||||
const std::string& username_fragment, const std::string& password)
|
||||
: thread_(thread),
|
||||
factory_(NULL),
|
||||
factory_(factory),
|
||||
send_retransmit_count_attribute_(false),
|
||||
network_(network),
|
||||
ip_(ip),
|
||||
|
@ -118,8 +118,8 @@ struct ProtocolAddress {
|
||||
class Port : public PortInterface, public talk_base::MessageHandler,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
Port(talk_base::Thread* thread, talk_base::Network* network,
|
||||
const talk_base::IPAddress& ip,
|
||||
Port(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network, const talk_base::IPAddress& ip,
|
||||
const std::string& username_fragment, const std::string& password);
|
||||
Port(talk_base::Thread* thread, const std::string& type,
|
||||
talk_base::PacketSocketFactory* factory,
|
||||
|
@ -766,6 +766,9 @@ class FakePacketSocketFactory : public talk_base::PacketSocketFactory {
|
||||
void set_next_client_tcp_socket(AsyncPacketSocket* next_client_tcp_socket) {
|
||||
next_client_tcp_socket_ = next_client_tcp_socket;
|
||||
}
|
||||
talk_base::AsyncResolverInterface* CreateAsyncResolver() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
AsyncPacketSocket* next_udp_socket_;
|
||||
|
@ -125,10 +125,11 @@ class StunBindingRequest : public StunRequest {
|
||||
};
|
||||
|
||||
UDPPort::UDPPort(talk_base::Thread* thread,
|
||||
talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network,
|
||||
talk_base::AsyncPacketSocket* socket,
|
||||
const std::string& username, const std::string& password)
|
||||
: Port(thread, network, socket->GetLocalAddress().ipaddr(),
|
||||
: Port(thread, factory, network, socket->GetLocalAddress().ipaddr(),
|
||||
username, password),
|
||||
requests_(thread),
|
||||
socket_(socket),
|
||||
@ -139,10 +140,10 @@ UDPPort::UDPPort(talk_base::Thread* thread,
|
||||
}
|
||||
|
||||
UDPPort::UDPPort(talk_base::Thread* thread,
|
||||
talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network,
|
||||
const talk_base::IPAddress& ip, int min_port, int max_port,
|
||||
const std::string& username, const std::string& password)
|
||||
talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network,
|
||||
const talk_base::IPAddress& ip, int min_port, int max_port,
|
||||
const std::string& username, const std::string& password)
|
||||
: Port(thread, LOCAL_PORT_TYPE, factory, network, ip, min_port, max_port,
|
||||
username, password),
|
||||
requests_(thread),
|
||||
@ -302,21 +303,21 @@ void UDPPort::ResolveStunAddress() {
|
||||
if (resolver_)
|
||||
return;
|
||||
|
||||
resolver_ = new talk_base::AsyncResolver();
|
||||
resolver_->SignalWorkDone.connect(this, &UDPPort::OnResolveResult);
|
||||
resolver_->set_address(server_addr_);
|
||||
resolver_->Start();
|
||||
resolver_ = socket_factory()->CreateAsyncResolver();
|
||||
resolver_->SignalDone.connect(this, &UDPPort::OnResolveResult);
|
||||
resolver_->Start(server_addr_);
|
||||
}
|
||||
|
||||
void UDPPort::OnResolveResult(talk_base::SignalThread* t) {
|
||||
ASSERT(t == resolver_);
|
||||
if (resolver_->error() != 0) {
|
||||
void UDPPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
|
||||
ASSERT(resolver == resolver_);
|
||||
if (resolver_->GetError() != 0 ||
|
||||
!resolver_->GetResolvedAddress(ip().family(), &server_addr_)) {
|
||||
LOG_J(LS_WARNING, this) << "StunPort: stun host lookup received error "
|
||||
<< resolver_->error();
|
||||
<< resolver_->GetError();
|
||||
OnStunBindingOrResolveRequestFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
server_addr_ = resolver_->address();
|
||||
SendStunBindingRequest();
|
||||
}
|
||||
|
||||
|
@ -46,11 +46,13 @@ namespace cricket {
|
||||
class UDPPort : public Port {
|
||||
public:
|
||||
static UDPPort* Create(talk_base::Thread* thread,
|
||||
talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network,
|
||||
talk_base::AsyncPacketSocket* socket,
|
||||
const std::string& username,
|
||||
const std::string& password) {
|
||||
UDPPort* port = new UDPPort(thread, network, socket, username, password);
|
||||
UDPPort* port = new UDPPort(thread, factory, network, socket,
|
||||
username, password);
|
||||
if (!port->Init()) {
|
||||
delete port;
|
||||
port = NULL;
|
||||
@ -66,8 +68,8 @@ class UDPPort : public Port {
|
||||
const std::string& username,
|
||||
const std::string& password) {
|
||||
UDPPort* port = new UDPPort(thread, factory, network,
|
||||
ip, min_port, max_port,
|
||||
username, password);
|
||||
ip, min_port, max_port,
|
||||
username, password);
|
||||
if (!port->Init()) {
|
||||
delete port;
|
||||
port = NULL;
|
||||
@ -114,8 +116,8 @@ class UDPPort : public Port {
|
||||
int min_port, int max_port,
|
||||
const std::string& username, const std::string& password);
|
||||
|
||||
UDPPort(talk_base::Thread* thread, talk_base::Network* network,
|
||||
talk_base::AsyncPacketSocket* socket,
|
||||
UDPPort(talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
|
||||
talk_base::Network* network, talk_base::AsyncPacketSocket* socket,
|
||||
const std::string& username, const std::string& password);
|
||||
|
||||
bool Init();
|
||||
@ -141,7 +143,7 @@ class UDPPort : public Port {
|
||||
private:
|
||||
// DNS resolution of the STUN server.
|
||||
void ResolveStunAddress();
|
||||
void OnResolveResult(talk_base::SignalThread* thread);
|
||||
void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
|
||||
|
||||
// Below methods handles binding request responses.
|
||||
void OnStunBindingRequestSucceeded(const talk_base::SocketAddress& stun_addr);
|
||||
@ -158,7 +160,7 @@ class UDPPort : public Port {
|
||||
StunRequestManager requests_;
|
||||
talk_base::AsyncPacketSocket* socket_;
|
||||
int error_;
|
||||
talk_base::AsyncResolver* resolver_;
|
||||
talk_base::AsyncResolverInterface* resolver_;
|
||||
bool ready_;
|
||||
int stun_keepalive_delay_;
|
||||
|
||||
|
@ -27,7 +27,10 @@
|
||||
|
||||
#include "talk/base/gunit.h"
|
||||
#include "talk/base/helpers.h"
|
||||
#include "talk/base/physicalsocketserver.h"
|
||||
#include "talk/base/scoped_ptr.h"
|
||||
#include "talk/base/socketaddress.h"
|
||||
#include "talk/base/virtualsocketserver.h"
|
||||
#include "talk/p2p/base/basicpacketsocketfactory.h"
|
||||
#include "talk/p2p/base/stunport.h"
|
||||
#include "talk/p2p/base/teststunserver.h"
|
||||
@ -48,7 +51,10 @@ class StunPortTest : public testing::Test,
|
||||
public sigslot::has_slots<> {
|
||||
public:
|
||||
StunPortTest()
|
||||
: network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
|
||||
: pss_(new talk_base::PhysicalSocketServer),
|
||||
ss_(new talk_base::VirtualSocketServer(pss_.get())),
|
||||
ss_scope_(ss_.get()),
|
||||
network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
|
||||
socket_factory_(talk_base::Thread::Current()),
|
||||
stun_server_(new cricket::TestStunServer(
|
||||
talk_base::Thread::Current(), kStunAddr)),
|
||||
@ -77,7 +83,8 @@ class StunPortTest : public testing::Test,
|
||||
ASSERT_TRUE(socket_ != NULL);
|
||||
socket_->SignalReadPacket.connect(this, &StunPortTest::OnReadPacket);
|
||||
stun_port_.reset(cricket::UDPPort::Create(
|
||||
talk_base::Thread::Current(), &network_, socket_.get(),
|
||||
talk_base::Thread::Current(), &socket_factory_,
|
||||
&network_, socket_.get(),
|
||||
talk_base::CreateRandomString(16), talk_base::CreateRandomString(22)));
|
||||
ASSERT_TRUE(stun_port_ != NULL);
|
||||
stun_port_->set_server_addr(server_addr);
|
||||
@ -120,6 +127,9 @@ class StunPortTest : public testing::Test,
|
||||
}
|
||||
|
||||
private:
|
||||
talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
|
||||
talk_base::scoped_ptr<talk_base::VirtualSocketServer> ss_;
|
||||
talk_base::SocketServerScope ss_scope_;
|
||||
talk_base::Network network_;
|
||||
talk_base::BasicPacketSocketFactory socket_factory_;
|
||||
talk_base::scoped_ptr<cricket::UDPPort> stun_port_;
|
||||
|
@ -399,22 +399,21 @@ void TurnPort::ResolveTurnAddress(const talk_base::SocketAddress& address) {
|
||||
if (resolver_)
|
||||
return;
|
||||
|
||||
resolver_ = new talk_base::AsyncResolver();
|
||||
resolver_->SignalWorkDone.connect(this, &TurnPort::OnResolveResult);
|
||||
resolver_->set_address(address);
|
||||
resolver_->Start();
|
||||
resolver_ = socket_factory()->CreateAsyncResolver();
|
||||
resolver_->SignalDone.connect(this, &TurnPort::OnResolveResult);
|
||||
resolver_->Start(address);
|
||||
}
|
||||
|
||||
void TurnPort::OnResolveResult(talk_base::SignalThread* signal_thread) {
|
||||
ASSERT(signal_thread == resolver_);
|
||||
if (resolver_->error() != 0) {
|
||||
void TurnPort::OnResolveResult(talk_base::AsyncResolverInterface* resolver) {
|
||||
ASSERT(resolver == resolver_);
|
||||
if (resolver_->GetError() != 0 ||
|
||||
!resolver_->GetResolvedAddress(ip().family(), &server_address_.address)) {
|
||||
LOG_J(LS_WARNING, this) << "TURN host lookup received error "
|
||||
<< resolver_->error();
|
||||
<< resolver_->GetError();
|
||||
OnAllocateError();
|
||||
return;
|
||||
}
|
||||
|
||||
server_address_.address = resolver_->address();
|
||||
PrepareAddress();
|
||||
}
|
||||
|
||||
|
@ -123,7 +123,7 @@ class TurnPort : public Port {
|
||||
}
|
||||
|
||||
void ResolveTurnAddress(const talk_base::SocketAddress& address);
|
||||
void OnResolveResult(talk_base::SignalThread* signal_thread);
|
||||
void OnResolveResult(talk_base::AsyncResolverInterface* resolver);
|
||||
|
||||
void AddRequestAuthInfo(StunMessage* msg);
|
||||
void OnSendStunPacket(const void* data, size_t size, StunRequest* request);
|
||||
@ -157,7 +157,7 @@ class TurnPort : public Port {
|
||||
|
||||
talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
|
||||
SocketOptionsMap socket_options_;
|
||||
talk_base::AsyncResolver* resolver_;
|
||||
talk_base::AsyncResolverInterface* resolver_;
|
||||
int error_;
|
||||
|
||||
StunRequestManager request_manager_;
|
||||
|
@ -857,7 +857,8 @@ void AllocationSequence::CreateUDPPorts() {
|
||||
// is enabled completely.
|
||||
UDPPort* port = NULL;
|
||||
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) && udp_socket_) {
|
||||
port = UDPPort::Create(session_->network_thread(), network_,
|
||||
port = UDPPort::Create(session_->network_thread(),
|
||||
session_->socket_factory(), network_,
|
||||
udp_socket_.get(),
|
||||
session_->username(), session_->password());
|
||||
} else {
|
||||
|
Loading…
x
Reference in New Issue
Block a user