| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/message_loop_proxy.h" | 10 #include "base/message_loop_proxy.h" |
| 11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
| 12 #include "remoting/base/constants.h" | 12 #include "remoting/base/constants.h" |
| 13 #include "remoting/base/encoder.h" | 13 #include "remoting/base/encoder.h" |
| 14 #include "remoting/base/encoder_row_based.h" | 14 #include "remoting/base/encoder_row_based.h" |
| 15 #include "remoting/base/encoder_vp8.h" | 15 #include "remoting/base/encoder_vp8.h" |
| 16 #include "remoting/host/chromoting_host_context.h" | 16 #include "remoting/host/chromoting_host_context.h" |
| 17 #include "remoting/host/curtain.h" | 17 #include "remoting/host/curtain.h" |
| 18 #include "remoting/host/desktop_environment.h" | 18 #include "remoting/host/desktop_environment.h" |
| 19 #include "remoting/host/event_executor.h" | 19 #include "remoting/host/event_executor.h" |
| 20 #include "remoting/host/host_config.h" | 20 #include "remoting/host/host_config.h" |
| 21 #include "remoting/host/host_key_pair.h" | 21 #include "remoting/host/host_key_pair.h" |
| 22 #include "remoting/host/screen_recorder.h" | 22 #include "remoting/host/screen_recorder.h" |
| 23 #include "remoting/host/user_authenticator.h" | |
| 24 #include "remoting/jingle_glue/xmpp_signal_strategy.h" | 23 #include "remoting/jingle_glue/xmpp_signal_strategy.h" |
| 25 #include "remoting/protocol/connection_to_client.h" | 24 #include "remoting/protocol/connection_to_client.h" |
| 26 #include "remoting/protocol/client_stub.h" | 25 #include "remoting/protocol/client_stub.h" |
| 27 #include "remoting/protocol/host_stub.h" | 26 #include "remoting/protocol/host_stub.h" |
| 28 #include "remoting/protocol/input_stub.h" | 27 #include "remoting/protocol/input_stub.h" |
| 29 #include "remoting/protocol/jingle_session_manager.h" | 28 #include "remoting/protocol/jingle_session_manager.h" |
| 30 #include "remoting/protocol/session_config.h" | 29 #include "remoting/protocol/session_config.h" |
| 31 | 30 |
| 32 using remoting::protocol::ConnectionToClient; | 31 using remoting::protocol::ConnectionToClient; |
| 33 using remoting::protocol::InputStub; | 32 using remoting::protocol::InputStub; |
| 34 | 33 |
| 35 namespace remoting { | 34 namespace remoting { |
| 36 | 35 |
| 37 // static | 36 // static |
| 38 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, | 37 ChromotingHost* ChromotingHost::Create(ChromotingHostContext* context, |
| 39 MutableHostConfig* config, | 38 MutableHostConfig* config, |
| 40 DesktopEnvironment* environment, | 39 DesktopEnvironment* environment, |
| 41 AccessVerifier* access_verifier, | |
| 42 bool allow_nat_traversal) { | 40 bool allow_nat_traversal) { |
| 43 return new ChromotingHost(context, config, environment, access_verifier, | 41 return new ChromotingHost(context, config, environment, allow_nat_traversal); |
| 44 allow_nat_traversal); | |
| 45 } | 42 } |
| 46 | 43 |
| 47 ChromotingHost::ChromotingHost(ChromotingHostContext* context, | 44 ChromotingHost::ChromotingHost(ChromotingHostContext* context, |
| 48 MutableHostConfig* config, | 45 MutableHostConfig* config, |
| 49 DesktopEnvironment* environment, | 46 DesktopEnvironment* environment, |
| 50 AccessVerifier* access_verifier, | |
| 51 bool allow_nat_traversal) | 47 bool allow_nat_traversal) |
| 52 : context_(context), | 48 : context_(context), |
| 53 desktop_environment_(environment), | 49 desktop_environment_(environment), |
| 54 config_(config), | 50 config_(config), |
| 55 access_verifier_(access_verifier), | |
| 56 allow_nat_traversal_(allow_nat_traversal), | 51 allow_nat_traversal_(allow_nat_traversal), |
| 57 stopping_recorders_(0), | 52 stopping_recorders_(0), |
| 58 state_(kInitial), | 53 state_(kInitial), |
| 59 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), | 54 protocol_config_(protocol::CandidateSessionConfig::CreateDefault()), |
| 60 is_curtained_(false), | 55 is_curtained_(false), |
| 61 is_it2me_(false) { | 56 is_it2me_(false) { |
| 62 DCHECK(desktop_environment_); | 57 DCHECK(desktop_environment_); |
| 63 desktop_environment_->set_host(this); | 58 desktop_environment_->set_host(this); |
| 64 } | 59 } |
| 65 | 60 |
| 66 ChromotingHost::~ChromotingHost() { | 61 ChromotingHost::~ChromotingHost() { |
| 67 DCHECK(clients_.empty()); | 62 DCHECK(clients_.empty()); |
| 68 } | 63 } |
| 69 | 64 |
| 70 void ChromotingHost::Start() { | 65 void ChromotingHost::Start() { |
| 71 if (!context_->network_message_loop()->BelongsToCurrentThread()) { | 66 if (!context_->network_message_loop()->BelongsToCurrentThread()) { |
| 72 context_->network_message_loop()->PostTask( | 67 context_->network_message_loop()->PostTask( |
| 73 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); | 68 FROM_HERE, base::Bind(&ChromotingHost::Start, this)); |
| 74 return; | 69 return; |
| 75 } | 70 } |
| 76 | 71 |
| 77 LOG(INFO) << "Starting host"; | 72 LOG(INFO) << "Starting host"; |
| 78 DCHECK(!signal_strategy_.get()); | 73 DCHECK(!signal_strategy_.get()); |
| 79 DCHECK(access_verifier_.get()); | |
| 80 | 74 |
| 81 // Make sure this object is not started. | 75 // Make sure this object is not started. |
| 82 if (state_ != kInitial) | 76 if (state_ != kInitial) |
| 83 return; | 77 return; |
| 84 state_ = kStarted; | 78 state_ = kStarted; |
| 85 | 79 |
| 86 // Use an XMPP connection to the Talk network for session signalling. | 80 // Use an XMPP connection to the Talk network for session signalling. |
| 87 std::string xmpp_login; | 81 std::string xmpp_login; |
| 88 std::string xmpp_auth_token; | 82 std::string xmpp_auth_token; |
| 89 std::string xmpp_auth_service; | 83 std::string xmpp_auth_service; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 (*it)->OnClientAuthenticated(jid); | 195 (*it)->OnClientAuthenticated(jid); |
| 202 } | 196 } |
| 203 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, | 197 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, |
| 204 // including closing the connection on failure of a critical operation. | 198 // including closing the connection on failure of a critical operation. |
| 205 EnableCurtainMode(true); | 199 EnableCurtainMode(true); |
| 206 | 200 |
| 207 std::string username = jid.substr(0, jid.find('/')); | 201 std::string username = jid.substr(0, jid.find('/')); |
| 208 desktop_environment_->OnConnect(username); | 202 desktop_environment_->OnConnect(username); |
| 209 } | 203 } |
| 210 | 204 |
| 205 void ChromotingHost::OnSessionAuthenticationFailed(ClientSession* client) { |
| 206 // Notify observers. |
| 207 for (StatusObserverList::iterator it = status_observers_.begin(); |
| 208 it != status_observers_.end(); ++it) { |
| 209 (*it)->OnAccessDenied(); |
| 210 } |
| 211 } |
| 212 |
| 211 void ChromotingHost::OnSessionClosed(ClientSession* client) { | 213 void ChromotingHost::OnSessionClosed(ClientSession* client) { |
| 212 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 214 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); |
| 213 | 215 |
| 214 scoped_ptr<ClientSession> client_destroyer(client); | 216 scoped_ptr<ClientSession> client_destroyer(client); |
| 215 | 217 |
| 216 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); | 218 ClientList::iterator it = std::find(clients_.begin(), clients_.end(), client); |
| 217 CHECK(it != clients_.end()); | 219 CHECK(it != clients_.end()); |
| 218 clients_.erase(it); | 220 clients_.erase(it); |
| 219 | 221 |
| 220 if (recorder_.get()) { | 222 if (recorder_.get()) { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 void ChromotingHost::OnIncomingSession( | 300 void ChromotingHost::OnIncomingSession( |
| 299 protocol::Session* session, | 301 protocol::Session* session, |
| 300 protocol::SessionManager::IncomingSessionResponse* response) { | 302 protocol::SessionManager::IncomingSessionResponse* response) { |
| 301 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 303 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); |
| 302 | 304 |
| 303 if (state_ != kStarted) { | 305 if (state_ != kStarted) { |
| 304 *response = protocol::SessionManager::DECLINE; | 306 *response = protocol::SessionManager::DECLINE; |
| 305 return; | 307 return; |
| 306 } | 308 } |
| 307 | 309 |
| 308 // Check that the client has access to the host. | |
| 309 if (!access_verifier_->VerifyPermissions(session->jid(), | |
| 310 session->initiator_token())) { | |
| 311 *response = protocol::SessionManager::DECLINE; | |
| 312 | |
| 313 // Notify observers. | |
| 314 for (StatusObserverList::iterator it = status_observers_.begin(); | |
| 315 it != status_observers_.end(); ++it) { | |
| 316 (*it)->OnAccessDenied(); | |
| 317 } | |
| 318 return; | |
| 319 } | |
| 320 | |
| 321 // If we are running Me2Mom and already have an authenticated client then | 310 // If we are running Me2Mom and already have an authenticated client then |
| 322 // one of the connections may be an attacker, so both are suspect. | 311 // one of the connections may be an attacker, so both are suspect. |
| 323 if (is_it2me_ && AuthenticatedClientsCount() > 0) { | 312 if (is_it2me_ && AuthenticatedClientsCount() > 0) { |
| 324 *response = protocol::SessionManager::DECLINE; | 313 *response = protocol::SessionManager::DECLINE; |
| 325 | 314 |
| 326 // Close existing sessions and shutdown the host. | 315 // Close existing sessions and shutdown the host. |
| 327 Shutdown(base::Closure()); | 316 Shutdown(base::Closure()); |
| 328 return; | 317 return; |
| 329 } | 318 } |
| 330 | 319 |
| 331 // TODO(simonmorris): The resolution is set in the video stream now, | 320 // TODO(simonmorris): The resolution is set in the video stream now, |
| 332 // so it doesn't need to be set here. | 321 // so it doesn't need to be set here. |
| 333 *protocol_config_->mutable_initial_resolution() = | 322 *protocol_config_->mutable_initial_resolution() = |
| 334 protocol::ScreenResolution(2048, 2048); | 323 protocol::ScreenResolution(2048, 2048); |
| 335 // TODO(sergeyu): Respect resolution requested by the client if supported. | 324 // TODO(sergeyu): Respect resolution requested by the client if supported. |
| 336 protocol::SessionConfig config; | 325 protocol::SessionConfig config; |
| 337 if (!protocol_config_->Select(session->candidate_config(), | 326 if (!protocol_config_->Select(session->candidate_config(), |
| 338 true /* force_host_resolution */, &config)) { | 327 true /* force_host_resolution */, &config)) { |
| 339 LOG(WARNING) << "Rejecting connection from " << session->jid() | 328 LOG(WARNING) << "Rejecting connection from " << session->jid() |
| 340 << " because no compatible configuration has been found."; | 329 << " because no compatible configuration has been found."; |
| 341 *response = protocol::SessionManager::INCOMPATIBLE; | 330 *response = protocol::SessionManager::INCOMPATIBLE; |
| 342 return; | 331 return; |
| 343 } | 332 } |
| 344 | 333 |
| 345 session->set_config(config); | 334 session->set_config(config); |
| 346 session->set_receiver_token( | |
| 347 GenerateHostAuthToken(session->initiator_token())); | |
| 348 | |
| 349 // Provide the Access Code as shared secret for SSL channel authentication. | 335 // Provide the Access Code as shared secret for SSL channel authentication. |
| 350 session->set_shared_secret(access_code_); | 336 session->set_shared_secret(access_code_); |
| 351 | 337 |
| 352 *response = protocol::SessionManager::ACCEPT; | 338 *response = protocol::SessionManager::ACCEPT; |
| 353 | 339 |
| 354 LOG(INFO) << "Client connected: " << session->jid(); | 340 LOG(INFO) << "Client connected: " << session->jid(); |
| 355 | 341 |
| 356 // Create a client object. | 342 // Create a client object. |
| 357 protocol::ConnectionToClient* connection = | 343 protocol::ConnectionToClient* connection = |
| 358 new protocol::ConnectionToClient(session); | 344 new protocol::ConnectionToClient(session); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 return EncoderRowBased::CreateVerbatimEncoder(); | 397 return EncoderRowBased::CreateVerbatimEncoder(); |
| 412 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { | 398 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { |
| 413 return EncoderRowBased::CreateZlibEncoder(); | 399 return EncoderRowBased::CreateZlibEncoder(); |
| 414 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { | 400 } else if (video_config.codec == protocol::ChannelConfig::CODEC_VP8) { |
| 415 return new remoting::EncoderVp8(); | 401 return new remoting::EncoderVp8(); |
| 416 } | 402 } |
| 417 | 403 |
| 418 return NULL; | 404 return NULL; |
| 419 } | 405 } |
| 420 | 406 |
| 421 std::string ChromotingHost::GenerateHostAuthToken( | |
| 422 const std::string& encoded_client_token) { | |
| 423 // TODO(ajwong): Return the signature of this instead. | |
| 424 return encoded_client_token; | |
| 425 } | |
| 426 | |
| 427 int ChromotingHost::AuthenticatedClientsCount() const { | 407 int ChromotingHost::AuthenticatedClientsCount() const { |
| 428 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); | 408 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); |
| 429 | 409 |
| 430 int authenticated_clients = 0; | 410 int authenticated_clients = 0; |
| 431 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end(); | 411 for (ClientList::const_iterator it = clients_.begin(); it != clients_.end(); |
| 432 ++it) { | 412 ++it) { |
| 433 if ((*it)->authenticated()) | 413 if ((*it)->authenticated()) |
| 434 ++authenticated_clients; | 414 ++authenticated_clients; |
| 435 } | 415 } |
| 436 return authenticated_clients; | 416 return authenticated_clients; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 486 } | 466 } |
| 487 | 467 |
| 488 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); | 468 for (std::vector<base::Closure>::iterator it = shutdown_tasks_.begin(); |
| 489 it != shutdown_tasks_.end(); ++it) { | 469 it != shutdown_tasks_.end(); ++it) { |
| 490 it->Run(); | 470 it->Run(); |
| 491 } | 471 } |
| 492 shutdown_tasks_.clear(); | 472 shutdown_tasks_.clear(); |
| 493 } | 473 } |
| 494 | 474 |
| 495 } // namespace remoting | 475 } // namespace remoting |
| OLD | NEW |