| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "build/build_config.h" | 7 #include "build/build_config.h" |
| 8 #include "remoting/base/constants.h" | 8 #include "remoting/base/constants.h" |
| 9 #include "remoting/base/encoder.h" | 9 #include "remoting/base/encoder.h" |
| 10 #include "remoting/base/encoder_row_based.h" | 10 #include "remoting/base/encoder_row_based.h" |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 // Connect to the talk network with a JingleClient. | 100 // Connect to the talk network with a JingleClient. |
| 101 signal_strategy_.reset( | 101 signal_strategy_.reset( |
| 102 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, | 102 new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, |
| 103 xmpp_auth_token, | 103 xmpp_auth_token, |
| 104 kChromotingTokenServiceName)); | 104 kChromotingTokenServiceName)); |
| 105 jingle_client_ = new JingleClient(context_->jingle_thread(), | 105 jingle_client_ = new JingleClient(context_->jingle_thread(), |
| 106 signal_strategy_.get(), | 106 signal_strategy_.get(), |
| 107 NULL, | 107 NULL, |
| 108 this); | 108 this); |
| 109 jingle_client_->Init(); | 109 jingle_client_->Init(); |
| 110 | |
| 111 heartbeat_sender_ = | |
| 112 new HeartbeatSender(context_->jingle_thread()->message_loop(), | |
| 113 jingle_client_.get(), config_); | |
| 114 if (!heartbeat_sender_->Init()) { | |
| 115 LOG(ERROR) << "Failed to initialize HeartbeatSender."; | |
| 116 return; | |
| 117 } | |
| 118 } | 110 } |
| 119 | 111 |
| 120 // This method is called when we need to destroy the host process. | 112 // This method is called when we need to destroy the host process. |
| 121 void ChromotingHost::Shutdown() { | 113 void ChromotingHost::Shutdown() { |
| 122 if (MessageLoop::current() != context_->main_message_loop()) { | 114 if (MessageLoop::current() != context_->main_message_loop()) { |
| 123 context_->main_message_loop()->PostTask( | 115 context_->main_message_loop()->PostTask( |
| 124 FROM_HERE, | 116 FROM_HERE, |
| 125 NewRunnableMethod(this, &ChromotingHost::Shutdown)); | 117 NewRunnableMethod(this, &ChromotingHost::Shutdown)); |
| 126 return; | 118 return; |
| 127 } | 119 } |
| (...skipping 12 matching lines...) Expand all Loading... |
| 140 if (recorder_.get()) { | 132 if (recorder_.get()) { |
| 141 recorder_->RemoveAllConnections(); | 133 recorder_->RemoveAllConnections(); |
| 142 } | 134 } |
| 143 | 135 |
| 144 // Disconnect the clients. | 136 // Disconnect the clients. |
| 145 for (size_t i = 0; i < clients_.size(); i++) { | 137 for (size_t i = 0; i < clients_.size(); i++) { |
| 146 clients_[i]->Disconnect(); | 138 clients_[i]->Disconnect(); |
| 147 } | 139 } |
| 148 clients_.clear(); | 140 clients_.clear(); |
| 149 | 141 |
| 150 // Stop the heartbeat sender. | 142 // Notify observers. |
| 151 if (heartbeat_sender_) { | 143 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 152 heartbeat_sender_->Stop(); | 144 it != status_observers_.end(); ++it) { |
| 145 (*it)->OnShutdown(); |
| 153 } | 146 } |
| 154 | 147 |
| 155 // Stop chromotocol session manager. | 148 // Stop chromotocol session manager. |
| 156 if (session_manager_) { | 149 if (session_manager_) { |
| 157 session_manager_->Close( | 150 session_manager_->Close( |
| 158 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); | 151 NewRunnableMethod(this, &ChromotingHost::OnServerClosed)); |
| 159 } | 152 } |
| 160 | 153 |
| 161 // Disconnect from the talk network. | 154 // Disconnect from the talk network. |
| 162 if (jingle_client_) { | 155 if (jingle_client_) { |
| 163 jingle_client_->Close(); | 156 jingle_client_->Close(); |
| 164 } | 157 } |
| 165 | 158 |
| 166 if (recorder_.get()) { | 159 if (recorder_.get()) { |
| 167 recorder_->Stop(shutdown_task_.release()); | 160 recorder_->Stop(shutdown_task_.release()); |
| 168 } else { | 161 } else { |
| 169 shutdown_task_->Run(); | 162 shutdown_task_->Run(); |
| 170 shutdown_task_.reset(); | 163 shutdown_task_.reset(); |
| 171 } | 164 } |
| 172 } | 165 } |
| 173 | 166 |
| 167 void ChromotingHost::AddStatusObserver( |
| 168 const scoped_refptr<HostStatusObserver>& observer) { |
| 169 DCHECK_EQ(state_, kInitial); |
| 170 status_observers_.push_back(observer); |
| 171 } |
| 172 |
| 174 //////////////////////////////////////////////////////////////////////////// | 173 //////////////////////////////////////////////////////////////////////////// |
| 175 // protocol::ConnectionToClient::EventHandler implementations | 174 // protocol::ConnectionToClient::EventHandler implementations |
| 176 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { | 175 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { |
| 177 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 176 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
| 178 VLOG(1) << "Connection to client established."; | 177 VLOG(1) << "Connection to client established."; |
| 179 } | 178 } |
| 180 | 179 |
| 181 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { | 180 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { |
| 182 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); | 181 DCHECK_EQ(context_->network_message_loop(), MessageLoop::current()); |
| 183 | 182 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 196 FROM_HERE, | 195 FROM_HERE, |
| 197 NewRunnableMethod(this, &ChromotingHost::OnClientDisconnected, | 196 NewRunnableMethod(this, &ChromotingHost::OnClientDisconnected, |
| 198 make_scoped_refptr(connection))); | 197 make_scoped_refptr(connection))); |
| 199 } | 198 } |
| 200 | 199 |
| 201 //////////////////////////////////////////////////////////////////////////// | 200 //////////////////////////////////////////////////////////////////////////// |
| 202 // JingleClient::Callback implementations | 201 // JingleClient::Callback implementations |
| 203 void ChromotingHost::OnStateChange(JingleClient* jingle_client, | 202 void ChromotingHost::OnStateChange(JingleClient* jingle_client, |
| 204 JingleClient::State state) { | 203 JingleClient::State state) { |
| 205 if (state == JingleClient::CONNECTED) { | 204 if (state == JingleClient::CONNECTED) { |
| 205 std::string jid = jingle_client->GetFullJid(); |
| 206 |
| 206 DCHECK_EQ(jingle_client_.get(), jingle_client); | 207 DCHECK_EQ(jingle_client_.get(), jingle_client); |
| 207 VLOG(1) << "Host connected as " << jingle_client->GetFullJid(); | 208 VLOG(1) << "Host connected as " << jid; |
| 208 | 209 |
| 209 // Create and start session manager. | 210 // Create and start session manager. |
| 210 protocol::JingleSessionManager* server = | 211 protocol::JingleSessionManager* server = |
| 211 new protocol::JingleSessionManager(context_->jingle_thread()); | 212 new protocol::JingleSessionManager(context_->jingle_thread()); |
| 213 // TODO(ajwong): Make this a command switch when we're more stable. |
| 214 server->set_allow_local_ips(true); |
| 212 | 215 |
| 213 // Assign key and certificate to server. | 216 // Assign key and certificate to server. |
| 214 HostKeyPair key_pair; | 217 HostKeyPair key_pair; |
| 215 CHECK(key_pair.Load(config_)) | 218 CHECK(key_pair.Load(config_)) |
| 216 << "Failed to load server authentication data"; | 219 << "Failed to load server authentication data"; |
| 217 | 220 |
| 218 // TODO(ajwong): Make this a command switch when we're more stable. | 221 server->Init(jid, jingle_client->session_manager(), |
| 219 server->set_allow_local_ips(true); | |
| 220 server->Init(jingle_client->GetFullJid(), | |
| 221 jingle_client->session_manager(), | |
| 222 NewCallback(this, &ChromotingHost::OnNewClientSession), | 222 NewCallback(this, &ChromotingHost::OnNewClientSession), |
| 223 key_pair.CopyPrivateKey(), | 223 key_pair.CopyPrivateKey(), key_pair.GenerateCertificate()); |
| 224 key_pair.GenerateCertificate()); | |
| 225 | 224 |
| 226 session_manager_ = server; | 225 session_manager_ = server; |
| 227 // Start heartbeating. | 226 |
| 228 heartbeat_sender_->Start(); | 227 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 228 it != status_observers_.end(); ++it) { |
| 229 (*it)->OnSignallingConnected(signal_strategy_.get(), jid); |
| 230 } |
| 229 } else if (state == JingleClient::CLOSED) { | 231 } else if (state == JingleClient::CLOSED) { |
| 230 VLOG(1) << "Host disconnected from talk network."; | 232 VLOG(1) << "Host disconnected from talk network."; |
| 231 | 233 |
| 232 // Stop heartbeating. | 234 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 233 heartbeat_sender_->Stop(); | 235 it != status_observers_.end(); ++it) { |
| 234 | 236 (*it)->OnSignallingDisconnected(); |
| 237 } |
| 235 // TODO(sergeyu): We should try reconnecting here instead of terminating | 238 // TODO(sergeyu): We should try reconnecting here instead of terminating |
| 236 // the host. | 239 // the host. |
| 237 Shutdown(); | 240 Shutdown(); |
| 238 } | 241 } |
| 239 } | 242 } |
| 240 | 243 |
| 241 void ChromotingHost::OnNewClientSession( | 244 void ChromotingHost::OnNewClientSession( |
| 242 protocol::Session* session, | 245 protocol::Session* session, |
| 243 protocol::SessionManager::IncomingSessionResponse* response) { | 246 protocol::SessionManager::IncomingSessionResponse* response) { |
| 244 base::AutoLock auto_lock(lock_); | 247 base::AutoLock auto_lock(lock_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 } | 306 } |
| 304 | 307 |
| 305 void ChromotingHost::OnServerClosed() { | 308 void ChromotingHost::OnServerClosed() { |
| 306 // Don't need to do anything here. | 309 // Don't need to do anything here. |
| 307 } | 310 } |
| 308 | 311 |
| 309 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 312 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
| 310 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 313 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
| 311 | 314 |
| 312 // Find the client session corresponding to the given connection. | 315 // Find the client session corresponding to the given connection. |
| 313 std::vector<scoped_refptr<ClientSession> >::iterator client; | 316 ClientList::iterator client; |
| 314 for (client = clients_.begin(); client != clients_.end(); ++client) { | 317 for (client = clients_.begin(); client != clients_.end(); |
| 318 ++client) { |
| 315 if (client->get()->connection() == connection) | 319 if (client->get()->connection() == connection) |
| 316 break; | 320 break; |
| 317 } | 321 } |
| 318 if (client == clients_.end()) | 322 if (client == clients_.end()) |
| 319 return; | 323 return; |
| 320 | 324 |
| 321 // Remove the connection from the session manager and stop the session. | 325 // Remove the connection from the session manager and stop the session. |
| 322 // TODO(hclam): Stop only if the last connection disconnected. | 326 // TODO(hclam): Stop only if the last connection disconnected. |
| 323 if (recorder_.get()) { | 327 if (recorder_.get()) { |
| 324 recorder_->RemoveConnection(connection); | 328 recorder_->RemoveConnection(connection); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 return NULL; | 363 return NULL; |
| 360 } | 364 } |
| 361 | 365 |
| 362 std::string ChromotingHost::GenerateHostAuthToken( | 366 std::string ChromotingHost::GenerateHostAuthToken( |
| 363 const std::string& encoded_client_token) { | 367 const std::string& encoded_client_token) { |
| 364 // TODO(ajwong): Return the signature of this instead. | 368 // TODO(ajwong): Return the signature of this instead. |
| 365 return encoded_client_token; | 369 return encoded_client_token; |
| 366 } | 370 } |
| 367 | 371 |
| 368 bool ChromotingHost::HasAuthenticatedClients() const { | 372 bool ChromotingHost::HasAuthenticatedClients() const { |
| 369 std::vector<scoped_refptr<ClientSession> >::const_iterator it; | 373 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end(); |
| 370 for (it = clients_.begin(); it != clients_.end(); ++it) { | 374 ++it) { |
| 371 if (it->get()->authenticated()) | 375 if (it->get()->authenticated()) |
| 372 return true; | 376 return true; |
| 373 } | 377 } |
| 374 return false; | 378 return false; |
| 375 } | 379 } |
| 376 | 380 |
| 377 void ChromotingHost::EnableCurtainMode(bool enable) { | 381 void ChromotingHost::EnableCurtainMode(bool enable) { |
| 378 // TODO(jamiewalch): This will need to be more sophisticated when we think | 382 // TODO(jamiewalch): This will need to be more sophisticated when we think |
| 379 // about proper crash recovery and daemon mode. | 383 // about proper crash recovery and daemon mode. |
| 380 if (enable == is_curtained_) | 384 if (enable == is_curtained_) |
| (...skipping 14 matching lines...) Expand all Loading... |
| 395 } | 399 } |
| 396 | 400 |
| 397 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 401 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
| 398 status->set_success(true); | 402 status->set_success(true); |
| 399 connection->client_stub()->BeginSessionResponse( | 403 connection->client_stub()->BeginSessionResponse( |
| 400 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 404 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
| 401 | 405 |
| 402 // Disconnect all other clients. | 406 // Disconnect all other clients. |
| 403 // Iterate over a copy of the list of clients, to avoid mutating the list | 407 // Iterate over a copy of the list of clients, to avoid mutating the list |
| 404 // while iterating over it. | 408 // while iterating over it. |
| 405 std::vector<scoped_refptr<ClientSession> > clients_copy(clients_); | 409 ClientList clients_copy(clients_); |
| 406 std::vector<scoped_refptr<ClientSession> >::const_iterator client; | 410 for (ClientList::const_iterator client = clients_copy.begin(); |
| 407 for (client = clients_copy.begin(); client != clients_copy.end(); client++) { | 411 client != clients_copy.end(); client++) { |
| 408 ConnectionToClient* connection_other = client->get()->connection(); | 412 ConnectionToClient* connection_other = client->get()->connection(); |
| 409 if (connection_other != connection) { | 413 if (connection_other != connection) { |
| 410 OnClientDisconnected(connection_other); | 414 OnClientDisconnected(connection_other); |
| 411 } | 415 } |
| 412 } | 416 } |
| 413 // Those disconnections should have killed the screen recorder. | 417 // Those disconnections should have killed the screen recorder. |
| 414 CHECK(recorder_.get() == NULL); | 418 CHECK(recorder_.get() == NULL); |
| 415 | 419 |
| 416 // Create a new RecordSession if there was none. | 420 // Create a new RecordSession if there was none. |
| 417 if (!recorder_.get()) { | 421 if (!recorder_.get()) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 441 return; | 445 return; |
| 442 } | 446 } |
| 443 | 447 |
| 444 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 448 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
| 445 status->set_success(false); | 449 status->set_success(false); |
| 446 connection->client_stub()->BeginSessionResponse( | 450 connection->client_stub()->BeginSessionResponse( |
| 447 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 451 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
| 448 } | 452 } |
| 449 | 453 |
| 450 } // namespace remoting | 454 } // namespace remoting |
| OLD | NEW |