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

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: - Created 8 years, 10 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
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"
9 #include "remoting/jingle_glue/signal_strategy.h" 12 #include "remoting/jingle_glue/signal_strategy.h"
10 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h" 13 #include "third_party/libjingle/source/talk/xmllite/xmlelement.h"
11 #include "third_party/libjingle/source/talk/xmpp/constants.h" 14 #include "third_party/libjingle/source/talk/xmpp/constants.h"
12 15
13 namespace remoting { 16 namespace remoting {
14 17
15 // static 18 // static
16 scoped_ptr<buzz::XmlElement> IqSender::MakeIqStanza( 19 scoped_ptr<buzz::XmlElement> IqSender::MakeIqStanza(
17 const std::string& type, 20 const std::string& type,
(...skipping 11 matching lines...) Expand all
29 : signal_strategy_(signal_strategy) { 32 : signal_strategy_(signal_strategy) {
30 signal_strategy_->AddListener(this); 33 signal_strategy_->AddListener(this);
31 } 34 }
32 35
33 IqSender::~IqSender() { 36 IqSender::~IqSender() {
34 signal_strategy_->RemoveListener(this); 37 signal_strategy_->RemoveListener(this);
35 } 38 }
36 39
37 scoped_ptr<IqRequest> IqSender::SendIq(scoped_ptr<buzz::XmlElement> stanza, 40 scoped_ptr<IqRequest> IqSender::SendIq(scoped_ptr<buzz::XmlElement> stanza,
38 const ReplyCallback& callback) { 41 const ReplyCallback& callback) {
42 std::string addressee = stanza->Attr(buzz::QN_TO);
39 std::string id = signal_strategy_->GetNextId(); 43 std::string id = signal_strategy_->GetNextId();
40 stanza->AddAttr(buzz::QN_ID, id); 44 stanza->AddAttr(buzz::QN_ID, id);
41 if (!signal_strategy_->SendStanza(stanza.Pass())) { 45 if (!signal_strategy_->SendStanza(stanza.Pass())) {
42 return scoped_ptr<IqRequest>(NULL); 46 return scoped_ptr<IqRequest>(NULL);
43 } 47 }
44 DCHECK(requests_.find(id) == requests_.end()); 48 DCHECK(requests_.find(id) == requests_.end());
45 scoped_ptr<IqRequest> request(new IqRequest(this, callback)); 49 scoped_ptr<IqRequest> request(new IqRequest(this, callback, addressee));
46 if (!callback.is_null()) 50 if (!callback.is_null())
47 requests_[id] = request.get(); 51 requests_[id] = request.get();
48 return request.Pass(); 52 return request.Pass();
49 } 53 }
50 54
51 scoped_ptr<IqRequest> IqSender::SendIq(const std::string& type, 55 scoped_ptr<IqRequest> IqSender::SendIq(const std::string& type,
52 const std::string& addressee, 56 const std::string& addressee,
53 scoped_ptr<buzz::XmlElement> iq_body, 57 scoped_ptr<buzz::XmlElement> iq_body,
54 const ReplyCallback& callback) { 58 const ReplyCallback& callback) {
55 return SendIq(MakeIqStanza(type, addressee, iq_body.Pass()), callback); 59 return SendIq(MakeIqStanza(type, addressee, iq_body.Pass()), callback);
(...skipping 29 matching lines...) Expand all
85 if (type != "result" && type != "error") { 89 if (type != "result" && type != "error") {
86 return false; 90 return false;
87 } 91 }
88 92
89 const std::string& id = stanza->Attr(buzz::QN_ID); 93 const std::string& id = stanza->Attr(buzz::QN_ID);
90 if (id.empty()) { 94 if (id.empty()) {
91 LOG(WARNING) << "IQ packet missing id " << stanza->Str(); 95 LOG(WARNING) << "IQ packet missing id " << stanza->Str();
92 return false; 96 return false;
93 } 97 }
94 98
99 std::string from = stanza->Attr(buzz::QN_FROM);
100
95 IqRequestMap::iterator it = requests_.find(id); 101 IqRequestMap::iterator it = requests_.find(id);
102
103 // This is a hack to workaround the issue with the WCS changing IDs
104 // of IQ responses sent from client to host. Whenever we receive a
105 // stanza with an unknown ID we try to match it with an outstanding
106 // request sent to the same peer.
107 if (it == requests_.end()) {
108 for (it = requests_.begin(); it != requests_.end(); ++it) {
109 if (it->second->addressee_ == from) {
110 break;
111 }
112 }
113 }
114
simonmorris 2012/02/24 00:11:31 This is fragile if the host can send multiple requ
Sergey Ulanov 2012/02/24 21:56:31 I believe with the current code it will not happen
simonmorris 2012/02/24 22:32:51 OK
96 if (it == requests_.end()) { 115 if (it == requests_.end()) {
97 return false; 116 return false;
98 } 117 }
99 118
100 IqRequest* request = it->second; 119 IqRequest* request = it->second;
120
121 if (request->addressee_ != from) {
122 LOG(ERROR) << "Received IQ response from from a invalid JID. Ignoring it."
123 << " Message received from: " << from
124 << " Original JID: " << request->addressee_;
125 return false;
126 }
127
101 requests_.erase(it); 128 requests_.erase(it);
129 request->OnResponse(stanza);
102 130
103 request->OnResponse(stanza);
104 return true; 131 return true;
105 } 132 }
106 133
107 IqRequest::IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback) 134 IqRequest::IqRequest(IqSender* sender, const IqSender::ReplyCallback& callback,
135 const std::string& addressee)
108 : sender_(sender), 136 : sender_(sender),
109 callback_(callback) { 137 callback_(callback),
138 addressee_(addressee) {
110 } 139 }
111 140
112 IqRequest::~IqRequest() { 141 IqRequest::~IqRequest() {
113 sender_->RemoveRequest(this); 142 sender_->RemoveRequest(this);
114 } 143 }
115 144
145 void IqRequest::SetTimeout(base::TimeDelta timeout) {
146 base::MessageLoopProxy::current()->PostDelayedTask(
147 FROM_HERE, base::Bind(&IqRequest::OnTimeout, AsWeakPtr()),
148 timeout.InMilliseconds());
149 }
150
151 void IqRequest::CallCallback(const buzz::XmlElement* stanza) {
152 if (!callback_.is_null()) {
153 IqSender::ReplyCallback callback(callback_);
154 callback_.Reset();
155 callback.Run(this, stanza);
156 }
157 }
158
159 void IqRequest::OnTimeout() {
160 CallCallback(NULL);
161 }
162
116 void IqRequest::OnResponse(const buzz::XmlElement* stanza) { 163 void IqRequest::OnResponse(const buzz::XmlElement* stanza) {
117 DCHECK(!callback_.is_null()); 164 CallCallback(stanza);
118 IqSender::ReplyCallback callback(callback_);
119 callback_.Reset();
120 callback.Run(stanza);
121 } 165 }
122 166
123 } // namespace remoting 167 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698