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 weak_factory_(this) { | 84 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 // Destroy the session manager to make sure that |signal_strategy_| does not |
| 103 // have any listeners registered. |
| 104 session_manager_.reset(); |
| 105 |
| 106 // Notify observers. |
| 107 if (started_) |
| 108 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnShutdown()); |
96 } | 109 } |
97 | 110 |
98 void ChromotingHost::Start(const std::string& xmpp_login) { | 111 void ChromotingHost::Start(const std::string& xmpp_login) { |
99 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 112 DCHECK(CalledOnValidThread()); |
| 113 DCHECK(!started_); |
100 | 114 |
101 LOG(INFO) << "Starting host"; | 115 LOG(INFO) << "Starting host"; |
102 | 116 started_ = true; |
103 // Make sure this object is not started. | 117 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, OnStart(xmpp_login)); |
104 if (state_ != kInitial) | |
105 return; | |
106 state_ = kStarted; | |
107 | |
108 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | |
109 OnStart(xmpp_login)); | |
110 | 118 |
111 // Start the SessionManager, supplying this ChromotingHost as the listener. | 119 // Start the SessionManager, supplying this ChromotingHost as the listener. |
112 session_manager_->Init(signal_strategy_, this); | 120 session_manager_->Init(signal_strategy_, this); |
113 } | 121 } |
114 | 122 |
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) { | 123 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { |
157 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 124 DCHECK(CalledOnValidThread()); |
158 status_observers_.AddObserver(observer); | 125 status_observers_.AddObserver(observer); |
159 } | 126 } |
160 | 127 |
161 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { | 128 void ChromotingHost::RemoveStatusObserver(HostStatusObserver* observer) { |
162 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 129 DCHECK(CalledOnValidThread()); |
163 status_observers_.RemoveObserver(observer); | 130 status_observers_.RemoveObserver(observer); |
164 } | 131 } |
165 | 132 |
166 void ChromotingHost::RejectAuthenticatingClient() { | 133 void ChromotingHost::RejectAuthenticatingClient() { |
167 DCHECK(authenticating_client_); | 134 DCHECK(authenticating_client_); |
168 reject_authenticating_client_ = true; | 135 reject_authenticating_client_ = true; |
169 } | 136 } |
170 | 137 |
171 void ChromotingHost::SetAuthenticatorFactory( | 138 void ChromotingHost::SetAuthenticatorFactory( |
172 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { | 139 scoped_ptr<protocol::AuthenticatorFactory> authenticator_factory) { |
173 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 140 DCHECK(CalledOnValidThread()); |
174 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); | 141 session_manager_->set_authenticator_factory(authenticator_factory.Pass()); |
175 } | 142 } |
176 | 143 |
177 void ChromotingHost::SetMaximumSessionDuration( | 144 void ChromotingHost::SetMaximumSessionDuration( |
178 const base::TimeDelta& max_session_duration) { | 145 const base::TimeDelta& max_session_duration) { |
179 max_session_duration_ = max_session_duration; | 146 max_session_duration_ = max_session_duration; |
180 } | 147 } |
181 | 148 |
182 //////////////////////////////////////////////////////////////////////////// | 149 //////////////////////////////////////////////////////////////////////////// |
183 // protocol::ClientSession::EventHandler implementation. | 150 // protocol::ClientSession::EventHandler implementation. |
184 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { | 151 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) { |
185 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 152 DCHECK(CalledOnValidThread()); |
186 | 153 |
187 login_backoff_.Reset(); | 154 login_backoff_.Reset(); |
188 | 155 |
189 // Disconnect all other clients. |it| should be advanced before Disconnect() | 156 // Disconnect all other clients. |it| should be advanced before Disconnect() |
190 // is called to avoid it becoming invalid when the client is removed from | 157 // is called to avoid it becoming invalid when the client is removed from |
191 // the list. | 158 // the list. |
192 ClientList::iterator it = clients_.begin(); | 159 ClientList::iterator it = clients_.begin(); |
193 while (it != clients_.end()) { | 160 while (it != clients_.end()) { |
194 ClientSession* other_client = *it++; | 161 ClientSession* other_client = *it++; |
195 if (other_client != client) | 162 if (other_client != client) |
(...skipping 12 matching lines...) Expand all Loading... |
208 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 175 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
209 OnClientAuthenticated(jid)); | 176 OnClientAuthenticated(jid)); |
210 authenticating_client_ = false; | 177 authenticating_client_ = false; |
211 | 178 |
212 if (reject_authenticating_client_) { | 179 if (reject_authenticating_client_) { |
213 client->DisconnectSession(); | 180 client->DisconnectSession(); |
214 } | 181 } |
215 } | 182 } |
216 | 183 |
217 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { | 184 void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { |
218 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 185 DCHECK(CalledOnValidThread()); |
219 | 186 |
220 // Notify observers. | 187 // Notify observers. |
221 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 188 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
222 OnClientConnected(client->client_jid())); | 189 OnClientConnected(client->client_jid())); |
223 } | 190 } |
224 | 191 |
225 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { | 192 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { |
226 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 193 DCHECK(CalledOnValidThread()); |
227 | 194 |
228 // Notify observers. | 195 // Notify observers. |
229 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 196 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
230 OnAccessDenied(client->client_jid())); | 197 OnAccessDenied(client->client_jid())); |
231 } | 198 } |
232 | 199 |
233 void ChromotingHost::OnSessionClosed(ClientSession* client) { | 200 void ChromotingHost::OnSessionClosed(ClientSession* client) { |
234 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 201 DCHECK(CalledOnValidThread()); |
235 | 202 |
236 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); | 203 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); |
237 CHECK(it != clients_.end()); | 204 CHECK(it != clients_.end()); |
238 | 205 |
239 if (client->is_authenticated()) { | 206 if (client->is_authenticated()) { |
240 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 207 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
241 OnClientDisconnected(client->client_jid())); | 208 OnClientDisconnected(client->client_jid())); |
242 } | 209 } |
243 | 210 |
244 clients_.erase(it); | 211 clients_.erase(it); |
245 delete client; | 212 delete client; |
246 | |
247 if (state_ == kStopping && clients_.empty()) | |
248 ShutdownFinish(); | |
249 } | 213 } |
250 | 214 |
251 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, | 215 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, |
252 int64 sequence_number) { | 216 int64 sequence_number) { |
253 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 217 DCHECK(CalledOnValidThread()); |
254 } | 218 } |
255 | 219 |
256 void ChromotingHost::OnSessionRouteChange( | 220 void ChromotingHost::OnSessionRouteChange( |
257 ClientSession* session, | 221 ClientSession* session, |
258 const std::string& channel_name, | 222 const std::string& channel_name, |
259 const protocol::TransportRoute& route) { | 223 const protocol::TransportRoute& route) { |
260 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 224 DCHECK(CalledOnValidThread()); |
261 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, | 225 FOR_EACH_OBSERVER(HostStatusObserver, status_observers_, |
262 OnClientRouteChange(session->client_jid(), channel_name, | 226 OnClientRouteChange(session->client_jid(), channel_name, |
263 route)); | 227 route)); |
264 } | 228 } |
265 | 229 |
266 void ChromotingHost::OnSessionManagerReady() { | 230 void ChromotingHost::OnSessionManagerReady() { |
267 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 231 DCHECK(CalledOnValidThread()); |
268 // Don't need to do anything here, just wait for incoming | 232 // Don't need to do anything here, just wait for incoming |
269 // connections. | 233 // connections. |
270 } | 234 } |
271 | 235 |
272 void ChromotingHost::OnIncomingSession( | 236 void ChromotingHost::OnIncomingSession( |
273 protocol::Session* session, | 237 protocol::Session* session, |
274 protocol::SessionManager::IncomingSessionResponse* response) { | 238 protocol::SessionManager::IncomingSessionResponse* response) { |
275 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 239 DCHECK(CalledOnValidThread()); |
276 | 240 |
277 if (state_ != kStarted) { | 241 if (!started_) { |
278 *response = protocol::SessionManager::DECLINE; | 242 *response = protocol::SessionManager::DECLINE; |
279 return; | 243 return; |
280 } | 244 } |
281 | 245 |
282 if (login_backoff_.ShouldRejectRequest()) { | 246 if (login_backoff_.ShouldRejectRequest()) { |
283 *response = protocol::SessionManager::OVERLOAD; | 247 *response = protocol::SessionManager::OVERLOAD; |
284 return; | 248 return; |
285 } | 249 } |
286 | 250 |
287 // We treat each incoming connection as a failure to authenticate, | 251 // We treat each incoming connection as a failure to authenticate, |
(...skipping 28 matching lines...) Expand all Loading... |
316 network_task_runner_, | 280 network_task_runner_, |
317 ui_task_runner_, | 281 ui_task_runner_, |
318 connection.Pass(), | 282 connection.Pass(), |
319 desktop_environment_factory_, | 283 desktop_environment_factory_, |
320 max_session_duration_); | 284 max_session_duration_); |
321 clients_.push_back(client); | 285 clients_.push_back(client); |
322 } | 286 } |
323 | 287 |
324 void ChromotingHost::set_protocol_config( | 288 void ChromotingHost::set_protocol_config( |
325 scoped_ptr<protocol::CandidateSessionConfig> config) { | 289 scoped_ptr<protocol::CandidateSessionConfig> config) { |
326 DCHECK(network_task_runner_->BelongsToCurrentThread()); | 290 DCHECK(CalledOnValidThread()); |
327 DCHECK(config.get()); | 291 DCHECK(config.get()); |
328 DCHECK_EQ(state_, kInitial); | 292 DCHECK(!started_); |
329 protocol_config_ = config.Pass(); | 293 protocol_config_ = config.Pass(); |
330 } | 294 } |
331 | 295 |
332 void ChromotingHost::DisconnectAllClients() { | 296 void ChromotingHost::DisconnectAllClients() { |
333 if (!network_task_runner_->BelongsToCurrentThread()) { | 297 DCHECK(CalledOnValidThread()); |
334 network_task_runner_->PostTask( | |
335 FROM_HERE, base::Bind(&ChromotingHost::DisconnectAllClients, this)); | |
336 return; | |
337 } | |
338 | 298 |
339 while (!clients_.empty()) { | 299 while (!clients_.empty()) { |
340 size_t size = clients_.size(); | 300 size_t size = clients_.size(); |
341 clients_.front()->DisconnectSession(); | 301 clients_.front()->DisconnectSession(); |
342 CHECK_EQ(clients_.size(), size - 1); | 302 CHECK_EQ(clients_.size(), size - 1); |
343 } | 303 } |
344 } | 304 } |
345 | 305 |
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 | 306 } // namespace remoting |
OLD | NEW |