| 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 |