diff options
Diffstat (limited to 'remoting/jingle_glue')
-rw-r--r-- | remoting/jingle_glue/iq_request.cc | 90 | ||||
-rw-r--r-- | remoting/jingle_glue/iq_request.h | 98 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client.cc | 245 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client.h | 153 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_client_unittest.cc | 15 |
5 files changed, 412 insertions, 189 deletions
diff --git a/remoting/jingle_glue/iq_request.cc b/remoting/jingle_glue/iq_request.cc index c56ef4c..8d53b40 100644 --- a/remoting/jingle_glue/iq_request.cc +++ b/remoting/jingle_glue/iq_request.cc @@ -7,28 +7,42 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/scoped_ptr.h" -#include "remoting/jingle_glue/jingle_client.h" #include "third_party/libjingle/source/talk/xmpp/constants.h" -#include "third_party/libjingle/source/talk/xmpp/xmppengine.h" +#include "third_party/libjingle/source/talk/xmpp/xmppclient.h" namespace remoting { -IqRequest::IqRequest(JingleClient* jingle_client) - : jingle_client_(jingle_client), +// static +buzz::XmlElement* IqRequest::MakeIqStanza(const std::string& type, + const std::string& addressee, + buzz::XmlElement* iq_body, + const std::string& id) { + buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_IQ); + stanza->AddAttr(buzz::QN_TYPE, type); + stanza->AddAttr(buzz::QN_TO, addressee); + stanza->AddAttr(buzz::QN_ID, id); + stanza->AddElement(iq_body); + return stanza; +} + +XmppIqRequest::XmppIqRequest(MessageLoop* message_loop, + buzz::XmppClient* xmpp_client) + : message_loop_(message_loop), + xmpp_client_(xmpp_client), cookie_(NULL) { - DCHECK(jingle_client_ != NULL); - DCHECK(MessageLoop::current() == jingle_client_->message_loop()); + DCHECK(xmpp_client_); + DCHECK_EQ(MessageLoop::current(), message_loop_); } -IqRequest::~IqRequest() { - DCHECK(MessageLoop::current() == jingle_client_->message_loop()); +XmppIqRequest::~XmppIqRequest() { + DCHECK_EQ(MessageLoop::current(), message_loop_); Unregister(); } -void IqRequest::SendIq(const std::string& type, +void XmppIqRequest::SendIq(const std::string& type, const std::string& addressee, buzz::XmlElement* iq_body) { - DCHECK(MessageLoop::current() == jingle_client_->message_loop()); + DCHECK_EQ(MessageLoop::current(), message_loop_); // Unregister the handler if it is already registered. Unregister(); @@ -36,44 +50,54 @@ void IqRequest::SendIq(const std::string& type, DCHECK_GT(type.length(), 0U); DCHECK_GT(addressee.length(), 0U); - buzz::XmppClient* xmpp_client = jingle_client_->xmpp_client(); - DCHECK(xmpp_client); // Expect that connection is active. - scoped_ptr<buzz::XmlElement> stanza(MakeIqStanza(type, addressee, iq_body, - xmpp_client->NextId())); + xmpp_client_->NextId())); - xmpp_client->engine()->SendIq(stanza.get(), this, &cookie_); -} - -// static -buzz::XmlElement* IqRequest::MakeIqStanza(const std::string& type, - const std::string& addressee, - buzz::XmlElement* iq_body, - const std::string& id) { - buzz::XmlElement* stanza = new buzz::XmlElement(buzz::QN_IQ); - stanza->AddAttr(buzz::QN_TYPE, type); - stanza->AddAttr(buzz::QN_TO, addressee); - stanza->AddAttr(buzz::QN_ID, id); - stanza->AddElement(iq_body); - return stanza; + xmpp_client_->engine()->SendIq(stanza.get(), this, &cookie_); } -void IqRequest::Unregister() { +void XmppIqRequest::Unregister() { if (cookie_) { - buzz::XmppClient* xmpp_client = jingle_client_->xmpp_client(); // No need to unregister the handler if the client has been destroyed. - if (xmpp_client) { - xmpp_client->engine()->RemoveIqHandler(cookie_, NULL); + if (xmpp_client_) { + xmpp_client_->engine()->RemoveIqHandler(cookie_, NULL); } cookie_ = NULL; } } -void IqRequest::IqResponse(buzz::XmppIqCookie cookie, +void XmppIqRequest::IqResponse(buzz::XmppIqCookie cookie, const buzz::XmlElement* stanza) { if (callback_.get() != NULL) { callback_->Run(stanza); } } +JavascriptIqRequest::JavascriptIqRequest() { +} + +JavascriptIqRequest::~JavascriptIqRequest() { +} + +void JavascriptIqRequest::SendIq(const std::string& type, + const std::string& addressee, + buzz::XmlElement* iq_body) { + NOTIMPLEMENTED(); + // TODO(ajwong): The "1" below is completely wrong. Need to change to use a + // sequence that just increments or something. + scoped_ptr<buzz::XmlElement> stanza( + MakeIqStanza(type, addressee, iq_body, "1")); + + xmpp_proxy_->SendIq(stanza->Str()); +} + +void JavascriptIqRequest::ReceiveIq(const std::string& iq_response) { + // TODO(ajwong): Somehow send this to callback_ here. + LOG(ERROR) << "Got IQ!!!!!!\n" << iq_response; +} + +void JavascriptIqRequest::set_callback(ReplyCallback* callback) { + callback_.reset(callback); +} + } // namespace remoting diff --git a/remoting/jingle_glue/iq_request.h b/remoting/jingle_glue/iq_request.h index 6933b17..3d11034 100644 --- a/remoting/jingle_glue/iq_request.h +++ b/remoting/jingle_glue/iq_request.h @@ -9,11 +9,42 @@ #include "base/callback.h" #include "base/gtest_prod_util.h" +#include "base/weak_ptr.h" #include "third_party/libjingle/source/talk/xmpp/xmppengine.h" +class MessageLoop; + +namespace buzz { +class XmppClient; +} // namespace buzz + namespace remoting { -class JingleClient; +class JavascriptIqRequest; +class ChromotingScriptableObject; + +class XmppProxy : public base::RefCountedThreadSafe<XmppProxy> { + public: + XmppProxy() {} + + // Must be run on pepper thread. + virtual void AttachScriptableObject( + ChromotingScriptableObject* scriptable_object) = 0; + + // Must be run on jingle thread. + virtual void AttachJavascriptIqRequest( + JavascriptIqRequest* javascript_iq_request) = 0; + + virtual void SendIq(const std::string& iq_request_xml) = 0; + virtual void ReceiveIq(const std::string& iq_response_xml) = 0; + + protected: + friend class base::RefCountedThreadSafe<XmppProxy>; + virtual ~XmppProxy() {} + + private: + DISALLOW_COPY_AND_ASSIGN(XmppProxy); +}; // IqRequest class can be used to send an IQ stanza and then receive reply // stanza for that request. It sends outgoing stanza when SendIq() is called, @@ -21,22 +52,67 @@ class JingleClient; // set_callback(). If multiple IQ stanzas are send with SendIq() then only reply // to the last one will be received. // The class must be used on the jingle thread only. -class IqRequest : private buzz::XmppIqHandler { +class IqRequest { public: typedef Callback1<const buzz::XmlElement*>::Type ReplyCallback; - explicit IqRequest(JingleClient* jingle_client); - virtual ~IqRequest(); + IqRequest() {} + virtual ~IqRequest() {} // Sends stanza of type |type| to |addressee|. |iq_body| contains body of // the stanza. Ownership of |iq_body| is transfered to IqRequest. Must // be called on the jingle thread. virtual void SendIq(const std::string& type, const std::string& addressee, - buzz::XmlElement* iq_body); + buzz::XmlElement* iq_body) = 0; // Sets callback that is called when reply stanza is received. Callback // is called on the jingle thread. - void set_callback(ReplyCallback* callback) { + virtual void set_callback(ReplyCallback* callback) = 0; + + protected: + static buzz::XmlElement* MakeIqStanza(const std::string& type, + const std::string& addressee, + buzz::XmlElement* iq_body, + const std::string& id); + + private: + FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza); + + DISALLOW_COPY_AND_ASSIGN(IqRequest); +}; + +// TODO(ajwong): Is this class even used? The client side may never use +// IqRequests in the JingleClient. +class JavascriptIqRequest : public IqRequest, + public base::SupportsWeakPtr<JavascriptIqRequest> { + public: + JavascriptIqRequest(); + virtual ~JavascriptIqRequest(); + + virtual void SendIq(const std::string& type, const std::string& addressee, + buzz::XmlElement* iq_body); + + virtual void ReceiveIq(const std::string& iq_response); + + virtual void set_callback(ReplyCallback* callback); + + private: + scoped_ptr<ReplyCallback> callback_; + scoped_refptr<XmppProxy> xmpp_proxy_; + + FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza); +}; + +class XmppIqRequest : public IqRequest, private buzz::XmppIqHandler { + public: + typedef Callback1<const buzz::XmlElement*>::Type ReplyCallback; + + XmppIqRequest(MessageLoop* message_loop, buzz::XmppClient* xmpp_client); + virtual ~XmppIqRequest(); + + virtual void SendIq(const std::string& type, const std::string& addressee, + buzz::XmlElement* iq_body); + virtual void set_callback(ReplyCallback* callback) { callback_.reset(callback); } @@ -47,14 +123,12 @@ class IqRequest : private buzz::XmppIqHandler { virtual void IqResponse(buzz::XmppIqCookie cookie, const buzz::XmlElement* stanza); - static buzz::XmlElement* MakeIqStanza(const std::string& type, - const std::string& addressee, - buzz::XmlElement* iq_body, - const std::string& id); - void Unregister(); - scoped_refptr<JingleClient> jingle_client_; + // TODO(ajwong): This used to hold a reference to the jingle client...make + // sure the lifetime names sense now. + MessageLoop* message_loop_; + buzz::XmppClient* xmpp_client_; buzz::XmppIqCookie cookie_; scoped_ptr<ReplyCallback> callback_; }; diff --git a/remoting/jingle_glue/jingle_client.cc b/remoting/jingle_glue/jingle_client.cc index 7b00d79..02593ed 100644 --- a/remoting/jingle_glue/jingle_client.cc +++ b/remoting/jingle_glue/jingle_client.cc @@ -22,79 +22,178 @@ namespace remoting { -JingleClient::JingleClient(JingleThread* thread) - : thread_(thread), - callback_(NULL), - client_(NULL), - state_(START), - initialized_(false), - closed_(false) { -} - -JingleClient::~JingleClient() { - base::AutoLock auto_lock(state_lock_); - DCHECK(!initialized_ || closed_); +// The XmppSignalStrategy encapsulates all the logic to perform the signaling +// STUN/ICE for jingle via a direct XMPP connection. +// +// This class is not threadsafe. +XmppSignalStrategy::XmppSignalStrategy(JingleThread* jingle_thread, + const std::string& username, + const std::string& auth_token, + const std::string& auth_token_service) + : thread_(jingle_thread), + username_(username), + auth_token_(auth_token), + auth_token_service_(auth_token_service), + xmpp_client_(NULL), + observer_(NULL) { } -void JingleClient::Init( - const std::string& username, const std::string& auth_token, - const std::string& auth_token_service, Callback* callback) { - DCHECK_NE(username, ""); - - { - base::AutoLock auto_lock(state_lock_); - DCHECK(!initialized_ && !closed_); - initialized_ = true; - - DCHECK(callback != NULL); - callback_ = callback; - } - - message_loop()->PostTask( - FROM_HERE, NewRunnableMethod(this, &JingleClient::DoInitialize, - username, auth_token, auth_token_service)); +XmppSignalStrategy::~XmppSignalStrategy() { } -void JingleClient::DoInitialize(const std::string& username, - const std::string& auth_token, - const std::string& auth_token_service) { - DCHECK_EQ(message_loop(), MessageLoop::current()); +void XmppSignalStrategy::Init(StatusObserver* observer) { + observer_ = observer; - buzz::Jid login_jid(username); + buzz::Jid login_jid(username_); buzz::XmppClientSettings settings; settings.set_user(login_jid.node()); settings.set_host(login_jid.domain()); settings.set_resource("chromoting"); settings.set_use_tls(true); - settings.set_token_service(auth_token_service); - settings.set_auth_cookie(auth_token); + settings.set_token_service(auth_token_service_); + settings.set_auth_cookie(auth_token_); settings.set_server(talk_base::SocketAddress("talk.google.com", 5222)); - client_ = new buzz::XmppClient(thread_->task_pump()); - client_->SignalStateChange.connect( - this, &JingleClient::OnConnectionStateChanged); - buzz::AsyncSocket* socket = new XmppSocketAdapter(settings, false); - client_->Connect(settings, "", socket, CreatePreXmppAuth(settings)); - client_->Start(); + xmpp_client_ = new buzz::XmppClient(thread_->task_pump()); + xmpp_client_->Connect(settings, "", socket, CreatePreXmppAuth(settings)); + xmpp_client_->SignalStateChange.connect( + this, &XmppSignalStrategy::OnConnectionStateChanged); + xmpp_client_->Start(); + // Setup the port allocation based on jingle connections. network_manager_.reset(new talk_base::NetworkManager()); - RelayPortAllocator* port_allocator = new RelayPortAllocator(network_manager_.get(), "transp2"); + port_allocator->SetJingleInfo(xmpp_client_); port_allocator_.reset(port_allocator); - port_allocator->SetJingleInfo(client_); +} - session_manager_.reset(new cricket::SessionManager(port_allocator_.get())); +cricket::BasicPortAllocator* XmppSignalStrategy::port_allocator() { + return port_allocator_.get(); +} +void XmppSignalStrategy::StartSession( + cricket::SessionManager* session_manager) { cricket::SessionManagerTask* receiver = - new cricket::SessionManagerTask(client_, session_manager_.get()); + new cricket::SessionManagerTask(xmpp_client_, session_manager); receiver->EnableOutgoingMessages(); receiver->Start(); } +void XmppSignalStrategy::EndSession() { + if (xmpp_client_) { + xmpp_client_->Disconnect(); + // Client is deleted by TaskRunner. + xmpp_client_ = NULL; + } +} + +IqRequest* XmppSignalStrategy::CreateIqRequest() { + return new XmppIqRequest(thread_->message_loop(), xmpp_client_); +} + +void XmppSignalStrategy::OnConnectionStateChanged( + buzz::XmppEngine::State state) { + switch (state) { + case buzz::XmppEngine::STATE_START: + observer_->OnStateChange(StatusObserver::START); + break; + case buzz::XmppEngine::STATE_OPENING: + observer_->OnStateChange(StatusObserver::CONNECTING); + break; + case buzz::XmppEngine::STATE_OPEN: + observer_->OnJidChange(xmpp_client_->jid().Str()); + observer_->OnStateChange(StatusObserver::CONNECTED); + break; + case buzz::XmppEngine::STATE_CLOSED: + observer_->OnStateChange(StatusObserver::CLOSED); + // Client is destroyed by the TaskRunner after the client is + // closed. Reset the pointer so we don't try to use it later. + xmpp_client_ = NULL; + break; + default: + NOTREACHED(); + break; + } +} + +buzz::PreXmppAuth* XmppSignalStrategy::CreatePreXmppAuth( + const buzz::XmppClientSettings& settings) { + buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY); + return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(), + settings.token_service()); +} + + +JavascriptSignalStrategy::JavascriptSignalStrategy() { +} + +JavascriptSignalStrategy::~JavascriptSignalStrategy() { +} + +void JavascriptSignalStrategy::Init(StatusObserver* observer) { + NOTIMPLEMENTED(); +} + +cricket::BasicPortAllocator* JavascriptSignalStrategy::port_allocator() { + NOTIMPLEMENTED(); + return NULL; +} + +void JavascriptSignalStrategy::StartSession( + cricket::SessionManager* session_manager) { + NOTIMPLEMENTED(); +} + +void JavascriptSignalStrategy::EndSession() { + NOTIMPLEMENTED(); +} + +IqRequest* JavascriptSignalStrategy::CreateIqRequest() { + return new JavascriptIqRequest(); +} + +JingleClient::JingleClient(JingleThread* thread, + SignalStrategy* signal_strategy, + Callback* callback) + : thread_(thread), + state_(START), + initialized_(false), + closed_(false), + callback_(callback), + signal_strategy_(signal_strategy) { +} + +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()); + + signal_strategy_->Init(this); + + session_manager_.reset( + new cricket::SessionManager(signal_strategy_->port_allocator())); + + signal_strategy_->StartSession(session_manager_.get()); +} + void JingleClient::Close() { Close(NULL); } @@ -121,14 +220,9 @@ void JingleClient::DoClose() { DCHECK(closed_); session_manager_.reset(); - port_allocator_.reset(); - network_manager_.reset(); - - if (client_) { - client_->Disconnect(); - // Client is deleted by TaskRunner. - client_ = NULL; - } + signal_strategy_->EndSession(); + // TODO(ajwong): SignalStrategy should drop all resources at EndSession(). + signal_strategy_ = NULL; if (closed_task_.get()) { closed_task_->Run(); @@ -137,12 +231,12 @@ void JingleClient::DoClose() { } std::string JingleClient::GetFullJid() { - base::AutoLock auto_lock(full_jid_lock_); + base::AutoLock auto_lock(jid_lock_); return full_jid_; } IqRequest* JingleClient::CreateIqRequest() { - return new IqRequest(this); + return signal_strategy_->CreateIqRequest(); } MessageLoop* JingleClient::message_loop() { @@ -154,36 +248,7 @@ cricket::SessionManager* JingleClient::session_manager() { return session_manager_.get(); } -void JingleClient::OnConnectionStateChanged(buzz::XmppEngine::State state) { - switch (state) { - case buzz::XmppEngine::STATE_START: - UpdateState(START); - break; - case buzz::XmppEngine::STATE_OPENING: - UpdateState(CONNECTING); - break; - case buzz::XmppEngine::STATE_OPEN: - SetFullJid(client_->jid().Str()); - UpdateState(CONNECTED); - break; - case buzz::XmppEngine::STATE_CLOSED: - UpdateState(CLOSED); - // Client is destroyed by the TaskRunner after the client is - // closed. Reset the pointer so we don't try to use it later. - client_ = NULL; - break; - default: - NOTREACHED(); - break; - } -} - -void JingleClient::SetFullJid(const std::string& full_jid) { - base::AutoLock auto_lock(full_jid_lock_); - full_jid_ = full_jid; -} - -void JingleClient::UpdateState(State new_state) { +void JingleClient::OnStateChange(State new_state) { if (new_state != state_) { state_ = new_state; { @@ -196,11 +261,9 @@ void JingleClient::UpdateState(State new_state) { } } -buzz::PreXmppAuth* JingleClient::CreatePreXmppAuth( - const buzz::XmppClientSettings& settings) { - buzz::Jid jid(settings.user(), settings.host(), buzz::STR_EMPTY); - return new notifier::GaiaTokenPreXmppAuth(jid.Str(), settings.auth_cookie(), - settings.token_service()); +void JingleClient::OnJidChange(const std::string& full_jid) { + base::AutoLock auto_lock(jid_lock_); + full_jid_ = full_jid; } } // namespace remoting diff --git a/remoting/jingle_glue/jingle_client.h b/remoting/jingle_glue/jingle_client.h index 173e90e..f60e029 100644 --- a/remoting/jingle_glue/jingle_client.h +++ b/remoting/jingle_glue/jingle_client.h @@ -7,6 +7,7 @@ #include <string> +#include "base/gtest_prod_util.h" #include "base/ref_counted.h" #include "base/synchronization/lock.h" #include "third_party/libjingle/source/talk/xmpp/xmppclient.h" @@ -35,16 +36,90 @@ namespace remoting { class IqRequest; class JingleThread; -class JingleClient : public base::RefCountedThreadSafe<JingleClient>, - public sigslot::has_slots<> { +// TODO(ajwong): The SignalStrategy stuff needs to be separated out to separate +// files. +class SignalStrategy { public: - enum State { - START, // Initial state. - CONNECTING, - CONNECTED, - CLOSED, + class StatusObserver { + public: + enum State { + START, + CONNECTING, + CONNECTED, + CLOSED, + }; + + // Called when state of the connection is changed. + virtual void OnStateChange(State state) = 0; + virtual void OnJidChange(const std::string& full_jid) = 0; }; + SignalStrategy() {} + virtual ~SignalStrategy() {} + virtual void Init(StatusObserver* observer) = 0; + virtual cricket::BasicPortAllocator* port_allocator() = 0; + virtual void StartSession(cricket::SessionManager* session_manager) = 0; + virtual void EndSession() = 0; + virtual IqRequest* CreateIqRequest() = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(SignalStrategy); +}; + +class XmppSignalStrategy : public SignalStrategy, public sigslot::has_slots<> { + public: + XmppSignalStrategy(JingleThread* thread, + const std::string& username, + const std::string& auth_token, + const std::string& auth_token_service); + virtual ~XmppSignalStrategy(); + + virtual void Init(StatusObserver* observer); + virtual cricket::BasicPortAllocator* port_allocator(); + virtual void StartSession(cricket::SessionManager* session_manager); + virtual void EndSession(); + virtual IqRequest* CreateIqRequest(); + + private: + void OnConnectionStateChanged(buzz::XmppEngine::State state); + static buzz::PreXmppAuth* CreatePreXmppAuth( + const buzz::XmppClientSettings& settings); + + JingleThread* thread_; + + std::string username_; + std::string auth_token_; + std::string auth_token_service_; + buzz::XmppClient* xmpp_client_; + StatusObserver* observer_; + scoped_ptr<talk_base::NetworkManager> network_manager_; + scoped_ptr<cricket::BasicPortAllocator> port_allocator_; + + private: + friend class JingleClientTest; + + DISALLOW_COPY_AND_ASSIGN(XmppSignalStrategy); +}; + +class JavascriptSignalStrategy : public SignalStrategy { + public: + JavascriptSignalStrategy(); + virtual ~JavascriptSignalStrategy(); + + virtual void Init(StatusObserver* observer); + virtual cricket::BasicPortAllocator* port_allocator(); + virtual void StartSession(cricket::SessionManager* session_manager); + virtual void EndSession(); + virtual IqRequest* CreateIqRequest(); + + private: + DISALLOW_COPY_AND_ASSIGN(JavascriptSignalStrategy); +}; + + +class JingleClient : public base::RefCountedThreadSafe<JingleClient>, + public SignalStrategy::StatusObserver { + public: class Callback { public: virtual ~Callback() {} @@ -53,17 +128,13 @@ class JingleClient : public base::RefCountedThreadSafe<JingleClient>, virtual void OnStateChange(JingleClient* client, State state) = 0; }; - // Creates a JingleClient object that executes on |thread|. This does not - // take ownership of |thread| and expects that the thread is started before - // the constructor is called, and only stopped after the JingleClient object - // has been destructed. - explicit JingleClient(JingleThread* thread); - virtual ~JingleClient(); + JingleClient(JingleThread* thread, SignalStrategy* signal_strategy, + Callback* callback); + ~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(const std::string& username, const std::string& auth_token, - const std::string& auth_token_service, Callback* callback); + void Init(); // Closes XMPP connection and stops the thread. Must be called before the // object is destroyed. If specified, |closed_task| is executed after the @@ -77,64 +148,52 @@ class JingleClient : public base::RefCountedThreadSafe<JingleClient>, // Creates new IqRequest for this client. Ownership for of the created object // is transfered to the caller. - virtual IqRequest* CreateIqRequest(); - - // Current connection state of the client. - State state() { return state_; } - - // Returns XmppClient object for the xmpp connection or NULL if not connected. - buzz::XmppClient* xmpp_client() { return client_; } - - // Message loop used by this object to execute tasks. - MessageLoop* message_loop(); + 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(); + private: friend class HeartbeatSenderTest; friend class JingleClientTest; - void OnConnectionStateChanged(buzz::XmppEngine::State state); - - void DoInitialize(const std::string& username, - const std::string& auth_token, - const std::string& auth_token_service); - - // Used by Close(). + void DoInitialize(); void DoClose(); - void SetFullJid(const std::string& full_jid); - // Updates current state of the connection. Must be called only in // the jingle thread. void UpdateState(State new_state); - buzz::PreXmppAuth* CreatePreXmppAuth( - const buzz::XmppClientSettings& settings); + virtual void OnStateChange(State state); + virtual void OnJidChange(const std::string& full_jid); // JingleThread used for the connection. Set in the constructor. JingleThread* thread_; - // Callback for this object. Callback must not be called if closed_ == true. - Callback* callback_; - - // The XmppClient and its state and jid. - buzz::XmppClient* client_; - State state_; - base::Lock full_jid_lock_; - std::string full_jid_; - // 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_; - scoped_ptr<talk_base::NetworkManager> network_manager_; - scoped_ptr<cricket::BasicPortAllocator> port_allocator_; + // 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<cricket::SessionManager> session_manager_; DISALLOW_COPY_AND_ASSIGN(JingleClient); diff --git a/remoting/jingle_glue/jingle_client_unittest.cc b/remoting/jingle_glue/jingle_client_unittest.cc index 807f061..3d9f574 100644 --- a/remoting/jingle_glue/jingle_client_unittest.cc +++ b/remoting/jingle_glue/jingle_client_unittest.cc @@ -29,22 +29,25 @@ class JingleClientTest : public testing::Test { // A helper that calls OnConnectionStateChanged(). Need this because we want // to call it on the jingle thread. - static void ChangeState(JingleClient* client, buzz::XmppEngine::State state, + static void ChangeState(XmppSignalStrategy* strategy, + buzz::XmppEngine::State state, base::WaitableEvent* done_event) { - client->OnConnectionStateChanged(state); + strategy->OnConnectionStateChanged(state); if (done_event) done_event->Signal(); } protected: virtual void SetUp() { - client_ = new JingleClient(&thread_); + signal_strategy_.reset(new XmppSignalStrategy(&thread_, "", "", "")); + client_ = new JingleClient(&thread_, signal_strategy_.get(), &callback_); // Fake initialization client_->initialized_ = true; - client_->callback_ = &callback_; + signal_strategy_->observer_ = client_; } JingleThread thread_; + scoped_ptr<XmppSignalStrategy> signal_strategy_; scoped_refptr<JingleClient> client_; MockJingleClientCallback callback_; }; @@ -57,7 +60,7 @@ TEST_F(JingleClientTest, OnStateChanged) { base::WaitableEvent state_changed_event(true, false); thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( - &JingleClientTest::ChangeState, client_, + &JingleClientTest::ChangeState, signal_strategy_.get(), buzz::XmppEngine::STATE_OPENING, &state_changed_event)); state_changed_event.Wait(); @@ -73,7 +76,7 @@ TEST_F(JingleClientTest, Close) { client_->Close(); // Verify that the channel doesn't call callback anymore. thread_.message_loop()->PostTask(FROM_HERE, NewRunnableFunction( - &JingleClientTest::ChangeState, client_, + &JingleClientTest::ChangeState, signal_strategy_.get(), buzz::XmppEngine::STATE_OPENING, static_cast<base::WaitableEvent*>(NULL))); thread_.Stop(); |