summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-09 06:19:33 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-02-09 06:19:33 +0000
commita209823c14a3468b6a7bd877ce53140e4c69d5f4 (patch)
tree81bbb776dd552c56cf3a9798fc372ef01d03f0ac /remoting
parentfe57eb240ec0b058a4e2ccc5fbfececa8952b4e6 (diff)
downloadchromium_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.cc219
-rw-r--r--remoting/protocol/pepper_session.h21
-rw-r--r--remoting/protocol/pepper_session_manager.cc26
-rw-r--r--remoting/protocol/pepper_session_unittest.cc13
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_;