Index: remoting/host/it2me/it2me_impl.cc |
diff --git a/remoting/host/it2me/it2me_impl.cc b/remoting/host/it2me/it2me_impl.cc |
deleted file mode 100644 |
index 7b1b4c4565173453e4c9e680c03058804b1546af..0000000000000000000000000000000000000000 |
--- a/remoting/host/it2me/it2me_impl.cc |
+++ /dev/null |
@@ -1,468 +0,0 @@ |
-// Copyright 2013 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/host/it2me/it2me_impl.h" |
- |
-#include "base/bind.h" |
-#include "base/strings/string_util.h" |
-#include "base/synchronization/waitable_event.h" |
-#include "base/threading/platform_thread.h" |
-#include "net/socket/client_socket_factory.h" |
-#include "remoting/base/auto_thread.h" |
-#include "remoting/base/rsa_key_pair.h" |
-#include "remoting/host/chromoting_host.h" |
-#include "remoting/host/chromoting_host_context.h" |
-#include "remoting/host/host_event_logger.h" |
-#include "remoting/host/host_secret.h" |
-#include "remoting/host/it2me_desktop_environment.h" |
-#include "remoting/host/policy_hack/policy_watcher.h" |
-#include "remoting/host/register_support_host_request.h" |
-#include "remoting/host/session_manager_factory.h" |
-#include "remoting/jingle_glue/network_settings.h" |
-#include "remoting/protocol/it2me_host_authenticator_factory.h" |
- |
-namespace remoting { |
- |
-namespace { |
- |
-// This is used for tagging system event logs. |
-const char kApplicationName[] = "chromoting"; |
-const int kMaxLoginAttempts = 5; |
- |
-} // namespace |
- |
-It2MeImpl::It2MeImpl( |
- scoped_ptr<ChromotingHostContext> host_context, |
- scoped_refptr<base::SingleThreadTaskRunner> plugin_task_runner, |
- base::WeakPtr<It2MeImpl::Observer> observer, |
- const XmppSignalStrategy::XmppServerConfig& xmpp_server_config, |
- const std::string& directory_bot_jid) |
- : host_context_(host_context.Pass()), |
- plugin_task_runner_(plugin_task_runner), |
- observer_(observer), |
- xmpp_server_config_(xmpp_server_config), |
- directory_bot_jid_(directory_bot_jid), |
- state_(kDisconnected), |
- failed_login_attempts_(0), |
- nat_traversal_enabled_(false), |
- policy_received_(false) { |
- DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
-} |
- |
-void It2MeImpl::Connect() { |
- if (!host_context_->ui_task_runner()->BelongsToCurrentThread()) { |
- DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
- host_context_->ui_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Connect, this)); |
- return; |
- } |
- |
- desktop_environment_factory_.reset(new It2MeDesktopEnvironmentFactory( |
- host_context_->network_task_runner(), |
- host_context_->input_task_runner(), |
- host_context_->ui_task_runner())); |
- |
- // Start monitoring configured policies. |
- policy_watcher_.reset( |
- policy_hack::PolicyWatcher::Create(host_context_->network_task_runner())); |
- policy_watcher_->StartWatching( |
- base::Bind(&It2MeImpl::OnPolicyUpdate, this)); |
- |
- // Switch to the network thread to start the actual connection. |
- host_context_->network_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::ReadPolicyAndConnect, this)); |
-} |
- |
-void It2MeImpl::Disconnect() { |
- if (!host_context_->network_task_runner()->BelongsToCurrentThread()) { |
- DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
- host_context_->network_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Disconnect, this)); |
- return; |
- } |
- |
- switch (state_) { |
- case kDisconnected: |
- ShutdownOnNetworkThread(); |
- return; |
- |
- case kStarting: |
- SetState(kDisconnecting); |
- SetState(kDisconnected); |
- ShutdownOnNetworkThread(); |
- return; |
- |
- case kDisconnecting: |
- return; |
- |
- default: |
- SetState(kDisconnecting); |
- |
- if (!host_) { |
- SetState(kDisconnected); |
- ShutdownOnNetworkThread(); |
- return; |
- } |
- |
- // Deleting the host destroys SignalStrategy synchronously, but |
- // SignalStrategy::Listener handlers are not allowed to destroy |
- // SignalStrategy, so post task to destroy the host later. |
- host_context_->network_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnNetworkThread, this)); |
- return; |
- } |
-} |
- |
-void It2MeImpl::RequestNatPolicy() { |
- if (!host_context_->network_task_runner()->BelongsToCurrentThread()) { |
- DCHECK(plugin_task_runner_->BelongsToCurrentThread()); |
- host_context_->network_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::RequestNatPolicy, this)); |
- return; |
- } |
- |
- if (policy_received_) |
- UpdateNatPolicy(nat_traversal_enabled_); |
-} |
- |
-void It2MeImpl::ReadPolicyAndConnect() { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- SetState(kStarting); |
- |
- // Only proceed to FinishConnect() if at least one policy update has been |
- // received. |
- if (policy_received_) { |
- FinishConnect(); |
- } else { |
- // Otherwise, create the policy watcher, and thunk the connect. |
- pending_connect_ = |
- base::Bind(&It2MeImpl::FinishConnect, this); |
- } |
-} |
- |
-void It2MeImpl::FinishConnect() { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- if (state_ != kStarting) { |
- // Host has been stopped while we were fetching policy. |
- return; |
- } |
- |
- // Check the host domain policy. |
- if (!required_host_domain_.empty() && |
- !EndsWith(xmpp_server_config_.username, |
- std::string("@") + required_host_domain_, false)) { |
- SetState(kInvalidDomainError); |
- return; |
- } |
- |
- // Generate a key pair for the Host to use. |
- // TODO(wez): Move this to the worker thread. |
- host_key_pair_ = RsaKeyPair::Generate(); |
- |
- // Create XMPP connection. |
- scoped_ptr<SignalStrategy> signal_strategy( |
- new XmppSignalStrategy(net::ClientSocketFactory::GetDefaultFactory(), |
- host_context_->url_request_context_getter(), |
- xmpp_server_config_)); |
- |
- // Request registration of the host for support. |
- scoped_ptr<RegisterSupportHostRequest> register_request( |
- new RegisterSupportHostRequest( |
- signal_strategy.get(), host_key_pair_, directory_bot_jid_, |
- base::Bind(&It2MeImpl::OnReceivedSupportID, |
- base::Unretained(this)))); |
- |
- // Beyond this point nothing can fail, so save the config and request. |
- signal_strategy_ = signal_strategy.Pass(); |
- register_request_ = register_request.Pass(); |
- |
- // If NAT traversal is off then limit port range to allow firewall pin-holing. |
- LOG(INFO) << "NAT state: " << nat_traversal_enabled_; |
- NetworkSettings network_settings( |
- nat_traversal_enabled_ ? |
- NetworkSettings::NAT_TRAVERSAL_ENABLED : |
- NetworkSettings::NAT_TRAVERSAL_DISABLED); |
- if (!nat_traversal_enabled_) { |
- network_settings.min_port = NetworkSettings::kDefaultMinPort; |
- network_settings.max_port = NetworkSettings::kDefaultMaxPort; |
- } |
- |
- // Create the host. |
- host_.reset(new ChromotingHost( |
- signal_strategy_.get(), |
- desktop_environment_factory_.get(), |
- CreateHostSessionManager(network_settings, |
- host_context_->url_request_context_getter()), |
- host_context_->audio_task_runner(), |
- host_context_->input_task_runner(), |
- host_context_->video_capture_task_runner(), |
- host_context_->video_encode_task_runner(), |
- host_context_->network_task_runner(), |
- host_context_->ui_task_runner())); |
- host_->AddStatusObserver(this); |
- log_to_server_.reset( |
- new LogToServer(host_->AsWeakPtr(), ServerLogEntry::IT2ME, |
- signal_strategy_.get(), directory_bot_jid_)); |
- |
- // Disable audio by default. |
- // TODO(sergeyu): Add UI to enable it. |
- scoped_ptr<protocol::CandidateSessionConfig> protocol_config = |
- protocol::CandidateSessionConfig::CreateDefault(); |
- protocol::CandidateSessionConfig::DisableAudioChannel(protocol_config.get()); |
- |
- // VP9 encode is not yet supported. |
- protocol::CandidateSessionConfig::DisableVideoCodec( |
- protocol_config.get(), protocol::ChannelConfig::CODEC_VP9); |
- |
- host_->set_protocol_config(protocol_config.Pass()); |
- |
- // Create event logger. |
- host_event_logger_ = |
- HostEventLogger::Create(host_->AsWeakPtr(), kApplicationName); |
- |
- // Connect signaling and start the host. |
- signal_strategy_->Connect(); |
- host_->Start(xmpp_server_config_.username); |
- |
- SetState(kRequestedAccessCode); |
- return; |
-} |
- |
-void It2MeImpl::ShutdownOnNetworkThread() { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- DCHECK(state_ == kDisconnecting || state_ == kDisconnected); |
- |
- if (state_ == kDisconnecting) { |
- host_event_logger_.reset(); |
- host_->RemoveStatusObserver(this); |
- host_.reset(); |
- |
- register_request_.reset(); |
- log_to_server_.reset(); |
- signal_strategy_.reset(); |
- SetState(kDisconnected); |
- } |
- |
- host_context_->ui_task_runner()->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::ShutdownOnUiThread, this)); |
-} |
- |
-void It2MeImpl::ShutdownOnUiThread() { |
- DCHECK(host_context_->ui_task_runner()->BelongsToCurrentThread()); |
- |
- // Destroy the DesktopEnvironmentFactory, to free thread references. |
- desktop_environment_factory_.reset(); |
- |
- // Stop listening for policy updates. |
- if (policy_watcher_.get()) { |
- base::WaitableEvent policy_watcher_stopped_(true, false); |
- policy_watcher_->StopWatching(&policy_watcher_stopped_); |
- policy_watcher_stopped_.Wait(); |
- policy_watcher_.reset(); |
- } |
-} |
- |
-void It2MeImpl::OnAccessDenied(const std::string& jid) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- ++failed_login_attempts_; |
- if (failed_login_attempts_ == kMaxLoginAttempts) { |
- Disconnect(); |
- } |
-} |
- |
-void It2MeImpl::OnClientAuthenticated( |
- const std::string& jid) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- if (state_ == kDisconnecting) { |
- // Ignore the new connection if we are disconnecting. |
- return; |
- } |
- if (state_ == kConnected) { |
- // If we already connected another client then one of the connections may be |
- // an attacker, so both are suspect and we have to reject the second |
- // connection and shutdown the host. |
- host_->RejectAuthenticatingClient(); |
- Disconnect(); |
- return; |
- } |
- |
- std::string client_username = jid; |
- size_t pos = client_username.find('/'); |
- if (pos != std::string::npos) |
- client_username.replace(pos, std::string::npos, ""); |
- |
- LOG(INFO) << "Client " << client_username << " connected."; |
- |
- // Pass the client user name to the script object before changing state. |
- plugin_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnClientAuthenticated, |
- observer_, client_username)); |
- |
- SetState(kConnected); |
-} |
- |
-void It2MeImpl::OnClientDisconnected( |
- const std::string& jid) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- Disconnect(); |
-} |
- |
-void It2MeImpl::OnPolicyUpdate( |
- scoped_ptr<base::DictionaryValue> policies) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- bool nat_policy; |
- if (policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName, |
- &nat_policy)) { |
- UpdateNatPolicy(nat_policy); |
- } |
- std::string host_domain; |
- if (policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName, |
- &host_domain)) { |
- UpdateHostDomainPolicy(host_domain); |
- } |
- |
- policy_received_ = true; |
- |
- if (!pending_connect_.is_null()) { |
- pending_connect_.Run(); |
- pending_connect_.Reset(); |
- } |
-} |
- |
-void It2MeImpl::UpdateNatPolicy( |
- bool nat_traversal_enabled) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- VLOG(2) << "UpdateNatPolicy: " << nat_traversal_enabled; |
- |
- // When transitioning from enabled to disabled, force disconnect any |
- // existing session. |
- if (nat_traversal_enabled_ && !nat_traversal_enabled && IsConnected()) { |
- Disconnect(); |
- } |
- |
- nat_traversal_enabled_ = nat_traversal_enabled; |
- |
- // Notify the web-app of the policy setting. |
- plugin_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnNatPolicyChanged, |
- observer_, nat_traversal_enabled_)); |
-} |
- |
-void It2MeImpl::UpdateHostDomainPolicy( |
- const std::string& host_domain) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- VLOG(2) << "UpdateHostDomainPolicy: " << host_domain; |
- |
- // When setting a host domain policy, force disconnect any existing session. |
- if (!host_domain.empty() && IsConnected()) { |
- Disconnect(); |
- } |
- |
- required_host_domain_ = host_domain; |
-} |
- |
-It2MeImpl::~It2MeImpl() { |
- // Check that resources that need to be torn down on the UI thread are gone. |
- DCHECK(!desktop_environment_factory_.get()); |
- DCHECK(!policy_watcher_.get()); |
-} |
- |
-void It2MeImpl::SetState(It2MeHostState state) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- switch (state_) { |
- case kDisconnected: |
- DCHECK(state == kStarting || |
- state == kError) << state; |
- break; |
- case kStarting: |
- DCHECK(state == kRequestedAccessCode || |
- state == kDisconnecting || |
- state == kError || |
- state == kInvalidDomainError) << state; |
- break; |
- case kRequestedAccessCode: |
- DCHECK(state == kReceivedAccessCode || |
- state == kDisconnecting || |
- state == kError) << state; |
- break; |
- case kReceivedAccessCode: |
- DCHECK(state == kConnected || |
- state == kDisconnecting || |
- state == kError) << state; |
- break; |
- case kConnected: |
- DCHECK(state == kDisconnecting || |
- state == kDisconnected || |
- state == kError) << state; |
- break; |
- case kDisconnecting: |
- DCHECK(state == kDisconnected) << state; |
- break; |
- case kError: |
- DCHECK(state == kDisconnecting) << state; |
- break; |
- case kInvalidDomainError: |
- DCHECK(state == kDisconnecting) << state; |
- break; |
- }; |
- |
- state_ = state; |
- |
- // Post a state-change notification to the web-app. |
- plugin_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStateChanged, |
- observer_, state)); |
-} |
- |
-bool It2MeImpl::IsConnected() const { |
- return state_ == kRequestedAccessCode || state_ == kReceivedAccessCode || |
- state_ == kConnected; |
-} |
- |
-void It2MeImpl::OnReceivedSupportID( |
- bool success, |
- const std::string& support_id, |
- const base::TimeDelta& lifetime) { |
- DCHECK(host_context_->network_task_runner()->BelongsToCurrentThread()); |
- |
- if (!success) { |
- SetState(kError); |
- Disconnect(); |
- return; |
- } |
- |
- std::string host_secret = GenerateSupportHostSecret(); |
- std::string access_code = support_id + host_secret; |
- |
- std::string local_certificate = host_key_pair_->GenerateCertificate(); |
- if (local_certificate.empty()) { |
- LOG(ERROR) << "Failed to generate host certificate."; |
- SetState(kError); |
- Disconnect(); |
- return; |
- } |
- |
- scoped_ptr<protocol::AuthenticatorFactory> factory( |
- new protocol::It2MeHostAuthenticatorFactory( |
- local_certificate, host_key_pair_, access_code)); |
- host_->SetAuthenticatorFactory(factory.Pass()); |
- |
- // Pass the Access Code to the script object before changing state. |
- plugin_task_runner_->PostTask( |
- FROM_HERE, base::Bind(&It2MeImpl::Observer::OnStoreAccessCode, |
- observer_, access_code, lifetime)); |
- |
- SetState(kReceivedAccessCode); |
-} |
- |
-} // namespace remoting |