diff options
21 files changed, 339 insertions, 692 deletions
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 19d87b1..f38e928 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -85,13 +85,13 @@ ChromotingHost::~ChromotingHost() { } void ChromotingHost::Start() { - if (MessageLoop::current() != context_->main_message_loop()) { - context_->main_message_loop()->PostTask( + if (MessageLoop::current() != context_->network_message_loop()) { + context_->network_message_loop()->PostTask( FROM_HERE, base::Bind(&ChromotingHost::Start, this)); return; } - DCHECK(!jingle_client_); + DCHECK(!signal_strategy_.get()); DCHECK(access_verifier_.get()); // Make sure this object is not started. @@ -117,10 +117,7 @@ void ChromotingHost::Start() { new XmppSignalStrategy(context_->jingle_thread(), xmpp_login, xmpp_auth_token, xmpp_auth_service)); - jingle_client_ = new JingleClient(context_->network_message_loop(), - signal_strategy_.get(), - NULL, NULL, NULL, this); - jingle_client_->Init(); + signal_strategy_->Init(this); } // This method is called when we need to destroy the host process. @@ -165,10 +162,10 @@ void ChromotingHost::Shutdown(Task* shutdown_task) { // Stop chromotocol session manager. if (session_manager_) { session_manager_->Close( - NewRunnableMethod(this, &ChromotingHost::ShutdownJingleClient)); + NewRunnableMethod(this, &ChromotingHost::ShutdownSignaling)); session_manager_ = NULL; } else { - ShutdownJingleClient(); + ShutdownSignaling(); } } @@ -224,19 +221,17 @@ void ChromotingHost::OnSequenceNumberUpdated(ConnectionToClient* connection, //////////////////////////////////////////////////////////////////////////// // JingleClient::Callback implementations -void ChromotingHost::OnStateChange(JingleClient* jingle_client, - JingleClient::State state) { +void ChromotingHost::OnStateChange( + SignalStrategy::StatusObserver::State state) { DCHECK_EQ(MessageLoop::current(), context_->network_message_loop()); - if (state == JingleClient::CONNECTED) { - std::string jid = jingle_client->GetFullJid(); - - DCHECK_EQ(jingle_client_.get(), jingle_client); - VLOG(1) << "Host connected as " << jid; + if (state == SignalStrategy::StatusObserver::CONNECTED) { + VLOG(1) << "Host connected as " << local_jid_; // Create and start session manager. protocol::JingleSessionManager* server = - new protocol::JingleSessionManager(context_->network_message_loop()); + new protocol::JingleSessionManager(context_->network_message_loop(), + NULL, NULL, NULL); // TODO(ajwong): Make this a command switch when we're more stable. server->set_allow_local_ips(true); @@ -245,7 +240,7 @@ void ChromotingHost::OnStateChange(JingleClient* jingle_client, CHECK(key_pair.Load(config_)) << "Failed to load server authentication data"; - server->Init(jid, jingle_client->session_manager(), + server->Init(local_jid_, signal_strategy_.get(), NewCallback(this, &ChromotingHost::OnNewClientSession), key_pair.CopyPrivateKey(), key_pair.GenerateCertificate()); @@ -253,9 +248,9 @@ void ChromotingHost::OnStateChange(JingleClient* jingle_client, for (StatusObserverList::iterator it = status_observers_.begin(); it != status_observers_.end(); ++it) { - (*it)->OnSignallingConnected(signal_strategy_.get(), jid); + (*it)->OnSignallingConnected(signal_strategy_.get(), local_jid_); } - } else if (state == JingleClient::CLOSED) { + } else if (state == SignalStrategy::StatusObserver::CLOSED) { VLOG(1) << "Host disconnected from talk network."; for (StatusObserverList::iterator it = status_observers_.begin(); it != status_observers_.end(); ++it) { @@ -268,6 +263,11 @@ void ChromotingHost::OnStateChange(JingleClient* jingle_client, } } +void ChromotingHost::OnJidChange(const std::string& full_jid) { + DCHECK_EQ(MessageLoop::current(), context_->network_message_loop()); + local_jid_ = full_jid; +} + void ChromotingHost::OnNewClientSession( protocol::Session* session, protocol::SessionManager::IncomingSessionResponse* response) { @@ -630,30 +630,18 @@ void ChromotingHost::ContinueWindowTimerFunc() { ShowContinueWindow(true); } -void ChromotingHost::ShutdownJingleClient() { - if (MessageLoop::current() != context_->main_message_loop()) { - context_->main_message_loop()->PostTask( - FROM_HERE, base::Bind(&ChromotingHost::ShutdownJingleClient, this)); - return; - } - - // Disconnect from the talk network. - if (jingle_client_) { - jingle_client_->Close(base::Bind( - &ChromotingHost::ShutdownSignallingDisconnected, this)); - } else { - ShutdownRecorder(); - } -} - -void ChromotingHost::ShutdownSignallingDisconnected() { +void ChromotingHost::ShutdownSignaling() { if (MessageLoop::current() != context_->network_message_loop()) { context_->network_message_loop()->PostTask( - FROM_HERE, base::Bind( - &ChromotingHost::ShutdownSignallingDisconnected, this)); + FROM_HERE, base::Bind(&ChromotingHost::ShutdownSignaling, this)); return; } + if (signal_strategy_.get()) { + signal_strategy_->Close(); + signal_strategy_.reset(); + } + for (StatusObserverList::iterator it = status_observers_.begin(); it != status_observers_.end(); ++it) { (*it)->OnSignallingDisconnected(); diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 6f969d4..760d895 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -16,8 +16,8 @@ #include "remoting/host/client_session.h" #include "remoting/host/desktop_environment.h" #include "remoting/host/host_status_observer.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" +#include "remoting/jingle_glue/signal_strategy.h" #include "remoting/protocol/session_manager.h" #include "remoting/protocol/connection_to_client.h" @@ -66,7 +66,7 @@ class ScreenRecorder; class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, public protocol::ConnectionToClient::EventHandler, public ClientSession::EventHandler, - public JingleClient::Callback { + public SignalStrategy::StatusObserver { public: // Factory methods that must be used to create ChromotingHost instances. // Default capturer and input stub are used if it is not specified. @@ -99,7 +99,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, void AddStatusObserver(HostStatusObserver* observer); //////////////////////////////////////////////////////////////////////////// - // protocol::ConnectionToClient::EventHandler implementations + // protocol::ConnectionToClient::EventHandler implementation. virtual void OnConnectionOpened(protocol::ConnectionToClient* client); virtual void OnConnectionClosed(protocol::ConnectionToClient* client); virtual void OnConnectionFailed(protocol::ConnectionToClient* client); @@ -107,11 +107,13 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, int64 sequence_number); //////////////////////////////////////////////////////////////////////////// - // JingleClient::Callback implementations - virtual void OnStateChange(JingleClient* client, JingleClient::State state); + // SignalStrategy implementation. + virtual void OnStateChange( + SignalStrategy::StatusObserver::State state) OVERRIDE; + virtual void OnJidChange(const std::string& full_jid) OVERRIDE; //////////////////////////////////////////////////////////////////////////// - // ClientSession::EventHandler implementations + // ClientSession::EventHandler implementation. virtual void LocalLoginSucceeded( scoped_refptr<protocol::ConnectionToClient> client); virtual void LocalLoginFailed( @@ -190,8 +192,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, void ContinueWindowTimerFunc(); // The following methods are called during shutdown. - void ShutdownJingleClient(); - void ShutdownSignallingDisconnected(); + void ShutdownSignaling(); void ShutdownRecorder(); void ShutdownFinish(); @@ -204,9 +205,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, scoped_ptr<SignalStrategy> signal_strategy_; - // The libjingle client. This is used to connect to the talk network to - // receive connection requests from chromoting client. - scoped_refptr<JingleClient> jingle_client_; + std::string local_jid_; scoped_refptr<protocol::SessionManager> session_manager_; diff --git a/remoting/host/heartbeat_sender.cc b/remoting/host/heartbeat_sender.cc index da552c5..ad87658 100644 --- a/remoting/host/heartbeat_sender.cc +++ b/remoting/host/heartbeat_sender.cc @@ -11,8 +11,8 @@ #include "remoting/base/constants.h" #include "remoting/host/host_config.h" #include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" +#include "remoting/jingle_glue/signal_strategy.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" #include "third_party/libjingle/source/talk/xmpp/constants.h" diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc index 4ffa458..617bf03 100644 --- a/remoting/host/heartbeat_sender_unittest.cc +++ b/remoting/host/heartbeat_sender_unittest.cc @@ -12,7 +12,6 @@ #include "remoting/host/in_memory_host_config.h" #include "remoting/host/test_key_pair.h" #include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/remoting/host/register_support_host_request.cc b/remoting/host/register_support_host_request.cc index 0e716dc..bd16b6b 100644 --- a/remoting/host/register_support_host_request.cc +++ b/remoting/host/register_support_host_request.cc @@ -11,8 +11,8 @@ #include "remoting/base/constants.h" #include "remoting/host/host_config.h" #include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" +#include "remoting/jingle_glue/signal_strategy.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" #include "third_party/libjingle/source/talk/xmpp/constants.h" diff --git a/remoting/host/register_support_host_request_unittest.cc b/remoting/host/register_support_host_request_unittest.cc index 58c639e..c290581 100644 --- a/remoting/host/register_support_host_request_unittest.cc +++ b/remoting/host/register_support_host_request_unittest.cc @@ -13,7 +13,6 @@ #include "remoting/host/in_memory_host_config.h" #include "remoting/host/test_key_pair.h" #include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/mock_objects.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/remoting/jingle_glue/fake_signal_strategy.cc b/remoting/jingle_glue/fake_signal_strategy.cc index b44721e..98cfc42 100644 --- a/remoting/jingle_glue/fake_signal_strategy.cc +++ b/remoting/jingle_glue/fake_signal_strategy.cc @@ -24,7 +24,8 @@ FakeSignalStrategy::FakeSignalStrategy(const std::string& jid) : jid_(jid), peer_(NULL), listener_(NULL), - last_id_(0) { + last_id_(0), + ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)) { } @@ -58,9 +59,7 @@ void FakeSignalStrategy::SendStanza(buzz::XmlElement* stanza) { stanza->SetAttr(buzz::QN_FROM, jid_); if (peer_) { - MessageLoop::current()->PostTask( - FROM_HERE, base::Bind(&FakeSignalStrategy::OnIncomingMessage, - base::Unretained(peer_), stanza)); + peer_->OnIncomingMessage(stanza); } else { delete stanza; } @@ -78,6 +77,12 @@ IqRequest* FakeSignalStrategy::CreateIqRequest() { } void FakeSignalStrategy::OnIncomingMessage(buzz::XmlElement* stanza) { + MessageLoop::current()->PostTask( + FROM_HERE, task_factory_.NewRunnableMethod( + &FakeSignalStrategy::DeliverIncomingMessage, stanza)); +} + +void FakeSignalStrategy::DeliverIncomingMessage(buzz::XmlElement* stanza) { const std::string& to_field = stanza->Attr(buzz::QN_TO); if (to_field != jid_) { LOG(WARNING) << "Dropping stanza that is addressed to " << to_field diff --git a/remoting/jingle_glue/fake_signal_strategy.h b/remoting/jingle_glue/fake_signal_strategy.h index 40f6ee1..83e1ae9 100644 --- a/remoting/jingle_glue/fake_signal_strategy.h +++ b/remoting/jingle_glue/fake_signal_strategy.h @@ -7,6 +7,7 @@ #include <string> +#include "base/task.h" #include "base/threading/non_thread_safe.h" #include "remoting/jingle_glue/javascript_iq_request.h" #include "remoting/jingle_glue/signal_strategy.h" @@ -33,6 +34,8 @@ class FakeSignalStrategy : public SignalStrategy, // Called by the |peer_|. Takes ownership of |stanza|. void OnIncomingMessage(buzz::XmlElement* stanza); + void DeliverIncomingMessage(buzz::XmlElement* stanza); + std::string jid_; FakeSignalStrategy* peer_; Listener* listener_; @@ -40,6 +43,8 @@ class FakeSignalStrategy : public SignalStrategy, int last_id_; + ScopedRunnableMethodFactory<FakeSignalStrategy> task_factory_; + DISALLOW_COPY_AND_ASSIGN(FakeSignalStrategy); }; diff --git a/remoting/jingle_glue/javascript_signal_strategy.h b/remoting/jingle_glue/javascript_signal_strategy.h index 89ef460..81b6e0c 100644 --- a/remoting/jingle_glue/javascript_signal_strategy.h +++ b/remoting/jingle_glue/javascript_signal_strategy.h @@ -16,7 +16,6 @@ namespace remoting { -class JingleSignalingConnector; class XmppProxy; class JavascriptSignalStrategy : public SignalStrategy, diff --git a/remoting/jingle_glue/jingle_client.cc b/remoting/jingle_glue/jingle_client.cc deleted file mode 100644 index b013c66..0000000 --- a/remoting/jingle_glue/jingle_client.cc +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/jingle_glue/jingle_client.h" - -#include "base/bind.h" -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/string_util.h" -#include "remoting/jingle_glue/http_port_allocator.h" -#include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_info_request.h" -#include "remoting/jingle_glue/jingle_signaling_connector.h" -#include "remoting/jingle_glue/jingle_thread.h" -#include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h" -#include "third_party/libjingle/source/talk/base/ssladapter.h" -#include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" -#include "third_party/libjingle/source/talk/p2p/base/transport.h" -#include "third_party/libjingle/source/talk/session/tunnel/tunnelsessionclient.h" - -namespace remoting { - -JingleClient::JingleClient(MessageLoop* message_loop, - SignalStrategy* signal_strategy, - talk_base::NetworkManager* network_manager, - talk_base::PacketSocketFactory* socket_factory, - PortAllocatorSessionFactory* session_factory, - Callback* callback) - : enable_nat_traversing_(false), - message_loop_(message_loop), - state_(START), - initialized_(false), - closed_(false), - initialized_finished_(false), - callback_(callback), - signal_strategy_(signal_strategy), - network_manager_(network_manager), - socket_factory_(socket_factory), - port_allocator_session_factory_(session_factory) { - DCHECK(message_loop_); -} - -JingleClient::~JingleClient() { - base::AutoLock auto_lock(state_lock_); - DCHECK(!initialized_ || closed_); -} - -void JingleClient::Init() { - { - base::AutoLock auto_lock(state_lock_); - DCHECK(!initialized_ && !closed_); - initialized_ = true; - } - - message_loop_->PostTask( - FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize)); -} - -void JingleClient::DoInitialize() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - if (!network_manager_.get()) { - VLOG(1) << "Creating talk_base::NetworkManager."; - network_manager_.reset(new talk_base::NetworkManager()); - } - if (!socket_factory_.get()) { - VLOG(1) << "Creating talk_base::BasicPacketSocketFactory."; - socket_factory_.reset(new talk_base::BasicPacketSocketFactory( - talk_base::Thread::Current())); - } - - port_allocator_.reset( - new remoting::HttpPortAllocator( - network_manager_.get(), socket_factory_.get(), - port_allocator_session_factory_.get(), "transp2")); - if (!enable_nat_traversing_) { - port_allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_STUN | - cricket::PORTALLOCATOR_DISABLE_RELAY); - } - - // TODO(ajwong): The strategy needs a "start" command or something. Right - // now, Init() implicitly starts processing events. Thus, we must have the - // other fields of JingleClient initialized first, otherwise the state-change - // may occur and callback into class before we're done initializing. - signal_strategy_->Init(this); - - if (enable_nat_traversing_) { - jingle_info_request_.reset( - new JingleInfoRequest(signal_strategy_->CreateIqRequest())); - jingle_info_request_->SetCallback( - NewCallback(this, &JingleClient::OnJingleInfo)); - jingle_info_request_->Run( - NewRunnableMethod(this, &JingleClient::DoStartSession)); - } else { - DoStartSession(); - } -} - -void JingleClient::DoStartSession() { - session_manager_.reset( - new cricket::SessionManager(port_allocator_.get())); - jingle_signaling_connector_.reset( - new JingleSignalingConnector(signal_strategy_, session_manager_.get())); - - // TODO(ajwong): Major hack to synchronize state change logic. Since the Xmpp - // connection starts first, it move the state to CONNECTED before we've gotten - // the jingle stun and relay information. Thus, we have to delay signaling - // until now. There is a parallel if to disable signaling in the - // OnStateChange logic. - initialized_finished_ = true; - if (!closed_ && state_ == CONNECTED) { - callback_->OnStateChange(this, state_); - } -} - -void JingleClient::Close(const base::Closure& closed_task) { - { - base::AutoLock auto_lock(state_lock_); - // If the client is already closed then don't close again. - if (closed_) { - message_loop_->PostTask(FROM_HERE, closed_task); - return; - } - } - - message_loop_->PostTask( - FROM_HERE, NewRunnableMethod(this, &JingleClient::DoClose, closed_task)); -} - -void JingleClient::DoClose(const base::Closure& closed_task) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - jingle_signaling_connector_.reset(); - session_manager_.reset(); - if (signal_strategy_) { - signal_strategy_->Close(); - signal_strategy_ = NULL; - } - - closed_ = true; - closed_task.Run(); -} - -std::string JingleClient::GetFullJid() { - base::AutoLock auto_lock(jid_lock_); - return full_jid_; -} - -IqRequest* JingleClient::CreateIqRequest() { - return signal_strategy_->CreateIqRequest(); -} - -MessageLoop* JingleClient::message_loop() { - return message_loop_; -} - -cricket::SessionManager* JingleClient::session_manager() { - DCHECK_EQ(message_loop_, MessageLoop::current()); - return session_manager_.get(); -} - -void JingleClient::OnStateChange(State new_state) { - if (new_state != state_) { - state_ = new_state; - { - // We have to have the lock held, otherwise we cannot be sure that - // the client hasn't been closed when we call the callback. - base::AutoLock auto_lock(state_lock_); - if (!closed_) { - // TODO(ajwong): HACK! remove this. See DoStartSession() for details. - // - // If state is connected, only signal if initialized_finished_ is also - // finished. - if (state_ != CONNECTED || initialized_finished_) { - callback_->OnStateChange(this, new_state); - } - } - } - } -} - -void JingleClient::OnJidChange(const std::string& full_jid) { - base::AutoLock auto_lock(jid_lock_); - full_jid_ = full_jid; -} - -void JingleClient::OnJingleInfo( - const std::string& token, - const std::vector<std::string>& relay_hosts, - const std::vector<talk_base::SocketAddress>& stun_hosts) { - if (port_allocator_.get()) { - // TODO(ajwong): Avoid string processing if log-level is low. - std::string stun_servers; - for (size_t i = 0; i < stun_hosts.size(); ++i) { - stun_servers += stun_hosts[i].ToString() + "; "; - } - LOG(INFO) << "Configuring with relay token: " << token - << ", relays: " << JoinString(relay_hosts, ';') - << ", stun: " << stun_servers; - port_allocator_->SetRelayToken(token); - port_allocator_->SetStunHosts(stun_hosts); - port_allocator_->SetRelayHosts(relay_hosts); - } else { - LOG(INFO) << "Jingle info found but no port allocator."; - } -} - -} // namespace remoting diff --git a/remoting/jingle_glue/jingle_client.h b/remoting/jingle_glue/jingle_client.h deleted file mode 100644 index 6879ee7..0000000 --- a/remoting/jingle_glue/jingle_client.h +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_JINGLE_GLUE_JINGLE_CLIENT_H_ -#define REMOTING_JINGLE_GLUE_JINGLE_CLIENT_H_ - -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" -#include "base/synchronization/lock.h" -#include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/signal_strategy.h" -#include "remoting/jingle_glue/xmpp_proxy.h" - -class MessageLoop; -class Task; - -namespace talk_base { -class NetworkManager; -class PacketSocketFactory; -class SocketAddress; -} // namespace talk_base - -namespace cricket { -class HttpPortAllocator; -} // namespace cricket - -namespace cricket { -class BasicPortAllocator; -class SessionManager; -} // namespace cricket - -namespace remoting { - -class JingleInfoRequest; -class JingleSignalingConnector; -class PortAllocatorSessionFactory; - -class JingleClient : public base::RefCountedThreadSafe<JingleClient>, - public SignalStrategy::StatusObserver { - public: - class Callback { - public: - virtual ~Callback() {} - - // Called when state of the connection is changed. - virtual void OnStateChange(JingleClient* client, State state) = 0; - }; - - // Physical sockets are used if |network_manager| and - // |socket_factory| are set to NULL. Otherwise ownership of these - // objects is given to JingleClient. - JingleClient(MessageLoop* message_loop, - SignalStrategy* signal_strategy, - talk_base::NetworkManager* network_manager, - talk_base::PacketSocketFactory* socket_factory, - PortAllocatorSessionFactory* session_factory, - Callback* callback); - virtual ~JingleClient(); - - // Starts the XMPP connection initialization. Must be called only once. - // |callback| specifies callback object for the client and must not be NULL. - void Init(); - - // Closes XMPP connection and stops the thread. Must be called - // before the object is destroyed. |closed_task| is executed after - // the connection is successfully closed. - void Close(const base::Closure& closed_task); - - // Returns JID with resource ID. Empty string is returned if full JID is not - // known yet, i.e. authentication hasn't finished. - std::string GetFullJid(); - - // Creates new IqRequest for this client. Ownership for of the created object - // is transfered to the caller. - IqRequest* CreateIqRequest(); - - // The session manager used by this client. Must be called from the - // jingle thread only. Returns NULL if the client is not active. - cricket::SessionManager* session_manager(); - - // Message loop used by this object to execute tasks. - MessageLoop* message_loop(); - - // SignalStrategy::StatusObserver implementation. - virtual void OnStateChange(State state); - virtual void OnJidChange(const std::string& full_jid); - - private: - friend class JingleClientTest; - - void DoInitialize(); - void DoStartSession(); - void DoClose(const base::Closure& closed_task); - - // Updates current state of the connection. Must be called only in - // the jingle thread. - void UpdateState(State new_state); - - // Virtual for mocking in a unittest. - void OnJingleInfo(const std::string& token, - const std::vector<std::string>& relay_hosts, - const std::vector<talk_base::SocketAddress>& stun_hosts); - - // This must be set to true to enable NAT traversal. STUN/Relay - // servers are not used when NAT traversal is disabled, so P2P - // connection will works only when both peers are on the same - // network. - bool enable_nat_traversing_; - - MessageLoop* message_loop_; - - // Current state of the object. - // Must be locked when accessing initialized_ or closed_. - base::Lock state_lock_; - State state_; - bool initialized_; - bool closed_; - scoped_ptr<Task> closed_task_; - - // TODO(ajwong): HACK! remove this. See DoStartSession() for details. - bool initialized_finished_; - - // We need a separate lock for the jid since the |state_lock_| may be held - // over a callback which can end up having a double lock. - // - // TODO(ajwong): Can we avoid holding the |state_lock_| over a callback and - // remove this extra lock? - base::Lock jid_lock_; - std::string full_jid_; - - // Callback for this object. Callback must not be called if closed_ == true. - Callback* callback_; - - SignalStrategy* signal_strategy_; - scoped_ptr<talk_base::NetworkManager> network_manager_; - scoped_ptr<talk_base::PacketSocketFactory> socket_factory_; - scoped_ptr<cricket::HttpPortAllocator> port_allocator_; - scoped_ptr<PortAllocatorSessionFactory> port_allocator_session_factory_; - scoped_ptr<cricket::SessionManager> session_manager_; - - scoped_ptr<JingleInfoRequest> jingle_info_request_; - scoped_ptr<JingleSignalingConnector> jingle_signaling_connector_; - - DISALLOW_COPY_AND_ASSIGN(JingleClient); -}; - -} // namespace remoting - -#endif // REMOTING_JINGLE_GLUE_JINGLE_CLIENT_H_ diff --git a/remoting/jingle_glue/jingle_client_unittest.cc b/remoting/jingle_glue/jingle_client_unittest.cc deleted file mode 100644 index 952aa36..0000000 --- a/remoting/jingle_glue/jingle_client_unittest.cc +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/bind.h" -#include "base/synchronization/waitable_event.h" -#include "remoting/jingle_glue/jingle_client.h" -#include "remoting/jingle_glue/jingle_thread.h" -#include "remoting/jingle_glue/xmpp_signal_strategy.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using testing::_; - -namespace remoting { - -class MockJingleClientCallback : public JingleClient::Callback { - public: - ~MockJingleClientCallback() { } - - MOCK_METHOD2(OnStateChange, void(JingleClient*, JingleClient::State)); -}; - -class JingleClientTest : public testing::Test { - public: - virtual ~JingleClientTest() { } - - static void OnClosed(bool* called) { - *called = true; - } - - // A helper that calls OnConnectionStateChanged(). Need this because we want - // to call it on the jingle thread. - static void ChangeState(XmppSignalStrategy* strategy, - buzz::XmppEngine::State state, - base::WaitableEvent* done_event) { - strategy->OnConnectionStateChanged(state); - if (done_event) - done_event->Signal(); - } - - protected: - virtual void SetUp() { - thread_.Start(); - - signal_strategy_.reset(new XmppSignalStrategy(&thread_, "", "", "")); - client_ = new JingleClient(thread_.message_loop(), signal_strategy_.get(), - NULL, NULL, NULL, &callback_); - // Fake initialization. - client_->initialized_ = true; - signal_strategy_->observer_ = client_; - } - - JingleThread thread_; - scoped_ptr<XmppSignalStrategy> signal_strategy_; - scoped_refptr<JingleClient> client_; - MockJingleClientCallback callback_; -}; - -TEST_F(JingleClientTest, OnStateChanged) { - EXPECT_CALL(callback_, OnStateChange(_, JingleClient::CONNECTING)) - .Times(1); - - base::WaitableEvent state_changed_event(true, false); - thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( - &JingleClientTest::ChangeState, signal_strategy_.get(), - buzz::XmppEngine::STATE_OPENING, &state_changed_event)); - state_changed_event.Wait(); - - base::WaitableEvent closed_event(true, false); - client_->Close(base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&closed_event))); - closed_event.Wait(); - - thread_.Stop(); -} - -TEST_F(JingleClientTest, Close) { - EXPECT_CALL(callback_, OnStateChange(_, _)) - .Times(0); - base::WaitableEvent closed_event(true, false); - client_->Close(base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&closed_event))); - closed_event.Wait(); - - // Verify that the channel doesn't call callback anymore. - thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( - &JingleClientTest::ChangeState, signal_strategy_.get(), - buzz::XmppEngine::STATE_OPENING, - static_cast<base::WaitableEvent*>(NULL))); - thread_.Stop(); -} - -TEST_F(JingleClientTest, ClosedTask) { - bool closed = false; - client_->Close(base::Bind(&JingleClientTest::OnClosed, &closed)); - thread_.Stop(); - EXPECT_TRUE(closed); -} - -TEST_F(JingleClientTest, DoubleClose) { - bool closed1 = false; - client_->Close(base::Bind(&JingleClientTest::OnClosed, &closed1)); - bool closed2 = false; - client_->Close(base::Bind(&JingleClientTest::OnClosed, &closed2)); - thread_.Stop(); - EXPECT_TRUE(closed1 && closed2); -} - -} // namespace remoting diff --git a/remoting/jingle_glue/mock_objects.h b/remoting/jingle_glue/mock_objects.h index a6a76e0..e32e203 100644 --- a/remoting/jingle_glue/mock_objects.h +++ b/remoting/jingle_glue/mock_objects.h @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/memory/scoped_ptr.h" #include "remoting/jingle_glue/iq_request.h" -#include "remoting/jingle_glue/jingle_client.h" +#include "remoting/jingle_glue/signal_strategy.h" #include "testing/gmock/include/gmock/gmock.h" namespace remoting { diff --git a/remoting/protocol/connection_to_host.cc b/remoting/protocol/connection_to_host.cc index 074f2b3..03f388c 100644 --- a/remoting/protocol/connection_to_host.cc +++ b/remoting/protocol/connection_to_host.cc @@ -64,20 +64,16 @@ void ConnectionToHost::Connect(scoped_refptr<XmppProxy> xmpp_proxy, video_stub_ = video_stub; access_code_ = access_code; - // Initialize |jingle_client_|. - JavascriptSignalStrategy* strategy = new JavascriptSignalStrategy(your_jid); - strategy->AttachXmppProxy(xmpp_proxy); - signal_strategy_.reset(strategy); - jingle_client_ = - new JingleClient(message_loop_, signal_strategy_.get(), - network_manager_.release(), socket_factory_.release(), - port_allocator_session_factory_.release(), this); - jingle_client_->Init(); - // Save jid of the host. The actual connection is created later after - // |jingle_client_| is connected. + // |signal_strategy_| is connected. host_jid_ = host_jid; host_public_key_ = host_public_key; + + // Initialize |signal_strategy_|. + JavascriptSignalStrategy* strategy = new JavascriptSignalStrategy(your_jid); + strategy->AttachXmppProxy(xmpp_proxy); + signal_strategy_.reset(strategy); + signal_strategy_->Init(this); } void ConnectionToHost::Disconnect(const base::Closure& shutdown_task) { @@ -100,24 +96,24 @@ void ConnectionToHost::Disconnect(const base::Closure& shutdown_task) { void ConnectionToHost::InitSession() { DCHECK_EQ(message_loop_, MessageLoop::current()); - std::string jid = jingle_client_->GetFullJid(); - // Initialize chromotocol |session_manager_|. JingleSessionManager* session_manager = - new JingleSessionManager(message_loop_); + new JingleSessionManager(message_loop_, network_manager_.release(), + socket_factory_.release(), + port_allocator_session_factory_.release()); + // TODO(ajwong): Make this a command switch when we're more stable. session_manager->set_allow_local_ips(true); session_manager->Init( - jid, jingle_client_->session_manager(), - NewCallback(this, &ConnectionToHost::OnNewSession), - NULL, NULL); + local_jid_, signal_strategy_.get(), + NewCallback(this, &ConnectionToHost::OnNewSession), NULL, NULL); session_manager_ = session_manager; CandidateSessionConfig* candidate_config = CandidateSessionConfig::CreateDefault(); std::string client_token = - protocol::GenerateSupportAuthToken(jid, access_code_); + protocol::GenerateSupportAuthToken(local_jid_, access_code_); // Initialize |session_|. session_ = session_manager_->Connect( @@ -144,19 +140,10 @@ void ConnectionToHost::OnServerClosed(const base::Closure& shutdown_task) { session_manager_ = NULL; - if (jingle_client_) { - jingle_client_->Close(base::Bind(&ConnectionToHost::OnJingleClientClosed, - base::Unretained(this), shutdown_task)); - } else { - OnJingleClientClosed(shutdown_task); + if (signal_strategy_.get()) { + signal_strategy_->Close(); + signal_strategy_.reset(); } -} - -void ConnectionToHost::OnJingleClientClosed( - const base::Closure& shutdown_task) { - DCHECK_EQ(message_loop_, MessageLoop::current()); - - signal_strategy_.reset(); shutdown_task.Run(); } @@ -165,22 +152,26 @@ const SessionConfig* ConnectionToHost::config() { return session_->config(); } -// JingleClient::Callback interface. -void ConnectionToHost::OnStateChange(JingleClient* client, - JingleClient::State state) { + +void ConnectionToHost::OnStateChange( + SignalStrategy::StatusObserver::State state) { DCHECK_EQ(message_loop_, MessageLoop::current()); - DCHECK(client); DCHECK(event_callback_); - if (state == JingleClient::CONNECTED) { - VLOG(1) << "Connected as: " << client->GetFullJid(); + if (state == SignalStrategy::StatusObserver::CONNECTED) { + VLOG(1) << "Connected as: " << local_jid_; InitSession(); - } else if (state == JingleClient::CLOSED) { + } else if (state == SignalStrategy::StatusObserver::CLOSED) { VLOG(1) << "Connection closed."; event_callback_->OnConnectionClosed(this); } } +void ConnectionToHost::OnJidChange(const std::string& full_jid) { + DCHECK_EQ(message_loop_, MessageLoop::current()); + local_jid_ = full_jid; +} + void ConnectionToHost::OnNewSession(Session* session, SessionManager::IncomingSessionResponse* response) { DCHECK_EQ(message_loop_, MessageLoop::current()); diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h index e0511a6..6132fb9 100644 --- a/remoting/protocol/connection_to_host.h +++ b/remoting/protocol/connection_to_host.h @@ -10,7 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/task.h" -#include "remoting/jingle_glue/jingle_client.h" +#include "remoting/jingle_glue/signal_strategy.h" #include "remoting/proto/internal.pb.h" #include "remoting/protocol/connection_to_host.h" #include "remoting/protocol/host_stub.h" @@ -21,6 +21,11 @@ class MessageLoop; +namespace talk_base { +class NetworkManager; +class PacketSocketFactory; +} // namespace talk_base + namespace remoting { class JingleThread; @@ -36,7 +41,7 @@ class SessionConfig; class VideoReader; class VideoStub; -class ConnectionToHost : public JingleClient::Callback { +class ConnectionToHost : public SignalStrategy::StatusObserver { public: enum State { STATE_EMPTY, @@ -87,8 +92,10 @@ class ConnectionToHost : public JingleClient::Callback { virtual HostStub* host_stub(); - // JingleClient::Callback interface. - virtual void OnStateChange(JingleClient* client, JingleClient::State state); + // SignalStrategy::StatusObserver interface. + virtual void OnStateChange( + SignalStrategy::StatusObserver::State state) OVERRIDE; + virtual void OnJidChange(const std::string& full_jid) OVERRIDE; // Callback for chromotocol SessionManager. void OnNewSession( @@ -116,7 +123,6 @@ class ConnectionToHost : public JingleClient::Callback { // server, and then disconnect XMPP connection. void OnDisconnected(const base::Closure& shutdown_task); void OnServerClosed(const base::Closure& shutdown_task); - void OnJingleClientClosed(const base::Closure& shutdown_task); // Internal state of the connection. State state_; @@ -128,7 +134,7 @@ class ConnectionToHost : public JingleClient::Callback { scoped_ptr<PortAllocatorSessionFactory> port_allocator_session_factory_; scoped_ptr<SignalStrategy> signal_strategy_; - scoped_refptr<JingleClient> jingle_client_; + std::string local_jid_; scoped_refptr<SessionManager> session_manager_; scoped_refptr<Session> session_; diff --git a/remoting/protocol/jingle_session_manager.cc b/remoting/protocol/jingle_session_manager.cc index 0c6e272..a4b62e7 100644 --- a/remoting/protocol/jingle_session_manager.cc +++ b/remoting/protocol/jingle_session_manager.cc @@ -7,7 +7,15 @@ #include <limits> #include "base/message_loop.h" +#include "base/string_util.h" #include "remoting/base/constants.h" +#include "remoting/jingle_glue/http_port_allocator.h" +#include "remoting/jingle_glue/jingle_info_request.h" +#include "remoting/jingle_glue/jingle_signaling_connector.h" +#include "remoting/jingle_glue/signal_strategy.h" +#include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h" +#include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h" +#include "third_party/libjingle/source/talk/p2p/base/transport.h" #include "third_party/libjingle/source/talk/p2p/base/constants.h" #include "third_party/libjingle/source/talk/p2p/base/transport.h" #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" @@ -17,17 +25,29 @@ using buzz::XmlElement; namespace remoting { namespace protocol { -JingleSessionManager::JingleSessionManager(MessageLoop* message_loop) +JingleSessionManager::JingleSessionManager( + MessageLoop* message_loop, + talk_base::NetworkManager* network_manager, + talk_base::PacketSocketFactory* socket_factory, + PortAllocatorSessionFactory* port_allocator_session_factory) : message_loop_(message_loop), - cricket_session_manager_(NULL), + network_manager_(network_manager), + socket_factory_(socket_factory), + port_allocator_session_factory_(port_allocator_session_factory), + signal_strategy_(NULL), + enable_nat_traversing_(false), allow_local_ips_(false), closed_(false) { DCHECK(message_loop); } +JingleSessionManager::~JingleSessionManager() { + DCHECK(closed_); +} + void JingleSessionManager::Init( const std::string& local_jid, - cricket::SessionManager* cricket_session_manager, + SignalStrategy* signal_strategy, IncomingSessionCallback* incoming_session_callback, crypto::RSAPrivateKey* private_key, scoped_refptr<net::X509Certificate> certificate) { @@ -35,24 +55,49 @@ void JingleSessionManager::Init( message_loop_->PostTask( FROM_HERE, NewRunnableMethod( this, &JingleSessionManager::Init, - local_jid, cricket_session_manager, incoming_session_callback, + local_jid, signal_strategy, incoming_session_callback, private_key, certificate)); return; } - DCHECK(cricket_session_manager); + DCHECK(signal_strategy); DCHECK(incoming_session_callback); local_jid_ = local_jid; certificate_ = certificate; private_key_.reset(private_key); incoming_session_callback_.reset(incoming_session_callback); - cricket_session_manager_ = cricket_session_manager; - cricket_session_manager_->AddClient(kChromotingXmlNamespace, this); -} + signal_strategy_ = signal_strategy; -JingleSessionManager::~JingleSessionManager() { - DCHECK(closed_); + if (!network_manager_.get()) { + VLOG(1) << "Creating talk_base::NetworkManager."; + network_manager_.reset(new talk_base::NetworkManager()); + } + if (!socket_factory_.get()) { + VLOG(1) << "Creating talk_base::BasicPacketSocketFactory."; + socket_factory_.reset(new talk_base::BasicPacketSocketFactory( + talk_base::Thread::Current())); + } + + port_allocator_.reset( + new remoting::HttpPortAllocator( + network_manager_.get(), socket_factory_.get(), + port_allocator_session_factory_.get(), "transp2")); + if (!enable_nat_traversing_) { + port_allocator_->set_flags(cricket::PORTALLOCATOR_DISABLE_STUN | + cricket::PORTALLOCATOR_DISABLE_RELAY); + } + + if (enable_nat_traversing_) { + jingle_info_request_.reset( + new JingleInfoRequest(signal_strategy_->CreateIqRequest())); + jingle_info_request_->SetCallback( + NewCallback(this, &JingleSessionManager::OnJingleInfo)); + jingle_info_request_->Run( + NewRunnableMethod(this, &JingleSessionManager::DoStartSessionManager)); + } else { + DoStartSessionManager(); + } } void JingleSessionManager::Close(Task* closed_task) { @@ -71,6 +116,8 @@ void JingleSessionManager::Close(Task* closed_task) { cricket_session_manager_->DestroySession(session); sessions_.pop_front(); } + jingle_signaling_connector_.reset(); + cricket_session_manager_.reset(); closed_ = true; } @@ -226,6 +273,36 @@ bool JingleSessionManager::ParseContent( return *content != NULL; } +void JingleSessionManager::OnJingleInfo( + const std::string& token, + const std::vector<std::string>& relay_hosts, + const std::vector<talk_base::SocketAddress>& stun_hosts) { + if (port_allocator_.get()) { + // TODO(ajwong): Avoid string processing if log-level is low. + std::string stun_servers; + for (size_t i = 0; i < stun_hosts.size(); ++i) { + stun_servers += stun_hosts[i].ToString() + "; "; + } + LOG(INFO) << "Configuring with relay token: " << token + << ", relays: " << JoinString(relay_hosts, ';') + << ", stun: " << stun_servers; + port_allocator_->SetRelayToken(token); + port_allocator_->SetStunHosts(stun_hosts); + port_allocator_->SetRelayHosts(relay_hosts); + } else { + LOG(INFO) << "Jingle info found but no port allocator."; + } +} + +void JingleSessionManager::DoStartSessionManager() { + cricket_session_manager_.reset( + new cricket::SessionManager(port_allocator_.get())); + cricket_session_manager_->AddClient(kChromotingXmlNamespace, this); + + jingle_signaling_connector_.reset(new JingleSignalingConnector( + signal_strategy_, cricket_session_manager_.get())); +} + bool JingleSessionManager::WriteContent( cricket::SignalingProtocol protocol, const cricket::ContentDescription* content, diff --git a/remoting/protocol/jingle_session_manager.h b/remoting/protocol/jingle_session_manager.h index eb6ca8b..a0cdb97 100644 --- a/remoting/protocol/jingle_session_manager.h +++ b/remoting/protocol/jingle_session_manager.h @@ -18,15 +18,17 @@ class MessageLoop; -namespace crypto { -class RSAPrivateKey; -} // namespace base - namespace cricket { +class HttpPortAllocator; class SessionManager; } // namespace cricket namespace remoting { + +class JingleInfoRequest; +class JingleSignalingConnector; +class PortAllocatorSessionFactory; + namespace protocol { // This class implements SessionClient for Chromoting sessions. It acts as a @@ -36,30 +38,25 @@ class JingleSessionManager : public protocol::SessionManager, public cricket::SessionClient { public: - explicit JingleSessionManager(MessageLoop* message_loop); - - // Initializes the session client. Doesn't accept ownership of the - // |session_manager|. Close() must be called _before_ the |session_manager| - // is destroyed. - // If this object is used in server mode, then |private_key| and - // |certificate| are used to establish a secured communication with the - // client. It will also take ownership of these objects. - // In case this is used in client mode, pass in NULL for both private key and - // certificate. + JingleSessionManager( + MessageLoop* message_loop, + talk_base::NetworkManager* network_manager, + talk_base::PacketSocketFactory* socket_factory, + PortAllocatorSessionFactory* port_allocator_session_factory); + + // SessionManager interface. virtual void Init(const std::string& local_jid, - cricket::SessionManager* cricket_session_manager, + SignalStrategy* signal_strategy, IncomingSessionCallback* incoming_session_callback, crypto::RSAPrivateKey* private_key, - scoped_refptr<net::X509Certificate> certificate); - - // SessionManager interface. + scoped_refptr<net::X509Certificate> certificate) OVERRIDE; virtual scoped_refptr<protocol::Session> Connect( const std::string& host_jid, const std::string& host_public_key, const std::string& client_token, CandidateSessionConfig* config, - protocol::Session::StateChangeCallback* state_change_callback); - virtual void Close(Task* closed_task); + protocol::Session::StateChangeCallback* state_change_callback) OVERRIDE; + virtual void Close(Task* closed_task) OVERRIDE; void set_allow_local_ips(bool allow_local_ips); @@ -97,6 +94,15 @@ class JingleSessionManager const std::string& client_token, protocol::Session::StateChangeCallback* state_change_callback); + // Callback for JingleInfoRequest. + void OnJingleInfo( + const std::string& token, + const std::vector<std::string>& relay_hosts, + const std::vector<talk_base::SocketAddress>& stun_hosts); + + // Creates cricket::SessionManager. + void DoStartSessionManager(); + // Creates session description for outgoing session. cricket::SessionDescription* CreateClientSessionDescription( const CandidateSessionConfig* candidate_config, @@ -107,18 +113,33 @@ class JingleSessionManager const CandidateSessionConfig* candidate_config, scoped_refptr<net::X509Certificate> certificate); - std::string local_jid_; // Full jid for the local side of the session. MessageLoop* message_loop_; - cricket::SessionManager* cricket_session_manager_; + scoped_ptr<talk_base::NetworkManager> network_manager_; + scoped_ptr<talk_base::PacketSocketFactory> socket_factory_; + scoped_ptr<PortAllocatorSessionFactory> port_allocator_session_factory_; + + std::string local_jid_; // Full jid for the local side of the session. + SignalStrategy* signal_strategy_; scoped_ptr<IncomingSessionCallback> incoming_session_callback_; + scoped_refptr<net::X509Certificate> certificate_; + scoped_ptr<crypto::RSAPrivateKey> private_key_; + + // This must be set to true to enable NAT traversal. STUN/Relay + // servers are not used when NAT traversal is disabled, so P2P + // connection will works only when both peers are on the same + // network. + bool enable_nat_traversing_; bool allow_local_ips_; + + scoped_ptr<cricket::HttpPortAllocator> port_allocator_; + scoped_ptr<cricket::SessionManager> cricket_session_manager_; + scoped_ptr<JingleInfoRequest> jingle_info_request_; + scoped_ptr<JingleSignalingConnector> jingle_signaling_connector_; + bool closed_; std::list<scoped_refptr<JingleSession> > sessions_; - scoped_refptr<net::X509Certificate> certificate_; - scoped_ptr<crypto::RSAPrivateKey> private_key_; - DISALLOW_COPY_AND_ASSIGN(JingleSessionManager); }; diff --git a/remoting/protocol/jingle_session_unittest.cc b/remoting/protocol/jingle_session_unittest.cc index 71d446e..f2e45f6 100644 --- a/remoting/protocol/jingle_session_unittest.cc +++ b/remoting/protocol/jingle_session_unittest.cc @@ -15,8 +15,8 @@ #include "net/socket/socket.h" #include "remoting/protocol/jingle_session.h" #include "remoting/protocol/jingle_session_manager.h" -#include "remoting/protocol/session_manager_pair.h" #include "remoting/jingle_glue/jingle_thread.h" +#include "remoting/jingle_glue/fake_signal_strategy.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/libjingle/source/talk/p2p/client/basicportallocator.h" @@ -50,6 +50,9 @@ const int kTestDataSize = kMessages * kMessageSize; const int kUdpWriteDelayMs = 10; const char kTestToken[] = "a_dummy_token"; +const char kHostJid[] = "host1@gmail.com/123"; +const char kClientJid[] = "host2@gmail.com/321"; + const char kTestHostPublicKey[] = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3nk/8ILc0JBqHgOS0UCOIl4m" "0GUd2FIiZ/6Fc9D/iiyUgli+FIY5dwsrSoNJ87sYGifVDh8a5fdZNV5y58CcrapI5fJI" @@ -91,15 +94,9 @@ class JingleSessionTest : public testing::Test { virtual void TearDown() { CloseSessions(); - - if (host_server_) { - host_server_->Close(NewRunnableFunction( - &JingleSessionTest::DoNothing)); - } - if (client_server_) { - client_server_->Close(NewRunnableFunction( - &JingleSessionTest::DoNothing)); - } + thread_.message_loop()->PostTask( + FROM_HERE, NewRunnableMethod( + this, &JingleSessionTest::DoCloseSessionManager)); thread_.Stop(); } @@ -112,14 +109,9 @@ class JingleSessionTest : public testing::Test { } void CloseSessions() { - if (host_session_) { - host_session_->Close(NewRunnableFunction( - &JingleSessionTest::DoNothing)); - } - if (client_session_) { - client_session_->Close(NewRunnableFunction( - &JingleSessionTest::DoNothing)); - } + thread_.message_loop()->PostTask( + FROM_HERE, NewRunnableMethod( + this, &JingleSessionTest::DoCloseSessions)); SyncWithJingleThread(); } @@ -149,28 +141,55 @@ class JingleSessionTest : public testing::Test { scoped_ptr<crypto::RSAPrivateKey> private_key( crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vector)); - session_manager_pair_ = new SessionManagerPair(&thread_); - session_manager_pair_->Init(); - host_server_ = new JingleSessionManager(thread_.message_loop()); + host_signal_strategy_.reset(new FakeSignalStrategy(kHostJid)); + client_signal_strategy_.reset(new FakeSignalStrategy(kClientJid)); + FakeSignalStrategy::Connect(host_signal_strategy_.get(), + client_signal_strategy_.get()); + + host_server_ = + new JingleSessionManager(thread_.message_loop(), NULL, NULL, NULL); host_server_->set_allow_local_ips(true); host_server_->Init( - SessionManagerPair::kHostJid, - session_manager_pair_->host_session_manager(), + kHostJid, host_signal_strategy_.get(), NewCallback(&host_server_callback_, &MockSessionManagerCallback::OnIncomingSession), private_key.release(), cert); - client_server_ = new JingleSessionManager(thread_.message_loop()); + client_server_ = + new JingleSessionManager(thread_.message_loop(), NULL, NULL, NULL); client_server_->set_allow_local_ips(true); client_server_->Init( - SessionManagerPair::kClientJid, - session_manager_pair_->client_session_manager(), + kClientJid, client_signal_strategy_.get(), NewCallback(&client_server_callback_, &MockSessionManagerCallback::OnIncomingSession), NULL, NULL); } + void DoCloseSessions() { + if (host_session_) { + host_session_->Close(NewRunnableFunction( + &JingleSessionTest::DoNothing)); + } + if (client_session_) { + client_session_->Close(NewRunnableFunction( + &JingleSessionTest::DoNothing)); + } + } + + void DoCloseSessionManager() { + if (host_server_) { + host_server_->Close(NewRunnableFunction(&JingleSessionTest::DoNothing)); + host_server_ = NULL; + } + if (client_server_) { + client_server_->Close(NewRunnableFunction(&JingleSessionTest::DoNothing)); + client_server_ = NULL; + } + host_signal_strategy_.reset(); + client_signal_strategy_.reset(); + } + bool InitiateConnection() { EXPECT_CALL(host_server_callback_, OnIncomingSession(_, _)) .WillOnce(DoAll( @@ -178,7 +197,7 @@ class JingleSessionTest : public testing::Test { this, &JingleSessionTest::SetHostSession)), SetArgumentPointee<1>(protocol::SessionManager::ACCEPT))); - base::WaitableEvent host_connected_event(false, false); + base::WaitableEvent host_connected_event(true, false); EXPECT_CALL(host_connection_callback_, OnStateChange(Session::CONNECTING)) .Times(1); @@ -192,7 +211,7 @@ class JingleSessionTest : public testing::Test { OnStateChange(Session::CLOSED)) .Times(1); - base::WaitableEvent client_connected_event(false, false); + base::WaitableEvent client_connected_event(true, false); EXPECT_CALL(client_connection_callback_, OnStateChange(Session::CONNECTING)) .Times(1); @@ -207,7 +226,7 @@ class JingleSessionTest : public testing::Test { .Times(1); client_session_ = client_server_->Connect( - SessionManagerPair::kHostJid, kTestHostPublicKey, kTestToken, + kHostJid, kTestHostPublicKey, kTestToken, CandidateSessionConfig::CreateDefault(), NewCallback(&client_connection_callback_, &MockSessionCallback::OnStateChange)); @@ -232,7 +251,9 @@ class JingleSessionTest : public testing::Test { } JingleThread thread_; - scoped_refptr<SessionManagerPair> session_manager_pair_; + scoped_ptr<FakeSignalStrategy> host_signal_strategy_; + scoped_ptr<FakeSignalStrategy> client_signal_strategy_; + scoped_refptr<JingleSessionManager> host_server_; MockSessionManagerCallback host_server_callback_; scoped_refptr<JingleSessionManager> client_server_; @@ -567,7 +588,7 @@ TEST_F(JingleSessionTest, RejectConnection) { EXPECT_CALL(host_server_callback_, OnIncomingSession(_, _)) .WillOnce(SetArgumentPointee<1>(protocol::SessionManager::DECLINE)); - base::WaitableEvent done_event(false, false); + base::WaitableEvent done_event(true, false); EXPECT_CALL(client_connection_callback_, OnStateChange(Session::CONNECTING)) .Times(1); @@ -577,9 +598,7 @@ TEST_F(JingleSessionTest, RejectConnection) { .WillOnce(InvokeWithoutArgs(&done_event, &base::WaitableEvent::Signal)); client_session_ = client_server_->Connect( - SessionManagerPair::kHostJid, - kTestHostPublicKey, - kTestToken, + kHostJid, kTestHostPublicKey, kTestToken, CandidateSessionConfig::CreateDefault(), NewCallback(&client_connection_callback_, &MockSessionCallback::OnStateChange)); diff --git a/remoting/protocol/protocol_test_client.cc b/remoting/protocol/protocol_test_client.cc index e19aa5f42..4a1a1b1 100644 --- a/remoting/protocol/protocol_test_client.cc +++ b/remoting/protocol/protocol_test_client.cc @@ -24,7 +24,6 @@ extern "C" { #include "net/base/net_errors.h" #include "net/socket/socket.h" #include "remoting/base/constants.h" -#include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" #include "remoting/jingle_glue/xmpp_signal_strategy.h" #include "remoting/protocol/jingle_session_manager.h" @@ -42,9 +41,9 @@ class ProtocolTestClient; class ProtocolTestConnection : public base::RefCountedThreadSafe<ProtocolTestConnection> { public: - ProtocolTestConnection(ProtocolTestClient* client, MessageLoop* message_loop) + ProtocolTestConnection(ProtocolTestClient* client) : client_(client), - message_loop_(message_loop), + message_loop_(MessageLoop::current()), session_(NULL), ALLOW_THIS_IN_INITIALIZER_LIST( write_cb_(this, &ProtocolTestConnection::OnWritten)), @@ -85,7 +84,7 @@ class ProtocolTestConnection }; class ProtocolTestClient - : public JingleClient::Callback, + : public SignalStrategy::StatusObserver, public base::RefCountedThreadSafe<ProtocolTestClient> { public: ProtocolTestClient() @@ -99,8 +98,10 @@ class ProtocolTestClient void OnConnectionClosed(ProtocolTestConnection* connection); - // JingleClient::Callback interface. - virtual void OnStateChange(JingleClient* client, JingleClient::State state); + // SignalStrategy::StatusObserver interface. + virtual void OnStateChange( + SignalStrategy::StatusObserver::State state) OVERRIDE; + virtual void OnJidChange(const std::string& full_jid) OVERRIDE; // callback for JingleSessionManager interface. virtual void OnNewSession( @@ -111,11 +112,10 @@ class ProtocolTestClient typedef std::list<scoped_refptr<ProtocolTestConnection> > ConnectionsList; void OnFinishedClosing(); - void DestroyConnection(scoped_refptr<ProtocolTestConnection> connection); std::string host_jid_; scoped_ptr<SignalStrategy> signal_strategy_; - scoped_refptr<JingleClient> client_; + std::string local_jid_; scoped_refptr<JingleSessionManager> session_manager_; ConnectionsList connections_; base::Lock connections_lock_; @@ -229,14 +229,13 @@ void ProtocolTestClient::Run(const std::string& username, const std::string& host_jid) { remoting::JingleThread jingle_thread; jingle_thread.Start(); + signal_strategy_.reset( new XmppSignalStrategy(&jingle_thread, username, auth_token, auth_service)); - client_ = new JingleClient(jingle_thread.message_loop(), - signal_strategy_.get(), NULL, NULL, NULL, this); - client_->Init(); - - session_manager_ = new JingleSessionManager(jingle_thread.message_loop()); + signal_strategy_->Init(this); + session_manager_ = new JingleSessionManager(jingle_thread.message_loop(), + NULL, NULL, NULL); host_jid_ = host_jid; @@ -269,45 +268,50 @@ void ProtocolTestClient::Run(const std::string& username, closed_event_.Wait(); } - base::WaitableEvent closed_event(true, false); - client_->Close(base::Bind(&base::WaitableEvent::Signal, - base::Unretained(&closed_event))); - closed_event.Wait(); + signal_strategy_->Close(); jingle_thread.Stop(); } void ProtocolTestClient::OnConnectionClosed( ProtocolTestConnection* connection) { - client_->message_loop()->PostTask( - FROM_HERE, NewRunnableMethod( - this, &ProtocolTestClient::DestroyConnection, - scoped_refptr<ProtocolTestConnection>(connection))); + connection->Close(); + base::AutoLock auto_lock(connections_lock_); + for (ConnectionsList::iterator it = connections_.begin(); + it != connections_.end(); ++it) { + if ((*it) == connection) { + connections_.erase(it); + return; + } + } } void ProtocolTestClient::OnStateChange( - JingleClient* client, JingleClient::State state) { - if (state == JingleClient::CONNECTED) { - std::cerr << "Connected as " << client->GetFullJid() << std::endl; + SignalStrategy::StatusObserver::State state) { + if (state == SignalStrategy::StatusObserver::CONNECTED) { + std::cerr << "Connected as " << local_jid_ << std::endl; session_manager_->Init( - client_->GetFullJid(), client_->session_manager(), + local_jid_, signal_strategy_.get(), NewCallback(this, &ProtocolTestClient::OnNewSession), NULL, NULL); session_manager_->set_allow_local_ips(true); if (host_jid_ != "") { - ProtocolTestConnection* connection = - new ProtocolTestConnection(this, client_->message_loop()); + ProtocolTestConnection* connection = new ProtocolTestConnection(this); connection->Init(session_manager_->Connect( host_jid_, "", kDummyAuthToken, CandidateSessionConfig::CreateDefault(), NewCallback(connection, &ProtocolTestConnection::OnStateChange))); connections_.push_back(make_scoped_refptr(connection)); } - } else if (state == JingleClient::CLOSED) { + } else if (state == SignalStrategy::StatusObserver::CLOSED) { std::cerr << "Connection closed" << std::endl; } } +void ProtocolTestClient::OnJidChange(const std::string& full_jid) { + local_jid_ = full_jid; +} + void ProtocolTestClient::OnNewSession( Session* session, SessionManager::IncomingSessionResponse* response) { @@ -316,8 +320,7 @@ void ProtocolTestClient::OnNewSession( session->set_config(SessionConfig::CreateDefault()); *response = SessionManager::ACCEPT; - ProtocolTestConnection* test_connection = - new ProtocolTestConnection(this, client_->message_loop()); + ProtocolTestConnection* test_connection = new ProtocolTestConnection(this); session->SetStateChangeCallback( NewCallback(test_connection, &ProtocolTestConnection::OnStateChange)); test_connection->Init(session); @@ -329,19 +332,6 @@ void ProtocolTestClient::OnFinishedClosing() { closed_event_.Signal(); } -void ProtocolTestClient::DestroyConnection( - scoped_refptr<ProtocolTestConnection> connection) { - connection->Close(); - base::AutoLock auto_lock(connections_lock_); - for (ConnectionsList::iterator it = connections_.begin(); - it != connections_.end(); ++it) { - if ((*it) == connection) { - connections_.erase(it); - return; - } - } -} - } // namespace protocol } // namespace remoting diff --git a/remoting/protocol/session_manager.h b/remoting/protocol/session_manager.h index 254ba27..e1cb990 100644 --- a/remoting/protocol/session_manager.h +++ b/remoting/protocol/session_manager.h @@ -54,7 +54,18 @@ class Task; +namespace crypto { +class RSAPrivateKey; +} // namespace base + +namespace net { +class X509Certificate; +} // namespace net + namespace remoting { + +class SignalStrategy; + namespace protocol { // Generic interface for Chromoting session manager. @@ -76,6 +87,20 @@ class SessionManager : public base::RefCountedThreadSafe<SessionManager> { typedef Callback2<Session*, IncomingSessionResponse*>::Type IncomingSessionCallback; + // Initializes the session client. Doesn't accept ownership of the + // |signal_strategy|. Close() must be called _before_ the |session_manager| + // is destroyed. + // If this object is used in server mode, then |private_key| and + // |certificate| are used to establish a secured communication with the + // client. It will also take ownership of these objects. + // In case this is used in client mode, pass in NULL for both private key and + // certificate. + virtual void Init(const std::string& local_jid, + SignalStrategy* signal_strategy, + IncomingSessionCallback* incoming_session_callback, + crypto::RSAPrivateKey* private_key, + scoped_refptr<net::X509Certificate> certificate) = 0; + // Tries to create a session to the host |jid|. // // |host_jid| is the full jid of the host to connect to. diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 2781604..b5177f9 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -501,8 +501,6 @@ 'jingle_glue/javascript_iq_request.h', 'jingle_glue/javascript_signal_strategy.cc', 'jingle_glue/javascript_signal_strategy.h', - 'jingle_glue/jingle_client.cc', - 'jingle_glue/jingle_client.h', 'jingle_glue/jingle_info_request.cc', 'jingle_glue/jingle_info_request.h', 'jingle_glue/jingle_signaling_connector.cc', @@ -716,7 +714,6 @@ 'jingle_glue/fake_signal_strategy.cc', 'jingle_glue/fake_signal_strategy.h', 'jingle_glue/iq_request_unittest.cc', - 'jingle_glue/jingle_client_unittest.cc', 'jingle_glue/jingle_thread_unittest.cc', 'jingle_glue/mock_objects.cc', 'jingle_glue/mock_objects.h', |