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.
4 
5 #include "remoting/host/chromoting_host.h"
6 
7 #include <stddef.h>
8 
9 #include <algorithm>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/command_line.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/single_thread_task_runner.h"
17 #include "build/build_config.h"
18 #include "jingle/glue/thread_wrapper.h"
19 #include "remoting/base/constants.h"
20 #include "remoting/base/logging.h"
21 #include "remoting/host/desktop_environment.h"
22 #include "remoting/host/host_config.h"
23 #include "remoting/host/input_injector.h"
24 #include "remoting/protocol/client_stub.h"
25 #include "remoting/protocol/host_stub.h"
26 #include "remoting/protocol/ice_connection_to_client.h"
27 #include "remoting/protocol/input_stub.h"
28 #include "remoting/protocol/transport_context.h"
29 #include "remoting/protocol/webrtc_connection_to_client.h"
30 
31 using remoting::protocol::ConnectionToClient;
32 using remoting::protocol::InputStub;
33 
34 namespace remoting {
35 
36 namespace {
37 
38 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
39   // Number of initial errors (in sequence) to ignore before applying
40   // exponential back-off rules.
41   5,
42 
43   // Initial delay for exponential back-off in ms.
44   2000,
45 
46   // Factor by which the waiting time will be multiplied.
47   2,
48 
49   // Fuzzing percentage. ex: 10% will spread requests randomly
50   // between 90%-100% of the calculated time.
51   0,
52 
53   // Maximum amount of time we are willing to delay our request in ms.
54   -1,
55 
56   // Time to keep an entry from being discarded even when it
57   // has no significant state, -1 to never discard.
58   -1,
59 
60   // Don't use initial delay unless the last request was an error.
61   false,
62 };
63 
64 }  // namespace
65 
ChromotingHost(DesktopEnvironmentFactory * desktop_environment_factory,std::unique_ptr<protocol::SessionManager> session_manager,scoped_refptr<protocol::TransportContext> transport_context,scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,const DesktopEnvironmentOptions & options)66 ChromotingHost::ChromotingHost(
67     DesktopEnvironmentFactory* desktop_environment_factory,
68     std::unique_ptr<protocol::SessionManager> session_manager,
69     scoped_refptr<protocol::TransportContext> transport_context,
70     scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner,
71     scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner,
72     const DesktopEnvironmentOptions& options)
73     : desktop_environment_factory_(desktop_environment_factory),
74       session_manager_(std::move(session_manager)),
75       transport_context_(transport_context),
76       audio_task_runner_(audio_task_runner),
77       video_encode_task_runner_(video_encode_task_runner),
78       status_monitor_(new HostStatusMonitor()),
79       login_backoff_(&kDefaultBackoffPolicy),
80       desktop_environment_options_(options) {
81   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
82 }
83 
~ChromotingHost()84 ChromotingHost::~ChromotingHost() {
85   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
86 
87   // Disconnect all of the clients.
88   while (!clients_.empty()) {
89     clients_.front()->DisconnectSession(protocol::OK);
90   }
91 
92   // Destroy the session manager to make sure that |signal_strategy_| does not
93   // have any listeners registered.
94   session_manager_.reset();
95 
96   // Notify observers.
97   if (started_) {
98     for (auto& observer : status_monitor_->observers())
99       observer.OnShutdown();
100   }
101 }
102 
Start(const std::string & host_owner_email)103 void ChromotingHost::Start(const std::string& host_owner_email) {
104   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
105   DCHECK(!started_);
106 
107   HOST_LOG << "Starting host";
108   started_ = true;
109   for (auto& observer : status_monitor_->observers())
110     observer.OnStart(host_owner_email);
111 
112   session_manager_->AcceptIncoming(base::BindRepeating(
113       &ChromotingHost::OnIncomingSession, base::Unretained(this)));
114 }
115 
AddExtension(std::unique_ptr<HostExtension> extension)116 void ChromotingHost::AddExtension(std::unique_ptr<HostExtension> extension) {
117   extensions_.push_back(std::move(extension));
118 }
119 
SetAuthenticatorFactory(std::unique_ptr<protocol::AuthenticatorFactory> authenticator_factory)120 void ChromotingHost::SetAuthenticatorFactory(
121     std::unique_ptr<protocol::AuthenticatorFactory> authenticator_factory) {
122   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
123   session_manager_->set_authenticator_factory(std::move(authenticator_factory));
124 }
125 
SetMaximumSessionDuration(const base::TimeDelta & max_session_duration)126 void ChromotingHost::SetMaximumSessionDuration(
127     const base::TimeDelta& max_session_duration) {
128   max_session_duration_ = max_session_duration;
129 }
130 
131 ////////////////////////////////////////////////////////////////////////////
132 // protocol::ClientSession::EventHandler implementation.
OnSessionAuthenticating(ClientSession * client)133 void ChromotingHost::OnSessionAuthenticating(ClientSession* client) {
134   // We treat each incoming connection as a failure to authenticate,
135   // and clear the backoff when a connection successfully
136   // authenticates. This allows the backoff to protect from parallel
137   // connection attempts as well as sequential ones.
138   if (login_backoff_.ShouldRejectRequest()) {
139     LOG(WARNING) << "Disconnecting client " << client->client_jid() << " due to"
140                     " an overload of failed login attempts.";
141     client->DisconnectSession(protocol::HOST_OVERLOAD);
142     return;
143   }
144   login_backoff_.InformOfRequest(false);
145 }
146 
OnSessionAuthenticated(ClientSession * client)147 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
148   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
149 
150   login_backoff_.Reset();
151 
152   // Disconnect all clients, except |client|.
153   base::WeakPtr<ChromotingHost> self = weak_factory_.GetWeakPtr();
154   while (clients_.size() > 1) {
155     clients_[(clients_.front().get() == client) ? 1 : 0]->DisconnectSession(
156         protocol::OK);
157 
158     // Quit if the host was destroyed.
159     if (!self)
160       return;
161   }
162 
163   // Disconnects above must have destroyed all other clients.
164   DCHECK_EQ(clients_.size(), 1U);
165   DCHECK(clients_.front().get() == client);
166 
167   // Notify observers that there is at least one authenticated client.
168   for (auto& observer : status_monitor_->observers())
169     observer.OnClientAuthenticated(client->client_jid());
170 }
171 
OnSessionChannelsConnected(ClientSession * client)172 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) {
173   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
174 
175   // Notify observers.
176   for (auto& observer : status_monitor_->observers())
177     observer.OnClientConnected(client->client_jid());
178 }
179 
OnSessionAuthenticationFailed(ClientSession * client)180 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) {
181   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
182 
183   // Notify observers.
184   for (auto& observer : status_monitor_->observers())
185     observer.OnAccessDenied(client->client_jid());
186 }
187 
OnSessionClosed(ClientSession * client)188 void ChromotingHost::OnSessionClosed(ClientSession* client) {
189   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
190 
191   auto it = std::find_if(clients_.begin(), clients_.end(),
192                          [client](const std::unique_ptr<ClientSession>& item) {
193                            return item.get() == client;
194                          });
195   CHECK(it != clients_.end());
196 
197   bool was_authenticated = client->is_authenticated();
198   std::string jid = client->client_jid();
199   clients_.erase(it);
200 
201   if (was_authenticated) {
202     for (auto& observer : status_monitor_->observers())
203       observer.OnClientDisconnected(jid);
204   }
205 }
206 
OnSessionRouteChange(ClientSession * session,const std::string & channel_name,const protocol::TransportRoute & route)207 void ChromotingHost::OnSessionRouteChange(
208     ClientSession* session,
209     const std::string& channel_name,
210     const protocol::TransportRoute& route) {
211   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
212   for (auto& observer : status_monitor_->observers())
213     observer.OnClientRouteChange(session->client_jid(), channel_name, route);
214 }
215 
OnIncomingSession(protocol::Session * session,protocol::SessionManager::IncomingSessionResponse * response)216 void ChromotingHost::OnIncomingSession(
217       protocol::Session* session,
218       protocol::SessionManager::IncomingSessionResponse* response) {
219   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
220   DCHECK(started_);
221 
222   if (login_backoff_.ShouldRejectRequest()) {
223     LOG(WARNING) << "Rejecting connection due to"
224                     " an overload of failed login attempts.";
225     *response = protocol::SessionManager::OVERLOAD;
226     return;
227   }
228 
229   *response = protocol::SessionManager::ACCEPT;
230 
231   HOST_LOG << "Client connected: " << session->jid();
232 
233   // Create either IceConnectionToClient or WebrtcConnectionToClient.
234   // TODO(sergeyu): Move this logic to the protocol layer.
235   std::unique_ptr<protocol::ConnectionToClient> connection;
236   if (session->config().protocol() ==
237       protocol::SessionConfig::Protocol::WEBRTC) {
238     connection.reset(new protocol::WebrtcConnectionToClient(
239         base::WrapUnique(session), transport_context_,
240         video_encode_task_runner_, audio_task_runner_));
241   } else {
242     connection.reset(new protocol::IceConnectionToClient(
243         base::WrapUnique(session), transport_context_,
244         video_encode_task_runner_, audio_task_runner_));
245   }
246 
247   // Create a ClientSession object.
248   std::vector<HostExtension*> extension_ptrs;
249   for (const auto& extension : extensions_)
250     extension_ptrs.push_back(extension.get());
251   clients_.push_back(std::make_unique<ClientSession>(
252       this, std::move(connection), desktop_environment_factory_,
253       desktop_environment_options_, max_session_duration_, pairing_registry_,
254       extension_ptrs));
255 }
256 
257 }  // namespace remoting
258