Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: remoting/host/chromoting_host.cc

Issue 8476018: Move ConnectionToClient::EventHandler from ChromotingHost to ClientSession (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 } 123 }
124 if (shutdown_task) 124 if (shutdown_task)
125 shutdown_tasks_.push_back(shutdown_task); 125 shutdown_tasks_.push_back(shutdown_task);
126 if (state_ == kStopping) 126 if (state_ == kStopping)
127 return; 127 return;
128 state_ = kStopping; 128 state_ = kStopping;
129 } 129 }
130 130
131 // Disconnect all of the clients, implicitly stopping the ScreenRecorder. 131 // Disconnect all of the clients, implicitly stopping the ScreenRecorder.
132 while (!clients_.empty()) { 132 while (!clients_.empty()) {
133 OnClientDisconnected(clients_.front()->connection()); 133 scoped_refptr<ClientSession> client = clients_.front();
134 client->Disconnect();
135 OnClientDisconnected(client);
Wez 2011/11/09 01:35:07 It seems strange that client->Disconnect() doesn't
Sergey Ulanov 2011/11/09 19:26:13 That is intentional. I think the code is simpler w
Wez 2011/11/09 23:34:50 I think it's different in this case. ChromotingHo
Sergey Ulanov 2011/11/10 00:55:57 I agree that it may not be a problem in this parti
Wez 2011/11/10 01:25:12 The caller can't touch the session object after Di
134 } 136 }
135 137
136 ShutdownNetwork(); 138 ShutdownNetwork();
137 } 139 }
138 140
139 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) { 141 void ChromotingHost::AddStatusObserver(HostStatusObserver* observer) {
140 DCHECK_EQ(state_, kInitial); 142 DCHECK_EQ(state_, kInitial);
141 status_observers_.push_back(observer); 143 status_observers_.push_back(observer);
142 } 144 }
143 145
144 //////////////////////////////////////////////////////////////////////////// 146 ////////////////////////////////////////////////////////////////////////////
145 // protocol::ConnectionToClient::EventHandler implementations 147 // protocol::ClientSession::EventHandler implementation.
146 void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { 148 void ChromotingHost::OnSessionAuthenticated(ClientSession* client) {
147 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); 149 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
148 VLOG(1) << "Connection to client established."; 150 protocol::Session* session = client->connection()->session();
149 context_->main_message_loop()->PostTask( 151 context_->main_message_loop()->PostTask(
150 FROM_HERE, base::Bind(&ChromotingHost::ProcessPreAuthentication, this, 152 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient,
151 make_scoped_refptr(connection))); 153 this, make_scoped_refptr(client),
154 session->config(), session->jid()));
152 } 155 }
153 156
154 void ChromotingHost::OnConnectionClosed(ConnectionToClient* connection) { 157 void ChromotingHost::OnSessionClosed(ClientSession* client) {
155 DCHECK(context_->network_message_loop()->BelongsToCurrentThread()); 158 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
156 159
157 VLOG(1) << "Connection to client closed."; 160 VLOG(1) << "Connection to client closed.";
158 context_->main_message_loop()->PostTask( 161 context_->main_message_loop()->PostTask(
159 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this, 162 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this,
160 make_scoped_refptr(connection))); 163 make_scoped_refptr(client)));
161 } 164 }
162 165
163 void ChromotingHost::OnConnectionFailed(ConnectionToClient* connection) { 166 void ChromotingHost::OnSessionSequenceNumber(ClientSession* session,
164 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
165
166 LOG(ERROR) << "Connection failed unexpectedly.";
167 context_->main_message_loop()->PostTask(
168 FROM_HERE, base::Bind(&ChromotingHost::OnClientDisconnected, this,
169 make_scoped_refptr(connection)));
170 }
171
172 void ChromotingHost::OnSequenceNumberUpdated(ConnectionToClient* connection,
173 int64 sequence_number) { 167 int64 sequence_number) {
174 // Update the sequence number in ScreenRecorder. 168 // Update the sequence number in ScreenRecorder.
175 if (MessageLoop::current() != context_->main_message_loop()) { 169 if (MessageLoop::current() != context_->main_message_loop()) {
176 context_->main_message_loop()->PostTask( 170 context_->main_message_loop()->PostTask(
177 FROM_HERE, base::Bind(&ChromotingHost::OnSequenceNumberUpdated, this, 171 FROM_HERE, base::Bind(&ChromotingHost::OnSessionSequenceNumber, this,
178 make_scoped_refptr(connection), sequence_number)); 172 make_scoped_refptr(session), sequence_number));
179 return; 173 return;
180 } 174 }
181 175
182 if (recorder_.get()) 176 if (recorder_.get())
183 recorder_->UpdateSequenceNumber(sequence_number); 177 recorder_->UpdateSequenceNumber(sequence_number);
184 } 178 }
185 179
186 //////////////////////////////////////////////////////////////////////////// 180 ////////////////////////////////////////////////////////////////////////////
187 // SignalStrategy::StatusObserver implementations 181 // SignalStrategy::StatusObserver implementations
188 void ChromotingHost::OnStateChange( 182 void ChromotingHost::OnStateChange(
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 session->set_receiver_token( 279 session->set_receiver_token(
286 GenerateHostAuthToken(session->initiator_token())); 280 GenerateHostAuthToken(session->initiator_token()));
287 281
288 // Provide the Access Code as shared secret for SSL channel authentication. 282 // Provide the Access Code as shared secret for SSL channel authentication.
289 session->set_shared_secret(access_code_); 283 session->set_shared_secret(access_code_);
290 284
291 *response = protocol::SessionManager::ACCEPT; 285 *response = protocol::SessionManager::ACCEPT;
292 286
293 LOG(INFO) << "Client connected: " << session->jid(); 287 LOG(INFO) << "Client connected: " << session->jid();
294 288
295 // We accept the connection, so create a connection object.
296 ConnectionToClient* connection = new ConnectionToClient(
297 context_->network_message_loop(), this);
298 connection->Init(session);
299
300 // Create a client object. 289 // Create a client object.
290 scoped_refptr<protocol::ConnectionToClient> connection =
291 new protocol::ConnectionToClient(context_->network_message_loop(),
292 session);
301 ClientSession* client = new ClientSession( 293 ClientSession* client = new ClientSession(
302 this, 294 this, connection,
303 connection,
304 desktop_environment_->event_executor(), 295 desktop_environment_->event_executor(),
305 desktop_environment_->capturer()); 296 desktop_environment_->capturer());
306 connection->set_host_stub(client);
307 connection->set_input_stub(client);
308 297
309 clients_.push_back(client); 298 clients_.push_back(client);
310 } 299 }
311 300
312 void ChromotingHost::set_protocol_config( 301 void ChromotingHost::set_protocol_config(
313 protocol::CandidateSessionConfig* config) { 302 protocol::CandidateSessionConfig* config) {
314 DCHECK(config_.get()); 303 DCHECK(config_.get());
315 DCHECK_EQ(state_, kInitial); 304 DCHECK_EQ(state_, kInitial);
316 protocol_config_.reset(config); 305 protocol_config_.reset(config);
317 } 306 }
(...skipping 26 matching lines...) Expand all
344 desktop_environment_->OnPause(pause); 333 desktop_environment_->OnPause(pause);
345 } 334 }
346 335
347 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) { 336 void ChromotingHost::SetUiStrings(const UiStrings& ui_strings) {
348 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 337 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
349 DCHECK_EQ(state_, kInitial); 338 DCHECK_EQ(state_, kInitial);
350 339
351 ui_strings_ = ui_strings; 340 ui_strings_ = ui_strings;
352 } 341 }
353 342
354 void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { 343 void ChromotingHost::OnClientDisconnected(ClientSession* client) {
355 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 344 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
356 345
357 // Find the client session corresponding to the given connection. 346 scoped_refptr<ClientSession> client_ref = client;
347
358 ClientList::iterator it; 348 ClientList::iterator it;
359 for (it = clients_.begin(); it != clients_.end(); ++it) { 349 for (it = clients_.begin(); it != clients_.end(); ++it) {
360 if (it->get()->connection() == connection) 350 if (it->get() == client)
361 break; 351 break;
362 } 352 }
363 if (it == clients_.end())
364 return;
365
366 scoped_refptr<ClientSession> client = *it;
367
368 clients_.erase(it); 353 clients_.erase(it);
369 354
370 if (recorder_.get()) { 355 if (recorder_.get()) {
371 recorder_->RemoveConnection(connection); 356 recorder_->RemoveConnection(client->connection());
372 } 357 }
373 358
374 // Close the connection to client just to be safe.
375 // TODO(garykac): This should be removed when we revisit our shutdown and
376 // disconnect code. This should only need to be done in
377 // ClientSession::Disconnect().
378 connection->Disconnect();
379
380 for (StatusObserverList::iterator it = status_observers_.begin(); 359 for (StatusObserverList::iterator it = status_observers_.begin();
381 it != status_observers_.end(); ++it) { 360 it != status_observers_.end(); ++it) {
382 (*it)->OnClientDisconnected(client->client_jid()); 361 (*it)->OnClientDisconnected(client->client_jid());
383 } 362 }
384 363
385 if (AuthenticatedClientsCount() == 0) { 364 if (AuthenticatedClientsCount() == 0) {
386 if (recorder_.get()) { 365 if (recorder_.get()) {
387 // Stop the recorder if there are no more clients. 366 // Stop the recorder if there are no more clients.
388 StopScreenRecorder(); 367 StopScreenRecorder();
389 } 368 }
390 369
391 // Disable the "curtain" if there are no more active clients. 370 // Disable the "curtain" if there are no more active clients.
392 EnableCurtainMode(false); 371 EnableCurtainMode(false);
393 if (is_it2me_) { 372 desktop_environment_->OnLastDisconnect();
394 desktop_environment_->OnLastDisconnect();
395 }
396 } 373 }
397
398 client->OnDisconnected();
399 } 374 }
400 375
401 // TODO(sergeyu): Move this to SessionManager? 376 // TODO(sergeyu): Move this to SessionManager?
402 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) { 377 Encoder* ChromotingHost::CreateEncoder(const protocol::SessionConfig& config) {
403 const protocol::ChannelConfig& video_config = config.video_config(); 378 const protocol::ChannelConfig& video_config = config.video_config();
404 379
405 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) { 380 if (video_config.codec == protocol::ChannelConfig::CODEC_VERBATIM) {
406 return EncoderRowBased::CreateVerbatimEncoder(); 381 return EncoderRowBased::CreateVerbatimEncoder();
407 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) { 382 } else if (video_config.codec == protocol::ChannelConfig::CODEC_ZIP) {
408 return EncoderRowBased::CreateZlibEncoder(); 383 return EncoderRowBased::CreateZlibEncoder();
(...skipping 23 matching lines...) Expand all
432 void ChromotingHost::EnableCurtainMode(bool enable) { 407 void ChromotingHost::EnableCurtainMode(bool enable) {
433 // TODO(jamiewalch): This will need to be more sophisticated when we think 408 // TODO(jamiewalch): This will need to be more sophisticated when we think
434 // about proper crash recovery and daemon mode. 409 // about proper crash recovery and daemon mode.
435 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost. 410 // TODO(wez): CurtainMode shouldn't be driven directly by ChromotingHost.
436 if (is_it2me_ || enable == is_curtained_) 411 if (is_it2me_ || enable == is_curtained_)
437 return; 412 return;
438 desktop_environment_->curtain()->EnableCurtainMode(enable); 413 desktop_environment_->curtain()->EnableCurtainMode(enable);
439 is_curtained_ = enable; 414 is_curtained_ = enable;
440 } 415 }
441 416
442 void ChromotingHost::OnAuthenticationComplete(
443 scoped_refptr<ConnectionToClient> connection) {
444 DCHECK(context_->network_message_loop()->BelongsToCurrentThread());
445
446 context_->main_message_loop()->PostTask(
447 FROM_HERE, base::Bind(&ChromotingHost::AddAuthenticatedClient,
448 this, connection, connection->session()->config(),
449 connection->session()->jid()));
450 }
451
452 void ChromotingHost::AddAuthenticatedClient( 417 void ChromotingHost::AddAuthenticatedClient(
453 scoped_refptr<ConnectionToClient> connection, 418 ClientSession* client,
454 const protocol::SessionConfig& config, 419 const protocol::SessionConfig& config,
455 const std::string& jid) { 420 const std::string& jid) {
456 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); 421 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
457 422
458 // Disconnect all other clients. 423 // Disconnect all other clients.
459 // Iterate over a copy of the list of clients, to avoid mutating the list 424 // Iterate over a copy of the list of clients, to avoid mutating the list
460 // while iterating over it. 425 // while iterating over it.
461 ClientList clients_copy(clients_); 426 ClientList clients_copy(clients_);
462 for (ClientList::const_iterator client = clients_copy.begin(); 427 for (ClientList::const_iterator other_client = clients_copy.begin();
463 client != clients_copy.end(); client++) { 428 other_client != clients_copy.end(); ++other_client) {
464 ConnectionToClient* connection_other = client->get()->connection(); 429 if ((*other_client) != client) {
465 if (connection_other != connection) { 430 (*other_client)->Disconnect();
466 OnClientDisconnected(connection_other); 431 OnClientDisconnected(*other_client);
467 } 432 }
468 } 433 }
434
469 // Those disconnections should have killed the screen recorder. 435 // Those disconnections should have killed the screen recorder.
470 CHECK(recorder_.get() == NULL); 436 CHECK(recorder_.get() == NULL);
471 437
472 // Create a new RecordSession if there was none. 438 // Create a new RecordSession if there was none.
473 if (!recorder_.get()) { 439 if (!recorder_.get()) {
474 // Then we create a ScreenRecorder passing the message loops that 440 // Then we create a ScreenRecorder passing the message loops that
475 // it should run on. 441 // it should run on.
476 Encoder* encoder = CreateEncoder(config); 442 Encoder* encoder = CreateEncoder(config);
477 443
478 recorder_ = new ScreenRecorder(context_->main_message_loop(), 444 recorder_ = new ScreenRecorder(context_->main_message_loop(),
479 context_->encode_message_loop(), 445 context_->encode_message_loop(),
480 context_->network_message_loop(), 446 context_->network_message_loop(),
481 desktop_environment_->capturer(), 447 desktop_environment_->capturer(),
482 encoder); 448 encoder);
483 } 449 }
484 450
485 // Immediately add the connection and start the session. 451 // Immediately add the connection and start the session.
486 recorder_->AddConnection(connection); 452 recorder_->AddConnection(client->connection());
487 recorder_->Start(); 453 recorder_->Start();
488 // Notify observers that there is at least one authenticated client. 454 // Notify observers that there is at least one authenticated client.
489 for (StatusObserverList::iterator it = status_observers_.begin(); 455 for (StatusObserverList::iterator it = status_observers_.begin();
490 it != status_observers_.end(); ++it) { 456 it != status_observers_.end(); ++it) {
491 (*it)->OnClientAuthenticated(jid); 457 (*it)->OnClientAuthenticated(jid);
492 } 458 }
493 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect, 459 // TODO(jamiewalch): Tidy up actions to be taken on connect/disconnect,
494 // including closing the connection on failure of a critical operation. 460 // including closing the connection on failure of a critical operation.
495 EnableCurtainMode(true); 461 EnableCurtainMode(true);
496 if (is_it2me_) { 462 if (is_it2me_) {
497 std::string username = jid; 463 std::string username = jid;
498 size_t pos = username.find('/'); 464 size_t pos = username.find('/');
499 if (pos != std::string::npos) 465 if (pos != std::string::npos)
500 username.replace(pos, std::string::npos, ""); 466 username.replace(pos, std::string::npos, "");
501 desktop_environment_->OnConnect(username); 467 desktop_environment_->OnConnect(username);
502 } 468 }
503 } 469 }
504 470
505 void ChromotingHost::ProcessPreAuthentication(
506 const scoped_refptr<ConnectionToClient>& connection) {
507 DCHECK_EQ(context_->main_message_loop(), MessageLoop::current());
508 // Find the client session corresponding to the given connection.
509 ClientList::iterator client;
510 for (client = clients_.begin(); client != clients_.end(); ++client) {
511 if (client->get()->connection() == connection)
512 break;
513 }
514 CHECK(client != clients_.end());
515
516 context_->network_message_loop()->PostTask(
517 FROM_HERE, base::Bind(&ClientSession::OnAuthenticationComplete,
518 client->get()));
519 }
520
521 void ChromotingHost::StopScreenRecorder() { 471 void ChromotingHost::StopScreenRecorder() {
522 DCHECK(MessageLoop::current() == context_->main_message_loop()); 472 DCHECK(MessageLoop::current() == context_->main_message_loop());
523 DCHECK(recorder_.get()); 473 DCHECK(recorder_.get());
524 474
525 ++stopping_recorders_; 475 ++stopping_recorders_;
526 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this)); 476 recorder_->Stop(base::Bind(&ChromotingHost::OnScreenRecorderStopped, this));
527 recorder_ = NULL; 477 recorder_ = NULL;
528 } 478 }
529 479
530 void ChromotingHost::OnScreenRecorderStopped() { 480 void ChromotingHost::OnScreenRecorderStopped() {
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 562
613 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin(); 563 for (std::vector<Task*>::iterator it = shutdown_tasks_.begin();
614 it != shutdown_tasks_.end(); ++it) { 564 it != shutdown_tasks_.end(); ++it) {
615 (*it)->Run(); 565 (*it)->Run();
616 delete *it; 566 delete *it;
617 } 567 }
618 shutdown_tasks_.clear(); 568 shutdown_tasks_.clear();
619 } 569 }
620 570
621 } // namespace remoting 571 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698