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