diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-09 06:19:33 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-02-09 06:19:33 +0000 |
commit | a209823c14a3468b6a7bd877ce53140e4c69d5f4 (patch) | |
tree | 81bbb776dd552c56cf3a9798fc372ef01d03f0ac /remoting | |
parent | fe57eb240ec0b058a4e2ccc5fbfececa8952b4e6 (diff) | |
download | chromium_src-a209823c14a3468b6a7bd877ce53140e4c69d5f4.zip chromium_src-a209823c14a3468b6a7bd877ce53140e4c69d5f4.tar.gz chromium_src-a209823c14a3468b6a7bd877ce53140e4c69d5f4.tar.bz2 |
Implement support for incoming sessions in PepperSessionManager.
PepperSessionManager will be used on the host site so it needs to be able
accept incoming connections. Also fixed some client-side bugs (e.g.
session-terminate wasn't always sent).
BUG=110485
Review URL: http://codereview.chromium.org/9353003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@121203 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/protocol/pepper_session.cc | 219 | ||||
-rw-r--r-- | remoting/protocol/pepper_session.h | 21 | ||||
-rw-r--r-- | remoting/protocol/pepper_session_manager.cc | 26 | ||||
-rw-r--r-- | remoting/protocol/pepper_session_unittest.cc | 13 |
4 files changed, 195 insertions, 84 deletions
diff --git a/remoting/protocol/pepper_session.cc b/remoting/protocol/pepper_session.cc index 2ac5c15..1866ece 100644 --- a/remoting/protocol/pepper_session.cc +++ b/remoting/protocol/pepper_session.cc @@ -15,6 +15,7 @@ #include "remoting/protocol/content_description.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/pepper_session_manager.h" +#include "remoting/protocol/session_config.h" #include "third_party/libjingle/source/talk/p2p/base/candidate.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" @@ -30,12 +31,26 @@ namespace { // than zero because ports are opened asynchronously in the browser // process. const int kTransportInfoSendDelayMs = 2; + +Session::Error AuthRejectionReasonToError( + Authenticator::RejectionReason reason) { + switch (reason) { + case Authenticator::INVALID_CREDENTIALS: + return Session::AUTHENTICATION_FAILED; + case Authenticator::PROTOCOL_ERROR: + return Session::INCOMPATIBLE_PROTOCOL; + } + NOTREACHED(); + return Session::UNKNOWN_ERROR; +} + } // namespace PepperSession::PepperSession(PepperSessionManager* session_manager) : session_manager_(session_manager), state_(INITIALIZING), - error_(OK) { + error_(OK), + config_is_set_(false) { } PepperSession::~PepperSession() { @@ -46,13 +61,14 @@ PepperSession::~PepperSession() { void PepperSession::SetStateChangeCallback( const StateChangeCallback& callback) { DCHECK(CalledOnValidThread()); + DCHECK(!callback.is_null()); state_change_callback_ = callback; } void PepperSession::SetRouteChangeCallback( const RouteChangeCallback& callback) { - // This callback is not used on the client side yet. - NOTREACHED(); + DCHECK(CalledOnValidThread()); + route_change_callback_ = callback; } Session::Error PepperSession::error() { @@ -83,7 +99,6 @@ void PepperSession::StartConnection( // Send session-initiate message. JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE, session_id_); - message.from = session_manager_->signal_strategy_->GetLocalJid(); message.description.reset( new ContentDescription(candidate_config_->Clone(), authenticator_->GetNextMessage())); @@ -95,6 +110,71 @@ void PepperSession::StartConnection( SetState(CONNECTING); } +void PepperSession::InitializeIncomingConnection( + const JingleMessage& initiate_message, + scoped_ptr<Authenticator> authenticator) { + DCHECK(CalledOnValidThread()); + DCHECK(initiate_message.description.get()); + DCHECK(authenticator.get()); + DCHECK_EQ(authenticator->state(), Authenticator::WAITING_MESSAGE); + + peer_jid_ = initiate_message.from; + authenticator_ = authenticator.Pass(); + session_id_ = initiate_message.sid; + candidate_config_ = initiate_message.description->config()->Clone(); + + SetState(CONNECTING); +} + +void PepperSession::AcceptIncomingConnection( + const JingleMessage& initiate_message) { + DCHECK(config_is_set_); + + // Process the first authentication message. + const buzz::XmlElement* first_auth_message = + initiate_message.description->authenticator_message(); + + if (!first_auth_message) { + CloseInternal(INCOMPATIBLE_PROTOCOL); + return; + } + + DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); + authenticator_->ProcessMessage(first_auth_message); + if (authenticator_->state() == Authenticator::REJECTED) { + CloseInternal(AuthRejectionReasonToError( + authenticator_->rejection_reason())); + return; + } + + // Send the session-accept message. + JingleMessage message(peer_jid_, JingleMessage::SESSION_ACCEPT, + session_id_); + + scoped_ptr<buzz::XmlElement> auth_message; + if (authenticator_->state() == Authenticator::MESSAGE_READY) + auth_message = authenticator_->GetNextMessage(); + + message.description.reset( + new ContentDescription(CandidateSessionConfig::CreateFrom(config_), + auth_message.Pass())); + initiate_request_.reset(session_manager_->iq_sender()->SendIq( + message.ToXml(), + base::Bind(&PepperSession::OnSessionInitiateResponse, + base::Unretained(this)))); + + // Update state. + SetState(CONNECTED); + + if (authenticator_->state() == Authenticator::ACCEPTED) { + SetState(AUTHENTICATED); + } else { + DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); + } + + return; +} + void PepperSession::OnSessionInitiateResponse( const buzz::XmlElement* response) { const std::string& type = response->Attr(buzz::QName("", "type")); @@ -105,15 +185,10 @@ void PepperSession::OnSessionInitiateResponse( // TODO(sergeyu): There may be different reasons for error // here. Parse the response stanza to find failure reason. - OnError(PEER_IS_OFFLINE); + CloseInternal(PEER_IS_OFFLINE); } } -void PepperSession::OnError(Error error) { - error_ = error; - CloseInternal(true); -} - void PepperSession::CreateStreamChannel( const std::string& name, const StreamChannelCallback& callback) { @@ -169,23 +244,15 @@ const SessionConfig& PepperSession::config() { void PepperSession::set_config(const SessionConfig& config) { DCHECK(CalledOnValidThread()); - // set_config() should never be called on the client. - NOTREACHED(); + DCHECK(!config_is_set_); + config_ = config; + config_is_set_ = true; } void PepperSession::Close() { DCHECK(CalledOnValidThread()); - if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) { - // Send session-terminate message. - JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, - session_id_); - scoped_ptr<IqRequest> terminate_request( - session_manager_->iq_sender()->SendIq( - message.ToXml(), IqSender::ReplyCallback())); - } - - CloseInternal(false); + CloseInternal(OK); } void PepperSession::OnTransportCandidate(Transport* transport, @@ -251,7 +318,7 @@ void PepperSession::OnAccept(const JingleMessage& message, if (!auth_message) { DLOG(WARNING) << "Received session-accept without authentication message " << auth_message->Str(); - OnError(INCOMPATIBLE_PROTOCOL); + CloseInternal(INCOMPATIBLE_PROTOCOL); return; } @@ -259,7 +326,7 @@ void PepperSession::OnAccept(const JingleMessage& message, authenticator_->ProcessMessage(auth_message); if (!InitializeConfigFromDescription(message.description.get())) { - OnError(INCOMPATIBLE_PROTOCOL); + CloseInternal(INCOMPATIBLE_PROTOCOL); return; } @@ -285,7 +352,7 @@ void PepperSession::OnSessionInfo(const JingleMessage& message, LOG(WARNING) << "Received unexpected authenticator message " << message.info->Str(); *reply = JingleMessageReply(JingleMessageReply::UNEXPECTED_REQUEST); - OnError(INCOMPATIBLE_PROTOCOL); + CloseInternal(INCOMPATIBLE_PROTOCOL); return; } @@ -311,38 +378,37 @@ void PepperSession::ProcessTransportInfo(const JingleMessage& message) { void PepperSession::OnTerminate(const JingleMessage& message, JingleMessageReply* reply) { - if (state_ == CONNECTING) { - switch (message.reason) { - case JingleMessage::DECLINE: - OnError(SESSION_REJECTED); - break; - - case JingleMessage::INCOMPATIBLE_PARAMETERS: - OnError(INCOMPATIBLE_PROTOCOL); - break; - - default: - LOG(WARNING) << "Received session-terminate message " - "with an unexpected reason."; - OnError(SESSION_REJECTED); - } + if (state_ != CONNECTING && state_ != CONNECTED && state_ != AUTHENTICATED) { + LOG(WARNING) << "Received unexpected session-terminate message."; + CloseInternal(INCOMPATIBLE_PROTOCOL); return; } - if (state_ != CONNECTED && state_ != AUTHENTICATED) { - LOG(WARNING) << "Received unexpected session-terminate message."; + switch (message.reason) { + case JingleMessage::SUCCESS: + if (state_ == CONNECTING) { + error_ = SESSION_REJECTED; + } else { + error_ = OK; + } + break; + case JingleMessage::DECLINE: + error_ = AUTHENTICATION_FAILED; + break; + case JingleMessage::GENERAL_ERROR: + error_ = CHANNEL_CONNECTION_ERROR; + break; + case JingleMessage::INCOMPATIBLE_PARAMETERS: + error_ = INCOMPATIBLE_PROTOCOL; + break; + default: + error_ = UNKNOWN_ERROR; } - if (message.reason == JingleMessage::SUCCESS) { - CloseInternal(false); - } else if (message.reason == JingleMessage::DECLINE) { - OnError(AUTHENTICATION_FAILED); - } else if (message.reason == JingleMessage::GENERAL_ERROR) { - OnError(CHANNEL_CONNECTION_ERROR); - } else if (message.reason == JingleMessage::INCOMPATIBLE_PARAMETERS) { - OnError(INCOMPATIBLE_PROTOCOL); + if (error_ != OK) { + SetState(FAILED); } else { - OnError(UNKNOWN_ERROR); + SetState(CLOSED); } } @@ -380,14 +446,8 @@ void PepperSession::ProcessAuthenticationStep() { if (authenticator_->state() == Authenticator::ACCEPTED) { SetState(AUTHENTICATED); } else if (authenticator_->state() == Authenticator::REJECTED) { - switch (authenticator_->rejection_reason()) { - case Authenticator::INVALID_CREDENTIALS: - OnError(AUTHENTICATION_FAILED); - break; - case Authenticator::PROTOCOL_ERROR: - OnError(INCOMPATIBLE_PROTOCOL); - break; - } + CloseInternal(AuthRejectionReasonToError( + authenticator_->rejection_reason())); } } @@ -397,7 +457,7 @@ void PepperSession::OnSessionInfoResponse(const buzz::XmlElement* response) { LOG(ERROR) << "Received error in response to session-info message: \"" << response->Str() << "\". Terminating the session."; - OnError(INCOMPATIBLE_PROTOCOL); + CloseInternal(INCOMPATIBLE_PROTOCOL); } } @@ -409,10 +469,10 @@ void PepperSession::OnTransportInfoResponse(const buzz::XmlElement* response) { << "\". Terminating the session."; if (state_ == CONNECTING) { - OnError(PEER_IS_OFFLINE); + CloseInternal(PEER_IS_OFFLINE); } else { // Host has disconnected without sending session-terminate message. - CloseInternal(false); + CloseInternal(OK); } } } @@ -427,14 +487,43 @@ void PepperSession::SendTransportInfo() { } -void PepperSession::CloseInternal(bool failed) { +void PepperSession::CloseInternal(Error error) { DCHECK(CalledOnValidThread()); + if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) { + // Send session-terminate message with the appropriate error code. + JingleMessage::Reason reason; + switch (error) { + case OK: + reason = JingleMessage::SUCCESS; + break; + case SESSION_REJECTED: + case AUTHENTICATION_FAILED: + reason = JingleMessage::DECLINE; + break; + case INCOMPATIBLE_PROTOCOL: + reason = JingleMessage::INCOMPATIBLE_PARAMETERS; + break; + default: + reason = JingleMessage::GENERAL_ERROR; + } + + JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, + session_id_); + message.reason = reason; + scoped_ptr<IqRequest> terminate_request( + session_manager_->iq_sender()->SendIq( + message.ToXml(), IqSender::ReplyCallback())); + } + + error_ = error; + if (state_ != FAILED && state_ != CLOSED) { - if (failed) + if (error != OK) { SetState(FAILED); - else + } else { SetState(CLOSED); + } } } diff --git a/remoting/protocol/pepper_session.h b/remoting/protocol/pepper_session.h index c8c87e7..3730d3a 100644 --- a/remoting/protocol/pepper_session.h +++ b/remoting/protocol/pepper_session.h @@ -13,6 +13,7 @@ #include "base/timer.h" #include "crypto/rsa_private_key.h" #include "net/base/completion_callback.h" +#include "remoting/protocol/authenticator.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/session.h" #include "remoting/protocol/session_config.h" @@ -29,7 +30,6 @@ class IqRequest; namespace protocol { -class Authenticator; class PepperSessionManager; // Implements the protocol::Session interface using the Pepper P2P @@ -67,24 +67,25 @@ class PepperSession : public Session, private: friend class PepperSessionManager; - friend class PepperStreamChannel; typedef std::map<std::string, Transport*> ChannelsMap; explicit PepperSession(PepperSessionManager* session_manager); - // Start cs connection by sending session-initiate message. + // Start connection by sending session-initiate message. void StartConnection(const std::string& peer_jid, scoped_ptr<Authenticator> authenticator, scoped_ptr<CandidateSessionConfig> config, const StateChangeCallback& state_change_callback); + // Called by PepperSessionManager for incoming connections. + void InitializeIncomingConnection(const JingleMessage& initiate_message, + scoped_ptr<Authenticator> authenticator); + void AcceptIncomingConnection(const JingleMessage& initiate_message); + // Handler for session-initiate response. void OnSessionInitiateResponse(const buzz::XmlElement* response); - // Called when an error occurs. Sets |error_| and closes the session. - void OnError(Error error); - // Called by PepperSessionManager on incoming |message|. Must fill // in |reply|. void OnIncomingMessage(const JingleMessage& message, @@ -105,8 +106,10 @@ class PepperSession : public Session, void SendTransportInfo(); void OnTransportInfoResponse(const buzz::XmlElement* response); - // Close all the channels and terminate the session. - void CloseInternal(bool failed); + // Terminates the session and sends session-terminate if it is + // necessary. |error| specifies the error code in case when the + // session is being closed due to an error. + void CloseInternal(Error error); // Sets |state_| to |new_state| and calls state change callback. void SetState(State new_state); @@ -115,12 +118,14 @@ class PepperSession : public Session, std::string peer_jid_; scoped_ptr<CandidateSessionConfig> candidate_config_; StateChangeCallback state_change_callback_; + RouteChangeCallback route_change_callback_; std::string session_id_; State state_; Error error_; SessionConfig config_; + bool config_is_set_; scoped_ptr<Authenticator> authenticator_; diff --git a/remoting/protocol/pepper_session_manager.cc b/remoting/protocol/pepper_session_manager.cc index c8a67c6..1521294 100644 --- a/remoting/protocol/pepper_session_manager.cc +++ b/remoting/protocol/pepper_session_manager.cc @@ -9,6 +9,7 @@ #include "remoting/jingle_glue/jingle_info_request.h" #include "remoting/jingle_glue/signal_strategy.h" #include "remoting/protocol/authenticator.h" +#include "remoting/protocol/content_description.h" #include "remoting/protocol/jingle_messages.h" #include "remoting/protocol/pepper_session.h" #include "third_party/libjingle/source/talk/base/socketaddress.h" @@ -131,9 +132,28 @@ bool PepperSessionManager::OnSignalStrategyIncomingStanza( } if (message.action == JingleMessage::SESSION_INITIATE) { - SendReply(stanza, JingleMessageReply( - JingleMessageReply::NOT_IMPLEMENTED, - "Can't accept sessions on the client")); + // Description must be present in session-initiate messages. + DCHECK(message.description.get()); + + scoped_ptr<Authenticator> authenticator = + authenticator_factory_->CreateAuthenticator( + message.from, message.description->authenticator_message()); + + PepperSession* session = new PepperSession(this); + session->InitializeIncomingConnection(message, authenticator.Pass()); + sessions_[session->session_id_] = session; + + IncomingSessionResponse response = SessionManager::DECLINE; + listener_->OnIncomingSession(session, &response); + + if (response == SessionManager::ACCEPT) { + session->AcceptIncomingConnection(message); + } else { + session->Close(); + delete session; + DCHECK(sessions_.find(message.sid) == sessions_.end()); + } + return true; } diff --git a/remoting/protocol/pepper_session_unittest.cc b/remoting/protocol/pepper_session_unittest.cc index 0f14b3e..499f52e 100644 --- a/remoting/protocol/pepper_session_unittest.cc +++ b/remoting/protocol/pepper_session_unittest.cc @@ -13,8 +13,6 @@ #include "remoting/protocol/channel_authenticator.h" #include "remoting/protocol/connection_tester.h" #include "remoting/protocol/fake_authenticator.h" -#include "remoting/protocol/jingle_session.h" -#include "remoting/protocol/jingle_session_manager.h" #include "remoting/protocol/pepper_session_manager.h" #include "remoting/jingle_glue/jingle_thread.h" #include "remoting/jingle_glue/fake_signal_strategy.h" @@ -58,8 +56,7 @@ class MockSessionCallback { class PepperSessionTest : public testing::Test { public: - PepperSessionTest() - : message_loop_(talk_base::Thread::Current()) { + PepperSessionTest() { } // Helper method that handles OnIncomingSession(). @@ -96,8 +93,8 @@ class PepperSessionTest : public testing::Test { EXPECT_CALL(host_server_listener_, OnSessionManagerReady()) .Times(1); - host_server_.reset(new JingleSessionManager( - base::MessageLoopProxy::current())); + host_server_.reset(new PepperSessionManager( + scoped_ptr<TransportFactory>(NULL))); host_server_->Init(host_signal_strategy_.get(), &host_server_listener_, NetworkSettings(false)); @@ -191,12 +188,12 @@ class PepperSessionTest : public testing::Test { message_loop_.RunAllPending(); } - JingleThreadMessageLoop message_loop_; + MessageLoop message_loop_; scoped_ptr<FakeSignalStrategy> host_signal_strategy_; scoped_ptr<FakeSignalStrategy> client_signal_strategy_; - scoped_ptr<JingleSessionManager> host_server_; + scoped_ptr<PepperSessionManager> host_server_; MockSessionManagerListener host_server_listener_; scoped_ptr<PepperSessionManager> client_server_; MockSessionManagerListener client_server_listener_; |