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