OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/chromoting_host.h" | 5 #include "remoting/host/chromoting_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
69 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) | 69 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
70 : desktop_environment_factory_(desktop_environment_factory), | 70 : desktop_environment_factory_(desktop_environment_factory), |
71 session_manager_(session_manager.Pass()), | 71 session_manager_(session_manager.Pass()), |
72 audio_task_runner_(audio_task_runner), | 72 audio_task_runner_(audio_task_runner), |
73 input_task_runner_(input_task_runner), | 73 input_task_runner_(input_task_runner), |
74 video_capture_task_runner_(video_capture_task_runner), | 74 video_capture_task_runner_(video_capture_task_runner), |
75 video_encode_task_runner_(video_encode_task_runner), | 75 video_encode_task_runner_(video_encode_task_runner), |
76 network_task_runner_(network_task_runner), | 76 network_task_runner_(network_task_runner), |
77 ui_task_runner_(ui_task_runner), | 77 ui_task_runner_(ui_task_runner), |
78 signal_strategy_(signal_strategy), | 78 signal_strategy_(signal_strategy), |
79 state_(kInitial), | 79 started_(false), |
80 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), | 80 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), |
81 login_backoff_(&kDefaultBackoffPolicy), | 81 login_backoff_(&kDefaultBackoffPolicy), |
82 authenticating_client_(false), | 82 authenticating_client_(false), |
83 reject_authenticating_client_(false), | 83 reject_authenticating_client_(false), |
84 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { | 84 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
| 85 DCHECK(network_task_runner_->BelongsToCurrentThread()); |
85 DCHECK(signal_strategy); | 86 DCHECK(signal_strategy); |
86 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
87 | 87 |
88 if (!desktop_environment_factory_->SupportsAudioCapture()) { | 88 if (!desktop_environment_factory_->SupportsAudioCapture()) { |
89 protocol::CandidateSessionConfig::DisableAudioChannel( | 89 protocol::CandidateSessionConfig::DisableAudioChannel( |
90 protocol_config_.get()); | 90 protocol_config_.get()); |
91 } | 91 } |
92 } | 92 } |
93 | 93 |
94 ChromotingHost::~ChromotingHost() { | 94 ChromotingHost::~ChromotingHost() { |
95 DCHECK(clients_.empty()); | 95 DCHECK(CalledOnValidThread()); |
| 96 |
| 97 // Disconnect all of the clients. |
| 98 while (!clients_.empty()) { |
| 99 clients_.front()->DisconnectSession(); |
| 100 } |
| 101 |
| 102 // Notify observers. |
| 103 if (started_) { |
| 104 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnShutdown()); |
| 105 } |
96 } | 106 } |
97 | 107 |
98 void ChromotingHost::Start(const std::string& xmpp_login) { | 108 void ChromotingHost::Start(const std::string& xmpp_login) { |
99 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 109 DCHECK(CalledOnValidThread()); |
| 110 DCHECK(!started_); |
100 | 111 |
101 LOG(INFO) << "Starting host"; | 112 LOG(INFO) << "Starting host"; |
102 | 113 started_ = true; |
103 // Make sure this object is not started. | |
104 if (state_ != kInitial) | |
105 return; | |
106 state_ = kStarted; | |
107 | |
108 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 114 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
109 OnStart(xmpp_login)); | 115 OnStart(xmpp_login)); |
110 | 116 |
111 // Start the SessionManager, supplying this ChromotingHost as the listener. | 117 // Start the SessionManager, supplying this ChromotingHost as the listener. |
112 session_manager_->Init(signal_strategy_, this); | 118 session_manager_->Init(signal_strategy_, this); |
113 } | 119 } |
114 | 120 |
115 // This method is called when we need to destroy the host process. | |
116 void ChromotingHost::Shutdown(const base::Closure& shutdown_task) { | |
117 if (!network_task_runner_->BelongsToCurrentThread()) { | |
118 network_task_runner_->PostTask( | |
119 FROM_HERE, base::Bind(&ChromotingHost::Shutdown, this, shutdown_task)); | |
120 return; | |
121 } | |
122 | |
123 switch (state_) { | |
124 case kInitial: | |
125 case kStopped: | |
126 // Nothing to do if we are not started. | |
127 state_ = kStopped; | |
128 if (!shutdown_task.is_null()) | |
129 network_task_runner_->PostTask(FROM_HERE, shutdown_task); | |
130 break; | |
131 | |
132 case kStopping: | |
133 // We are already stopping. Just save the task. | |
134 if (!shutdown_task.is_null()) | |
135 shutdown_tasks_.push_back(shutdown_task); | |
136 break; | |
137 | |
138 case kStarted: | |
139 if (!shutdown_task.is_null()) | |
140 shutdown_tasks_.push_back(shutdown_task); | |
141 state_ = kStopping; | |
142 | |
143 // Disconnect all of the clients. | |
144 while (!clients_.empty()) { | |
145 clients_.front()->DisconnectSession(); | |
146 } | |
147 | |
148 // Run the remaining shutdown tasks. | |
149 if (state_ == kStopping) | |
150 ShutdownFinish(); | |
151 | |
152 break; | |
153 } | |
154 } | |
155 | |
156 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { | 121 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { |
157 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 122 DCHECK(CalledOnValidThread()); |
158 status_observers_.AddObserver(observer); | 123 status_observers_.AddObserver(observer); |
159 } | 124 } |
160 | 125 |
161 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { | 126 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { |
162 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 127 DCHECK(CalledOnValidThread()); |
163 status_observers_.RemoveObserver(observer); | 128 status_observers_.RemoveObserver(observer); |
164 } | 129 } |
165 | 130 |
166 void ChromotingHost::RejectAuthenticatingClient() { | 131 void ChromotingHost::RejectAuthenticatingClient() { |
167 DCHECK(authenticating_client_); | 132 DCHECK(authenticating_client_); |
168 reject_authenticating_client_ = true; | 133 reject_authenticating_client_ = true; |
169 } | 134 } |
170 | 135 |
171 void ChromotingHost::SetAuthenticatorFactory( | 136 void ChromotingHost::SetAuthenticatorFactory( |
172 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { | 137 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { |
173 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 138 DCHECK(CalledOnValidThread()); |
174 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); | 139 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); |
175 } | 140 } |
176 | 141 |
177 void ChromotingHost::SetMaximumSessionDuration( | 142 void ChromotingHost::SetMaximumSessionDuration( |
178 const base::TimeDelta& max_session_duration) { | 143 const base::TimeDelta& max_session_duration) { |
179 max_session_duration_ = max_session_duration; | 144 max_session_duration_ = max_session_duration; |
180 } | 145 } |
181 | 146 |
182 //////////////////////////////////////////////////////////////////////////// | 147 //////////////////////////////////////////////////////////////////////////// |
183 // protocol::ClientSession::EventHandler implementation. | 148 // protocol::ClientSession::EventHandler implementation. |
184 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { | 149 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { |
185 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 150 DCHECK(CalledOnValidThread()); |
186 | 151 |
187 login_backoff_.Reset(); | 152 login_backoff_.Reset(); |
188 | 153 |
189 // Disconnect all other clients. |it| should be advanced before Disconnect() | 154 // Disconnect all other clients. |it| should be advanced before Disconnect() |
190 // is called to avoid it becoming invalid when the client is removed from | 155 // is called to avoid it becoming invalid when the client is removed from |
191 // the list. | 156 // the list. |
192 ClientList::iterator it = clients_.begin(); | 157 ClientList::iterator it = clients_.begin(); |
193 while (it != clients_.end()) { | 158 while (it != clients_.end()) { |
194 ClientSession* other_client = *it++; | 159 ClientSession* other_client = *it++; |
195 if (other_client != client) | 160 if (other_client != client) |
(...skipping 12 matching lines...) Expand all Loading... |
208 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 173 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
209 OnClientAuthenticated(jid)); | 174 OnClientAuthenticated(jid)); |
210 authenticating_client_ = false; | 175 authenticating_client_ = false; |
211 | 176 |
212 if (reject_authenticating_client_) { | 177 if (reject_authenticating_client_) { |
213 client->DisconnectSession(); | 178 client->DisconnectSession(); |
214 } | 179 } |
215 } | 180 } |
216 | 181 |
217 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { | 182 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { |
218 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 183 DCHECK(CalledOnValidThread()); |
219 | 184 |
220 // Notify observers. | 185 // Notify observers. |
221 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 186 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
222 OnClientConnected(client->client_jid())); | 187 OnClientConnected(client->client_jid())); |
223 } | 188 } |
224 | 189 |
225 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { | 190 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { |
226 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 191 DCHECK(CalledOnValidThread()); |
227 | 192 |
228 // Notify observers. | 193 // Notify observers. |
229 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 194 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
230 OnAccessDenied(client->client_jid())); | 195 OnAccessDenied(client->client_jid())); |
231 } | 196 } |
232 | 197 |
233 void ChromotingHost::OnSessionClosed(ClientSession* client) { | 198 void ChromotingHost::OnSessionClosed(ClientSession* client) { |
234 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 199 DCHECK(CalledOnValidThread()); |
235 | 200 |
236 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); | 201 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); |
237 CHECK(it != clients_.end()); | 202 CHECK(it != clients_.end()); |
238 | 203 |
239 if (client->is_authenticated()) { | 204 if (client->is_authenticated()) { |
240 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 205 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
241 OnClientDisconnected(client->client_jid())); | 206 OnClientDisconnected(client->client_jid())); |
242 } | 207 } |
243 | 208 |
244 clients_.erase(it); | 209 clients_.erase(it); |
245 delete client; | 210 delete client; |
246 | |
247 if (state_ == kStopping && clients_.empty()) | |
248 ShutdownFinish(); | |
249 } | 211 } |
250 | 212 |
251 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, | 213 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, |
252 int64 sequence_number) { | 214 int64 sequence_number) { |
253 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 215 DCHECK(CalledOnValidThread()); |
254 } | 216 } |
255 | 217 |
256 void ChromotingHost::OnSessionRouteChange( | 218 void ChromotingHost::OnSessionRouteChange( |
257 ClientSession* session, | 219 ClientSession* session, |
258 const std::string& channel_name, | 220 const std::string& channel_name, |
259 const protocol::TransportRoute& route) { | 221 const protocol::TransportRoute& route) { |
260 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 222 DCHECK(CalledOnValidThread()); |
261 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 223 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
262 OnClientRouteChange(session->client_jid(), channel_name, | 224 OnClientRouteChange(session->client_jid(), channel_name, |
263 route)); | 225 route)); |
264 } | 226 } |
265 | 227 |
266 void ChromotingHost::OnSessionManagerReady() { | 228 void ChromotingHost::OnSessionManagerReady() { |
267 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 229 DCHECK(CalledOnValidThread()); |
268 // Don't need to do anything here, just wait for incoming | 230 // Don't need to do anything here, just wait for incoming |
269 // connections. | 231 // connections. |
270 } | 232 } |
271 | 233 |
272 void ChromotingHost::OnIncomingSession( | 234 void ChromotingHost::OnIncomingSession( |
273 protocol::Session* session, | 235 protocol::Session* session, |
274 protocol::SessionManager::IncomingSessionResponse* response) { | 236 protocol::SessionManager::IncomingSessionResponse* response) { |
275 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 237 DCHECK(CalledOnValidThread()); |
276 | 238 |
277 if (state_ != kStarted) { | 239 if (!started_) { |
278 *response = protocol::SessionManager::DECLINE; | 240 *response = protocol::SessionManager::DECLINE; |
279 return; | 241 return; |
280 } | 242 } |
281 | 243 |
282 if (login_backoff_.ShouldRejectRequest()) { | 244 if (login_backoff_.ShouldRejectRequest()) { |
283 *response = protocol::SessionManager::OVERLOAD; | 245 *response = protocol::SessionManager::OVERLOAD; |
284 return; | 246 return; |
285 } | 247 } |
286 | 248 |
287 // We treat each incoming connection as a failure to authenticate, | 249 // We treat each incoming connection as a failure to authenticate, |
(...skipping 28 matching lines...) Expand all Loading... |
316 network_task_runner_, | 278 network_task_runner_, |
317 ui_task_runner_, | 279 ui_task_runner_, |
318 connection.Pass(), | 280 connection.Pass(), |
319 desktop_environment_factory_, | 281 desktop_environment_factory_, |
320 max_session_duration_); | 282 max_session_duration_); |
321 clients_.push_back(client); | 283 clients_.push_back(client); |
322 } | 284 } |
323 | 285 |
324 void ChromotingHost::set_protocol_config( | 286 void ChromotingHost::set_protocol_config( |
325 scoped_ptr<protocol::CandidateSessionConfig> config) { | 287 scoped_ptr<protocol::CandidateSessionConfig> config) { |
326 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 288 DCHECK(CalledOnValidThread()); |
327 DCHECK(config.get()); | 289 DCHECK(config.get()); |
328 DCHECK_EQ(state_, kInitial); | 290 DCHECK(!started_); |
329 protocol_config_ = config.Pass(); | 291 protocol_config_ = config.Pass(); |
330 } | 292 } |
331 | 293 |
332 void ChromotingHost::DisconnectAllClients() { | 294 void ChromotingHost::DisconnectAllClients() { |
333 if (!network_task_runner_->BelongsToCurrentThread()) { | 295 DCHECK(CalledOnValidThread()); |
334 network_task_runner_->PostTask( | |
335 FROM_HERE, base::Bind(&ChromotingHost::DisconnectAllClients, this)); | |
336 return; | |
337 } | |
338 | 296 |
339 while (!clients_.empty()) { | 297 while (!clients_.empty()) { |
340 size_t size = clients_.size(); | 298 size_t size = clients_.size(); |
341 clients_.front()->DisconnectSession(); | 299 clients_.front()->DisconnectSession(); |
342 CHECK_EQ(clients_.size(), size - 1); | 300 CHECK_EQ(clients_.size(), size - 1); |
343 } | 301 } |
344 } | 302 } |
345 | 303 |
346 void ChromotingHost::ShutdownFinish() { | |
347 DCHECK(network_task_runner_->BelongsToCurrentThread()); | |
348 DCHECK_EQ(state_, kStopping); | |
349 | |
350 state_ = kStopped; | |
351 | |
352 // Destroy session manager. | |
353 session_manager_.reset(); | |
354 | |
355 // Clear |desktop_environment_factory_| and |signal_strategy_| to | |
356 // ensure we don't try to touch them after running shutdown tasks | |
357 desktop_environment_factory_ = NULL; | |
358 signal_strategy_ = NULL; | |
359 | |
360 // Keep reference to |this|, so that we don't get destroyed while | |
361 // sending notifications. | |
362 scoped_refptr<ChromotingHost> self(this); | |
363 | |
364 // Notify observers. | |
365 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | |
366 OnShutdown()); | |
367 | |
368 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); | |
369 it != shutdown_tasks_.end(); ++it) { | |
370 it->Run(); | |
371 } | |
372 shutdown_tasks_.clear(); | |
373 | |
374 weak_factory_.InvalidateWeakPtrs(); | |
375 } | |
376 | |
377 } // namespace remoting | 304 } // namespace remoting |
OLD | NEW |