| Index: remoting/protocol/libjingle_transport_factory.cc
|
| diff --git a/remoting/protocol/libjingle_transport_factory.cc b/remoting/protocol/libjingle_transport_factory.cc
|
| index 76c3507aaa6d55b6e107ce364e0618a9ec33ebd2..ef22f2a95f380a950171448b590edd010894b21e 100644
|
| --- a/remoting/protocol/libjingle_transport_factory.cc
|
| +++ b/remoting/protocol/libjingle_transport_factory.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "remoting/protocol/libjingle_transport_factory.h"
|
|
|
| +#include "base/callback.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/thread_task_runner_handle.h"
|
| #include "base/timer/timer.h"
|
| @@ -13,9 +14,9 @@
|
| #include "jingle/glue/utils.h"
|
| #include "net/base/net_errors.h"
|
| #include "remoting/base/constants.h"
|
| +#include "remoting/jingle_glue/jingle_info_request.h"
|
| #include "remoting/jingle_glue/network_settings.h"
|
| #include "remoting/protocol/channel_authenticator.h"
|
| -#include "remoting/protocol/transport_config.h"
|
| #include "third_party/libjingle/source/talk/base/network.h"
|
| #include "third_party/libjingle/source/talk/p2p/base/constants.h"
|
| #include "third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.h"
|
| @@ -40,13 +41,21 @@ const int kTcpSendBufferSize = kTcpReceiveBufferSize + 30 * 1024;
|
| const int kMaxReconnectAttempts = 2;
|
| const int kReconnectDelaySeconds = 15;
|
|
|
| -class LibjingleStreamTransport : public StreamTransport,
|
| - public sigslot::has_slots<> {
|
| +// Get fresh STUN/Relay configuration every hour.
|
| +const int kJingleInfoUpdatePeriodSeconds = 3600;
|
| +
|
| +class LibjingleStreamTransport
|
| + : public StreamTransport,
|
| + public base::SupportsWeakPtr<LibjingleStreamTransport>,
|
| + public sigslot::has_slots<> {
|
| public:
|
| LibjingleStreamTransport(cricket::PortAllocator* port_allocator,
|
| - bool incoming_only);
|
| + const NetworkSettings& network_settings);
|
| virtual ~LibjingleStreamTransport();
|
|
|
| + // Called by JingleTransportFactory when it has fresh Jingle info.
|
| + void OnCanStart();
|
| +
|
| // StreamTransport interface.
|
| virtual void Initialize(
|
| const std::string& name,
|
| @@ -59,6 +68,8 @@ class LibjingleStreamTransport : public StreamTransport,
|
| virtual bool is_connected() const OVERRIDE;
|
|
|
| private:
|
| + void DoStart();
|
| +
|
| // Signal handlers for cricket::TransportChannel.
|
| void OnRequestSignaling(cricket::TransportChannelImpl* channel);
|
| void OnCandidateReady(cricket::TransportChannelImpl* channel,
|
| @@ -86,7 +97,7 @@ class LibjingleStreamTransport : public StreamTransport,
|
| void NotifyConnectFailed();
|
|
|
| cricket::PortAllocator* port_allocator_;
|
| - bool incoming_only_;
|
| + NetworkSettings network_settings_;
|
|
|
| std::string name_;
|
| EventHandler* event_handler_;
|
| @@ -95,6 +106,9 @@ class LibjingleStreamTransport : public StreamTransport,
|
| std::string ice_username_fragment_;
|
| std::string ice_password_;
|
|
|
| + bool can_start_;
|
| +
|
| + std::list<cricket::Candidate> pending_candidates_;
|
| scoped_ptr<cricket::P2PTransportChannel> channel_;
|
| bool channel_was_writable_;
|
| int connect_attempts_left_;
|
| @@ -108,13 +122,14 @@ class LibjingleStreamTransport : public StreamTransport,
|
|
|
| LibjingleStreamTransport::LibjingleStreamTransport(
|
| cricket::PortAllocator* port_allocator,
|
| - bool incoming_only)
|
| + const NetworkSettings& network_settings)
|
| : port_allocator_(port_allocator),
|
| - incoming_only_(incoming_only),
|
| + network_settings_(network_settings),
|
| event_handler_(NULL),
|
| ice_username_fragment_(
|
| talk_base::CreateRandomString(cricket::ICE_UFRAG_LENGTH)),
|
| ice_password_(talk_base::CreateRandomString(cricket::ICE_PWD_LENGTH)),
|
| + can_start_(false),
|
| channel_was_writable_(false),
|
| connect_attempts_left_(kMaxReconnectAttempts) {
|
| }
|
| @@ -131,6 +146,22 @@ LibjingleStreamTransport::~LibjingleStreamTransport() {
|
| }
|
| }
|
|
|
| +void LibjingleStreamTransport::OnCanStart() {
|
| + DCHECK(CalledOnValidThread());
|
| +
|
| + DCHECK(!can_start_);
|
| + can_start_ = true;
|
| +
|
| + // If Connect() has been called then start connection.
|
| + if (!callback_.is_null())
|
| + DoStart();
|
| +
|
| + while (!pending_candidates_.empty()) {
|
| + channel_->OnCandidate(pending_candidates_.front());
|
| + pending_candidates_.pop_front();
|
| + }
|
| +}
|
| +
|
| void LibjingleStreamTransport::Initialize(
|
| const std::string& name,
|
| Transport::EventHandler* event_handler,
|
| @@ -151,9 +182,13 @@ void LibjingleStreamTransport::Initialize(
|
| void LibjingleStreamTransport::Connect(
|
| const StreamTransport::ConnectedCallback& callback) {
|
| DCHECK(CalledOnValidThread());
|
| -
|
| callback_ = callback;
|
|
|
| + if (can_start_)
|
| + DoStart();
|
| +}
|
| +
|
| +void LibjingleStreamTransport::DoStart() {
|
| DCHECK(!channel_.get());
|
|
|
| // Create P2PTransportChannel, attach signal handlers and connect it.
|
| @@ -169,7 +204,10 @@ void LibjingleStreamTransport::Connect(
|
| this, &LibjingleStreamTransport::OnRouteChange);
|
| channel_->SignalWritableState.connect(
|
| this, &LibjingleStreamTransport::OnWritableState);
|
| - channel_->set_incoming_only(incoming_only_);
|
| + if (network_settings_.nat_traversal_mode ==
|
| + NetworkSettings::NAT_TRAVERSAL_DISABLED) {
|
| + channel_->set_incoming_only(true);
|
| + }
|
|
|
| channel_->Connect();
|
|
|
| @@ -211,7 +249,11 @@ void LibjingleStreamTransport::Connect(
|
| void LibjingleStreamTransport::AddRemoteCandidate(
|
| const cricket::Candidate& candidate) {
|
| DCHECK(CalledOnValidThread());
|
| - channel_->OnCandidate(candidate);
|
| + if (channel_) {
|
| + channel_->OnCandidate(candidate);
|
| + } else {
|
| + pending_candidates_.push_back(candidate);
|
| + }
|
| }
|
|
|
| const std::string& LibjingleStreamTransport::name() const {
|
| @@ -362,10 +404,12 @@ void LibjingleStreamTransport::NotifyConnectFailed() {
|
| } // namespace
|
|
|
| LibjingleTransportFactory::LibjingleTransportFactory(
|
| + SignalStrategy* signal_strategy,
|
| scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator,
|
| - bool incoming_only)
|
| - : port_allocator_(port_allocator.Pass()),
|
| - incoming_only_(incoming_only) {
|
| + const NetworkSettings& network_settings)
|
| + : signal_strategy_(signal_strategy),
|
| + port_allocator_(port_allocator.Pass()),
|
| + network_settings_(network_settings) {
|
| jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
|
| }
|
|
|
| @@ -377,27 +421,27 @@ LibjingleTransportFactory::~LibjingleTransportFactory() {
|
| task_runner->DeleteSoon(FROM_HERE, port_allocator_.release());
|
| }
|
|
|
| -void LibjingleTransportFactory::SetTransportConfig(
|
| - const TransportConfig& config) {
|
| - std::vector<talk_base::SocketAddress> stun_hosts;
|
| - talk_base::SocketAddress stun_address;
|
| - if (stun_address.FromString(config.stun_server)) {
|
| - stun_hosts.push_back(stun_address);
|
| - port_allocator_->SetStunHosts(stun_hosts);
|
| - } else {
|
| - LOG(ERROR) << "Failed to parse stun server address: "
|
| - << config.stun_server;
|
| - }
|
| -
|
| - std::vector<std::string> relay_hosts;
|
| - relay_hosts.push_back(config.relay_server);
|
| - port_allocator_->SetRelayHosts(relay_hosts);
|
| - port_allocator_->SetRelayToken(config.relay_token);
|
| +void LibjingleTransportFactory::PrepareTokens() {
|
| + EnsureFreshJingleInfo();
|
| }
|
|
|
| scoped_ptr<StreamTransport> LibjingleTransportFactory::CreateStreamTransport() {
|
| - return scoped_ptr<StreamTransport>(
|
| - new LibjingleStreamTransport(port_allocator_.get(), incoming_only_));
|
| + scoped_ptr<LibjingleStreamTransport> result(
|
| + new LibjingleStreamTransport(port_allocator_.get(), network_settings_));
|
| +
|
| + EnsureFreshJingleInfo();
|
| +
|
| + // If there is a pending |jingle_info_request_| delay starting the new
|
| + // transport until the request is finished.
|
| + if (jingle_info_request_) {
|
| + on_jingle_info_callbacks_.push_back(
|
| + base::Bind(&LibjingleStreamTransport::OnCanStart,
|
| + result->AsWeakPtr()));
|
| + } else {
|
| + result->OnCanStart();
|
| + }
|
| +
|
| + return result.PassAs<StreamTransport>();
|
| }
|
|
|
| scoped_ptr<DatagramTransport>
|
| @@ -406,5 +450,42 @@ LibjingleTransportFactory::CreateDatagramTransport() {
|
| return scoped_ptr<DatagramTransport>();
|
| }
|
|
|
| +void LibjingleTransportFactory::EnsureFreshJingleInfo() {
|
| + if (network_settings_.nat_traversal_mode !=
|
| + NetworkSettings::NAT_TRAVERSAL_ENABLED ||
|
| + jingle_info_request_) {
|
| + return;
|
| + }
|
| +
|
| + if (base::TimeTicks::Now() - last_jingle_info_update_time_ >
|
| + base::TimeDelta::FromSeconds(kJingleInfoUpdatePeriodSeconds)) {
|
| + jingle_info_request_.reset(new JingleInfoRequest(signal_strategy_));
|
| + jingle_info_request_->Send(base::Bind(
|
| + &LibjingleTransportFactory::OnJingleInfo, base::Unretained(this)));
|
| + }
|
| +}
|
| +
|
| +void LibjingleTransportFactory::OnJingleInfo(
|
| + const std::string& relay_token,
|
| + const std::vector<std::string>& relay_hosts,
|
| + const std::vector<talk_base::SocketAddress>& stun_hosts) {
|
| + if (!relay_token.empty() && !relay_hosts.empty()) {
|
| + port_allocator_->SetRelayHosts(relay_hosts);
|
| + port_allocator_->SetRelayToken(relay_token);
|
| + }
|
| + if (!stun_hosts.empty()) {
|
| + port_allocator_->SetStunHosts(stun_hosts);
|
| + }
|
| +
|
| + jingle_info_request_.reset();
|
| + if ((!relay_token.empty() && !relay_hosts.empty()) || !stun_hosts.empty())
|
| + last_jingle_info_update_time_ = base::TimeTicks::Now();
|
| +
|
| + while (!on_jingle_info_callbacks_.empty()) {
|
| + on_jingle_info_callbacks_.begin()->Run();
|
| + on_jingle_info_callbacks_.pop_front();
|
| + }
|
| +}
|
| +
|
| } // namespace protocol
|
| } // namespace remoting
|
|
|