summaryrefslogtreecommitdiffstats
path: root/remoting/jingle_glue
diff options
context:
space:
mode:
authorsergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-24 00:33:01 +0000
committersergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-24 00:33:01 +0000
commitd32d20571991e31c2db1965aae2983be23d46a89 (patch)
treee721e631845cac06db9c5dcb3b642e77dcdabbb6 /remoting/jingle_glue
parent7c233302e1f674178b5da4b40ca1ff8c2b80fe7b (diff)
downloadchromium_src-d32d20571991e31c2db1965aae2983be23d46a89.zip
chromium_src-d32d20571991e31c2db1965aae2983be23d46a89.tar.gz
chromium_src-d32d20571991e31c2db1965aae2983be23d46a89.tar.bz2
Properly handle errors received in response to session messages.
BUG=93531 TEST=Client shows error when host is down. Review URL: http://codereview.chromium.org/7685045 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@97956 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/jingle_glue')
-rw-r--r--remoting/jingle_glue/jingle_signaling_connector.cc66
-rw-r--r--remoting/jingle_glue/jingle_signaling_connector.h5
2 files changed, 56 insertions, 15 deletions
diff --git a/remoting/jingle_glue/jingle_signaling_connector.cc b/remoting/jingle_glue/jingle_signaling_connector.cc
index cd60523..8fe2a15 100644
--- a/remoting/jingle_glue/jingle_signaling_connector.cc
+++ b/remoting/jingle_glue/jingle_signaling_connector.cc
@@ -5,6 +5,7 @@
#include "remoting/jingle_glue/jingle_signaling_connector.h"
#include "base/logging.h"
+#include "base/stl_util.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"
@@ -12,6 +13,20 @@
namespace remoting {
+namespace {
+
+// GTalk sometimes generates service-unavailable error messages with
+// incorrect namespace. This method fixes such messages.
+// TODO(sergeyu): Fix this on the server side.
+void FixErrorStanza(buzz::XmlElement* stanza) {
+ if (!stanza->FirstNamed(buzz::QN_ERROR)) {
+ buzz::XmlElement* error = stanza->FirstNamed(buzz::QName("", "error"));
+ error->SetName(buzz::QN_ERROR);
+ }
+}
+
+} // namespace
+
JingleSignalingConnector::JingleSignalingConnector(
SignalStrategy* signal_strategy,
cricket::SessionManager* session_manager)
@@ -30,25 +45,38 @@ JingleSignalingConnector::JingleSignalingConnector(
JingleSignalingConnector::~JingleSignalingConnector() {
signal_strategy_->SetListener(NULL);
+ STLDeleteContainerPairSecondPointers(pending_requests_.begin(),
+ pending_requests_.end());
}
bool JingleSignalingConnector::OnIncomingStanza(
const buzz::XmlElement* stanza) {
- // 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(stanza)) {
session_manager_->OnIncomingMessage(stanza);
return true;
}
+ if (stanza->Name() == buzz::QN_IQ) {
+ std::string type = stanza->Attr(buzz::QN_TYPE);
+ std::string id = stanza->Attr(buzz::QN_ID);
+ if ((type == "error" || type == "result") && !id.empty()) {
+ IqRequestsMap::iterator it = pending_requests_.find(id);
+ if (it != pending_requests_.end()) {
+ if (type == "result") {
+ session_manager_->OnIncomingResponse(it->second, stanza);
+ } else {
+ scoped_ptr<buzz::XmlElement> stanza_copy(
+ new buzz::XmlElement(*stanza));
+ FixErrorStanza(stanza_copy.get());
+ session_manager_->OnFailedSend(it->second, stanza_copy.get());
+ }
+ delete it->second;
+ pending_requests_.erase(it);
+ return true;
+ }
+ }
+ }
+
return false;
}
@@ -58,10 +86,20 @@ void JingleSignalingConnector::OnOutgoingMessage(
DCHECK_EQ(session_manager, session_manager_);
scoped_ptr<buzz::XmlElement> stanza_copy(new buzz::XmlElement(*stanza));
- // Add ID attribute for Iq stanzas if it is not there.
- if (stanza_copy->Name() == buzz::QN_IQ &&
- stanza_copy->Attr(buzz::QN_ID).empty()) {
- stanza_copy->SetAttr(buzz::QN_ID, signal_strategy_->GetNextId());
+ if (stanza_copy->Name() == buzz::QN_IQ) {
+ std::string type = stanza_copy->Attr(buzz::QN_TYPE);
+ if (type == "set" || type == "get") {
+ std::string id = stanza_copy->Attr(buzz::QN_ID);
+
+ // Add ID attribute for set and get stanzas if it is not there.
+ if (id.empty()) {
+ id = signal_strategy_->GetNextId();
+ stanza_copy->SetAttr(buzz::QN_ID, id);
+ }
+
+ // Save the outgoing request for OnIncomingResponse().
+ pending_requests_[id] = new buzz::XmlElement(*stanza);
+ }
}
signal_strategy_->SendStanza(stanza_copy.release());
diff --git a/remoting/jingle_glue/jingle_signaling_connector.h b/remoting/jingle_glue/jingle_signaling_connector.h
index d14e0e6..c45c269 100644
--- a/remoting/jingle_glue/jingle_signaling_connector.h
+++ b/remoting/jingle_glue/jingle_signaling_connector.h
@@ -5,6 +5,8 @@
#ifndef REMOTING_JINGLE_GLUE_JINGLE_SIGNALING_CONNECTOR_H_
#define REMOTING_JINGLE_GLUE_JINGLE_SIGNALING_CONNECTOR_H_
+#include <map>
+
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "remoting/jingle_glue/signal_strategy.h"
@@ -45,13 +47,14 @@ class JingleSignalingConnector : public SignalStrategy::Listener,
virtual bool OnIncomingStanza(const buzz::XmlElement* stanza) OVERRIDE;
private:
- void OnResponse(const buzz::XmlElement* stanza);
+ typedef std::map<std::string, buzz::XmlElement*> IqRequestsMap;
void OnOutgoingMessage(cricket::SessionManager* manager,
const buzz::XmlElement* stanza);
SignalStrategy* signal_strategy_;
cricket::SessionManager* session_manager_;
+ IqRequestsMap pending_requests_;
DISALLOW_COPY_AND_ASSIGN(JingleSignalingConnector);
};