Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: remoting/jingle_glue/iq_sender.cc

Issue 9452038: Implement timeouts for IQ requests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix release build Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/jingle_glue/iq_sender.h ('k') | remoting/jingle_glue/iq_sender_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "remoting/jingle_glue/iq_sender.h" 5 #include "remoting/jingle_glue/iq_sender.h"
6 6
7 #include "base/bind.h"
8 #include "base/location.h"
7 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/message_loop_proxy.h"
8 #include "base/string_number_conversions.h" 11 #include "base/string_number_conversions.h"
12 #include "base/time.h"
9 #include "remoting/jingle_glue/signal_strategy.h" 13 #include "remoting/jingle_glue/signal_strategy.h"
10 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 14 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
11 #include "third_party/libjingle/source/talk/xmpp/constants.h" 15 #include "third_party/libjingle/source/talk/xmpp/constants.h"
12 16
13 namespace remoting { 17 namespace remoting {
14 18
15 // static 19 // static
16 scoped_ptr<buzz::XmlElement> IqSender::MakeIqStanza( 20 scoped_ptr<buzz::XmlElement> IqSender::MakeIqStanza(
17 const std::string& type, 21 const std::string& type,
18 const std::string& addressee, 22 const std::string& addressee,
(...skipping 10 matching lines...) Expand all
29 : signal_strategy_(signal_strategy) { 33 : signal_strategy_(signal_strategy) {
30 signal_strategy_->AddListener(this); 34 signal_strategy_->AddListener(this);
31 } 35 }
32 36
33 IqSender::~IqSender() { 37 IqSender::~IqSender() {
34 signal_strategy_->RemoveListener(this); 38 signal_strategy_->RemoveListener(this);
35 } 39 }
36 40
37 scoped_ptr<IqRequest> IqSender::SendIq(scoped_ptr<buzz::XmlElement> stanza, 41 scoped_ptr<IqRequest> IqSender::SendIq(scoped_ptr<buzz::XmlElement> stanza,
38 const ReplyCallback& callback) { 42 const ReplyCallback& callback) {
43 std::string addressee = stanza->Attr(buzz::QN_TO);
39 std::string id = signal_strategy_->GetNextId(); 44 std::string id = signal_strategy_->GetNextId();
40 stanza->AddAttr(buzz::QN_ID, id); 45 stanza->AddAttr(buzz::QN_ID, id);
41 if (!signal_strategy_->SendStanza(stanza.Pass())) { 46 if (!signal_strategy_->SendStanza(stanza.Pass())) {
42 return scoped_ptr<IqRequest>(NULL); 47 return scoped_ptr<IqRequest>(NULL);
43 } 48 }
44 DCHECK(requests_.find(id) == requests_.end()); 49 DCHECK(requests_.find(id) == requests_.end());
45 scoped_ptr<IqRequest> request(new IqRequest(this, callback)); 50 scoped_ptr<IqRequest> request(new IqRequest(this, callback, addressee));
46 if (!callback.is_null()) 51 if (!callback.is_null())
47 requests_[id] = request.get(); 52 requests_[id] = request.get();
48 return request.Pass(); 53 return request.Pass();
49 } 54 }
50 55
51 scoped_ptr<IqRequest> IqSender::SendIq(const std::string& type, 56 scoped_ptr<IqRequest> IqSender::SendIq(const std::string& type,
52 const std::string& addressee, 57 const std::string& addressee,
53 scoped_ptr<buzz::XmlElement> iq_body, 58 scoped_ptr<buzz::XmlElement> iq_body,
54 const ReplyCallback& callback) { 59 const ReplyCallback& callback) {
55 return SendIq(MakeIqStanza(type, addressee, iq_body.Pass()), callback); 60 return SendIq(MakeIqStanza(type, addressee, iq_body.Pass()), callback);
(...skipping 29 matching lines...) Expand all
85 if (type != "result" && type != "error") { 90 if (type != "result" && type != "error") {
86 return false; 91 return false;
87 } 92 }
88 93
89 const std::string& id = stanza->Attr(buzz::QN_ID); 94 const std::string& id = stanza->Attr(buzz::QN_ID);
90 if (id.empty()) { 95 if (id.empty()) {
91 LOG(WARNING) << "IQ packet missing id " << stanza->Str(); 96 LOG(WARNING) << "IQ packet missing id " << stanza->Str();
92 return false; 97 return false;
93 } 98 }
94 99
100 std::string from = stanza->Attr(buzz::QN_FROM);
101
95 IqRequestMap::iterator it = requests_.find(id); 102 IqRequestMap::iterator it = requests_.find(id);
103
104 // This is a hack to workaround the issue with the WCS changing IDs
105 // of IQ responses sent from client to host. Whenever we receive a
106 // stanza with an unknown ID we try to match it with an outstanding
107 // request sent to the same peer.
108 if (it == requests_.end()) {
109 for (it = requests_.begin(); it != requests_.end(); ++it) {
110 if (it->second->addressee_ == from) {
111 break;
112 }
113 }
114 }
115
96 if (it == requests_.end()) { 116 if (it == requests_.end()) {
97 return false; 117 return false;
98 } 118 }
99 119
100 IqRequest* request = it->second; 120 IqRequest* request = it->second;
121
122 if (request->addressee_ != from) {
123 LOG(ERROR) << "Received IQ response from from a invalid JID. Ignoring it."
124 << " Message received from: " << from
125 << " Original JID: " << request->addressee_;
126 return false;
127 }
128
101 requests_.erase(it); 129 requests_.erase(it);
130 request->OnResponse(stanza);
102 131
103 request->OnResponse(stanza);
104 return true; 132 return true;
105 } 133 }
106 134
107 IqRequest::IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback) 135 IqRequest::IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback,
136 const std::string& addressee)
108 : sender_(sender), 137 : sender_(sender),
109 callback_(callback) { 138 callback_(callback),
139 addressee_(addressee) {
110 } 140 }
111 141
112 IqRequest::~IqRequest() { 142 IqRequest::~IqRequest() {
113 sender_->RemoveRequest(this); 143 sender_->RemoveRequest(this);
114 } 144 }
115 145
146 void IqRequest::SetTimeout(base::TimeDelta timeout) {
147 base::MessageLoopProxy::current()->PostDelayedTask(
148 FROM_HERE, base::Bind(&IqRequest::OnTimeout, AsWeakPtr()),
149 timeout.InMilliseconds());
150 }
151
152 void IqRequest::CallCallback(const buzz::XmlElement* stanza) {
153 if (!callback_.is_null()) {
154 IqSender::ReplyCallback callback(callback_);
155 callback_.Reset();
156 callback.Run(this, stanza);
157 }
158 }
159
160 void IqRequest::OnTimeout() {
161 CallCallback(NULL);
162 }
163
116 void IqRequest::OnResponse(const buzz::XmlElement* stanza) { 164 void IqRequest::OnResponse(const buzz::XmlElement* stanza) {
117 DCHECK(!callback_.is_null()); 165 CallCallback(stanza);
118 IqSender::ReplyCallback callback(callback_);
119 callback_.Reset();
120 callback.Run(stanza);
121 } 166 }
122 167
123 } // namespace remoting 168 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/jingle_glue/iq_sender.h ('k') | remoting/jingle_glue/iq_sender_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698