summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-22 19:39:27 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-06-22 19:39:27 +0000
commitd64c8244fb7a456a2ffd81b418f06528920c4e81 (patch)
tree4b218d579e5d48928aa29ca0e76978bc1aeb0094
parentce310a752d7fe78ec81d2bd1553a4bd34e990b25 (diff)
downloadchromium_src-d64c8244fb7a456a2ffd81b418f06528920c4e81.zip
chromium_src-d64c8244fb7a456a2ffd81b418f06528920c4e81.tar.gz
chromium_src-d64c8244fb7a456a2ffd81b418f06528920c4e81.tar.bz2
Split iq_request.[h|cc] into multiple files.
BUG=None TEST=compiles Review URL: http://codereview.chromium.org/7211033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90073 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--remoting/jingle_glue/iq_request.cc306
-rw-r--r--remoting/jingle_glue/iq_request.h200
-rw-r--r--remoting/jingle_glue/javascript_iq_request.cc137
-rw-r--r--remoting/jingle_glue/javascript_iq_request.h100
-rw-r--r--remoting/jingle_glue/javascript_signal_strategy.cc7
-rw-r--r--remoting/jingle_glue/javascript_signal_strategy.h5
-rw-r--r--remoting/jingle_glue/jingle_client.cc1
-rw-r--r--remoting/jingle_glue/jingle_client.h4
-rw-r--r--remoting/jingle_glue/jingle_info_request.cc94
-rw-r--r--remoting/jingle_glue/jingle_info_request.h70
-rw-r--r--remoting/jingle_glue/jingle_signaling_connector.cc61
-rw-r--r--remoting/jingle_glue/jingle_signaling_connector.h58
-rw-r--r--remoting/jingle_glue/xmpp_iq_request.cc65
-rw-r--r--remoting/jingle_glue/xmpp_iq_request.h52
-rw-r--r--remoting/jingle_glue/xmpp_signal_strategy.cc2
-rw-r--r--remoting/remoting.gyp8
16 files changed, 660 insertions, 510 deletions
diff --git a/remoting/jingle_glue/iq_request.cc b/remoting/jingle_glue/iq_request.cc
index 07d2c81..3ea2726 100644
--- a/remoting/jingle_glue/iq_request.cc
+++ b/remoting/jingle_glue/iq_request.cc
@@ -4,13 +4,8 @@
#include "remoting/jingle_glue/iq_request.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/string_number_conversions.h"
-#include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
#include "third_party/libjingle/source/talk/xmpp/constants.h"
-#include "third_party/libjingle/source/talk/xmpp/xmppclient.h"
namespace remoting {
@@ -27,303 +22,4 @@ buzz::XmlElement* IqRequest::MakeIqStanza(const std::string& type,
return stanza;
}
-XmppIqRequest::XmppIqRequest(MessageLoop* message_loop,
- buzz::XmppClient* xmpp_client)
- : message_loop_(message_loop),
- xmpp_client_(xmpp_client),
- cookie_(NULL) {
- DCHECK(xmpp_client_);
- DCHECK_EQ(MessageLoop::current(), message_loop_);
-}
-
-XmppIqRequest::~XmppIqRequest() {
- DCHECK_EQ(MessageLoop::current(), message_loop_);
- Unregister();
-}
-
-void XmppIqRequest::SendIq(const std::string& type,
- const std::string& addressee,
- buzz::XmlElement* iq_body) {
- DCHECK_EQ(MessageLoop::current(), message_loop_);
-
- // Unregister the handler if it is already registered.
- Unregister();
-
- DCHECK_GT(type.length(), 0U);
-
- scoped_ptr<buzz::XmlElement> stanza(MakeIqStanza(type, addressee, iq_body,
- xmpp_client_->NextId()));
-
- xmpp_client_->engine()->SendIq(stanza.get(), this, &cookie_);
-}
-
-void XmppIqRequest::set_callback(ReplyCallback* callback) {
- callback_.reset(callback);
-}
-
-void XmppIqRequest::Unregister() {
- if (cookie_) {
- // No need to unregister the handler if the client has been destroyed.
- if (xmpp_client_) {
- xmpp_client_->engine()->RemoveIqHandler(cookie_, NULL);
- }
- cookie_ = NULL;
- }
-}
-
-void XmppIqRequest::IqResponse(buzz::XmppIqCookie cookie,
- const buzz::XmlElement* stanza) {
- if (callback_.get() != NULL) {
- callback_->Run(stanza);
- }
-}
-
-JavascriptIqRegistry::JavascriptIqRegistry()
- : current_id_(0),
- default_handler_(NULL) {
-}
-
-JavascriptIqRegistry::~JavascriptIqRegistry() {
-}
-
-void JavascriptIqRegistry::RemoveAllRequests(JavascriptIqRequest* request) {
- IqRequestMap::iterator it = requests_.begin();
- while (it != requests_.end()) {
- IqRequestMap::iterator cur = it;
- ++it;
- if (cur->second == request) {
- requests_.erase(cur);
- }
- }
-}
-
-void JavascriptIqRegistry::SetDefaultHandler(JavascriptIqRequest* new_handler) {
- // Should only allow a new handler if |default_handler_| is NULL.
- CHECK(default_handler_ == NULL || !new_handler);
- default_handler_ = new_handler;
-}
-
-void JavascriptIqRegistry::OnIq(const std::string& response_xml) {
- // TODO(ajwong): Can we cleanup this dispatch at all? The send is from
- // JavascriptIqRequest but the return is in JavascriptIqRegistry.
- scoped_ptr<buzz::XmlElement> stanza(buzz::XmlElement::ForStr(response_xml));
-
- if (!stanza.get()) {
- LOG(WARNING) << "Malformed XML received" << response_xml;
- return;
- }
-
- LOG(ERROR) << "IQ Received: " << stanza->Str();
- if (stanza->Name() != buzz::QN_IQ) {
- LOG(WARNING) << "Received unexpected non-IQ packet" << stanza->Str();
- return;
- }
-
- if (!stanza->HasAttr(buzz::QN_ID)) {
- LOG(WARNING) << "IQ packet missing id" << stanza->Str();
- return;
- }
-
- const std::string& id = stanza->Attr(buzz::QN_ID);
-
- IqRequestMap::iterator it = requests_.find(id);
- if (it == requests_.end()) {
- if (!default_handler_) {
- VLOG(1) << "Dropping IQ packet with no request id: " << stanza->Str();
- } else {
- if (default_handler_->callback_.get()) {
- default_handler_->callback_->Run(stanza.get());
- } else {
- VLOG(1) << "default handler has no callback, so dropping: "
- << stanza->Str();
- }
- }
- } else {
- // TODO(ajwong): We should look at the logic inside libjingle's
- // XmppTask::MatchResponseIq() and make sure we're fully in sync.
- // They check more fields and conditions than us.
-
- // TODO(ajwong): This logic is weird. We add to the register in
- // JavascriptIqRequest::SendIq(), but remove in
- // JavascriptIqRegistry::OnIq(). We should try to keep the
- // registration/deregistration in one spot.
- if (it->second->callback_.get()) {
- it->second->callback_->Run(stanza.get());
- } else {
- VLOG(1) << "No callback, so dropping: " << stanza->Str();
- }
- requests_.erase(it);
- }
-}
-
-std::string JavascriptIqRegistry::RegisterRequest(
- JavascriptIqRequest* request) {
- ++current_id_;
- std::string id_as_string = base::IntToString(current_id_);
-
- requests_[id_as_string] = request;
- return id_as_string;
-}
-
-JavascriptIqRequest::JavascriptIqRequest(JavascriptIqRegistry* registry,
- scoped_refptr<XmppProxy> xmpp_proxy)
- : xmpp_proxy_(xmpp_proxy),
- registry_(registry),
- is_default_handler_(false) {
-}
-
-JavascriptIqRequest::~JavascriptIqRequest() {
- registry_->RemoveAllRequests(this);
- if (is_default_handler_) {
- registry_->SetDefaultHandler(NULL);
- }
-}
-
-void JavascriptIqRequest::SendIq(const std::string& type,
- const std::string& addressee,
- buzz::XmlElement* iq_body) {
- scoped_ptr<buzz::XmlElement> stanza(
- MakeIqStanza(type, addressee, iq_body,
- registry_->RegisterRequest(this)));
-
- xmpp_proxy_->SendIq(stanza->Str());
-}
-
-void JavascriptIqRequest::SendRawIq(buzz::XmlElement* stanza) {
- xmpp_proxy_->SendIq(stanza->Str());
-}
-
-void JavascriptIqRequest::BecomeDefaultHandler() {
- is_default_handler_ = true;
- registry_->SetDefaultHandler(this);
-}
-
-void JavascriptIqRequest::set_callback(ReplyCallback* callback) {
- callback_.reset(callback);
-}
-
-JingleInfoRequest::JingleInfoRequest(IqRequest* request)
- : request_(request) {
- request_->set_callback(NewCallback(this, &JingleInfoRequest::OnResponse));
-}
-
-JingleInfoRequest::~JingleInfoRequest() {
-}
-
-void JingleInfoRequest::Run(Task* done) {
- done_cb_.reset(done);
- request_->SendIq(buzz::STR_GET, buzz::STR_EMPTY,
- new buzz::XmlElement(buzz::QN_JINGLE_INFO_QUERY, true));
-}
-
-void JingleInfoRequest::SetCallback(OnJingleInfoCallback* callback) {
- on_jingle_info_cb_.reset(callback);
-}
-
-void JingleInfoRequest::DetachCallback() {
- on_jingle_info_cb_.reset();
-}
-
-void JingleInfoRequest::OnResponse(const buzz::XmlElement* stanza) {
- std::vector<std::string> relay_hosts;
- std::vector<talk_base::SocketAddress> stun_hosts;
- std::string relay_token;
-
- const buzz::XmlElement* query =
- stanza->FirstNamed(buzz::QN_JINGLE_INFO_QUERY);
- if (query == NULL) {
- LOG(WARNING) << "No Jingle info found in Jingle Info query response."
- << stanza->Str();
- return;
- }
-
- const buzz::XmlElement* stun = query->FirstNamed(buzz::QN_JINGLE_INFO_STUN);
- if (stun) {
- for (const buzz::XmlElement* server =
- stun->FirstNamed(buzz::QN_JINGLE_INFO_SERVER);
- server != NULL;
- server = server->NextNamed(buzz::QN_JINGLE_INFO_SERVER)) {
- std::string host = server->Attr(buzz::QN_JINGLE_INFO_HOST);
- std::string port_str = server->Attr(buzz::QN_JINGLE_INFO_UDP);
- if (host != buzz::STR_EMPTY && port_str != buzz::STR_EMPTY) {
- int port;
- if (!base::StringToInt(port_str, &port)) {
- LOG(WARNING) << "Unable to parse port in stanza" << stanza->Str();
- } else {
- stun_hosts.push_back(talk_base::SocketAddress(host, port));
- }
- }
- }
- }
-
- const buzz::XmlElement* relay = query->FirstNamed(buzz::QN_JINGLE_INFO_RELAY);
- if (relay) {
- relay_token = relay->TextNamed(buzz::QN_JINGLE_INFO_TOKEN);
- for (const buzz::XmlElement* server =
- relay->FirstNamed(buzz::QN_JINGLE_INFO_SERVER);
- server != NULL;
- server = server->NextNamed(buzz::QN_JINGLE_INFO_SERVER)) {
- std::string host = server->Attr(buzz::QN_JINGLE_INFO_HOST);
- if (host != buzz::STR_EMPTY) {
- relay_hosts.push_back(host);
- }
- }
- }
-
- if (on_jingle_info_cb_.get()) {
- on_jingle_info_cb_->Run(relay_token, relay_hosts, stun_hosts);
- } else {
- LOG(INFO) << "Iq reply parsed with no callback. Dropping" << stanza->Str();
- }
-
- DetachCallback();
- done_cb_->Run();
-}
-
-SessionStartRequest::SessionStartRequest(
- JavascriptIqRequest* request,
- cricket::SessionManager* session_manager)
- : request_(request),
- session_manager_(session_manager) {
- request_->set_callback(NewCallback(this, &SessionStartRequest::OnResponse));
-}
-
-SessionStartRequest::~SessionStartRequest() {
-}
-
-void SessionStartRequest::Run() {
- session_manager_->SignalOutgoingMessage.connect(
- this, &SessionStartRequest::OnOutgoingMessage);
-
- // TODO(ajwong): Why are we connecting SessionManager to itself?
- session_manager_->SignalRequestSignaling.connect(
- session_manager_, &cricket::SessionManager::OnSignalingReady);
- request_->BecomeDefaultHandler();
-}
-
-void SessionStartRequest::OnResponse(const buzz::XmlElement* response) {
- // TODO(ajwong): Techncially, when SessionManager sends IQ packets, it
- // actually expects a response in SessionSendTask(). However, if you look in
- // SessionManager::OnIncomingResponse(), it does nothing with the response.
- // Also, if no response is found, we are supposed to call
- // SessionManager::OnFailedSend().
- //
- // However, for right now, we just ignore those, and only propagate
- // messages outside of the request/reply framework to
- // SessionManager::OnIncomingMessage.
-
- if (session_manager_->IsSessionMessage(response)) {
- session_manager_->OnIncomingMessage(response);
- }
-}
-
-void SessionStartRequest::OnOutgoingMessage(
- cricket::SessionManager* session_manager,
- const buzz::XmlElement* stanza) {
- // TODO(ajwong): Are we just supposed to not use |session_manager|?
- DCHECK_EQ(session_manager, session_manager_);
- scoped_ptr<buzz::XmlElement> stanza_copy(new buzz::XmlElement(*stanza));
- request_->SendRawIq(stanza_copy.get());
-}
-
} // namespace remoting
diff --git a/remoting/jingle_glue/iq_request.h b/remoting/jingle_glue/iq_request.h
index 9d6c689..9e946ad 100644
--- a/remoting/jingle_glue/iq_request.h
+++ b/remoting/jingle_glue/iq_request.h
@@ -5,32 +5,15 @@
#ifndef REMOTING_JINGLE_GLUE_IQ_REQUEST_H_
#define REMOTING_JINGLE_GLUE_IQ_REQUEST_H_
-#include <map>
#include <string>
-#include <vector>
#include "base/callback_old.h"
#include "base/gtest_prod_util.h"
-#include "base/memory/weak_ptr.h"
-#include "remoting/jingle_glue/xmpp_proxy.h"
-#include "third_party/libjingle/source/talk/base/sigslot.h"
-#include "third_party/libjingle/source/talk/xmpp/xmppengine.h"
-
-class MessageLoop;
-class Task;
namespace buzz {
-class XmppClient;
+class XmlElement;
} // namespace buzz
-namespace cricket {
-class SessionManager;
-} // namespace cricket
-
-namespace talk_base {
-class SocketAddress;
-} // namespace talk_base
-
namespace remoting {
// IqRequest class can be used to send an IQ stanza and then receive reply
@@ -67,187 +50,6 @@ class IqRequest {
DISALLOW_COPY_AND_ASSIGN(IqRequest);
};
-class JavascriptIqRequest;
-
-class JavascriptIqRegistry : public XmppProxy::ResponseCallback {
- public:
- JavascriptIqRegistry();
- virtual ~JavascriptIqRegistry();
-
- // Dispatches the response to the IqRequest callback immediately.
- //
- // Does not take ownership of stanza.
- void DispatchResponse(buzz::XmlElement* stanza);
-
- // Registers |request|, returning the request ID used.
- std::string RegisterRequest(JavascriptIqRequest* request);
-
- // Removes all entries in the registry that refer to |request|. Useful when
- // |request| is about to be destructed.
- void RemoveAllRequests(JavascriptIqRequest* request);
-
- void SetDefaultHandler(JavascriptIqRequest* default_request);
-
- private:
- typedef std::map<std::string, JavascriptIqRequest*> IqRequestMap;
-
- // XmppProxy::ResponseCallback interface.
- virtual void OnIq(const std::string& response_xml);
-
- IqRequestMap requests_;
- int current_id_;
- JavascriptIqRequest* default_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(JavascriptIqRegistry);
-};
-
-// This call must only be used on the thread it was created on.
-class JavascriptIqRequest : public IqRequest {
- public:
- JavascriptIqRequest(JavascriptIqRegistry* registry,
- scoped_refptr<XmppProxy> xmpp_proxy);
- virtual ~JavascriptIqRequest();
-
- virtual void SendIq(const std::string& type, const std::string& addressee,
- buzz::XmlElement* iq_body);
-
- // Similar to SendIq(), but has 3 major differences:
- //
- // (1) It does absoluately no error checking. Caller is responsible for
- // validity.
- // (2) It doesn't add an Iq envelope. Caller is again responsible.
- // (3) BecomeDefaultHandler() must have been called.
- //
- // TODO(ajwong): We need to rationalize the semantics of these two APIs.
- // SendRawIq() is a hack for SessionStartRequest which uses a different memory
- // management convention.
- void SendRawIq(buzz::XmlElement* stanza);
-
- // This function is a hack to support SessionStartRequest. It registers the
- // current JavascriptIqRequest instance to be the single passthrough filter
- // for the associated JavascriptIqRegistry. What this means is that any IQ
- // packet that does not match a previous respone packet will be funneled
- // through to this JavascriptIqRegistry instance (basically a default
- // handler). It also means that the registry will not be tracking any of the
- // packets sent from this JavascriptIqRegistry instance.
- //
- // TODO(ajwong): We need to take a high-level look at IqRequest to understand
- // how to make this API cleaner.
- virtual void BecomeDefaultHandler();
-
- virtual void set_callback(ReplyCallback* callback);
-
- private:
- friend class JavascriptIqRegistry;
-
- scoped_ptr<ReplyCallback> callback_;
- scoped_refptr<XmppProxy> xmpp_proxy_;
- JavascriptIqRegistry* registry_;
- bool is_default_handler_;
-
- 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);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza);
-
- // XmppIqHandler interface.
- virtual void IqResponse(buzz::XmppIqCookie cookie,
- const buzz::XmlElement* stanza);
-
- void Unregister();
-
- // 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_;
-};
-
-// JingleInfoRequest handles making an IQ request to the Google talk network for
-// discovering stun/relay information for use in establishing a Jingle
-// connection.
-//
-// Clients should instantiate this class, and set a callback to receive the
-// configuration information. The query will be made when Run() is called. The
-// query is finisehd when the |done| task given to Run() is invokved.
-//
-// This class is not threadsafe and should be used on the same thread it is
-// created on.
-//
-// TODO(ajwong): Move to another file.
-// TODO(ajwong): Add support for a timeout.
-class JingleInfoRequest {
- public:
- // Callback to receive the Jingle configuration settings. The argumetns are
- // passed by pointer so the receive may call swap on them. The receiver does
- // NOT own the arguments, which are guaranteed only to be alive for the
- // duration of the callback.
- typedef Callback3<const std::string&, const std::vector<std::string>&,
- const std::vector<talk_base::SocketAddress>&>::Type
- OnJingleInfoCallback;
-
- explicit JingleInfoRequest(IqRequest* request);
- ~JingleInfoRequest();
-
- void Run(Task* done);
- void SetCallback(OnJingleInfoCallback* callback);
- void DetachCallback();
-
- private:
- void OnResponse(const buzz::XmlElement* stanza);
-
- scoped_ptr<IqRequest> request_;
- scoped_ptr<OnJingleInfoCallback> on_jingle_info_cb_;
- scoped_ptr<Task> done_cb_;
-
- DISALLOW_COPY_AND_ASSIGN(JingleInfoRequest);
-};
-
-// This class handles proxying the Jingle establishment messages between the
-// client and the server when proxying XMPP through Javascript.
-//
-// The |request| object is used to send and receive IQ stanzas from the XMPP
-// network. The |session_manager| controls sending and receiving of stanzas
-// after Run() is invoked.
-//
-// This class is not threadsafe, and should only be used on the thread it is
-// created on.
-//
-// TODO(ajwong): Move into its own file, and rename to something better since
-// this is not actually a Request. Maybe SessionEstablishmentConnector.
-class SessionStartRequest : public sigslot::has_slots<> {
- public:
- SessionStartRequest(JavascriptIqRequest* request,
- cricket::SessionManager* session_manager);
- virtual ~SessionStartRequest();
-
- void Run();
-
- private:
- void OnResponse(const buzz::XmlElement* stanza);
-
- void OnOutgoingMessage(cricket::SessionManager* manager,
- const buzz::XmlElement* stanza);
-
- scoped_ptr<JavascriptIqRequest> request_;
- cricket::SessionManager* session_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(SessionStartRequest);
-};
-
} // namespace remoting
#endif // REMOTING_JINGLE_GLUE_IQ_REQUEST_H_
diff --git a/remoting/jingle_glue/javascript_iq_request.cc b/remoting/jingle_glue/javascript_iq_request.cc
new file mode 100644
index 0000000..8b63dcc
--- /dev/null
+++ b/remoting/jingle_glue/javascript_iq_request.cc
@@ -0,0 +1,137 @@
+// 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/javascript_iq_request.h"
+
+#include "base/string_number_conversions.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
+#include "third_party/libjingle/source/talk/xmpp/constants.h"
+
+namespace remoting {
+
+JavascriptIqRegistry::JavascriptIqRegistry()
+ : current_id_(0),
+ default_handler_(NULL) {
+}
+
+JavascriptIqRegistry::~JavascriptIqRegistry() {
+}
+
+void JavascriptIqRegistry::RemoveAllRequests(JavascriptIqRequest* request) {
+ IqRequestMap::iterator it = requests_.begin();
+ while (it != requests_.end()) {
+ IqRequestMap::iterator cur = it;
+ ++it;
+ if (cur->second == request) {
+ requests_.erase(cur);
+ }
+ }
+}
+
+void JavascriptIqRegistry::SetDefaultHandler(JavascriptIqRequest* new_handler) {
+ // Should only allow a new handler if |default_handler_| is NULL.
+ CHECK(default_handler_ == NULL || !new_handler);
+ default_handler_ = new_handler;
+}
+
+void JavascriptIqRegistry::OnIq(const std::string& response_xml) {
+ // TODO(ajwong): Can we cleanup this dispatch at all? The send is from
+ // JavascriptIqRequest but the return is in JavascriptIqRegistry.
+ scoped_ptr<buzz::XmlElement> stanza(buzz::XmlElement::ForStr(response_xml));
+
+ if (!stanza.get()) {
+ LOG(WARNING) << "Malformed XML received" << response_xml;
+ return;
+ }
+
+ LOG(ERROR) << "IQ Received: " << stanza->Str();
+ if (stanza->Name() != buzz::QN_IQ) {
+ LOG(WARNING) << "Received unexpected non-IQ packet" << stanza->Str();
+ return;
+ }
+
+ if (!stanza->HasAttr(buzz::QN_ID)) {
+ LOG(WARNING) << "IQ packet missing id" << stanza->Str();
+ return;
+ }
+
+ const std::string& id = stanza->Attr(buzz::QN_ID);
+
+ IqRequestMap::iterator it = requests_.find(id);
+ if (it == requests_.end()) {
+ if (!default_handler_) {
+ VLOG(1) << "Dropping IQ packet with no request id: " << stanza->Str();
+ } else {
+ if (default_handler_->callback_.get()) {
+ default_handler_->callback_->Run(stanza.get());
+ } else {
+ VLOG(1) << "default handler has no callback, so dropping: "
+ << stanza->Str();
+ }
+ }
+ } else {
+ // TODO(ajwong): We should look at the logic inside libjingle's
+ // XmppTask::MatchResponseIq() and make sure we're fully in sync.
+ // They check more fields and conditions than us.
+
+ // TODO(ajwong): This logic is weird. We add to the register in
+ // JavascriptIqRequest::SendIq(), but remove in
+ // JavascriptIqRegistry::OnIq(). We should try to keep the
+ // registration/deregistration in one spot.
+ if (it->second->callback_.get()) {
+ it->second->callback_->Run(stanza.get());
+ } else {
+ VLOG(1) << "No callback, so dropping: " << stanza->Str();
+ }
+ requests_.erase(it);
+ }
+}
+
+std::string JavascriptIqRegistry::RegisterRequest(
+ JavascriptIqRequest* request) {
+ ++current_id_;
+ std::string id_as_string = base::IntToString(current_id_);
+
+ requests_[id_as_string] = request;
+ return id_as_string;
+}
+
+JavascriptIqRequest::JavascriptIqRequest(JavascriptIqRegistry* registry,
+ scoped_refptr<XmppProxy> xmpp_proxy)
+ : xmpp_proxy_(xmpp_proxy),
+ registry_(registry),
+ is_default_handler_(false) {
+}
+
+JavascriptIqRequest::~JavascriptIqRequest() {
+ registry_->RemoveAllRequests(this);
+ if (is_default_handler_) {
+ registry_->SetDefaultHandler(NULL);
+ }
+}
+
+void JavascriptIqRequest::SendIq(const std::string& type,
+ const std::string& addressee,
+ buzz::XmlElement* iq_body) {
+ scoped_ptr<buzz::XmlElement> stanza(
+ MakeIqStanza(type, addressee, iq_body,
+ registry_->RegisterRequest(this)));
+
+ xmpp_proxy_->SendIq(stanza->Str());
+}
+
+void JavascriptIqRequest::SendRawIq(buzz::XmlElement* stanza) {
+ xmpp_proxy_->SendIq(stanza->Str());
+}
+
+void JavascriptIqRequest::BecomeDefaultHandler() {
+ is_default_handler_ = true;
+ registry_->SetDefaultHandler(this);
+}
+
+void JavascriptIqRequest::set_callback(ReplyCallback* callback) {
+ callback_.reset(callback);
+}
+
+} // namespace remoting
diff --git a/remoting/jingle_glue/javascript_iq_request.h b/remoting/jingle_glue/javascript_iq_request.h
new file mode 100644
index 0000000..0de9574
--- /dev/null
+++ b/remoting/jingle_glue/javascript_iq_request.h
@@ -0,0 +1,100 @@
+// 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_JAVASCRIPT_IQ_REQUEST_H_
+#define REMOTING_JINGLE_GLUE_JAVASCRIPT_IQ_REQUEST_H_
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "remoting/jingle_glue/iq_request.h"
+#include "remoting/jingle_glue/xmpp_proxy.h"
+
+namespace remoting {
+
+class JavascriptIqRequest;
+
+class JavascriptIqRegistry : public XmppProxy::ResponseCallback {
+ public:
+ JavascriptIqRegistry();
+ virtual ~JavascriptIqRegistry();
+
+ // Dispatches the response to the IqRequest callback immediately.
+ //
+ // Does not take ownership of stanza.
+ void DispatchResponse(buzz::XmlElement* stanza);
+
+ // Registers |request|, returning the request ID used.
+ std::string RegisterRequest(JavascriptIqRequest* request);
+
+ // Removes all entries in the registry that refer to |request|. Useful when
+ // |request| is about to be destructed.
+ void RemoveAllRequests(JavascriptIqRequest* request);
+
+ void SetDefaultHandler(JavascriptIqRequest* default_request);
+
+ private:
+ typedef std::map<std::string, JavascriptIqRequest*> IqRequestMap;
+
+ // XmppProxy::ResponseCallback interface.
+ virtual void OnIq(const std::string& response_xml);
+
+ IqRequestMap requests_;
+ int current_id_;
+ JavascriptIqRequest* default_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(JavascriptIqRegistry);
+};
+
+// This call must only be used on the thread it was created on.
+class JavascriptIqRequest : public IqRequest {
+ public:
+ JavascriptIqRequest(JavascriptIqRegistry* registry,
+ scoped_refptr<XmppProxy> xmpp_proxy);
+ virtual ~JavascriptIqRequest();
+
+ // Similar to SendIq(), but has 3 major differences:
+ //
+ // (1) It does absoluately no error checking. Caller is responsible for
+ // validity.
+ // (2) It doesn't add an Iq envelope. Caller is again responsible.
+ // (3) BecomeDefaultHandler() must have been called.
+ //
+ // TODO(ajwong): We need to rationalize the semantics of these two
+ // APIs. SendRawIq() is a hack for JingleSignalingConnector which
+ // uses a different memory management convention.
+ void SendRawIq(buzz::XmlElement* stanza);
+
+ // This function is a hack to support SessionStartRequest. It registers the
+ // current JavascriptIqRequest instance to be the single passthrough filter
+ // for the associated JavascriptIqRegistry. What this means is that any IQ
+ // packet that does not match a previous respone packet will be funneled
+ // through to this JavascriptIqRegistry instance (basically a default
+ // handler). It also means that the registry will not be tracking any of the
+ // packets sent from this JavascriptIqRegistry instance.
+ //
+ // TODO(ajwong): We need to take a high-level look at IqRequest to understand
+ // how to make this API cleaner.
+ void BecomeDefaultHandler();
+
+ // IqRequest interface.
+ virtual void SendIq(const std::string& type, const std::string& addressee,
+ buzz::XmlElement* iq_body) OVERRIDE;
+ virtual void set_callback(ReplyCallback* callback) OVERRIDE;
+
+ private:
+ friend class JavascriptIqRegistry;
+
+ scoped_ptr<ReplyCallback> callback_;
+ scoped_refptr<XmppProxy> xmpp_proxy_;
+ JavascriptIqRegistry* registry_;
+ bool is_default_handler_;
+
+ FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_JINGLE_GLUE_JAVASCRIPT_IQ_REQUEST_H_
diff --git a/remoting/jingle_glue/javascript_signal_strategy.cc b/remoting/jingle_glue/javascript_signal_strategy.cc
index b3f14dd..2f5b64f 100644
--- a/remoting/jingle_glue/javascript_signal_strategy.cc
+++ b/remoting/jingle_glue/javascript_signal_strategy.cc
@@ -5,6 +5,7 @@
#include "remoting/jingle_glue/javascript_signal_strategy.h"
#include "remoting/jingle_glue/iq_request.h"
+#include "remoting/jingle_glue/jingle_signaling_connector.h"
#include "remoting/jingle_glue/xmpp_proxy.h"
namespace remoting {
@@ -36,9 +37,9 @@ void JavascriptSignalStrategy::Init(StatusObserver* observer) {
void JavascriptSignalStrategy::StartSession(
cricket::SessionManager* session_manager) {
- session_start_request_.reset(
- new SessionStartRequest(CreateIqRequest(), session_manager));
- session_start_request_->Run();
+ jingle_signaling_connector_.reset(
+ new JingleSignalingConnector(CreateIqRequest(), session_manager));
+ jingle_signaling_connector_->Run();
}
void JavascriptSignalStrategy::EndSession() {
diff --git a/remoting/jingle_glue/javascript_signal_strategy.h b/remoting/jingle_glue/javascript_signal_strategy.h
index b96c2c7..033ba0e 100644
--- a/remoting/jingle_glue/javascript_signal_strategy.h
+++ b/remoting/jingle_glue/javascript_signal_strategy.h
@@ -10,10 +10,11 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "remoting/jingle_glue/iq_request.h"
+#include "remoting/jingle_glue/javascript_iq_request.h"
namespace remoting {
+class JingleSignalingConnector;
class XmppProxy;
class JavascriptSignalStrategy : public SignalStrategy {
@@ -33,7 +34,7 @@ class JavascriptSignalStrategy : public SignalStrategy {
std::string your_jid_;
scoped_refptr<XmppProxy> xmpp_proxy_;
JavascriptIqRegistry iq_registry_;
- scoped_ptr<SessionStartRequest> session_start_request_;
+ scoped_ptr<JingleSignalingConnector> jingle_signaling_connector_;
DISALLOW_COPY_AND_ASSIGN(JavascriptSignalStrategy);
};
diff --git a/remoting/jingle_glue/jingle_client.cc b/remoting/jingle_glue/jingle_client.cc
index 374af970..87f8c58 100644
--- a/remoting/jingle_glue/jingle_client.cc
+++ b/remoting/jingle_glue/jingle_client.cc
@@ -9,6 +9,7 @@
#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_thread.h"
#include "third_party/libjingle/source/talk/base/basicpacketsocketfactory.h"
#include "third_party/libjingle/source/talk/base/ssladapter.h"
diff --git a/remoting/jingle_glue/jingle_client.h b/remoting/jingle_glue/jingle_client.h
index 5dc2d23..646afac 100644
--- a/remoting/jingle_glue/jingle_client.h
+++ b/remoting/jingle_glue/jingle_client.h
@@ -6,9 +6,11 @@
#define REMOTING_JINGLE_GLUE_JINGLE_CLIENT_H_
#include <string>
+#include <vector>
#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"
@@ -20,6 +22,7 @@ class Task;
namespace talk_base {
class NetworkManager;
class PacketSocketFactory;
+class SocketAddress;
} // namespace talk_base
namespace cricket {
@@ -33,6 +36,7 @@ class SessionManager;
namespace remoting {
+class JingleInfoRequest;
class JingleThread;
class PortAllocatorSessionFactory;
diff --git a/remoting/jingle_glue/jingle_info_request.cc b/remoting/jingle_glue/jingle_info_request.cc
new file mode 100644
index 0000000..d8529a6
--- /dev/null
+++ b/remoting/jingle_glue/jingle_info_request.cc
@@ -0,0 +1,94 @@
+// 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_info_request.h"
+
+#include "base/task.h"
+#include "base/string_number_conversions.h"
+#include "remoting/jingle_glue/iq_request.h"
+#include "third_party/libjingle/source/talk/base/socketaddress.h"
+#include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
+#include "third_party/libjingle/source/talk/xmpp/constants.h"
+
+namespace remoting {
+
+JingleInfoRequest::JingleInfoRequest(IqRequest* request)
+ : request_(request) {
+ request_->set_callback(NewCallback(this, &JingleInfoRequest::OnResponse));
+}
+
+JingleInfoRequest::~JingleInfoRequest() {
+}
+
+void JingleInfoRequest::Run(Task* done) {
+ done_cb_.reset(done);
+ request_->SendIq(buzz::STR_GET, buzz::STR_EMPTY,
+ new buzz::XmlElement(buzz::QN_JINGLE_INFO_QUERY, true));
+}
+
+void JingleInfoRequest::SetCallback(OnJingleInfoCallback* callback) {
+ on_jingle_info_cb_.reset(callback);
+}
+
+void JingleInfoRequest::DetachCallback() {
+ on_jingle_info_cb_.reset();
+}
+
+void JingleInfoRequest::OnResponse(const buzz::XmlElement* stanza) {
+ std::vector<std::string> relay_hosts;
+ std::vector<talk_base::SocketAddress> stun_hosts;
+ std::string relay_token;
+
+ const buzz::XmlElement* query =
+ stanza->FirstNamed(buzz::QN_JINGLE_INFO_QUERY);
+ if (query == NULL) {
+ LOG(WARNING) << "No Jingle info found in Jingle Info query response."
+ << stanza->Str();
+ return;
+ }
+
+ const buzz::XmlElement* stun = query->FirstNamed(buzz::QN_JINGLE_INFO_STUN);
+ if (stun) {
+ for (const buzz::XmlElement* server =
+ stun->FirstNamed(buzz::QN_JINGLE_INFO_SERVER);
+ server != NULL;
+ server = server->NextNamed(buzz::QN_JINGLE_INFO_SERVER)) {
+ std::string host = server->Attr(buzz::QN_JINGLE_INFO_HOST);
+ std::string port_str = server->Attr(buzz::QN_JINGLE_INFO_UDP);
+ if (host != buzz::STR_EMPTY && port_str != buzz::STR_EMPTY) {
+ int port;
+ if (!base::StringToInt(port_str, &port)) {
+ LOG(WARNING) << "Unable to parse port in stanza" << stanza->Str();
+ } else {
+ stun_hosts.push_back(talk_base::SocketAddress(host, port));
+ }
+ }
+ }
+ }
+
+ const buzz::XmlElement* relay = query->FirstNamed(buzz::QN_JINGLE_INFO_RELAY);
+ if (relay) {
+ relay_token = relay->TextNamed(buzz::QN_JINGLE_INFO_TOKEN);
+ for (const buzz::XmlElement* server =
+ relay->FirstNamed(buzz::QN_JINGLE_INFO_SERVER);
+ server != NULL;
+ server = server->NextNamed(buzz::QN_JINGLE_INFO_SERVER)) {
+ std::string host = server->Attr(buzz::QN_JINGLE_INFO_HOST);
+ if (host != buzz::STR_EMPTY) {
+ relay_hosts.push_back(host);
+ }
+ }
+ }
+
+ if (on_jingle_info_cb_.get()) {
+ on_jingle_info_cb_->Run(relay_token, relay_hosts, stun_hosts);
+ } else {
+ LOG(INFO) << "Iq reply parsed with no callback. Dropping" << stanza->Str();
+ }
+
+ DetachCallback();
+ done_cb_->Run();
+}
+
+} // namespace remoting
diff --git a/remoting/jingle_glue/jingle_info_request.h b/remoting/jingle_glue/jingle_info_request.h
new file mode 100644
index 0000000..fee561f
--- /dev/null
+++ b/remoting/jingle_glue/jingle_info_request.h
@@ -0,0 +1,70 @@
+// 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_INFO_REQUEST_H_
+#define REMOTING_JINGLE_GLUE_JINGLE_INFO_REQUEST_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback_old.h"
+#include "base/memory/scoped_ptr.h"
+
+class Task;
+
+namespace buzz {
+class XmlElement;
+} // namespace buzz
+
+namespace talk_base {
+class SocketAddress;
+} // namespace talk_base
+
+namespace remoting {
+
+class IqRequest;
+
+// JingleInfoRequest handles making an IQ request to the Google talk network for
+// discovering stun/relay information for use in establishing a Jingle
+// connection.
+//
+// Clients should instantiate this class, and set a callback to receive the
+// configuration information. The query will be made when Run() is called. The
+// query is finisehd when the |done| task given to Run() is invokved.
+//
+// This class is not threadsafe and should be used on the same thread it is
+// created on.
+//
+// TODO(ajwong): Add support for a timeout.
+class JingleInfoRequest {
+ public:
+ // Callback to receive the Jingle configuration settings. The argumetns are
+ // passed by pointer so the receive may call swap on them. The receiver does
+ // NOT own the arguments, which are guaranteed only to be alive for the
+ // duration of the callback.
+ typedef Callback3<const std::string&, const std::vector<std::string>&,
+ const std::vector<talk_base::SocketAddress>&>::Type
+ OnJingleInfoCallback;
+
+ explicit JingleInfoRequest(IqRequest* request);
+ ~JingleInfoRequest();
+
+ void Run(Task* done);
+ void SetCallback(OnJingleInfoCallback* callback);
+ void DetachCallback();
+
+ private:
+ void OnResponse(const buzz::XmlElement* stanza);
+
+ scoped_ptr<IqRequest> request_;
+ scoped_ptr<OnJingleInfoCallback> on_jingle_info_cb_;
+ scoped_ptr<Task> done_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(JingleInfoRequest);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_JINGLE_GLUE_JINGLE_INFO_REQUEST_H_
diff --git a/remoting/jingle_glue/jingle_signaling_connector.cc b/remoting/jingle_glue/jingle_signaling_connector.cc
new file mode 100644
index 0000000..f2666d2
--- /dev/null
+++ b/remoting/jingle_glue/jingle_signaling_connector.cc
@@ -0,0 +1,61 @@
+// 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_signaling_connector.h"
+
+#include "remoting/jingle_glue/javascript_iq_request.h"
+#include "third_party/libjingle/source/talk/p2p/base/sessionmanager.h"
+#include "third_party/libjingle/source/talk/xmpp/constants.h"
+#include "third_party/libjingle/source/talk/xmpp/xmppclient.h"
+
+namespace remoting {
+
+JingleSignalingConnector::JingleSignalingConnector(
+ JavascriptIqRequest* request,
+ cricket::SessionManager* session_manager)
+ : request_(request),
+ session_manager_(session_manager) {
+ request_->set_callback(
+ NewCallback(this, &JingleSignalingConnector::OnResponse));
+}
+
+JingleSignalingConnector::~JingleSignalingConnector() {
+}
+
+void JingleSignalingConnector::Run() {
+ session_manager_->SignalOutgoingMessage.connect(
+ this, &JingleSignalingConnector::OnOutgoingMessage);
+
+ // TODO(ajwong): Why are we connecting SessionManager to itself?
+ session_manager_->SignalRequestSignaling.connect(
+ session_manager_, &cricket::SessionManager::OnSignalingReady);
+ request_->BecomeDefaultHandler();
+}
+
+void JingleSignalingConnector::OnResponse(const buzz::XmlElement* response) {
+ // TODO(ajwong): Techncially, when SessionManager sends IQ packets, it
+ // actually expects a response in SessionSendTask(). However, if you look in
+ // SessionManager::OnIncomingResponse(), it does nothing with the response.
+ // Also, if no response is found, we are supposed to call
+ // SessionManager::OnFailedSend().
+ //
+ // However, for right now, we just ignore those, and only propagate
+ // messages outside of the request/reply framework to
+ // SessionManager::OnIncomingMessage.
+
+ if (session_manager_->IsSessionMessage(response)) {
+ session_manager_->OnIncomingMessage(response);
+ }
+}
+
+void JingleSignalingConnector::OnOutgoingMessage(
+ cricket::SessionManager* session_manager,
+ const buzz::XmlElement* stanza) {
+ // TODO(ajwong): Are we just supposed to not use |session_manager|?
+ DCHECK_EQ(session_manager, session_manager_);
+ scoped_ptr<buzz::XmlElement> stanza_copy(new buzz::XmlElement(*stanza));
+ request_->SendRawIq(stanza_copy.get());
+}
+
+} // namespace remoting
diff --git a/remoting/jingle_glue/jingle_signaling_connector.h b/remoting/jingle_glue/jingle_signaling_connector.h
new file mode 100644
index 0000000..74e872e
--- /dev/null
+++ b/remoting/jingle_glue/jingle_signaling_connector.h
@@ -0,0 +1,58 @@
+// 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_SIGNALING_CONNECTOR_H_
+#define REMOTING_JINGLE_GLUE_JINGLE_SIGNALING_CONNECTOR_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/libjingle/source/talk/base/sigslot.h"
+
+namespace buzz {
+class XmlElement;
+} // namespace buzz
+
+namespace cricket {
+class SessionManager;
+} // namespace cricket
+
+namespace remoting {
+
+class JavascriptIqRequest;
+
+// This class handles proxying the Jingle establishment messages between the
+// client and the server when proxying XMPP through Javascript.
+//
+// The |request| object is used to send and receive IQ stanzas from the XMPP
+// network. The |session_manager| controls sending and receiving of stanzas
+// after Run() is invoked.
+//
+// This class is not threadsafe, and should only be used on the thread it is
+// created on.
+//
+// TODO(sergeyu): This class should not depend on JavascriptIqRequest:
+// it should work with SignalStrategy instead.
+class JingleSignalingConnector : public sigslot::has_slots<> {
+ public:
+ JingleSignalingConnector(JavascriptIqRequest* request,
+ cricket::SessionManager* session_manager);
+ virtual ~JingleSignalingConnector();
+
+ void Run();
+
+ private:
+ void OnResponse(const buzz::XmlElement* stanza);
+
+ void OnOutgoingMessage(cricket::SessionManager* manager,
+ const buzz::XmlElement* stanza);
+
+ scoped_ptr<JavascriptIqRequest> request_;
+ cricket::SessionManager* session_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(JingleSignalingConnector);
+};
+
+} // namespace remoting
+
+#endif // REMOTING_JINGLE_GLUE_JINGLE_SIGNALING_CONNECTOR_H_
diff --git a/remoting/jingle_glue/xmpp_iq_request.cc b/remoting/jingle_glue/xmpp_iq_request.cc
new file mode 100644
index 0000000..ee55536
--- /dev/null
+++ b/remoting/jingle_glue/xmpp_iq_request.cc
@@ -0,0 +1,65 @@
+// 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/xmpp_iq_request.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "third_party/libjingle/source/talk/xmpp/constants.h"
+#include "third_party/libjingle/source/talk/xmpp/xmppclient.h"
+
+namespace remoting {
+
+XmppIqRequest::XmppIqRequest(MessageLoop* message_loop,
+ buzz::XmppClient* xmpp_client)
+ : message_loop_(message_loop),
+ xmpp_client_(xmpp_client),
+ cookie_(NULL) {
+ DCHECK(xmpp_client_);
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+}
+
+XmppIqRequest::~XmppIqRequest() {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+ Unregister();
+}
+
+void XmppIqRequest::SendIq(const std::string& type,
+ const std::string& addressee,
+ buzz::XmlElement* iq_body) {
+ DCHECK_EQ(MessageLoop::current(), message_loop_);
+
+ // Unregister the handler if it is already registered.
+ Unregister();
+
+ DCHECK_GT(type.length(), 0U);
+
+ scoped_ptr<buzz::XmlElement> stanza(MakeIqStanza(type, addressee, iq_body,
+ xmpp_client_->NextId()));
+
+ xmpp_client_->engine()->SendIq(stanza.get(), this, &cookie_);
+}
+
+void XmppIqRequest::set_callback(ReplyCallback* callback) {
+ callback_.reset(callback);
+}
+
+void XmppIqRequest::Unregister() {
+ if (cookie_) {
+ // No need to unregister the handler if the client has been destroyed.
+ if (xmpp_client_) {
+ xmpp_client_->engine()->RemoveIqHandler(cookie_, NULL);
+ }
+ cookie_ = NULL;
+ }
+}
+
+void XmppIqRequest::IqResponse(buzz::XmppIqCookie cookie,
+ const buzz::XmlElement* stanza) {
+ if (callback_.get() != NULL) {
+ callback_->Run(stanza);
+ }
+}
+
+} // namespace remoting
diff --git a/remoting/jingle_glue/xmpp_iq_request.h b/remoting/jingle_glue/xmpp_iq_request.h
new file mode 100644
index 0000000..2e1b8b4
--- /dev/null
+++ b/remoting/jingle_glue/xmpp_iq_request.h
@@ -0,0 +1,52 @@
+// 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_XMPP_IQ_REQUEST_H_
+#define REMOTING_JINGLE_GLUE_XMPP_IQ_REQUEST_H_
+
+#include "base/compiler_specific.h"
+#include "remoting/jingle_glue/iq_request.h"
+#include "third_party/libjingle/source/talk/base/sigslot.h"
+#include "third_party/libjingle/source/talk/xmpp/xmppengine.h"
+
+class MessageLoop;
+
+namespace buzz {
+class XmppClient;
+} // namespace buzz
+
+namespace remoting {
+
+class XmppIqRequest : public IqRequest, public buzz::XmppIqHandler {
+ public:
+ typedef Callback1<const buzz::XmlElement*>::Type ReplyCallback;
+
+ XmppIqRequest(MessageLoop* message_loop, buzz::XmppClient* xmpp_client);
+ virtual ~XmppIqRequest();
+
+ // IqRequest interface.
+ virtual void SendIq(const std::string& type, const std::string& addressee,
+ buzz::XmlElement* iq_body) OVERRIDE;
+ virtual void set_callback(ReplyCallback* callback) OVERRIDE;
+
+ // buzz::XmppIqHandler interface.
+ virtual void IqResponse(buzz::XmppIqCookie cookie,
+ const buzz::XmlElement* stanza) OVERRIDE;
+
+ private:
+ FRIEND_TEST_ALL_PREFIXES(IqRequestTest, MakeIqStanza);
+
+ void Unregister();
+
+ // 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_;
+};
+
+} // namespace remoting
+
+#endif // REMOTING_JINGLE_GLUE_XMPP_IQ_REQUEST_H_
diff --git a/remoting/jingle_glue/xmpp_signal_strategy.cc b/remoting/jingle_glue/xmpp_signal_strategy.cc
index feb9209..9f177fe 100644
--- a/remoting/jingle_glue/xmpp_signal_strategy.cc
+++ b/remoting/jingle_glue/xmpp_signal_strategy.cc
@@ -5,8 +5,8 @@
#include "remoting/jingle_glue/xmpp_signal_strategy.h"
#include "jingle/notifier/base/gaia_token_pre_xmpp_auth.h"
-#include "remoting/jingle_glue/iq_request.h"
#include "remoting/jingle_glue/jingle_thread.h"
+#include "remoting/jingle_glue/xmpp_iq_request.h"
#include "remoting/jingle_glue/xmpp_socket_adapter.h"
#include "third_party/libjingle/source/talk/base/asyncsocket.h"
#include "third_party/libjingle/source/talk/p2p/client/sessionmanagertask.h"
diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp
index 72e6e17..c714a02 100644
--- a/remoting/remoting.gyp
+++ b/remoting/remoting.gyp
@@ -537,10 +537,16 @@
'jingle_glue/http_port_allocator.h',
'jingle_glue/iq_request.cc',
'jingle_glue/iq_request.h',
+ 'jingle_glue/javascript_iq_request.cc',
+ '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',
+ 'jingle_glue/jingle_signaling_connector.h',
'jingle_glue/jingle_thread.cc',
'jingle_glue/jingle_thread.h',
'jingle_glue/signal_strategy.h',
@@ -548,6 +554,8 @@
'jingle_glue/ssl_adapter.cc',
'jingle_glue/ssl_socket_adapter.cc',
'jingle_glue/ssl_socket_adapter.h',
+ 'jingle_glue/xmpp_iq_request.cc',
+ 'jingle_glue/xmpp_iq_request.h',
'jingle_glue/xmpp_proxy.h',
'jingle_glue/xmpp_signal_strategy.cc',
'jingle_glue/xmpp_signal_strategy.h',