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

Side by Side Diff: remoting/protocol/jingle_session.cc

Issue 9447087: Revert 123635 - 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
« no previous file with comments | « remoting/protocol/jingle_session.h ('k') | no next file » | 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/protocol/jingle_session.h" 5 #include "remoting/protocol/jingle_session.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 14 matching lines...) Expand all
25 namespace protocol { 25 namespace protocol {
26 26
27 namespace { 27 namespace {
28 // Delay after candidate creation before sending transport-info 28 // Delay after candidate creation before sending transport-info
29 // message. This is neccessary to be able to pack multiple candidates 29 // message. This is neccessary to be able to pack multiple candidates
30 // into one transport-info messages. The value needs to be greater 30 // into one transport-info messages. The value needs to be greater
31 // than zero because ports are opened asynchronously in the browser 31 // than zero because ports are opened asynchronously in the browser
32 // process. 32 // process.
33 const int kTransportInfoSendDelayMs = 2; 33 const int kTransportInfoSendDelayMs = 2;
34 34
35 // How long we should wait for a response from the other end. This
36 // value is used for all requests include |session-initiate| and
37 // |transport-info|.
38 const int kMessageResponseTimeoutSeconds = 10;
39
40 Session::Error AuthRejectionReasonToError( 35 Session::Error AuthRejectionReasonToError(
41 Authenticator::RejectionReason reason) { 36 Authenticator::RejectionReason reason) {
42 switch (reason) { 37 switch (reason) {
43 case Authenticator::INVALID_CREDENTIALS: 38 case Authenticator::INVALID_CREDENTIALS:
44 return Session::AUTHENTICATION_FAILED; 39 return Session::AUTHENTICATION_FAILED;
45 case Authenticator::PROTOCOL_ERROR: 40 case Authenticator::PROTOCOL_ERROR:
46 return Session::INCOMPATIBLE_PROTOCOL; 41 return Session::INCOMPATIBLE_PROTOCOL;
47 } 42 }
48 NOTREACHED(); 43 NOTREACHED();
49 return Session::UNKNOWN_ERROR; 44 return Session::UNKNOWN_ERROR;
50 } 45 }
51 46
52 } // namespace 47 } // namespace
53 48
54 JingleSession::JingleSession(JingleSessionManager* session_manager) 49 JingleSession::JingleSession(JingleSessionManager* session_manager)
55 : session_manager_(session_manager), 50 : session_manager_(session_manager),
56 state_(INITIALIZING), 51 state_(INITIALIZING),
57 error_(OK), 52 error_(OK),
58 config_is_set_(false) { 53 config_is_set_(false) {
59 } 54 }
60 55
61 JingleSession::~JingleSession() { 56 JingleSession::~JingleSession() {
62 STLDeleteContainerPointers(pending_requests_.begin(),
63 pending_requests_.end());
64 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end()); 57 STLDeleteContainerPairSecondPointers(channels_.begin(), channels_.end());
65 session_manager_->SessionDestroyed(this); 58 session_manager_->SessionDestroyed(this);
66 } 59 }
67 60
68 void JingleSession::SetStateChangeCallback( 61 void JingleSession::SetStateChangeCallback(
69 const StateChangeCallback& callback) { 62 const StateChangeCallback& callback) {
70 DCHECK(CalledOnValidThread()); 63 DCHECK(CalledOnValidThread());
71 DCHECK(!callback.is_null()); 64 DCHECK(!callback.is_null());
72 state_change_callback_ = callback; 65 state_change_callback_ = callback;
73 } 66 }
(...skipping 28 matching lines...) Expand all
102 // enough entropy. In the worst case connection will fail when two 95 // enough entropy. In the worst case connection will fail when two
103 // clients generate the same session ID concurrently. 96 // clients generate the same session ID concurrently.
104 session_id_ = base::Int64ToString(base::RandGenerator(kint64max)); 97 session_id_ = base::Int64ToString(base::RandGenerator(kint64max));
105 98
106 // Send session-initiate message. 99 // Send session-initiate message.
107 JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE, 100 JingleMessage message(peer_jid_, JingleMessage::SESSION_INITIATE,
108 session_id_); 101 session_id_);
109 message.description.reset( 102 message.description.reset(
110 new ContentDescription(candidate_config_->Clone(), 103 new ContentDescription(candidate_config_->Clone(),
111 authenticator_->GetNextMessage())); 104 authenticator_->GetNextMessage()));
112 SendMessage(message); 105 initiate_request_ = session_manager_->iq_sender()->SendIq(
106 message.ToXml(),
107 base::Bind(&JingleSession::OnSessionInitiateResponse,
108 base::Unretained(this)));
113 109
114 SetState(CONNECTING); 110 SetState(CONNECTING);
115 } 111 }
116 112
117 void JingleSession::InitializeIncomingConnection( 113 void JingleSession::InitializeIncomingConnection(
118 const JingleMessage& initiate_message, 114 const JingleMessage& initiate_message,
119 scoped_ptr<Authenticator> authenticator) { 115 scoped_ptr<Authenticator> authenticator) {
120 DCHECK(CalledOnValidThread()); 116 DCHECK(CalledOnValidThread());
121 DCHECK(initiate_message.description.get()); 117 DCHECK(initiate_message.description.get());
122 DCHECK(authenticator.get()); 118 DCHECK(authenticator.get());
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
155 JingleMessage message(peer_jid_, JingleMessage::SESSION_ACCEPT, 151 JingleMessage message(peer_jid_, JingleMessage::SESSION_ACCEPT,
156 session_id_); 152 session_id_);
157 153
158 scoped_ptr<buzz::XmlElement> auth_message; 154 scoped_ptr<buzz::XmlElement> auth_message;
159 if (authenticator_->state() == Authenticator::MESSAGE_READY) 155 if (authenticator_->state() == Authenticator::MESSAGE_READY)
160 auth_message = authenticator_->GetNextMessage(); 156 auth_message = authenticator_->GetNextMessage();
161 157
162 message.description.reset( 158 message.description.reset(
163 new ContentDescription(CandidateSessionConfig::CreateFrom(config_), 159 new ContentDescription(CandidateSessionConfig::CreateFrom(config_),
164 auth_message.Pass())); 160 auth_message.Pass()));
165 SendMessage(message); 161 initiate_request_ = session_manager_->iq_sender()->SendIq(
162 message.ToXml(),
163 base::Bind(&JingleSession::OnSessionInitiateResponse,
164 base::Unretained(this)));
166 165
167 // Update state. 166 // Update state.
168 SetState(CONNECTED); 167 SetState(CONNECTED);
169 168
170 if (authenticator_->state() == Authenticator::ACCEPTED) { 169 if (authenticator_->state() == Authenticator::ACCEPTED) {
171 SetState(AUTHENTICATED); 170 SetState(AUTHENTICATED);
172 } else { 171 } else {
173 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE); 172 DCHECK_EQ(authenticator_->state(), Authenticator::WAITING_MESSAGE);
174 } 173 }
175 174
176 return; 175 return;
177 } 176 }
178 177
178 void JingleSession::OnSessionInitiateResponse(
179 const buzz::XmlElement* response) {
180 const std::string& type = response->Attr(buzz::QName("", "type"));
181 if (type != "result") {
182 LOG(ERROR) << "Received error in response to session-initiate message: \""
183 << response->Str()
184 << "\". Terminating the session.";
185
186 // TODO(sergeyu): There may be different reasons for error
187 // here. Parse the response stanza to find failure reason.
188 CloseInternal(PEER_IS_OFFLINE);
189 }
190 }
191
179 void JingleSession::CreateStreamChannel( 192 void JingleSession::CreateStreamChannel(
180 const std::string& name, 193 const std::string& name,
181 const StreamChannelCallback& callback) { 194 const StreamChannelCallback& callback) {
182 DCHECK(!channels_[name]); 195 DCHECK(!channels_[name]);
183 196
184 scoped_ptr<ChannelAuthenticator> channel_authenticator = 197 scoped_ptr<ChannelAuthenticator> channel_authenticator =
185 authenticator_->CreateChannelAuthenticator(); 198 authenticator_->CreateChannelAuthenticator();
186 scoped_ptr<StreamTransport> channel = 199 scoped_ptr<StreamTransport> channel =
187 session_manager_->transport_factory_->CreateStreamTransport(); 200 session_manager_->transport_factory_->CreateStreamTransport();
188 channel->Initialize(name, session_manager_->transport_config_, 201 channel->Initialize(name, session_manager_->transport_config_,
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 route.local_address); 275 route.local_address);
263 } 276 }
264 } 277 }
265 278
266 void JingleSession::OnTransportDeleted(Transport* transport) { 279 void JingleSession::OnTransportDeleted(Transport* transport) {
267 ChannelsMap::iterator it = channels_.find(transport->name()); 280 ChannelsMap::iterator it = channels_.find(transport->name());
268 DCHECK_EQ(it->second, transport); 281 DCHECK_EQ(it->second, transport);
269 channels_.erase(it); 282 channels_.erase(it);
270 } 283 }
271 284
272 void JingleSession::SendMessage(const JingleMessage& message) {
273 scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq(
274 message.ToXml(),
275 base::Bind(&JingleSession::OnMessageResponse,
276 base::Unretained(this), message.action));
277 if (request.get()) {
278 request->SetTimeout(
279 base::TimeDelta::FromSeconds(kMessageResponseTimeoutSeconds));
280 pending_requests_.push_back(request.release());
281 } else {
282 LOG(ERROR) << "Failed to send a "
283 << JingleMessage::GetActionName(message.action) << " message";
284 }
285 }
286
287 void JingleSession::OnMessageResponse(
288 JingleMessage::ActionType request_type,
289 IqRequest* request,
290 const buzz::XmlElement* response) {
291 Error error = OK;
292
293 std::string type_str = JingleMessage::GetActionName(request_type);
294
295 if (!response) {
296 LOG(ERROR) << type_str << " request timed out.";
297 // Most likely the session-initiate timeout indicates a problem
298 // with the signaling.
299 error = UNKNOWN_ERROR;
300 } else {
301 const std::string& type = response->Attr(buzz::QName("", "type"));
302 if (type != "result") {
303 LOG(ERROR) << "Received error in response to " << type_str
304 << " message: \"" << response->Str()
305 << "\". Terminating the session.";
306
307 switch (request_type) {
308 case JingleMessage::SESSION_INFO:
309 // session-info is used for the new authentication protocol,
310 // and wasn't previously supported.
311 error = INCOMPATIBLE_PROTOCOL;
312
313 default:
314 // TODO(sergeyu): There may be different reasons for error
315 // here. Parse the response stanza to find failure reason.
316 error = PEER_IS_OFFLINE;
317 }
318 }
319 }
320
321 CleanupPendingRequests(request);
322
323 if (error != OK) {
324 CloseInternal(error);
325 }
326 }
327
328 void JingleSession::CleanupPendingRequests(IqRequest* request) {
329 DCHECK(!pending_requests_.empty());
330 DCHECK(request);
331
332 // This method is called whenever a response to |request| is
333 // received. Here we delete that request and all requests that were
334 // sent before it. The idea here is that if we send messages A, B
335 // and C and then suddenly receive response to C then it means that
336 // either A and B messages or the corresponding response messages
337 // were somehow lost. E.g. that may happen when the client switches
338 // from one network to another. The best way to handle that case is
339 // to ignore errors and timeouts for A and B by deleting the
340 // corresponding IqRequest objects.
341 while (!pending_requests_.empty() && pending_requests_.front() != request) {
342 delete pending_requests_.front();
343 pending_requests_.pop_front();
344 }
345
346 // Delete the |request| itself.
347 DCHECK_EQ(request, pending_requests_.front());
348 delete request;
349 if (!pending_requests_.empty())
350 pending_requests_.pop_front();
351 }
352
353 void JingleSession::OnIncomingMessage(const JingleMessage& message, 285 void JingleSession::OnIncomingMessage(const JingleMessage& message,
354 const ReplyCallback& reply_callback) { 286 const ReplyCallback& reply_callback) {
355 DCHECK(CalledOnValidThread()); 287 DCHECK(CalledOnValidThread());
356 288
357 if (message.from != peer_jid_) { 289 if (message.from != peer_jid_) {
358 // Ignore messages received from a different Jid. 290 // Ignore messages received from a different Jid.
359 reply_callback.Run(JingleMessageReply::INVALID_SID); 291 reply_callback.Run(JingleMessageReply::INVALID_SID);
360 return; 292 return;
361 } 293 }
362 294
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 return true; 444 return true;
513 } 445 }
514 446
515 void JingleSession::ProcessAuthenticationStep() { 447 void JingleSession::ProcessAuthenticationStep() {
516 DCHECK_EQ(state_, CONNECTED); 448 DCHECK_EQ(state_, CONNECTED);
517 449
518 if (authenticator_->state() == Authenticator::MESSAGE_READY) { 450 if (authenticator_->state() == Authenticator::MESSAGE_READY) {
519 JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_); 451 JingleMessage message(peer_jid_, JingleMessage::SESSION_INFO, session_id_);
520 message.info = authenticator_->GetNextMessage(); 452 message.info = authenticator_->GetNextMessage();
521 DCHECK(message.info.get()); 453 DCHECK(message.info.get());
522 SendMessage(message); 454
455 session_info_request_ = session_manager_->iq_sender()->SendIq(
456 message.ToXml(), base::Bind(
457 &JingleSession::OnSessionInfoResponse,
458 base::Unretained(this)));
523 } 459 }
524 DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY); 460 DCHECK_NE(authenticator_->state(), Authenticator::MESSAGE_READY);
525 461
526 if (authenticator_->state() == Authenticator::ACCEPTED) { 462 if (authenticator_->state() == Authenticator::ACCEPTED) {
527 SetState(AUTHENTICATED); 463 SetState(AUTHENTICATED);
528 } else if (authenticator_->state() == Authenticator::REJECTED) { 464 } else if (authenticator_->state() == Authenticator::REJECTED) {
529 CloseInternal(AuthRejectionReasonToError( 465 CloseInternal(AuthRejectionReasonToError(
530 authenticator_->rejection_reason())); 466 authenticator_->rejection_reason()));
531 } 467 }
532 } 468 }
533 469
470 void JingleSession::OnSessionInfoResponse(const buzz::XmlElement* response) {
471 const std::string& type = response->Attr(buzz::QName("", "type"));
472 if (type != "result") {
473 LOG(ERROR) << "Received error in response to session-info message: \""
474 << response->Str()
475 << "\". Terminating the session.";
476 CloseInternal(INCOMPATIBLE_PROTOCOL);
477 }
478 }
479
480 void JingleSession::OnTransportInfoResponse(const buzz::XmlElement* response) {
481 const std::string& type = response->Attr(buzz::QName("", "type"));
482 if (type != "result") {
483 LOG(ERROR) << "Received error in response to session-initiate message: \""
484 << response->Str()
485 << "\". Terminating the session.";
486
487 if (state_ == CONNECTING) {
488 CloseInternal(PEER_IS_OFFLINE);
489 } else {
490 // Host has disconnected without sending session-terminate message.
491 CloseInternal(OK);
492 }
493 }
494 }
495
534 void JingleSession::SendTransportInfo() { 496 void JingleSession::SendTransportInfo() {
535 JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_); 497 JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_);
536 message.candidates.swap(pending_candidates_); 498 message.candidates.swap(pending_candidates_);
537 SendMessage(message); 499 transport_info_request_ = session_manager_->iq_sender()->SendIq(
500 message.ToXml(), base::Bind(
501 &JingleSession::OnTransportInfoResponse,
502 base::Unretained(this)));
538 } 503 }
539 504
505
540 void JingleSession::CloseInternal(Error error) { 506 void JingleSession::CloseInternal(Error error) {
541 DCHECK(CalledOnValidThread()); 507 DCHECK(CalledOnValidThread());
542 508
543 if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) { 509 if (state_ == CONNECTING || state_ == CONNECTED || state_ == AUTHENTICATED) {
544 // Send session-terminate message with the appropriate error code. 510 // Send session-terminate message with the appropriate error code.
545 JingleMessage::Reason reason; 511 JingleMessage::Reason reason;
546 switch (error) { 512 switch (error) {
547 case OK: 513 case OK:
548 reason = JingleMessage::SUCCESS; 514 reason = JingleMessage::SUCCESS;
549 break; 515 break;
550 case SESSION_REJECTED: 516 case SESSION_REJECTED:
551 case AUTHENTICATION_FAILED: 517 case AUTHENTICATION_FAILED:
552 reason = JingleMessage::DECLINE; 518 reason = JingleMessage::DECLINE;
553 break; 519 break;
554 case INCOMPATIBLE_PROTOCOL: 520 case INCOMPATIBLE_PROTOCOL:
555 reason = JingleMessage::INCOMPATIBLE_PARAMETERS; 521 reason = JingleMessage::INCOMPATIBLE_PARAMETERS;
556 break; 522 break;
557 default: 523 default:
558 reason = JingleMessage::GENERAL_ERROR; 524 reason = JingleMessage::GENERAL_ERROR;
559 } 525 }
560 526
561 JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE, 527 JingleMessage message(peer_jid_, JingleMessage::SESSION_TERMINATE,
562 session_id_); 528 session_id_);
563 message.reason = reason; 529 message.reason = reason;
564 SendMessage(message); 530 session_manager_->iq_sender()->SendIq(
531 message.ToXml(), IqSender::ReplyCallback());
565 } 532 }
566 533
567 error_ = error; 534 error_ = error;
568 535
569 if (state_ != FAILED && state_ != CLOSED) { 536 if (state_ != FAILED && state_ != CLOSED) {
570 if (error != OK) { 537 if (error != OK) {
571 SetState(FAILED); 538 SetState(FAILED);
572 } else { 539 } else {
573 SetState(CLOSED); 540 SetState(CLOSED);
574 } 541 }
575 } 542 }
576 } 543 }
577 544
578 void JingleSession::SetState(State new_state) { 545 void JingleSession::SetState(State new_state) {
579 DCHECK(CalledOnValidThread()); 546 DCHECK(CalledOnValidThread());
580 547
581 if (new_state != state_) { 548 if (new_state != state_) {
582 DCHECK_NE(state_, CLOSED); 549 DCHECK_NE(state_, CLOSED);
583 DCHECK_NE(state_, FAILED); 550 DCHECK_NE(state_, FAILED);
584 551
585 state_ = new_state; 552 state_ = new_state;
586 if (!state_change_callback_.is_null()) 553 if (!state_change_callback_.is_null())
587 state_change_callback_.Run(new_state); 554 state_change_callback_.Run(new_state);
588 } 555 }
589 } 556 }
590 557
591 } // namespace protocol 558 } // namespace protocol
592 } // namespace remoting 559 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/protocol/jingle_session.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698