Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / remoting / host / chromoting_host.cc
blobb2bd1f98745b8eaeaea4bdf2e5349d6fbe5f5ed7
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/host/chromoting_host.h"
7 #include <algorithm>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "build/build_config.h"
13 #include "jingle/glue/thread_wrapper.h"
14 #include "remoting/base/constants.h"
15 #include "remoting/base/logging.h"
16 #include "remoting/host/chromoting_host_context.h"
17 #include "remoting/host/desktop_environment.h"
18 #include "remoting/host/host_config.h"
19 #include "remoting/host/input_injector.h"
20 #include "remoting/host/video_frame_recorder.h"
21 #include "remoting/protocol/connection_to_client.h"
22 #include "remoting/protocol/client_stub.h"
23 #include "remoting/protocol/host_stub.h"
24 #include "remoting/protocol/input_stub.h"
26 using remoting::protocol::ConnectionToClient;
27 using remoting::protocol::InputStub;
29 namespace remoting {
31 namespace {
33 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
34 // Number of initial errors (in sequence) to ignore before applying
35 // exponential back-off rules.
38 // Initial delay for exponential back-off in ms.
39 2000,
41 // Factor by which the waiting time will be multiplied.
44 // Fuzzing percentage. ex: 10% will spread requests randomly
45 // between 90%-100% of the calculated time.
48 // Maximum amount of time we are willing to delay our request in ms.
49 -1,
51 // Time to keep an entry from being discarded even when it
52 // has no significant state, -1 to never discard.
53 -1,
55 // Don't use initial delay unless the last request was an error.
56 false,
59 } // namespace
61 ChromotingHost::ChromotingHost(
62 SignalStrategy* signal_strategy,
63 DesktopEnvironmentFactory* desktop_environment_factory,
64 scoped_ptr<protocol::SessionManager> session_manager,
65 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
66 scoped_refptr<base::SingleThreadTaskRunner> input_task_runner,
67 scoped_refptr<base::SingleThreadTaskRunner> video_capture_task_runner,
68 scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
69 scoped_refptr<base::SingleThreadTaskRunner> network_task_runner,
70 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
71 : desktop_environment_factory_(desktop_environment_factory),
72 session_manager_(session_manager.Pass()),
73 audio_task_runner_(audio_task_runner),
74 input_task_runner_(input_task_runner),
75 video_capture_task_runner_(video_capture_task_runner),
76 video_encode_task_runner_(video_encode_task_runner),
77 network_task_runner_(network_task_runner),
78 ui_task_runner_(ui_task_runner),
79 signal_strategy_(signal_strategy),
80 started_(false),
81 login_backoff_(&kDefaultBackoffPolicy),
82 authenticating_client_(false),
83 reject_authenticating_client_(false),
84 enable_curtaining_(false),
85 weak_factory_(this) {
86 DCHECK(network_task_runner_->BelongsToCurrentThread());
87 DCHECK(signal_strategy);
89 jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
92 ChromotingHost::~ChromotingHost() {
93 DCHECK(CalledOnValidThread());
95 // Disconnect all of the clients.
96 while (!clients_.empty()) {
97 clients_.front()->DisconnectSession();
100 // Destroy the session manager to make sure that |signal_strategy_| does not
101 // have any listeners registered.
102 session_manager_.reset();
104 // Notify observers.
105 if (started_)
106 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnShutdown());
109 void ChromotingHost::Start(const std::string& host_owner_email) {
110 DCHECK(CalledOnValidThread());
111 DCHECK(!started_);
113 HOST_LOG << "Starting host";
114 started_ = true;
115 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
116 OnStart(host_owner_email));
118 // Start the SessionManager, supplying this ChromotingHost as the listener.
119 session_manager_->Init(signal_strategy_, this);
122 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
123 DCHECK(CalledOnValidThread());
124 status_observers_.AddObserver(observer);
127 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) {
128 DCHECK(CalledOnValidThread());
129 status_observers_.RemoveObserver(observer);
132 void ChromotingHost::AddExtension(scoped_ptr<HostExtension> extension) {
133 extensions_.push_back(extension.release());
136 void ChromotingHost::RejectAuthenticatingClient() {
137 DCHECK(authenticating_client_);
138 reject_authenticating_client_ = true;
141 void ChromotingHost::SetAuthenticatorFactory(
142 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) {
143 DCHECK(CalledOnValidThread());
144 session_manager_->set_authenticator_factory(authenticator_factory.Pass());
147 void ChromotingHost::SetEnableCurtaining(bool enable) {
148 DCHECK(network_task_runner_->BelongsToCurrentThread());
150 if (enable_curtaining_ == enable)
151 return;
153 enable_curtaining_ = enable;
154 desktop_environment_factory_->SetEnableCurtaining(enable_curtaining_);
156 // Disconnect all existing clients because they might be running not
157 // curtained.
158 // TODO(alexeypa): fix this such that the curtain is applied to the not
159 // curtained sessions or disconnect only the client connected to not
160 // curtained sessions.
161 if (enable_curtaining_)
162 DisconnectAllClients();
165 void ChromotingHost::SetMaximumSessionDuration(
166 const base::TimeDelta& max_session_duration) {
167 max_session_duration_ = max_session_duration;
170 ////////////////////////////////////////////////////////////////////////////
171 // protocol::ClientSession::EventHandler implementation.
172 void ChromotingHost::OnSessionAuthenticating(ClientSession* client) {
173 // We treat each incoming connection as a failure to authenticate,
174 // and clear the backoff when a connection successfully
175 // authenticates. This allows the backoff to protect from parallel
176 // connection attempts as well as sequential ones.
177 if (login_backoff_.ShouldRejectRequest()) {
178 LOG(WARNING) << "Disconnecting client " << client->client_jid() << " due to"
179 " an overload of failed login attempts.";
180 client->DisconnectSession();
181 return;
183 login_backoff_.InformOfRequest(false);
186 bool ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
187 DCHECK(CalledOnValidThread());
189 login_backoff_.Reset();
191 // Disconnect all other clients. |it| should be advanced before Disconnect()
192 // is called to avoid it becoming invalid when the client is removed from
193 // the list.
194 ClientList::iterator it = clients_.begin();
195 while (it != clients_.end()) {
196 ClientSession* other_client = *it++;
197 if (other_client != client)
198 other_client->DisconnectSession();
201 // Disconnects above must have destroyed all other clients.
202 DCHECK_EQ(clients_.size(), 1U);
204 // Notify observers that there is at least one authenticated client.
205 const std::string& jid = client->client_jid();
207 reject_authenticating_client_ = false;
209 authenticating_client_ = true;
210 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
211 OnClientAuthenticated(jid));
212 authenticating_client_ = false;
214 return !reject_authenticating_client_;
217 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) {
218 DCHECK(CalledOnValidThread());
220 // Notify observers.
221 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
222 OnClientConnected(client->client_jid()));
225 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) {
226 DCHECK(CalledOnValidThread());
228 // Notify observers.
229 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
230 OnAccessDenied(client->client_jid()));
233 void ChromotingHost::OnSessionClosed(ClientSession* client) {
234 DCHECK(CalledOnValidThread());
236 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client);
237 CHECK(it != clients_.end());
239 if (client->is_authenticated()) {
240 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
241 OnClientDisconnected(client->client_jid()));
244 clients_.erase(it);
245 delete client;
248 void ChromotingHost::OnSessionRouteChange(
249 ClientSession* session,
250 const std::string& channel_name,
251 const protocol::TransportRoute& route) {
252 DCHECK(CalledOnValidThread());
253 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_,
254 OnClientRouteChange(session->client_jid(), channel_name,
255 route));
258 void ChromotingHost::OnSessionManagerReady() {
259 DCHECK(CalledOnValidThread());
260 // Don't need to do anything here, just wait for incoming
261 // connections.
264 void ChromotingHost::OnIncomingSession(
265 protocol::Session* session,
266 protocol::SessionManager::IncomingSessionResponse* response) {
267 DCHECK(CalledOnValidThread());
269 if (!started_) {
270 *response = protocol::SessionManager::DECLINE;
271 return;
274 if (login_backoff_.ShouldRejectRequest()) {
275 LOG(WARNING) << "Rejecting connection due to"
276 " an overload of failed login attempts.";
277 *response = protocol::SessionManager::OVERLOAD;
278 return;
281 *response = protocol::SessionManager::ACCEPT;
283 HOST_LOG << "Client connected: " << session->jid();
285 // Create a client object.
286 scoped_ptr<protocol::ConnectionToClient> connection(
287 new protocol::ConnectionToClient(session));
288 ClientSession* client = new ClientSession(
289 this,
290 audio_task_runner_,
291 input_task_runner_,
292 video_capture_task_runner_,
293 video_encode_task_runner_,
294 network_task_runner_,
295 ui_task_runner_,
296 connection.Pass(),
297 desktop_environment_factory_,
298 max_session_duration_,
299 pairing_registry_,
300 extensions_.get());
302 clients_.push_back(client);
305 void ChromotingHost::DisconnectAllClients() {
306 DCHECK(CalledOnValidThread());
308 while (!clients_.empty()) {
309 size_t size = clients_.size();
310 clients_.front()->DisconnectSession();
311 CHECK_EQ(clients_.size(), size - 1);
315 } // namespace remoting