diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 00:33:01 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-24 00:33:01 +0000 |
commit | d32d20571991e31c2db1965aae2983be23d46a89 (patch) | |
tree | e721e631845cac06db9c5dcb3b642e77dcdabbb6 /remoting/jingle_glue | |
parent | 7c233302e1f674178b5da4b40ca1ff8c2b80fe7b (diff) | |
download | chromium_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.cc | 66 | ||||
-rw-r--r-- | remoting/jingle_glue/jingle_signaling_connector.h | 5 |
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); }; |