| 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/protocol/jingle_session.h" | 5 #include "remoting/protocol/jingle_session.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/rand_util.h" | 8 #include "base/rand_util.h" |
| 9 #include "base/single_thread_task_runner.h" |
| 9 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
| 10 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/thread_task_runner_handle.h" |
| 11 #include "base/time/time.h" | 13 #include "base/time/time.h" |
| 12 #include "remoting/base/constants.h" | 14 #include "remoting/base/constants.h" |
| 13 #include "remoting/jingle_glue/iq_sender.h" | 15 #include "remoting/jingle_glue/iq_sender.h" |
| 14 #include "remoting/protocol/authenticator.h" | 16 #include "remoting/protocol/authenticator.h" |
| 15 #include "remoting/protocol/channel_authenticator.h" | 17 #include "remoting/protocol/channel_authenticator.h" |
| 16 #include "remoting/protocol/channel_multiplexer.h" | 18 #include "remoting/protocol/channel_multiplexer.h" |
| 17 #include "remoting/protocol/content_description.h" | 19 #include "remoting/protocol/content_description.h" |
| 18 #include "remoting/protocol/jingle_messages.h" | 20 #include "remoting/protocol/jingle_messages.h" |
| 19 #include "remoting/protocol/jingle_session_manager.h" | 21 #include "remoting/protocol/jingle_session_manager.h" |
| 20 #include "remoting/protocol/session_config.h" | 22 #include "remoting/protocol/session_config.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 return UNKNOWN_ERROR; | 58 return UNKNOWN_ERROR; |
| 57 } | 59 } |
| 58 | 60 |
| 59 } // namespace | 61 } // namespace |
| 60 | 62 |
| 61 JingleSession::JingleSession(JingleSessionManager* session_manager) | 63 JingleSession::JingleSession(JingleSessionManager* session_manager) |
| 62 : session_manager_(session_manager), | 64 : session_manager_(session_manager), |
| 63 event_handler_(NULL), | 65 event_handler_(NULL), |
| 64 state_(INITIALIZING), | 66 state_(INITIALIZING), |
| 65 error_(OK), | 67 error_(OK), |
| 66 config_is_set_(false) { | 68 config_is_set_(false), |
| 69 weak_factory_(this) { |
| 67 } | 70 } |
| 68 | 71 |
| 69 JingleSession::~JingleSession() { | 72 JingleSession::~JingleSession() { |
| 70 channel_multiplexer_.reset(); | 73 channel_multiplexer_.reset(); |
| 71 STLDeleteContainerPointers(pending_requests_.begin(), | 74 STLDeleteContainerPointers(pending_requests_.begin(), |
| 72 pending_requests_.end()); | 75 pending_requests_.end()); |
| 73 STLDeleteContainerPointers(transport_info_requests_.begin(), | 76 STLDeleteContainerPointers(transport_info_requests_.begin(), |
| 74 transport_info_requests_.end()); | 77 transport_info_requests_.end()); |
| 75 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); | 78 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); |
| 76 session_manager_->SessionDestroyed(this); | 79 session_manager_->SessionDestroyed(this); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 auth_message.Pass())); | 177 auth_message.Pass())); |
| 175 SendMessage(message); | 178 SendMessage(message); |
| 176 | 179 |
| 177 // Update state. | 180 // Update state. |
| 178 SetState(CONNECTED); | 181 SetState(CONNECTED); |
| 179 | 182 |
| 180 if (authenticator_->state() == Authenticator::ACCEPTED) { | 183 if (authenticator_->state() == Authenticator::ACCEPTED) { |
| 181 SetState(AUTHENTICATED); | 184 SetState(AUTHENTICATED); |
| 182 } else { | 185 } else { |
| 183 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); | 186 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); |
| 187 if (authenticator_->started()) { |
| 188 SetState(AUTHENTICATING); |
| 189 } |
| 184 } | 190 } |
| 185 | |
| 186 return; | |
| 187 } | 191 } |
| 188 | 192 |
| 189 const std::string& JingleSession::jid() { | 193 const std::string& JingleSession::jid() { |
| 190 DCHECK(CalledOnValidThread()); | 194 DCHECK(CalledOnValidThread()); |
| 191 return peer_jid_; | 195 return peer_jid_; |
| 192 } | 196 } |
| 193 | 197 |
| 194 const CandidateSessionConfig* JingleSession::candidate_config() { | 198 const CandidateSessionConfig* JingleSession::candidate_config() { |
| 195 DCHECK(CalledOnValidThread()); | 199 DCHECK(CalledOnValidThread()); |
| 196 return candidate_config_.get(); | 200 return candidate_config_.get(); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 } | 482 } |
| 479 | 483 |
| 480 void JingleSession::OnSessionInfo(const JingleMessage& message, | 484 void JingleSession::OnSessionInfo(const JingleMessage& message, |
| 481 const ReplyCallback& reply_callback) { | 485 const ReplyCallback& reply_callback) { |
| 482 if (!message.info.get() || | 486 if (!message.info.get() || |
| 483 !Authenticator::IsAuthenticatorMessage(message.info.get())) { | 487 !Authenticator::IsAuthenticatorMessage(message.info.get())) { |
| 484 reply_callback.Run(JingleMessageReply::UNSUPPORTED_INFO); | 488 reply_callback.Run(JingleMessageReply::UNSUPPORTED_INFO); |
| 485 return; | 489 return; |
| 486 } | 490 } |
| 487 | 491 |
| 488 if (state_ != CONNECTED || | 492 if ((state_ != CONNECTED && state_ != AUTHENTICATING) || |
| 489 authenticator_->state() != Authenticator::WAITING_MESSAGE) { | 493 authenticator_->state() != Authenticator::WAITING_MESSAGE) { |
| 490 LOG(WARNING) << "Received unexpected authenticator message " | 494 LOG(WARNING) << "Received unexpected authenticator message " |
| 491 << message.info->Str(); | 495 << message.info->Str(); |
| 492 reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST); | 496 reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST); |
| 493 CloseInternal(INCOMPATIBLE_PROTOCOL); | 497 CloseInternal(INCOMPATIBLE_PROTOCOL); |
| 494 return; | 498 return; |
| 495 } | 499 } |
| 496 | 500 |
| 497 reply_callback.Run(JingleMessageReply::NONE); | 501 reply_callback.Run(JingleMessageReply::NONE); |
| 498 | 502 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 510 } else { | 514 } else { |
| 511 // Transport info was received before the channel was created. | 515 // Transport info was received before the channel was created. |
| 512 // This could happen due to messages being reordered on the wire. | 516 // This could happen due to messages being reordered on the wire. |
| 513 pending_remote_candidates_.push_back(*it); | 517 pending_remote_candidates_.push_back(*it); |
| 514 } | 518 } |
| 515 } | 519 } |
| 516 } | 520 } |
| 517 | 521 |
| 518 void JingleSession::OnTerminate(const JingleMessage& message, | 522 void JingleSession::OnTerminate(const JingleMessage& message, |
| 519 const ReplyCallback& reply_callback) { | 523 const ReplyCallback& reply_callback) { |
| 520 if (state_ != CONNECTING && state_ != ACCEPTING && state_ != CONNECTED && | 524 if (!is_session_active()) { |
| 521 state_ != AUTHENTICATED) { | |
| 522 LOG(WARNING) << "Received unexpected session-terminate message."; | 525 LOG(WARNING) << "Received unexpected session-terminate message."; |
| 523 reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST); | 526 reply_callback.Run(JingleMessageReply::UNEXPECTED_REQUEST); |
| 524 return; | 527 return; |
| 525 } | 528 } |
| 526 | 529 |
| 527 reply_callback.Run(JingleMessageReply::NONE); | 530 reply_callback.Run(JingleMessageReply::NONE); |
| 528 | 531 |
| 529 switch (message.reason) { | 532 switch (message.reason) { |
| 530 case JingleMessage::SUCCESS: | 533 case JingleMessage::SUCCESS: |
| 531 if (state_ == CONNECTING) { | 534 if (state_ == CONNECTING) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 return false; | 573 return false; |
| 571 } | 574 } |
| 572 | 575 |
| 573 return true; | 576 return true; |
| 574 } | 577 } |
| 575 | 578 |
| 576 void JingleSession::ProcessAuthenticationStep() { | 579 void JingleSession::ProcessAuthenticationStep() { |
| 577 DCHECK(CalledOnValidThread()); | 580 DCHECK(CalledOnValidThread()); |
| 578 DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE); | 581 DCHECK_NE(authenticator_->state(), Authenticator::PROCESSING_MESSAGE); |
| 579 | 582 |
| 580 if (state_ != CONNECTED) { | 583 if (state_ != CONNECTED && state_ != AUTHENTICATING) { |
| 581 DCHECK(state_ == FAILED || state_ == CLOSED); | 584 DCHECK(state_ == FAILED || state_ == CLOSED); |
| 582 // The remote host closed the connection while the authentication was being | 585 // The remote host closed the connection while the authentication was being |
| 583 // processed asynchronously, nothing to do. | 586 // processed asynchronously, nothing to do. |
| 584 return; | 587 return; |
| 585 } | 588 } |
| 586 | 589 |
| 587 if (authenticator_->state() == Authenticator::MESSAGE_READY) { | 590 if (authenticator_->state() == Authenticator::MESSAGE_READY) { |
| 588 JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_); | 591 JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_); |
| 589 message.info = authenticator_->GetNextMessage(); | 592 message.info = authenticator_->GetNextMessage(); |
| 590 DCHECK(message.info.get()); | 593 DCHECK(message.info.get()); |
| 591 SendMessage(message); | 594 SendMessage(message); |
| 592 } | 595 } |
| 593 DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY); | 596 DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY); |
| 594 | 597 |
| 598 // The current JingleSession object can be destroyed by event_handler of |
| 599 // SetState(AUTHENTICATING) and cause subsequent dereferencing of the this |
| 600 // pointer to crash. To protect against it, we run ContinueAuthenticationStep |
| 601 // asychronously using a weak pointer. |
| 602 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 603 FROM_HERE, |
| 604 base::Bind(&JingleSession::ContinueAuthenticationStep, |
| 605 weak_factory_.GetWeakPtr())); |
| 606 |
| 607 if (authenticator_->started()) { |
| 608 SetState(AUTHENTICATING); |
| 609 } |
| 610 } |
| 611 |
| 612 void JingleSession::ContinueAuthenticationStep() { |
| 595 if (authenticator_->state() == Authenticator::ACCEPTED) { | 613 if (authenticator_->state() == Authenticator::ACCEPTED) { |
| 596 SetState(AUTHENTICATED); | 614 SetState(AUTHENTICATED); |
| 597 } else if (authenticator_->state() == Authenticator::REJECTED) { | 615 } else if (authenticator_->state() == Authenticator::REJECTED) { |
| 598 CloseInternal(AuthRejectionReasonToErrorCode( | 616 CloseInternal(AuthRejectionReasonToErrorCode( |
| 599 authenticator_->rejection_reason())); | 617 authenticator_->rejection_reason())); |
| 600 } | 618 } |
| 601 } | 619 } |
| 602 | 620 |
| 603 void JingleSession::CloseInternal(ErrorCode error) { | 621 void JingleSession::CloseInternal(ErrorCode error) { |
| 604 DCHECK(CalledOnValidThread()); | 622 DCHECK(CalledOnValidThread()); |
| 605 | 623 |
| 606 if (state_ == CONNECTING || state_ == ACCEPTING || state_ == CONNECTED || | 624 if (is_session_active()) { |
| 607 state_ == AUTHENTICATED) { | |
| 608 // Send session-terminate message with the appropriate error code. | 625 // Send session-terminate message with the appropriate error code. |
| 609 JingleMessage::Reason reason; | 626 JingleMessage::Reason reason; |
| 610 switch (error) { | 627 switch (error) { |
| 611 case OK: | 628 case OK: |
| 612 reason = JingleMessage::SUCCESS; | 629 reason = JingleMessage::SUCCESS; |
| 613 break; | 630 break; |
| 614 case SESSION_REJECTED: | 631 case SESSION_REJECTED: |
| 615 case AUTHENTICATION_FAILED: | 632 case AUTHENTICATION_FAILED: |
| 616 reason = JingleMessage::DECLINE; | 633 reason = JingleMessage::DECLINE; |
| 617 break; | 634 break; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 648 if (new_state != state_) { | 665 if (new_state != state_) { |
| 649 DCHECK_NE(state_, CLOSED); | 666 DCHECK_NE(state_, CLOSED); |
| 650 DCHECK_NE(state_, FAILED); | 667 DCHECK_NE(state_, FAILED); |
| 651 | 668 |
| 652 state_ = new_state; | 669 state_ = new_state; |
| 653 if (event_handler_) | 670 if (event_handler_) |
| 654 event_handler_->OnSessionStateChange(new_state); | 671 event_handler_->OnSessionStateChange(new_state); |
| 655 } | 672 } |
| 656 } | 673 } |
| 657 | 674 |
| 675 bool JingleSession::is_session_active() { |
| 676 return state_ == CONNECTING || state_ == ACCEPTING || state_ == CONNECTED || |
| 677 state_ == AUTHENTICATING || state_ == AUTHENTICATED; |
| 678 } |
| 679 |
| 658 } // namespace protocol | 680 } // namespace protocol |
| 659 } // namespace remoting | 681 } // namespace remoting |
| OLD | NEW |