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" |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 // Provide the Access Code as shared secret for SSL channel authentication. | 293 // Provide the Access Code as shared secret for SSL channel authentication. |
294 session->set_shared_secret(access_code_); | 294 session->set_shared_secret(access_code_); |
295 | 295 |
296 *response = protocol::SessionManager::ACCEPT; | 296 *response = protocol::SessionManager::ACCEPT; |
297 | 297 |
298 LOG(INFO) << "Client connected: " << session->jid(); | 298 LOG(INFO) << "Client connected: " << session->jid(); |
299 | 299 |
300 // We accept the connection, so create a connection object. | 300 // We accept the connection, so create a connection object. |
301 ConnectionToClient* connection = new ConnectionToClient( | 301 ConnectionToClient* connection = new ConnectionToClient( |
302 context_->network_message_loop(), this); | 302 context_->network_message_loop(), this); |
| 303 connection->Init(session); |
303 | 304 |
304 // Create a client object. | 305 // Create a client object. |
305 ClientSession* client = new ClientSession( | 306 ClientSession* client = new ClientSession( |
306 this, | 307 this, |
307 UserAuthenticator::Create(), | 308 UserAuthenticator::Create(), |
308 connection, | 309 connection, |
309 desktop_environment_->event_executor()); | 310 desktop_environment_->event_executor()); |
310 connection->set_host_stub(client); | 311 connection->set_host_stub(client); |
311 connection->set_input_stub(client); | 312 connection->set_input_stub(client); |
312 | 313 |
313 connection->Init(session); | |
314 | |
315 clients_.push_back(client); | 314 clients_.push_back(client); |
316 } | 315 } |
317 | 316 |
318 void ChromotingHost::set_protocol_config( | 317 void ChromotingHost::set_protocol_config( |
319 protocol::CandidateSessionConfig* config) { | 318 protocol::CandidateSessionConfig* config) { |
320 DCHECK(config_.get()); | 319 DCHECK(config_.get()); |
321 DCHECK_EQ(state_, kInitial); | 320 DCHECK_EQ(state_, kInitial); |
322 protocol_config_.reset(config); | 321 protocol_config_.reset(config); |
323 } | 322 } |
324 | 323 |
(...skipping 29 matching lines...) Expand all Loading... |
354 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 353 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
355 DCHECK_EQ(state_, kInitial); | 354 DCHECK_EQ(state_, kInitial); |
356 | 355 |
357 ui_strings_ = ui_strings; | 356 ui_strings_ = ui_strings; |
358 } | 357 } |
359 | 358 |
360 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { | 359 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { |
361 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 360 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
362 | 361 |
363 // Find the client session corresponding to the given connection. | 362 // Find the client session corresponding to the given connection. |
364 ClientList::iterator client; | 363 ClientList::iterator it; |
365 for (client = clients_.begin(); client != clients_.end(); ++client) { | 364 for (it = clients_.begin(); it != clients_.end(); ++it) { |
366 if (client->get()->connection() == connection) | 365 if (it->get()->connection() == connection) |
367 break; | 366 break; |
368 } | 367 } |
369 if (client == clients_.end()) | 368 if (it == clients_.end()) |
370 return; | 369 return; |
371 | 370 |
372 // Remove the connection from the session manager and stop the session. | 371 scoped_refptr<ClientSession> client = *it; |
373 // TODO(hclam): Stop only if the last connection disconnected. | 372 |
| 373 clients_.erase(it); |
| 374 |
374 if (recorder_.get()) { | 375 if (recorder_.get()) { |
375 recorder_->RemoveConnection(connection); | 376 recorder_->RemoveConnection(connection); |
376 // The recorder only exists to serve the unique authenticated client. | |
377 // If that client has disconnected, then we can kill the recorder. | |
378 if (client->get()->authenticated()) | |
379 StopScreenRecorder(); | |
380 } | 377 } |
381 | 378 |
382 // Close the connection to client just to be safe. | 379 // Close the connection to client just to be safe. |
383 connection->Disconnect(); | 380 connection->Disconnect(); |
384 | 381 |
385 // Also remove reference to ConnectionToClient from this object. | 382 if (client->authenticated()) { |
386 int old_authenticated_clients = AuthenticatedClientsCount(); | |
387 clients_.erase(client); | |
388 | |
389 // Notify the observers of the change, if any. | |
390 int authenticated_clients = AuthenticatedClientsCount(); | |
391 if (old_authenticated_clients != authenticated_clients) { | |
392 for (StatusObserverList::iterator it = status_observers_.begin(); | 383 for (StatusObserverList::iterator it = status_observers_.begin(); |
393 it != status_observers_.end(); ++it) { | 384 it != status_observers_.end(); ++it) { |
394 (*it)->OnClientDisconnected(connection); | 385 (*it)->OnClientDisconnected(client->client_jid()); |
395 } | 386 } |
396 } | 387 } |
397 | 388 |
398 // Disable the "curtain" if there are no more active clients. | |
399 if (AuthenticatedClientsCount() == 0) { | 389 if (AuthenticatedClientsCount() == 0) { |
| 390 if (recorder_.get()) { |
| 391 // Stop the recorder if there are no more clients. |
| 392 StopScreenRecorder(); |
| 393 } |
| 394 |
| 395 // Disable the "curtain" if there are no more active clients. |
400 EnableCurtainMode(false); | 396 EnableCurtainMode(false); |
401 if (is_it2me_) { | 397 if (is_it2me_) { |
402 desktop_environment_->OnLastDisconnect(); | 398 desktop_environment_->OnLastDisconnect(); |
403 } | 399 } |
404 } | 400 } |
405 } | 401 } |
406 | 402 |
407 // TODO(sergeyu): Move this to SessionManager? | 403 // TODO(sergeyu): Move this to SessionManager? |
408 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { | 404 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { |
409 const protocol::ChannelConfig& video_config = config.video_config(); | 405 const protocol::ChannelConfig& video_config = config.video_config(); |
(...skipping 30 matching lines...) Expand all Loading... |
440 // about proper crash recovery and daemon mode. | 436 // about proper crash recovery and daemon mode. |
441 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. | 437 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. |
442 if (is_it2me_ || enable == is_curtained_) | 438 if (is_it2me_ || enable == is_curtained_) |
443 return; | 439 return; |
444 desktop_environment_->curtain()->EnableCurtainMode(enable); | 440 desktop_environment_->curtain()->EnableCurtainMode(enable); |
445 is_curtained_ = enable; | 441 is_curtained_ = enable; |
446 } | 442 } |
447 | 443 |
448 void ChromotingHost::LocalLoginSucceeded( | 444 void ChromotingHost::LocalLoginSucceeded( |
449 scoped_refptr<ConnectionToClient> connection) { | 445 scoped_refptr<ConnectionToClient> connection) { |
450 if (MessageLoop::current() != context_->main_message_loop()) { | 446 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); |
451 context_->main_message_loop()->PostTask( | 447 |
452 FROM_HERE, base::Bind(&ChromotingHost::LocalLoginSucceeded, this, | 448 context_->main_message_loop()->PostTask( |
453 connection)); | 449 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient, |
454 return; | 450 this, connection, connection->session()->config(), |
455 } | 451 connection->session()->jid())); |
| 452 } |
| 453 |
| 454 void ChromotingHost::AddAuthenticatedClient( |
| 455 scoped_refptr<ConnectionToClient> connection, |
| 456 const protocol::SessionConfig& config, |
| 457 const std::string& jid) { |
| 458 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
456 | 459 |
457 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); | 460 protocol::LocalLoginStatus* status = new protocol::LocalLoginStatus(); |
458 status->set_success(true); | 461 status->set_success(true); |
459 connection->client_stub()->BeginSessionResponse( | 462 connection->client_stub()->BeginSessionResponse( |
460 status, new DeleteTask<protocol::LocalLoginStatus>(status)); | 463 status, new DeleteTask<protocol::LocalLoginStatus>(status)); |
461 | 464 |
462 // Disconnect all other clients. | 465 // Disconnect all other clients. |
463 // Iterate over a copy of the list of clients, to avoid mutating the list | 466 // Iterate over a copy of the list of clients, to avoid mutating the list |
464 // while iterating over it. | 467 // while iterating over it. |
465 ClientList clients_copy(clients_); | 468 ClientList clients_copy(clients_); |
466 for (ClientList::const_iterator client = clients_copy.begin(); | 469 for (ClientList::const_iterator client = clients_copy.begin(); |
467 client != clients_copy.end(); client++) { | 470 client != clients_copy.end(); client++) { |
468 ConnectionToClient* connection_other = client->get()->connection(); | 471 ConnectionToClient* connection_other = client->get()->connection(); |
469 if (connection_other != connection) { | 472 if (connection_other != connection) { |
470 OnClientDisconnected(connection_other); | 473 OnClientDisconnected(connection_other); |
471 } | 474 } |
472 } | 475 } |
473 // Those disconnections should have killed the screen recorder. | 476 // Those disconnections should have killed the screen recorder. |
474 CHECK(recorder_.get() == NULL); | 477 CHECK(recorder_.get() == NULL); |
475 | 478 |
476 // Create a new RecordSession if there was none. | 479 // Create a new RecordSession if there was none. |
477 if (!recorder_.get()) { | 480 if (!recorder_.get()) { |
478 // Then we create a ScreenRecorder passing the message loops that | 481 // Then we create a ScreenRecorder passing the message loops that |
479 // it should run on. | 482 // it should run on. |
480 Encoder* encoder = CreateEncoder(connection->session()->config()); | 483 Encoder* encoder = CreateEncoder(config); |
481 | 484 |
482 recorder_ = new ScreenRecorder(context_->main_message_loop(), | 485 recorder_ = new ScreenRecorder(context_->main_message_loop(), |
483 context_->encode_message_loop(), | 486 context_->encode_message_loop(), |
484 context_->network_message_loop(), | 487 context_->network_message_loop(), |
485 desktop_environment_->capturer(), | 488 desktop_environment_->capturer(), |
486 encoder); | 489 encoder); |
487 } | 490 } |
488 | 491 |
489 // Immediately add the connection and start the session. | 492 // Immediately add the connection and start the session. |
490 recorder_->AddConnection(connection); | 493 recorder_->AddConnection(connection); |
491 recorder_->Start(); | 494 recorder_->Start(); |
492 // Notify observers that there is at least one authenticated client. | 495 // Notify observers that there is at least one authenticated client. |
493 for (StatusObserverList::iterator it = status_observers_.begin(); | 496 for (StatusObserverList::iterator it = status_observers_.begin(); |
494 it != status_observers_.end(); ++it) { | 497 it != status_observers_.end(); ++it) { |
495 (*it)->OnClientAuthenticated(connection); | 498 (*it)->OnClientAuthenticated(jid); |
496 } | 499 } |
497 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, | 500 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, |
498 // including closing the connection on failure of a critical operation. | 501 // including closing the connection on failure of a critical operation. |
499 EnableCurtainMode(true); | 502 EnableCurtainMode(true); |
500 if (is_it2me_) { | 503 if (is_it2me_) { |
501 std::string username = connection->session()->jid(); | 504 std::string username = jid; |
502 size_t pos = username.find('/'); | 505 size_t pos = username.find('/'); |
503 if (pos != std::string::npos) | 506 if (pos != std::string::npos) |
504 username.replace(pos, std::string::npos, ""); | 507 username.replace(pos, std::string::npos, ""); |
505 desktop_environment_->OnConnect(username); | 508 desktop_environment_->OnConnect(username); |
506 } | 509 } |
507 } | 510 } |
508 | 511 |
509 void ChromotingHost::LocalLoginFailed( | 512 void ChromotingHost::LocalLoginFailed( |
510 scoped_refptr<ConnectionToClient> connection) { | 513 scoped_refptr<ConnectionToClient> connection) { |
511 if (MessageLoop::current() != context_->main_message_loop()) { | 514 if (MessageLoop::current() != context_->main_message_loop()) { |
(...skipping 12 matching lines...) Expand all Loading... |
524 void ChromotingHost::ProcessPreAuthentication( | 527 void ChromotingHost::ProcessPreAuthentication( |
525 const scoped_refptr<ConnectionToClient>& connection) { | 528 const scoped_refptr<ConnectionToClient>& connection) { |
526 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); | 529 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); |
527 // Find the client session corresponding to the given connection. | 530 // Find the client session corresponding to the given connection. |
528 ClientList::iterator client; | 531 ClientList::iterator client; |
529 for (client = clients_.begin(); client != clients_.end(); ++client) { | 532 for (client = clients_.begin(); client != clients_.end(); ++client) { |
530 if (client->get()->connection() == connection) | 533 if (client->get()->connection() == connection) |
531 break; | 534 break; |
532 } | 535 } |
533 CHECK(client != clients_.end()); | 536 CHECK(client != clients_.end()); |
534 client->get()->OnAuthorizationComplete(true); | 537 |
| 538 context_->network_message_loop()->PostTask( |
| 539 FROM_HERE, base::Bind(&ClientSession::OnAuthorizationComplete, |
| 540 client->get(), true)); |
535 } | 541 } |
536 | 542 |
537 void ChromotingHost::StopScreenRecorder() { | 543 void ChromotingHost::StopScreenRecorder() { |
538 DCHECK(MessageLoop::current() == context_->main_message_loop()); | 544 DCHECK(MessageLoop::current() == context_->main_message_loop()); |
539 DCHECK(recorder_.get()); | 545 DCHECK(recorder_.get()); |
540 | 546 |
541 ++stopping_recorders_; | 547 ++stopping_recorders_; |
542 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); | 548 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); |
543 recorder_ = NULL; | 549 recorder_ = NULL; |
544 } | 550 } |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 634 |
629 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); | 635 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); |
630 it != shutdown_tasks_.end(); ++it) { | 636 it != shutdown_tasks_.end(); ++it) { |
631 (*it)->Run(); | 637 (*it)->Run(); |
632 delete *it; | 638 delete *it; |
633 } | 639 } |
634 shutdown_tasks_.clear(); | 640 shutdown_tasks_.clear(); |
635 } | 641 } |
636 | 642 |
637 } // namespace remoting | 643 } // namespace remoting |
OLD | NEW |