diff options
-rw-r--r-- | remoting/client/jni/chromoting_jni_instance.cc | 4 | ||||
-rw-r--r-- | remoting/client/plugin/chromoting_instance.cc | 4 | ||||
-rw-r--r-- | remoting/host/it2me/it2me_host.cc | 2 | ||||
-rw-r--r-- | remoting/host/remoting_me2me_host.cc | 2 | ||||
-rw-r--r-- | remoting/host/session_manager_factory.cc | 15 | ||||
-rw-r--r-- | remoting/host/session_manager_factory.h | 4 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_info_request.cc | 30 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_info_request.h | 18 | ||||
-rw-r--r-- | remoting/protocol/connection_to_host.cc | 3 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_manager.cc | 51 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_manager.h | 13 | ||||
-rw-r--r-- | remoting/protocol/jingle_session_unittest.cc | 12 | ||||
-rw-r--r-- | remoting/protocol/libjingle_transport_factory.cc | 143 | ||||
-rw-r--r-- | remoting/protocol/libjingle_transport_factory.h | 35 | ||||
-rw-r--r-- | remoting/protocol/session_manager.h | 1 | ||||
-rw-r--r-- | remoting/protocol/transport.h | 8 | ||||
-rw-r--r-- | remoting/protocol/transport_config.cc | 17 | ||||
-rw-r--r-- | remoting/protocol/transport_config.h | 25 | ||||
-rw-r--r-- | remoting/remoting.gyp | 2 |
19 files changed, 210 insertions, 179 deletions
diff --git a/remoting/client/jni/chromoting_jni_instance.cc b/remoting/client/jni/chromoting_jni_instance.cc index 339cea8..641fcd8 100644 --- a/remoting/client/jni/chromoting_jni_instance.cc +++ b/remoting/client/jni/chromoting_jni_instance.cc @@ -309,7 +309,9 @@ void ChromotingJniInstance::ConnectToHostOnNetworkThread() { scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( - port_allocator.PassAs<cricket::HttpPortAllocatorBase>(), false)); + signaling_.get(), + port_allocator.PassAs<cricket::HttpPortAllocatorBase>(), + network_settings)); client_->Start(signaling_.get(), transport_factory.Pass()); } diff --git a/remoting/client/plugin/chromoting_instance.cc b/remoting/client/plugin/chromoting_instance.cc index ba69267..46e30f5 100644 --- a/remoting/client/plugin/chromoting_instance.cc +++ b/remoting/client/plugin/chromoting_instance.cc @@ -658,7 +658,9 @@ void ChromotingInstance::ConnectWithConfig(const ClientConfig& config, scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator( PepperPortAllocator::Create(this)); scoped_ptr<protocol::TransportFactory> transport_factory( - new protocol::LibjingleTransportFactory(port_allocator.Pass(), false)); + new protocol::LibjingleTransportFactory( + signal_strategy_.get(), port_allocator.Pass(), + NetworkSettings(NetworkSettings::NAT_TRAVERSAL_ENABLED))); // Kick off the connection. client_->Start(signal_strategy_.get(), transport_factory.Pass()); diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index 9aa88fe..fec201f 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc @@ -195,7 +195,7 @@ void It2MeHost::FinishConnect() { host_.reset(new ChromotingHost( signal_strategy_.get(), desktop_environment_factory_.get(), - CreateHostSessionManager(network_settings, + CreateHostSessionManager(signal_strategy_.get(), network_settings, host_context_->url_request_context_getter()), host_context_->audio_task_runner(), host_context_->input_task_runner(), diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index bc7e8a7..7a0faba 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc @@ -998,7 +998,7 @@ void HostProcess::StartHost() { host_.reset(new ChromotingHost( signal_strategy_.get(), desktop_environment_factory_.get(), - CreateHostSessionManager(network_settings, + CreateHostSessionManager(signal_strategy_.get(), network_settings, context_->url_request_context_getter()), context_->audio_task_runner(), context_->input_task_runner(), diff --git a/remoting/host/session_manager_factory.cc b/remoting/host/session_manager_factory.cc index cd5befc..a055df2 100644 --- a/remoting/host/session_manager_factory.cc +++ b/remoting/host/session_manager_factory.cc @@ -14,6 +14,7 @@ namespace remoting { scoped_ptr<protocol::SessionManager> CreateHostSessionManager( + SignalStrategy* signal_strategy, const NetworkSettings& network_settings, const scoped_refptr<net::URLRequestContextGetter>& url_request_context_getter) { @@ -22,22 +23,14 @@ scoped_ptr<protocol::SessionManager> CreateHostSessionManager( ChromiumPortAllocator::Create(url_request_context_getter, network_settings)); - bool incoming_only = network_settings.nat_traversal_mode == - NetworkSettings::NAT_TRAVERSAL_DISABLED; - scoped_ptr<protocol::TransportFactory> transport_factory( new protocol::LibjingleTransportFactory( + signal_strategy, port_allocator.PassAs<cricket::HttpPortAllocatorBase>(), - incoming_only)); - - // Use the Jingle protocol for channel-negotiation signalling between - // peer TransportFactories. - bool fetch_stun_relay_info = network_settings.nat_traversal_mode == - NetworkSettings::NAT_TRAVERSAL_ENABLED; + network_settings)); scoped_ptr<protocol::JingleSessionManager> session_manager( - new protocol::JingleSessionManager( - transport_factory.Pass(), fetch_stun_relay_info)); + new protocol::JingleSessionManager(transport_factory.Pass())); return session_manager.PassAs<protocol::SessionManager>(); } diff --git a/remoting/host/session_manager_factory.h b/remoting/host/session_manager_factory.h index 2c0a1b6..ce2a53d 100644 --- a/remoting/host/session_manager_factory.h +++ b/remoting/host/session_manager_factory.h @@ -15,12 +15,14 @@ class URLRequestContextGetter; namespace remoting { struct NetworkSettings; +class SignalStrategy; namespace protocol { - class SessionManager; +class SessionManager; } // namespace protocol scoped_ptr<protocol::SessionManager> CreateHostSessionManager( + SignalStrategy* signal_strategy, const NetworkSettings& network_settings, const scoped_refptr<net::URLRequestContextGetter>& url_request_context_getter); diff --git a/remoting/jingle_glue/jingle_info_request.cc b/remoting/jingle_glue/jingle_info_request.cc index e75b89f..d41f18a 100644 --- a/remoting/jingle_glue/jingle_info_request.cc +++ b/remoting/jingle_glue/jingle_info_request.cc @@ -8,6 +8,7 @@ #include "base/message_loop/message_loop.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" +#include "base/time/time.h" #include "net/base/net_util.h" #include "remoting/jingle_glue/iq_sender.h" #include "third_party/libjingle/source/talk/base/socketaddress.h" @@ -16,12 +17,13 @@ namespace remoting { +const int kRequestTimeoutSeconds = 5; + JingleInfoRequest::JingleInfoRequest(SignalStrategy* signal_strategy) : iq_sender_(signal_strategy) { } -JingleInfoRequest::~JingleInfoRequest() { -} +JingleInfoRequest::~JingleInfoRequest() {} void JingleInfoRequest::Send(const OnJingleInfoCallback& callback) { on_jingle_info_cb_ = callback; @@ -30,19 +32,39 @@ void JingleInfoRequest::Send(const OnJingleInfoCallback& callback) { request_ = iq_sender_.SendIq( buzz::STR_GET, buzz::STR_EMPTY, iq_body.Pass(), base::Bind(&JingleInfoRequest::OnResponse, base::Unretained(this))); + if (!request_) { + // If we failed to send IqRequest it means that SignalStrategy is + // disconnected. Notify the caller. + std::vector<talk_base::SocketAddress> stun_hosts; + std::vector<std::string> relay_hosts; + std::string relay_token; + on_jingle_info_cb_.Run(relay_token, relay_hosts, stun_hosts); + return; + } + request_->SetTimeout(base::TimeDelta::FromSeconds(kRequestTimeoutSeconds)); } void JingleInfoRequest::OnResponse(IqRequest* request, const buzz::XmlElement* stanza) { + std::vector<talk_base::SocketAddress> stun_hosts; + std::vector<std::string> relay_hosts; + std::string relay_token; + + if (!stanza) { + LOG(WARNING) << "Jingle info request has timed out."; + on_jingle_info_cb_.Run(relay_token, relay_hosts, stun_hosts); + return; + } + const buzz::XmlElement* query = stanza->FirstNamed(buzz::QN_JINGLE_INFO_QUERY); if (query == NULL) { LOG(WARNING) << "No Jingle info found in Jingle Info query response." << stanza->Str(); + on_jingle_info_cb_.Run(relay_token, relay_hosts, stun_hosts); return; } - std::vector<talk_base::SocketAddress> stun_hosts; const buzz::XmlElement* stun = query->FirstNamed(buzz::QN_JINGLE_INFO_STUN); if (stun) { for (const buzz::XmlElement* server = @@ -63,8 +85,6 @@ void JingleInfoRequest::OnResponse(IqRequest* request, } } - std::vector<std::string> relay_hosts; - std::string relay_token; const buzz::XmlElement* relay = query->FirstNamed(buzz::QN_JINGLE_INFO_RELAY); if (relay) { relay_token = relay->TextNamed(buzz::QN_JINGLE_INFO_TOKEN); diff --git a/remoting/jingle_glue/jingle_info_request.h b/remoting/jingle_glue/jingle_info_request.h index a1b10de..118aa4a 100644 --- a/remoting/jingle_glue/jingle_info_request.h +++ b/remoting/jingle_glue/jingle_info_request.h @@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/memory/scoped_ptr.h" #include "remoting/jingle_glue/iq_sender.h" -#include "third_party/libjingle/source/talk/base/sigslot.h" namespace buzz { class XmlElement; @@ -34,17 +33,14 @@ class SignalStrategy; // // This class is not threadsafe and should be used on the same thread it is // created on. -// -// TODO(ajwong): Add support for a timeout. -class JingleInfoRequest : public sigslot::has_slots<> { +class JingleInfoRequest { public: - // Callback to receive the Jingle configuration settings. The arguments are - // passed by pointer so the receive may call swap on them. The receiver does - // NOT own the arguments, which are guaranteed only to be alive for the - // duration of the callback. - typedef base::Callback<void ( - const std::string&, const std::vector<std::string>&, - const std::vector<talk_base::SocketAddress>&)> OnJingleInfoCallback; + // Callback to receive the Jingle configuration settings. All fields are empty + // if the request has timed out. + typedef base::Callback<void(const std::string& relay_token, + const std::vector<std::string>& relay_servers, + const std::vector<talk_base::SocketAddress>& + stun_servers)> OnJingleInfoCallback; explicit JingleInfoRequest(SignalStrategy* signal_strategy); virtual ~JingleInfoRequest(); diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index bcd77e5..e35ba22 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -92,8 +92,7 @@ void ConnectionToHost::Connect(SignalStrategy* signal_strategy, signal_strategy_->AddListener(this); signal_strategy_->Connect(); - session_manager_.reset(new JingleSessionManager( - transport_factory.Pass(), allow_nat_traversal_)); + session_manager_.reset(new JingleSessionManager(transport_factory.Pass())); session_manager_->Init(signal_strategy_, this); SetState(CONNECTING, OK); diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc index 7cb1586..58bcd4d 100644 --- a/remoting/protocol/jingle_session_manager.cc +++ b/remoting/protocol/jingle_session_manager.cc @@ -6,14 +6,12 @@ #include "base/bind.h" #include "remoting/jingle_glue/iq_sender.h" -#include "remoting/jingle_glue/jingle_info_request.h" #include "remoting/jingle_glue/signal_strategy.h" #include "remoting/protocol/authenticator.h" #include "remoting/protocol/content_description.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/transport.h" -#include "remoting/protocol/transport_config.h" #include "third_party/libjingle/source/talk/base/socketaddress.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" @@ -23,10 +21,8 @@ namespace remoting { namespace protocol { JingleSessionManager::JingleSessionManager( - scoped_ptr<TransportFactory> transport_factory, - bool fetch_stun_relay_config) + scoped_ptr<TransportFactory> transport_factory) : transport_factory_(transport_factory.Pass()), - fetch_stun_relay_config_(fetch_stun_relay_config), signal_strategy_(NULL), listener_(NULL), ready_(false) { @@ -48,35 +44,13 @@ void JingleSessionManager::Init( OnSignalStrategyStateChange(signal_strategy_->GetState()); } -void JingleSessionManager::OnJingleInfo( - const std::string& relay_token, - const std::vector<std::string>& relay_hosts, - const std::vector<talk_base::SocketAddress>& stun_hosts) { - DCHECK(CalledOnValidThread()); - - // TODO(sergeyu): Add support for multiple STUN/relay servers when - // it's implemented in libjingle and P2P Transport API. - TransportConfig config; - config.stun_server = stun_hosts[0].ToString(); - config.relay_server = relay_hosts[0]; - config.relay_token = relay_token; - transport_factory_->SetTransportConfig(config); - - VLOG(1) << "STUN server: " << config.stun_server - << " Relay server: " << config.relay_server - << " Relay token: " << config.relay_token; - - - if (!ready_) { - ready_ = true; - listener_->OnSessionManagerReady(); - } -} - scoped_ptr<Session> JingleSessionManager::Connect( const std::string& host_jid, scoped_ptr<Authenticator> authenticator, scoped_ptr<CandidateSessionConfig> config) { + // Notify |transport_factory_| that it may be used soon. + transport_factory_->PrepareTokens(); + scoped_ptr<JingleSession> session(new JingleSession(this)); session->StartConnection(host_jid, authenticator.Pass(), config.Pass()); sessions_[session->session_id_] = session.get(); @@ -90,7 +64,6 @@ void JingleSessionManager::Close() { DCHECK(sessions_.empty()); listener_ = NULL; - jingle_info_request_.reset(); if (signal_strategy_) { signal_strategy_->RemoveListener(this); @@ -106,16 +79,9 @@ void JingleSessionManager::set_authenticator_factory( void JingleSessionManager::OnSignalStrategyStateChange( SignalStrategy::State state) { - if (state == SignalStrategy::CONNECTED) { - // Request STUN/Relay info if necessary. - if (fetch_stun_relay_config_) { - jingle_info_request_.reset(new JingleInfoRequest(signal_strategy_)); - jingle_info_request_->Send(base::Bind(&JingleSessionManager::OnJingleInfo, - base::Unretained(this))); - } else if (!ready_) { - ready_ = true; - listener_->OnSessionManagerReady(); - } + if (state == SignalStrategy::CONNECTED && !ready_) { + ready_ = true; + listener_->OnSessionManagerReady(); } } @@ -137,6 +103,9 @@ bool JingleSessionManager::OnSignalStrategyIncomingStanza( SendReply(stanza, JingleMessageReply::NONE); + // Notify |transport_factory_| that it may be used soon. + transport_factory_->PrepareTokens(); + scoped_ptr<Authenticator> authenticator = authenticator_factory_->CreateAuthenticator( signal_strategy_->GetLocalJid(), message.from, diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h index 7130f3f..e808ad2 100644 --- a/remoting/protocol/jingle_session_manager.h +++ b/remoting/protocol/jingle_session_manager.h @@ -30,7 +30,6 @@ class SocketAddress; namespace remoting { class IqSender; -class JingleInfoRequest; namespace protocol { @@ -44,15 +43,7 @@ class TransportFactory; class JingleSessionManager : public SessionManager, public SignalStrategy::Listener { public: - // When |fetch_stun_relay_config| is set to true then - // JingleSessionManager will also try to query configuration of STUN - // and Relay servers from the signaling server. - // - // TODO(sergeyu): Move NAT-traversal config fetching to a separate - // class. - explicit JingleSessionManager( - scoped_ptr<TransportFactory> transport_factory, - bool fetch_stun_relay_config); + explicit JingleSessionManager(scoped_ptr<TransportFactory> transport_factory); virtual ~JingleSessionManager(); // SessionManager interface. @@ -99,8 +90,6 @@ class JingleSessionManager : public SessionManager, bool ready_; - scoped_ptr<JingleInfoRequest> jingle_info_request_; - SessionsMap sessions_; DISALLOW_COPY_AND_ASSIGN(JingleSessionManager); diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index 34e09d6..62e4d40 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc @@ -141,13 +141,14 @@ class JingleSessionTest : public testing::Test { EXPECT_CALL(host_server_listener_, OnSessionManagerReady()) .Times(1); - NetworkSettings network_settings; + NetworkSettings network_settings(NetworkSettings::NAT_TRAVERSAL_OUTGOING); scoped_ptr<TransportFactory> host_transport(new LibjingleTransportFactory( + NULL, ChromiumPortAllocator::Create(NULL, network_settings) .PassAs<cricket::HttpPortAllocatorBase>(), - false)); - host_server_.reset(new JingleSessionManager(host_transport.Pass(), false)); + network_settings)); + host_server_.reset(new JingleSessionManager(host_transport.Pass())); host_server_->Init(host_signal_strategy_.get(), &host_server_listener_); scoped_ptr<AuthenticatorFactory> factory( @@ -157,11 +158,12 @@ class JingleSessionTest : public testing::Test { EXPECT_CALL(client_server_listener_, OnSessionManagerReady()) .Times(1); scoped_ptr<TransportFactory> client_transport(new LibjingleTransportFactory( + NULL, ChromiumPortAllocator::Create(NULL, network_settings) .PassAs<cricket::HttpPortAllocatorBase>(), - false)); + network_settings)); client_server_.reset( - new JingleSessionManager(client_transport.Pass(), false)); + new JingleSessionManager(client_transport.Pass())); client_server_->Init(client_signal_strategy_.get(), &client_server_listener_); } diff --git a/remoting/protocol/libjingle_transport_factory.cc b/remoting/protocol/libjingle_transport_factory.cc index 76c3507..ef22f2a 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 diff --git a/remoting/protocol/libjingle_transport_factory.h b/remoting/protocol/libjingle_transport_factory.h index dfa0ab1..637410c 100644 --- a/remoting/protocol/libjingle_transport_factory.h +++ b/remoting/protocol/libjingle_transport_factory.h @@ -5,6 +5,10 @@ #ifndef REMOTING_PROTOCOL_LIBJINGLE_TRANSPORT_FACTORY_H_ #define REMOTING_PROTOCOL_LIBJINGLE_TRANSPORT_FACTORY_H_ +#include <list> + +#include "base/callback_forward.h" +#include "remoting/jingle_glue/network_settings.h" #include "remoting/protocol/transport.h" namespace cricket { @@ -19,34 +23,49 @@ class URLRequestContextGetter; namespace talk_base { class NetworkManager; class PacketSocketFactory; +class SocketAddress; } // namespace talk_base namespace remoting { -struct NetworkSettings; +class SignalStrategy; +class JingleInfoRequest; namespace protocol { class LibjingleTransportFactory : public TransportFactory { public: - // Need to use cricket::HttpPortAllocatorBase pointer for the - // |port_allocator|, so that it is possible to configure - // |port_allocator| with STUN/Relay addresses. - // TODO(sergeyu): Reconsider this design. + // |signal_strategy| must outlive LibjingleTransportFactory. Need to use + // cricket::HttpPortAllocatorBase pointer for the |port_allocator|, so that it + // is possible to configure |port_allocator| with STUN/Relay addresses. LibjingleTransportFactory( + SignalStrategy* signal_strategy, scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator, - bool incoming_only); + const NetworkSettings& network_settings); virtual ~LibjingleTransportFactory(); // TransportFactory interface. - virtual void SetTransportConfig(const TransportConfig& config) OVERRIDE; + virtual void PrepareTokens() OVERRIDE; virtual scoped_ptr<StreamTransport> CreateStreamTransport() OVERRIDE; virtual scoped_ptr<DatagramTransport> CreateDatagramTransport() OVERRIDE; private: + void EnsureFreshJingleInfo(); + void OnJingleInfo(const std::string& relay_token, + const std::vector<std::string>& relay_hosts, + const std::vector<talk_base::SocketAddress>& stun_hosts); + + SignalStrategy* signal_strategy_; scoped_ptr<cricket::HttpPortAllocatorBase> port_allocator_; - bool incoming_only_; + NetworkSettings network_settings_; + + base::TimeTicks last_jingle_info_update_time_; + scoped_ptr<JingleInfoRequest> jingle_info_request_; + + // When there is an active |jingle_info_request_| stores list of callbacks to + // be called once the |jingle_info_request_| is finished. + std::list<base::Closure> on_jingle_info_callbacks_; DISALLOW_COPY_AND_ASSIGN(LibjingleTransportFactory); }; diff --git a/remoting/protocol/session_manager.h b/remoting/protocol/session_manager.h index 37b9599..8ac484d 100644 --- a/remoting/protocol/session_manager.h +++ b/remoting/protocol/session_manager.h @@ -59,7 +59,6 @@ #include "base/memory/ref_counted.h" #include "base/threading/non_thread_safe.h" #include "remoting/protocol/session.h" -#include "remoting/protocol/transport_config.h" namespace remoting { diff --git a/remoting/protocol/transport.h b/remoting/protocol/transport.h index fe2f4e1..196b9d2 100644 --- a/remoting/protocol/transport.h +++ b/remoting/protocol/transport.h @@ -43,7 +43,6 @@ namespace remoting { namespace protocol { class ChannelAuthenticator; -struct TransportConfig; struct TransportRoute { enum RouteType { @@ -151,8 +150,11 @@ class TransportFactory { TransportFactory() { } virtual ~TransportFactory() { } - // Sets configuration for the transports created by this factory. - virtual void SetTransportConfig(const TransportConfig& config) = 0; + // Called to notify transport factory that a new transport might be created + // soon, e.g. when a new session is being created. Implementation may use it + // to start asynchronous preparation, e.g. fetch a new relay token if + // necessary while the session is being authenticated. + virtual void PrepareTokens() = 0; virtual scoped_ptr<StreamTransport> CreateStreamTransport() = 0; virtual scoped_ptr<DatagramTransport> CreateDatagramTransport() = 0; diff --git a/remoting/protocol/transport_config.cc b/remoting/protocol/transport_config.cc deleted file mode 100644 index 093e1b1..0000000 --- a/remoting/protocol/transport_config.cc +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/protocol/transport_config.h" - -namespace remoting { -namespace protocol { - -TransportConfig::TransportConfig() { -} - -TransportConfig::~TransportConfig() { -} - -} // namespace protocol -} // namespace remoting diff --git a/remoting/protocol/transport_config.h b/remoting/protocol/transport_config.h deleted file mode 100644 index d996bd5..0000000 --- a/remoting/protocol/transport_config.h +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_PROTOCOL_TRANSPORT_CONFIG_H_ -#define REMOTING_PROTOCOL_TRANSPORT_CONFIG_H_ - -#include <string> - -namespace remoting { -namespace protocol { - -struct TransportConfig { - TransportConfig(); - ~TransportConfig(); - - std::string stun_server; - std::string relay_server; - std::string relay_token; -}; - -} // namespace protocol -} // namespace remoting - -#endif // REMOTING_PROTOCOL_TRANSPORT_CONFIG_H_ diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index c4f6fde..ed93d2b 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -2767,8 +2767,6 @@ 'protocol/ssl_hmac_channel_authenticator.h', 'protocol/transport.cc', 'protocol/transport.h', - 'protocol/transport_config.cc', - 'protocol/transport_config.h', 'protocol/util.cc', 'protocol/util.h', 'protocol/third_party_authenticator_base.cc', |