From a23f0ca4ba5105eb76b6fa30447c806812a8f3c2 Mon Sep 17 00:00:00 2001 From: "sergeyu@chromium.org" Date: Wed, 13 Nov 2013 22:48:52 +0000 Subject: [PATCH] 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 --- talk/app/webrtc/datachannel.cc | 13 +- talk/app/webrtc/datachannel.h | 8 +- talk/app/webrtc/datachannel_unittest.cc | 51 ++++++++ talk/app/webrtc/mediastreamsignaling.cc | 87 +++++++------ talk/app/webrtc/mediastreamsignaling.h | 6 +- .../webrtc/mediastreamsignaling_unittest.cc | 84 +++++++++--- talk/app/webrtc/peerconnection.cc | 122 +++++++++++++----- .../webrtc/peerconnectionfactory_unittest.cc | 54 ++++++++ .../peerconnectioninterface_unittest.cc | 13 +- .../app/webrtc/test/fakedatachannelprovider.h | 20 +-- talk/app/webrtc/test/testsdpstrings.h | 5 +- talk/app/webrtc/webrtcsession.cc | 20 +-- talk/app/webrtc/webrtcsession.h | 2 - talk/base/asyncresolverinterface.h | 64 +++++++++ talk/base/autodetectproxy.cc | 35 +++-- talk/base/autodetectproxy.h | 9 +- talk/base/autodetectproxy_unittest.cc | 13 +- talk/base/httpclient.cc | 11 +- talk/base/httpclient.h | 4 +- talk/base/latebindingsymboltable.cc | 18 ++- talk/base/libdbusglibsymboltable.cc | 2 +- talk/base/macasyncsocket.cc | 5 +- talk/base/nethelpers.cc | 26 +++- talk/base/nethelpers.h | 17 ++- talk/base/physicalsocketserver.cc | 11 +- .../client/peer_connection_client.cc | 11 +- .../client/peer_connection_client.h | 2 +- talk/libjingle.gyp | 1 + talk/media/devices/libudevsymboltable.cc | 6 +- talk/media/webrtc/webrtcvideoengine.cc | 3 +- talk/media/webrtc/webrtcvoiceengine.cc | 5 +- talk/p2p/base/basicpacketsocketfactory.cc | 7 + talk/p2p/base/basicpacketsocketfactory.h | 2 + talk/p2p/base/packetsocketfactory.h | 3 + talk/p2p/base/port.cc | 6 +- talk/p2p/base/port.h | 4 +- talk/p2p/base/port_unittest.cc | 3 + talk/p2p/base/stunport.cc | 29 +++-- talk/p2p/base/stunport.h | 16 ++- talk/p2p/base/stunport_unittest.cc | 14 +- talk/p2p/base/turnport.cc | 17 ++- talk/p2p/base/turnport.h | 4 +- talk/p2p/client/basicportallocator.cc | 3 +- 43 files changed, 600 insertions(+), 236 deletions(-) create mode 100644 talk/base/asyncresolverinterface.h diff --git a/talk/app/webrtc/datachannel.cc b/talk/app/webrtc/datachannel.cc index 6f3048718..6c9e0bc43 100644 --- a/talk/app/webrtc/datachannel.cc +++ b/talk/app/webrtc/datachannel.cc @@ -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; diff --git a/talk/app/webrtc/datachannel.h b/talk/app/webrtc/datachannel.h index 5635e63e6..bf31aed5d 100644 --- a/talk/app/webrtc/datachannel.h +++ b/talk/app/webrtc/datachannel.h @@ -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, diff --git a/talk/app/webrtc/datachannel_unittest.cc b/talk/app/webrtc/datachannel_unittest.cc index dba24a2db..fdcd2f2cd 100644 --- a/talk/app/webrtc/datachannel_unittest.cc +++ b/talk/app/webrtc/datachannel_unittest.cc @@ -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 observer_; talk_base::scoped_refptr 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); +} diff --git a/talk/app/webrtc/mediastreamsignaling.cc b/talk/app/webrtc/mediastreamsignaling.cc index 8d2542569..7586938ce 100644 --- a/talk/app/webrtc/mediastreamsignaling.cc +++ b/talk/app/webrtc/mediastreamsignaling.cc @@ -208,10 +208,10 @@ void MediaStreamSignaling::TearDown() { bool MediaStreamSignaling::IsSctpSidAvailable(int sid) const { if (sid < 0 || sid > static_cast(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 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& 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 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); } } } diff --git a/talk/app/webrtc/mediastreamsignaling.h b/talk/app/webrtc/mediastreamsignaling.h index a0ed6199d..c600f0662 100644 --- a/talk/app/webrtc/mediastreamsignaling.h +++ b/talk/app/webrtc/mediastreamsignaling.h @@ -384,8 +384,10 @@ class MediaStreamSignaling { int last_allocated_sctp_odd_sid_; typedef std::map > - DataChannels; - DataChannels data_channels_; + RtpDataChannels; + typedef std::vector > SctpDataChannels; + RtpDataChannels rtp_data_channels_; + SctpDataChannels sctp_data_channels_; }; } // namespace webrtc diff --git a/talk/app/webrtc/mediastreamsignaling_unittest.cc b/talk/app/webrtc/mediastreamsignaling_unittest.cc index df4b1f506..5b88aa0c5 100644 --- a/talk/app/webrtc/mediastreamsignaling_unittest.cc +++ b/talk/app/webrtc/mediastreamsignaling_unittest.cc @@ -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 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 AddDataChannel( + cricket::DataChannelType type, const std::string& label, int id) { + webrtc::DataChannelInit config; + config.id = id; + talk_base::scoped_refptr 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 channel_manager_; talk_base::scoped_refptr reference_collection_; talk_base::scoped_ptr observer_; talk_base::scoped_ptr signaling_; + talk_base::scoped_ptr 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 provider( - new FakeDataChannelProvider()); - // Creates a DataChannel with id 1. - webrtc::DataChannelInit config; - config.id = 1; - talk_base::scoped_refptr 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 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)); } diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc index bc69d486a..17f187dbf 100644 --- a/talk/app/webrtc/peerconnection.cc +++ b/talk/app/webrtc/peerconnection.cc @@ -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 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(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(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) { diff --git a/talk/app/webrtc/peerconnectionfactory_unittest.cc b/talk/app/webrtc/peerconnectionfactory_unittest.cc index e3def6c24..4f0b7297e 100644 --- a/talk/app/webrtc/peerconnectionfactory_unittest.cc +++ b/talk/app/webrtc/peerconnectionfactory_unittest.cc @@ -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 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) { diff --git a/talk/app/webrtc/peerconnectioninterface_unittest.cc b/talk/app/webrtc/peerconnectioninterface_unittest.cc index ea94ee134..093b84268 100644 --- a/talk/app/webrtc/peerconnectioninterface_unittest.cc +++ b/talk/app/webrtc/peerconnectioninterface_unittest.cc @@ -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 diff --git a/talk/app/webrtc/test/fakedatachannelprovider.h b/talk/app/webrtc/test/fakedatachannelprovider.h index 429f4dff1..5b196983c 100644 --- a/talk/app/webrtc/test/fakedatachannelprovider.h +++ b/talk/app/webrtc/test/fakedatachannelprovider.h @@ -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 { diff --git a/talk/app/webrtc/test/testsdpstrings.h b/talk/app/webrtc/test/testsdpstrings.h index 9f95d361f..d6e9c2254 100644 --- a/talk/app/webrtc/test/testsdpstrings.h +++ b/talk/app/webrtc/test/testsdpstrings.h @@ -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[] = diff --git a/talk/app/webrtc/webrtcsession.cc b/talk/app/webrtc/webrtcsession.cc index 5935ea046..565eee3c4 100644 --- a/talk/app/webrtc/webrtcsession.cc +++ b/talk/app/webrtc/webrtcsession.cc @@ -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 { diff --git a/talk/app/webrtc/webrtcsession.h b/talk/app/webrtc/webrtcsession.h index 4a39a11d1..da994c5ef 100644 --- a/talk/app/webrtc/webrtcsession.h +++ b/talk/app/webrtc/webrtcsession.h @@ -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; diff --git a/talk/base/asyncresolverinterface.h b/talk/base/asyncresolverinterface.h new file mode 100644 index 000000000..4d77c4f88 --- /dev/null +++ b/talk/base/asyncresolverinterface.h @@ -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 SignalDone; +}; + +} // namespace talk_base + +#endif diff --git a/talk/base/autodetectproxy.cc b/talk/base/autodetectproxy.cc index 02cbaade5..a32043c1c 100644 --- a/talk/base/autodetectproxy.cc +++ b/talk/base/autodetectproxy.cc @@ -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(); } diff --git a/talk/base/autodetectproxy.h b/talk/base/autodetectproxy.h index a6ad3d113..2cbeb8275 100644 --- a/talk/base/autodetectproxy.h +++ b/talk/base/autodetectproxy.h @@ -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_; diff --git a/talk/base/autodetectproxy_unittest.cc b/talk/base/autodetectproxy_unittest.cc index 3fca4c6b4..18241a3e8 100644 --- a/talk/base/autodetectproxy_unittest.cc +++ b/talk/base/autodetectproxy_unittest.cc @@ -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: diff --git a/talk/base/httpclient.cc b/talk/base/httpclient.cc index 5a16676a3..5bee9114b 100644 --- a/talk/base/httpclient.cc +++ b/talk/base/httpclient.cc @@ -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) { diff --git a/talk/base/httpclient.h b/talk/base/httpclient.h index 2e77b0d18..03deb2286 100644 --- a/talk/base/httpclient.h +++ b/talk/base/httpclient.h @@ -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 context_; DiskCache* cache_; CacheState cache_state_; - AsyncResolver* resolver_; + AsyncResolverInterface* resolver_; }; ////////////////////////////////////////////////////////////////////// diff --git a/talk/base/latebindingsymboltable.cc b/talk/base/latebindingsymboltable.cc index 222621904..433844ee4 100644 --- a/talk/base/latebindingsymboltable.cc +++ b/talk/base/latebindingsymboltable.cc @@ -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 diff --git a/talk/base/libdbusglibsymboltable.cc b/talk/base/libdbusglibsymboltable.cc index 9c4be7f3d..6a3ebf3b1 100644 --- a/talk/base/libdbusglibsymboltable.cc +++ b/talk/base/libdbusglibsymboltable.cc @@ -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 diff --git a/talk/base/macasyncsocket.cc b/talk/base/macasyncsocket.cc index 54ad60461..7841b4bf5 100644 --- a/talk/base/macasyncsocket.cc +++ b/talk/base/macasyncsocket.cc @@ -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; } diff --git a/talk/base/nethelpers.cc b/talk/base/nethelpers.cc index 05e02c9f4..e6310ac45 100644 --- a/talk/base/nethelpers.cc +++ b/talk/base/nethelpers.cc @@ -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) { diff --git a/talk/base/nethelpers.h b/talk/base/nethelpers.h index 66f79108f..a49f48ac7 100644 --- a/talk/base/nethelpers.h +++ b/talk/base/nethelpers.h @@ -37,25 +37,30 @@ #include +#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& 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(); diff --git a/talk/base/physicalsocketserver.cc b/talk/base/physicalsocketserver.cc index 58a22fa1d..43be440e7 100644 --- a/talk/base/physicalsocketserver.cc +++ b/talk/base/physicalsocketserver.cc @@ -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 { diff --git a/talk/examples/peerconnection/client/peer_connection_client.cc b/talk/examples/peerconnection/client/peer_connection_client.cc index 403fabda1..9cdaedcbf 100644 --- a/talk/examples/peerconnection/client/peer_connection_client.cc +++ b/talk/examples/peerconnection/client/peer_connection_client.cc @@ -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; diff --git a/talk/examples/peerconnection/client/peer_connection_client.h b/talk/examples/peerconnection/client/peer_connection_client.h index d31262b67..43fee3456 100644 --- a/talk/examples/peerconnection/client/peer_connection_client.h +++ b/talk/examples/peerconnection/client/peer_connection_client.h @@ -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_; diff --git a/talk/libjingle.gyp b/talk/libjingle.gyp index 16044b515..4cbeaa3c9 100755 --- a/talk/libjingle.gyp +++ b/talk/libjingle.gyp @@ -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', diff --git a/talk/media/devices/libudevsymboltable.cc b/talk/media/devices/libudevsymboltable.cc index 9620cd2f2..20154e1fc 100644 --- a/talk/media/devices/libudevsymboltable.cc +++ b/talk/media/devices/libudevsymboltable.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"; } diff --git a/talk/media/webrtc/webrtcvideoengine.cc b/talk/media/webrtc/webrtcvideoengine.cc index ec38eeacf..6032134cf 100644 --- a/talk/media/webrtc/webrtcvideoengine.cc +++ b/talk/media/webrtc/webrtcvideoengine.cc @@ -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; } diff --git a/talk/media/webrtc/webrtcvoiceengine.cc b/talk/media/webrtc/webrtcvoiceengine.cc index ac8e06743..4911c5941 100644 --- a/talk/media/webrtc/webrtcvoiceengine.cc +++ b/talk/media/webrtc/webrtcvoiceengine.cc @@ -3065,9 +3065,12 @@ bool WebRtcVoiceMediaChannel::GetStats(VoiceMediaInfo* info) { static_cast(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. diff --git a/talk/p2p/base/basicpacketsocketfactory.cc b/talk/p2p/base/basicpacketsocketfactory.cc index 565aed3c0..758d49289 100644 --- a/talk/p2p/base/basicpacketsocketfactory.cc +++ b/talk/p2p/base/basicpacketsocketfactory.cc @@ -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) { diff --git a/talk/p2p/base/basicpacketsocketfactory.h b/talk/p2p/base/basicpacketsocketfactory.h index d4e76e714..27963c9f4 100644 --- a/talk/p2p/base/basicpacketsocketfactory.h +++ b/talk/p2p/base/basicpacketsocketfactory.h @@ -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); diff --git a/talk/p2p/base/packetsocketfactory.h b/talk/p2p/base/packetsocketfactory.h index 882a97417..e985b37fa 100644 --- a/talk/p2p/base/packetsocketfactory.h +++ b/talk/p2p/base/packetsocketfactory.h @@ -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); }; diff --git a/talk/p2p/base/port.cc b/talk/p2p/base/port.cc index 6e688dace..7d5238697 100644 --- a/talk/p2p/base/port.cc +++ b/talk/p2p/base/port.cc @@ -162,11 +162,11 @@ static std::string ComputeFoundation( return talk_base::ToString(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), diff --git a/talk/p2p/base/port.h b/talk/p2p/base/port.h index 7b89e5546..ab7fdedc0 100644 --- a/talk/p2p/base/port.h +++ b/talk/p2p/base/port.h @@ -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, diff --git a/talk/p2p/base/port_unittest.cc b/talk/p2p/base/port_unittest.cc index 1cc304911..a5271555e 100644 --- a/talk/p2p/base/port_unittest.cc +++ b/talk/p2p/base/port_unittest.cc @@ -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_; diff --git a/talk/p2p/base/stunport.cc b/talk/p2p/base/stunport.cc index b440bf4f6..283eade4e 100644 --- a/talk/p2p/base/stunport.cc +++ b/talk/p2p/base/stunport.cc @@ -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(); } diff --git a/talk/p2p/base/stunport.h b/talk/p2p/base/stunport.h index 7cfed4b7c..8f7255658 100644 --- a/talk/p2p/base/stunport.h +++ b/talk/p2p/base/stunport.h @@ -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_; diff --git a/talk/p2p/base/stunport_unittest.cc b/talk/p2p/base/stunport_unittest.cc index 3c1c6836f..12b32dbc4 100644 --- a/talk/p2p/base/stunport_unittest.cc +++ b/talk/p2p/base/stunport_unittest.cc @@ -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 pss_; + talk_base::scoped_ptr ss_; + talk_base::SocketServerScope ss_scope_; talk_base::Network network_; talk_base::BasicPacketSocketFactory socket_factory_; talk_base::scoped_ptr stun_port_; diff --git a/talk/p2p/base/turnport.cc b/talk/p2p/base/turnport.cc index 880af8397..14388e341 100644 --- a/talk/p2p/base/turnport.cc +++ b/talk/p2p/base/turnport.cc @@ -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(); } diff --git a/talk/p2p/base/turnport.h b/talk/p2p/base/turnport.h index 4462b0c8c..e5c03da12 100644 --- a/talk/p2p/base/turnport.h +++ b/talk/p2p/base/turnport.h @@ -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 socket_; SocketOptionsMap socket_options_; - talk_base::AsyncResolver* resolver_; + talk_base::AsyncResolverInterface* resolver_; int error_; StunRequestManager request_manager_; diff --git a/talk/p2p/client/basicportallocator.cc b/talk/p2p/client/basicportallocator.cc index 9f10d3394..a5310b70a 100644 --- a/talk/p2p/client/basicportallocator.cc +++ b/talk/p2p/client/basicportallocator.cc @@ -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 {