OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 | 117 |
118 // Wraps the comparison connection into a less than operator that puts higher | 118 // Wraps the comparison connection into a less than operator that puts higher |
119 // priority writable connections first. | 119 // priority writable connections first. |
120 class ConnectionCompare { | 120 class ConnectionCompare { |
121 public: | 121 public: |
122 bool operator()(const cricket::Connection *ca, | 122 bool operator()(const cricket::Connection *ca, |
123 const cricket::Connection *cb) { | 123 const cricket::Connection *cb) { |
124 cricket::Connection* a = const_cast<cricket::Connection*>(ca); | 124 cricket::Connection* a = const_cast<cricket::Connection*>(ca); |
125 cricket::Connection* b = const_cast<cricket::Connection*>(cb); | 125 cricket::Connection* b = const_cast<cricket::Connection*>(cb); |
126 | 126 |
127 // The IceProtocol is initialized to ICEPROTO_HYBRID and can be updated to | |
128 // GICE or RFC5245 when an answer SDP is set, or when a STUN message is | |
129 // received. So the port receiving the STUN message may have a different | |
130 // IceProtocol if the answer SDP is not set yet. | |
131 ASSERT(a->port()->IceProtocol() == b->port()->IceProtocol() || | |
132 a->port()->IceProtocol() == cricket::ICEPROTO_HYBRID || | |
133 b->port()->IceProtocol() == cricket::ICEPROTO_HYBRID); | |
134 | |
135 // Compare first on writability and static preferences. | 127 // Compare first on writability and static preferences. |
136 int cmp = CompareConnections(a, b); | 128 int cmp = CompareConnections(a, b); |
137 if (cmp > 0) | 129 if (cmp > 0) |
138 return true; | 130 return true; |
139 if (cmp < 0) | 131 if (cmp < 0) |
140 return false; | 132 return false; |
141 | 133 |
142 // Otherwise, sort based on latency estimate. | 134 // Otherwise, sort based on latency estimate. |
143 return a->rtt() < b->rtt(); | 135 return a->rtt() < b->rtt(); |
144 | 136 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
185 transport_(transport), | 177 transport_(transport), |
186 allocator_(allocator), | 178 allocator_(allocator), |
187 worker_thread_(rtc::Thread::Current()), | 179 worker_thread_(rtc::Thread::Current()), |
188 incoming_only_(false), | 180 incoming_only_(false), |
189 waiting_for_signaling_(false), | 181 waiting_for_signaling_(false), |
190 error_(0), | 182 error_(0), |
191 best_connection_(NULL), | 183 best_connection_(NULL), |
192 pending_best_connection_(NULL), | 184 pending_best_connection_(NULL), |
193 sort_dirty_(false), | 185 sort_dirty_(false), |
194 was_writable_(false), | 186 was_writable_(false), |
195 protocol_type_(ICEPROTO_HYBRID), | |
196 remote_ice_mode_(ICEMODE_FULL), | 187 remote_ice_mode_(ICEMODE_FULL), |
197 ice_role_(ICEROLE_UNKNOWN), | 188 ice_role_(ICEROLE_UNKNOWN), |
198 tiebreaker_(0), | 189 tiebreaker_(0), |
199 remote_candidate_generation_(0), | 190 remote_candidate_generation_(0), |
200 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 191 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
201 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { | 192 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { |
202 } | 193 } |
203 | 194 |
204 P2PTransportChannel::~P2PTransportChannel() { | 195 P2PTransportChannel::~P2PTransportChannel() { |
205 ASSERT(worker_thread_ == rtc::Thread::Current()); | 196 ASSERT(worker_thread_ == rtc::Thread::Current()); |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 << network->ToString() | 278 << network->ToString() |
288 << " has more than 1 connection."; | 279 << " has more than 1 connection."; |
289 return TransportChannelState::STATE_CONNECTING; | 280 return TransportChannelState::STATE_CONNECTING; |
290 } | 281 } |
291 } | 282 } |
292 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; | 283 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; |
293 | 284 |
294 return TransportChannelState::STATE_COMPLETED; | 285 return TransportChannelState::STATE_COMPLETED; |
295 } | 286 } |
296 | 287 |
297 bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const { | |
298 *type = protocol_type_; | |
299 return true; | |
300 } | |
301 | |
302 void P2PTransportChannel::SetIceProtocolType(IceProtocolType type) { | |
303 ASSERT(worker_thread_ == rtc::Thread::Current()); | |
304 | |
305 protocol_type_ = type; | |
306 for (std::vector<PortInterface *>::iterator it = ports_.begin(); | |
307 it != ports_.end(); ++it) { | |
308 (*it)->SetIceProtocolType(protocol_type_); | |
309 } | |
310 } | |
311 | |
312 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, | 288 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, |
313 const std::string& ice_pwd) { | 289 const std::string& ice_pwd) { |
314 ASSERT(worker_thread_ == rtc::Thread::Current()); | 290 ASSERT(worker_thread_ == rtc::Thread::Current()); |
315 bool ice_restart = false; | 291 bool ice_restart = false; |
316 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { | 292 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { |
317 // Restart candidate allocation if there is any change in either | 293 // Restart candidate allocation if there is any change in either |
318 // ice ufrag or password. | 294 // ice ufrag or password. |
319 ice_restart = | 295 ice_restart = |
320 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); | 296 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); |
321 } | 297 } |
(...skipping 19 matching lines...) Expand all Loading... |
341 remote_ice_ufrag_ = ice_ufrag; | 317 remote_ice_ufrag_ = ice_ufrag; |
342 remote_ice_pwd_ = ice_pwd; | 318 remote_ice_pwd_ = ice_pwd; |
343 | 319 |
344 // We need to update the credentials for any peer reflexive candidates. | 320 // We need to update the credentials for any peer reflexive candidates. |
345 std::vector<Connection*>::iterator it = connections_.begin(); | 321 std::vector<Connection*>::iterator it = connections_.begin(); |
346 for (; it != connections_.end(); ++it) { | 322 for (; it != connections_.end(); ++it) { |
347 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); | 323 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); |
348 } | 324 } |
349 | 325 |
350 if (ice_restart) { | 326 if (ice_restart) { |
351 // |candidate.generation()| is not signaled in ICEPROTO_RFC5245. | 327 // We need to keep track of the remote ice restart so newer |
352 // Therefore we need to keep track of the remote ice restart so | 328 // connections are prioritized over the older. |
353 // newer connections are prioritized over the older. | |
354 ++remote_candidate_generation_; | 329 ++remote_candidate_generation_; |
355 } | 330 } |
356 } | 331 } |
357 | 332 |
358 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { | 333 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |
359 remote_ice_mode_ = mode; | 334 remote_ice_mode_ = mode; |
360 } | 335 } |
361 | 336 |
362 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { | 337 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { |
363 if (receiving_timeout_ms < 0) { | 338 if (receiving_timeout_ms < 0) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 LOG_J(LS_WARNING, port) << "SetOption(" << it->first | 379 LOG_J(LS_WARNING, port) << "SetOption(" << it->first |
405 << ", " << it->second | 380 << ", " << it->second |
406 << ") failed: " << port->GetError(); | 381 << ") failed: " << port->GetError(); |
407 } | 382 } |
408 } | 383 } |
409 | 384 |
410 // Remember the ports and candidates, and signal that candidates are ready. | 385 // Remember the ports and candidates, and signal that candidates are ready. |
411 // The session will handle this, and send an initiate/accept/modify message | 386 // The session will handle this, and send an initiate/accept/modify message |
412 // if one is pending. | 387 // if one is pending. |
413 | 388 |
414 port->SetIceProtocolType(protocol_type_); | |
415 port->SetIceRole(ice_role_); | 389 port->SetIceRole(ice_role_); |
416 port->SetIceTiebreaker(tiebreaker_); | 390 port->SetIceTiebreaker(tiebreaker_); |
417 ports_.push_back(port); | 391 ports_.push_back(port); |
418 port->SignalUnknownAddress.connect( | 392 port->SignalUnknownAddress.connect( |
419 this, &P2PTransportChannel::OnUnknownAddress); | 393 this, &P2PTransportChannel::OnUnknownAddress); |
420 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); | 394 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); |
421 port->SignalRoleConflict.connect( | 395 port->SignalRoleConflict.connect( |
422 this, &P2PTransportChannel::OnRoleConflict); | 396 this, &P2PTransportChannel::OnRoleConflict); |
423 | 397 |
424 // Attempt to create a connection from this new port to all of the remote | 398 // Attempt to create a connection from this new port to all of the remote |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 | 473 |
500 Candidate remote_candidate; | 474 Candidate remote_candidate; |
501 bool remote_candidate_is_new = (candidate == nullptr); | 475 bool remote_candidate_is_new = (candidate == nullptr); |
502 if (!remote_candidate_is_new) { | 476 if (!remote_candidate_is_new) { |
503 remote_candidate = *candidate; | 477 remote_candidate = *candidate; |
504 if (ufrag_per_port) { | 478 if (ufrag_per_port) { |
505 remote_candidate.set_address(address); | 479 remote_candidate.set_address(address); |
506 } | 480 } |
507 } else { | 481 } else { |
508 // Create a new candidate with this address. | 482 // Create a new candidate with this address. |
509 std::string type; | |
510 int remote_candidate_priority; | 483 int remote_candidate_priority; |
511 if (port->IceProtocol() == ICEPROTO_RFC5245) { | |
512 // RFC 5245 | |
513 // If the source transport address of the request does not match any | |
514 // existing remote candidates, it represents a new peer reflexive remote | |
515 // candidate. | |
516 type = PRFLX_PORT_TYPE; | |
517 | 484 |
518 // The priority of the candidate is set to the PRIORITY attribute | 485 // The priority of the candidate is set to the PRIORITY attribute |
519 // from the request. | 486 // from the request. |
520 const StunUInt32Attribute* priority_attr = | 487 const StunUInt32Attribute* priority_attr = |
521 stun_msg->GetUInt32(STUN_ATTR_PRIORITY); | 488 stun_msg->GetUInt32(STUN_ATTR_PRIORITY); |
522 if (!priority_attr) { | 489 if (!priority_attr) { |
523 LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - " | 490 LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - " |
524 << "No STUN_ATTR_PRIORITY found in the " | 491 << "No STUN_ATTR_PRIORITY found in the " |
525 << "stun request message"; | 492 << "stun request message"; |
526 port->SendBindingErrorResponse(stun_msg, address, | 493 port->SendBindingErrorResponse(stun_msg, address, |
527 STUN_ERROR_BAD_REQUEST, | 494 STUN_ERROR_BAD_REQUEST, |
528 STUN_ERROR_REASON_BAD_REQUEST); | 495 STUN_ERROR_REASON_BAD_REQUEST); |
529 return; | 496 return; |
530 } | |
531 remote_candidate_priority = priority_attr->value(); | |
532 } else { | |
533 // G-ICE doesn't support prflx candidate. | |
534 // We set candidate type to STUN_PORT_TYPE if the binding request comes | |
535 // from a relay port or the shared socket is used. Otherwise we use the | |
536 // port's type as the candidate type. | |
537 if (port->Type() == RELAY_PORT_TYPE || port->SharedSocket()) { | |
538 type = STUN_PORT_TYPE; | |
539 } else { | |
540 type = port->Type(); | |
541 } | |
542 remote_candidate_priority = remote_candidate.GetPriority( | |
543 ICE_TYPE_PREFERENCE_PRFLX, port->Network()->preference(), 0); | |
544 } | 497 } |
| 498 remote_candidate_priority = priority_attr->value(); |
545 | 499 |
| 500 // RFC 5245 |
| 501 // If the source transport address of the request does not match any |
| 502 // existing remote candidates, it represents a new peer reflexive remote |
| 503 // candidate. |
546 remote_candidate = | 504 remote_candidate = |
547 Candidate(component(), ProtoToString(proto), address, 0, | 505 Candidate(component(), ProtoToString(proto), address, 0, |
548 remote_username, remote_password, type, 0U, ""); | 506 remote_username, remote_password, PRFLX_PORT_TYPE, 0U, ""); |
549 | 507 |
550 // From RFC 5245, section-7.2.1.3: | 508 // From RFC 5245, section-7.2.1.3: |
551 // The foundation of the candidate is set to an arbitrary value, different | 509 // The foundation of the candidate is set to an arbitrary value, different |
552 // from the foundation for all other remote candidates. | 510 // from the foundation for all other remote candidates. |
553 remote_candidate.set_foundation( | 511 remote_candidate.set_foundation( |
554 rtc::ToString<uint32>(rtc::ComputeCrc32(remote_candidate.id()))); | 512 rtc::ToString<uint32>(rtc::ComputeCrc32(remote_candidate.id()))); |
555 | 513 |
556 remote_candidate.set_priority(remote_candidate_priority); | 514 remote_candidate.set_priority(remote_candidate_priority); |
557 } | 515 } |
558 | 516 |
559 if (port->IceProtocol() == ICEPROTO_RFC5245) { | 517 // RFC5245, the agent constructs a pair whose local candidate is equal to |
560 // RFC5245, the agent constructs a pair whose local candidate is equal to | 518 // the transport address on which the STUN request was received, and a |
561 // the transport address on which the STUN request was received, and a | 519 // remote candidate equal to the source transport address where the |
562 // remote candidate equal to the source transport address where the | 520 // request came from. |
563 // request came from. | |
564 | 521 |
565 // There shouldn't be an existing connection with this remote address. | 522 // There shouldn't be an existing connection with this remote address. |
566 // When ports are muxed, this channel might get multiple unknown address | 523 // When ports are muxed, this channel might get multiple unknown address |
567 // signals. In that case if the connection is already exists, we should | 524 // signals. In that case if the connection is already exists, we should |
568 // simply ignore the signal othewise send server error. | 525 // simply ignore the signal othewise send server error. |
569 if (port->GetConnection(remote_candidate.address())) { | 526 if (port->GetConnection(remote_candidate.address())) { |
570 if (port_muxed) { | 527 if (port_muxed) { |
571 LOG(LS_INFO) << "Connection already exists for peer reflexive " | 528 LOG(LS_INFO) << "Connection already exists for peer reflexive " |
572 << "candidate: " << remote_candidate.ToString(); | 529 << "candidate: " << remote_candidate.ToString(); |
573 return; | 530 return; |
574 } else { | 531 } else { |
575 ASSERT(false); | |
576 port->SendBindingErrorResponse(stun_msg, address, | |
577 STUN_ERROR_SERVER_ERROR, | |
578 STUN_ERROR_REASON_SERVER_ERROR); | |
579 return; | |
580 } | |
581 } | |
582 | |
583 Connection* connection = port->CreateConnection( | |
584 remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT); | |
585 if (!connection) { | |
586 ASSERT(false); | 532 ASSERT(false); |
587 port->SendBindingErrorResponse(stun_msg, address, | 533 port->SendBindingErrorResponse(stun_msg, address, |
588 STUN_ERROR_SERVER_ERROR, | 534 STUN_ERROR_SERVER_ERROR, |
589 STUN_ERROR_REASON_SERVER_ERROR); | 535 STUN_ERROR_REASON_SERVER_ERROR); |
590 return; | 536 return; |
591 } | 537 } |
| 538 } |
592 | 539 |
593 LOG(LS_INFO) << "Adding connection from " | 540 Connection* connection = port->CreateConnection( |
594 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 541 remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT); |
595 << " candidate: " << remote_candidate.ToString(); | 542 if (!connection) { |
596 AddConnection(connection); | 543 ASSERT(false); |
597 connection->ReceivedPing(); | 544 port->SendBindingErrorResponse(stun_msg, address, |
| 545 STUN_ERROR_SERVER_ERROR, |
| 546 STUN_ERROR_REASON_SERVER_ERROR); |
| 547 return; |
| 548 } |
598 | 549 |
599 // Send the pinger a successful stun response. | 550 LOG(LS_INFO) << "Adding connection from " |
600 port->SendBindingResponse(stun_msg, address); | 551 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
| 552 << " candidate: " << remote_candidate.ToString(); |
| 553 AddConnection(connection); |
| 554 connection->ReceivedPing(); |
601 | 555 |
602 // Update the list of connections since we just added another. We do this | 556 // Update the list of connections since we just added another. We do this |
603 // after sending the response since it could (in principle) delete the | 557 // after sending the response since it could (in principle) delete the |
604 // connection in question. | 558 // connection in question. |
605 SortConnections(); | 559 SortConnections(); |
606 } else { | |
607 // Check for connectivity to this address. Create connections | |
608 // to this address across all local ports. First, add this as a new remote | |
609 // address | |
610 if (!CreateConnections(remote_candidate, port, true)) { | |
611 // Hopefully this won't occur, because changing a destination address | |
612 // shouldn't cause a new connection to fail | |
613 ASSERT(false); | |
614 port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR, | |
615 STUN_ERROR_REASON_SERVER_ERROR); | |
616 return; | |
617 } | |
618 | |
619 // Send the pinger a successful stun response. | |
620 port->SendBindingResponse(stun_msg, address); | |
621 | |
622 // Update the list of connections since we just added another. We do this | |
623 // after sending the response since it could (in principle) delete the | |
624 // connection in question. | |
625 SortConnections(); | |
626 } | |
627 } | 560 } |
628 | 561 |
629 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { | 562 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { |
630 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called | 563 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called |
631 // from Transport. | 564 // from Transport. |
632 } | 565 } |
633 | 566 |
634 // When the signalling channel is ready, we can really kick off the allocator | 567 // When the signalling channel is ready, we can really kick off the allocator |
635 void P2PTransportChannel::OnSignalingReady() { | 568 void P2PTransportChannel::OnSignalingReady() { |
636 ASSERT(worker_thread_ == rtc::Thread::Current()); | 569 ASSERT(worker_thread_ == rtc::Thread::Current()); |
637 if (waiting_for_signaling_) { | 570 if (waiting_for_signaling_) { |
638 waiting_for_signaling_ = false; | 571 waiting_for_signaling_ = false; |
639 AddAllocatorSession(allocator_->CreateSession( | 572 AddAllocatorSession(allocator_->CreateSession( |
640 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); | 573 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); |
641 } | 574 } |
642 } | 575 } |
643 | 576 |
644 void P2PTransportChannel::OnUseCandidate(Connection* conn) { | 577 void P2PTransportChannel::OnUseCandidate(Connection* conn) { |
645 ASSERT(worker_thread_ == rtc::Thread::Current()); | 578 ASSERT(worker_thread_ == rtc::Thread::Current()); |
646 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 579 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
647 ASSERT(protocol_type_ == ICEPROTO_RFC5245); | |
648 | 580 |
649 if (conn->write_state() == Connection::STATE_WRITABLE) { | 581 if (conn->write_state() == Connection::STATE_WRITABLE) { |
650 if (best_connection_ != conn) { | 582 if (best_connection_ != conn) { |
651 pending_best_connection_ = NULL; | 583 pending_best_connection_ = NULL; |
652 LOG(LS_INFO) << "Switching best connection on controlled side: " | 584 LOG(LS_INFO) << "Switching best connection on controlled side: " |
653 << conn->ToString(); | 585 << conn->ToString(); |
654 SwitchBestConnectionTo(conn); | 586 SwitchBestConnectionTo(conn); |
655 // Now we have selected the best connection, time to prune other existing | 587 // Now we have selected the best connection, time to prune other existing |
656 // connections and update the read/write state of the channel. | 588 // connections and update the read/write state of the channel. |
657 RequestSort(); | 589 RequestSort(); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
796 | 728 |
797 bool P2PTransportChannel::FindConnection( | 729 bool P2PTransportChannel::FindConnection( |
798 cricket::Connection* connection) const { | 730 cricket::Connection* connection) const { |
799 std::vector<Connection*>::const_iterator citer = | 731 std::vector<Connection*>::const_iterator citer = |
800 std::find(connections_.begin(), connections_.end(), connection); | 732 std::find(connections_.begin(), connections_.end(), connection); |
801 return citer != connections_.end(); | 733 return citer != connections_.end(); |
802 } | 734 } |
803 | 735 |
804 uint32 P2PTransportChannel::GetRemoteCandidateGeneration( | 736 uint32 P2PTransportChannel::GetRemoteCandidateGeneration( |
805 const Candidate& candidate) { | 737 const Candidate& candidate) { |
806 if (protocol_type_ == ICEPROTO_GOOGLE) { | 738 // We need to keep track of the remote ice restart so newer |
807 // The Candidate.generation() can be trusted. Nothing needs to be done. | 739 // connections are prioritized over the older. |
808 return candidate.generation(); | |
809 } | |
810 // |candidate.generation()| is not signaled in ICEPROTO_RFC5245. | |
811 // Therefore we need to keep track of the remote ice restart so | |
812 // newer connections are prioritized over the older. | |
813 ASSERT(candidate.generation() == 0 || | 740 ASSERT(candidate.generation() == 0 || |
814 candidate.generation() == remote_candidate_generation_); | 741 candidate.generation() == remote_candidate_generation_); |
815 return remote_candidate_generation_; | 742 return remote_candidate_generation_; |
816 } | 743 } |
817 | 744 |
818 // Check if remote candidate is already cached. | 745 // Check if remote candidate is already cached. |
819 bool P2PTransportChannel::IsDuplicateRemoteCandidate( | 746 bool P2PTransportChannel::IsDuplicateRemoteCandidate( |
820 const Candidate& candidate) { | 747 const Candidate& candidate) { |
821 for (uint32 i = 0; i < remote_candidates_.size(); ++i) { | 748 for (uint32 i = 0; i < remote_candidates_.size(); ++i) { |
822 if (remote_candidates_[i].IsEquivalent(candidate)) { | 749 if (remote_candidates_[i].IsEquivalent(candidate)) { |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
980 | 907 |
981 // Sort the available connections to find the best one. We also monitor | 908 // Sort the available connections to find the best one. We also monitor |
982 // the number of available connections and the current state. | 909 // the number of available connections and the current state. |
983 void P2PTransportChannel::SortConnections() { | 910 void P2PTransportChannel::SortConnections() { |
984 ASSERT(worker_thread_ == rtc::Thread::Current()); | 911 ASSERT(worker_thread_ == rtc::Thread::Current()); |
985 | 912 |
986 // Make sure the connection states are up-to-date since this affects how they | 913 // Make sure the connection states are up-to-date since this affects how they |
987 // will be sorted. | 914 // will be sorted. |
988 UpdateConnectionStates(); | 915 UpdateConnectionStates(); |
989 | 916 |
990 if (protocol_type_ == ICEPROTO_HYBRID) { | |
991 // If we are in hybrid mode, we are not sending any ping requests, so there | |
992 // is no point in sorting the connections. In hybrid state, ports can have | |
993 // different protocol than hybrid and protocol may differ from one another. | |
994 // Instead just update the state of this channel | |
995 UpdateChannelState(); | |
996 return; | |
997 } | |
998 | |
999 // Any changes after this point will require a re-sort. | 917 // Any changes after this point will require a re-sort. |
1000 sort_dirty_ = false; | 918 sort_dirty_ = false; |
1001 | 919 |
1002 // Get a list of the networks that we are using. | 920 // Get a list of the networks that we are using. |
1003 std::set<rtc::Network*> networks; | 921 std::set<rtc::Network*> networks; |
1004 for (uint32 i = 0; i < connections_.size(); ++i) | 922 for (uint32 i = 0; i < connections_.size(); ++i) |
1005 networks.insert(connections_[i]->port()->Network()); | 923 networks.insert(connections_[i]->port()->Network()); |
1006 | 924 |
1007 // Find the best alternative connection by sorting. It is important to note | 925 // Find the best alternative connection by sorting. It is important to note |
1008 // that amongst equal preference, writable connections, this will choose the | 926 // that amongst equal preference, writable connections, this will choose the |
1009 // one whose estimated latency is lowest. So it is the only one that we | 927 // one whose estimated latency is lowest. So it is the only one that we |
1010 // need to consider switching to. | 928 // need to consider switching to. |
1011 | 929 |
1012 ConnectionCompare cmp; | 930 ConnectionCompare cmp; |
1013 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 931 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
1014 LOG(LS_VERBOSE) << "Sorting available connections:"; | 932 LOG(LS_VERBOSE) << "Sorting available connections:"; |
1015 for (uint32 i = 0; i < connections_.size(); ++i) { | 933 for (uint32 i = 0; i < connections_.size(); ++i) { |
1016 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 934 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
1017 } | 935 } |
1018 | 936 |
1019 Connection* top_connection = NULL; | 937 Connection* top_connection = NULL; |
1020 if (connections_.size() > 0) | 938 if (connections_.size() > 0) |
1021 top_connection = connections_[0]; | 939 top_connection = connections_[0]; |
1022 | 940 |
1023 // We don't want to pick the best connections if channel is using RFC5245 | 941 // We don't want to pick the best connections if channel is |
1024 // and it's mode is CONTROLLED, as connections will be selected by the | 942 // CONTROLLED, as connections will be selected by the CONTROLLING |
1025 // CONTROLLING agent. | 943 // agent. |
1026 | 944 |
1027 // If necessary, switch to the new choice. | 945 // If necessary, switch to the new choice. |
1028 if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) { | 946 if (ice_role_ == ICEROLE_CONTROLLING) { |
1029 if (ShouldSwitch(best_connection_, top_connection)) { | 947 if (ShouldSwitch(best_connection_, top_connection)) { |
1030 LOG(LS_INFO) << "Switching best connection on controlling side: " | 948 LOG(LS_INFO) << "Switching best connection on controlling side: " |
1031 << top_connection->ToString(); | 949 << top_connection->ToString(); |
1032 SwitchBestConnectionTo(top_connection); | 950 SwitchBestConnectionTo(top_connection); |
1033 } | 951 } |
1034 } | 952 } |
1035 | 953 |
1036 // We can prune any connection for which there is a connected, writable | 954 // We can prune any connection for which there is a connected, writable |
1037 // connection on the same network with better or equal priority. We leave | 955 // connection on the same network with better or equal priority. We leave |
1038 // those with better priority just in case they become writable later (at | 956 // those with better priority just in case they become writable later (at |
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1277 // that have received a ping but have not sent a ping since receiving | 1195 // that have received a ping but have not sent a ping since receiving |
1278 // it (last_received_ping > last_sent_ping). But we shouldn't do | 1196 // it (last_received_ping > last_sent_ping). But we shouldn't do |
1279 // triggered checks if the connection is already writable. | 1197 // triggered checks if the connection is already writable. |
1280 Connection* oldest_needing_triggered_check = nullptr; | 1198 Connection* oldest_needing_triggered_check = nullptr; |
1281 Connection* oldest = nullptr; | 1199 Connection* oldest = nullptr; |
1282 for (Connection* conn : connections_) { | 1200 for (Connection* conn : connections_) { |
1283 if (!IsPingable(conn)) { | 1201 if (!IsPingable(conn)) { |
1284 continue; | 1202 continue; |
1285 } | 1203 } |
1286 bool needs_triggered_check = | 1204 bool needs_triggered_check = |
1287 (protocol_type_ == ICEPROTO_RFC5245 && | 1205 (!conn->writable() && |
1288 !conn->writable() && | |
1289 conn->last_ping_received() > conn->last_ping_sent()); | 1206 conn->last_ping_received() > conn->last_ping_sent()); |
1290 if (needs_triggered_check && | 1207 if (needs_triggered_check && |
1291 (!oldest_needing_triggered_check || | 1208 (!oldest_needing_triggered_check || |
1292 (conn->last_ping_received() < | 1209 (conn->last_ping_received() < |
1293 oldest_needing_triggered_check->last_ping_received()))) { | 1210 oldest_needing_triggered_check->last_ping_received()))) { |
1294 oldest_needing_triggered_check = conn; | 1211 oldest_needing_triggered_check = conn; |
1295 } | 1212 } |
1296 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { | 1213 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { |
1297 oldest = conn; | 1214 oldest = conn; |
1298 } | 1215 } |
(...skipping 14 matching lines...) Expand all Loading... |
1313 // a) Channel is in FULL ICE AND | 1230 // a) Channel is in FULL ICE AND |
1314 // a.1) |conn| is the best connection OR | 1231 // a.1) |conn| is the best connection OR |
1315 // a.2) there is no best connection OR | 1232 // a.2) there is no best connection OR |
1316 // a.3) the best connection is unwritable OR | 1233 // a.3) the best connection is unwritable OR |
1317 // a.4) |conn| has higher priority than best_connection. | 1234 // a.4) |conn| has higher priority than best_connection. |
1318 // b) we're doing LITE ICE AND | 1235 // b) we're doing LITE ICE AND |
1319 // b.1) |conn| is the best_connection AND | 1236 // b.1) |conn| is the best_connection AND |
1320 // b.2) |conn| is writable. | 1237 // b.2) |conn| is writable. |
1321 void P2PTransportChannel::PingConnection(Connection* conn) { | 1238 void P2PTransportChannel::PingConnection(Connection* conn) { |
1322 bool use_candidate = false; | 1239 bool use_candidate = false; |
1323 if (protocol_type_ == ICEPROTO_RFC5245) { | 1240 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
1324 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1241 use_candidate = (conn == best_connection_) || |
1325 use_candidate = (conn == best_connection_) || | 1242 (best_connection_ == NULL) || |
1326 (best_connection_ == NULL) || | 1243 (!best_connection_->writable()) || |
1327 (!best_connection_->writable()) || | 1244 (conn->priority() > best_connection_->priority()); |
1328 (conn->priority() > best_connection_->priority()); | 1245 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { |
1329 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1246 use_candidate = best_connection_->writable(); |
1330 use_candidate = best_connection_->writable(); | |
1331 } | |
1332 } | 1247 } |
1333 conn->set_use_candidate_attr(use_candidate); | 1248 conn->set_use_candidate_attr(use_candidate); |
1334 conn->Ping(rtc::Time()); | 1249 conn->Ping(rtc::Time()); |
1335 } | 1250 } |
1336 | 1251 |
1337 // When a connection's state changes, we need to figure out who to use as | 1252 // When a connection's state changes, we need to figure out who to use as |
1338 // the best connection again. It could have become usable, or become unusable. | 1253 // the best connection again. It could have become usable, or become unusable. |
1339 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1254 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
1340 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1255 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1341 | 1256 |
1342 // Update the best connection if the state change is from pending best | 1257 // Update the best connection if the state change is from pending best |
1343 // connection and role is controlled. | 1258 // connection and role is controlled. |
1344 if (protocol_type_ == ICEPROTO_RFC5245 && ice_role_ == ICEROLE_CONTROLLED) { | 1259 if (ice_role_ == ICEROLE_CONTROLLED) { |
1345 if (connection == pending_best_connection_ && connection->writable()) { | 1260 if (connection == pending_best_connection_ && connection->writable()) { |
1346 pending_best_connection_ = NULL; | 1261 pending_best_connection_ = NULL; |
1347 LOG(LS_INFO) << "Switching best connection on controlled side" | 1262 LOG(LS_INFO) << "Switching best connection on controlled side" |
1348 << " because it's now writable: " << connection->ToString(); | 1263 << " because it's now writable: " << connection->ToString(); |
1349 SwitchBestConnectionTo(connection); | 1264 SwitchBestConnectionTo(connection); |
1350 } | 1265 } |
1351 } | 1266 } |
1352 | 1267 |
1353 // We have to unroll the stack before doing this because we may be changing | 1268 // We have to unroll the stack before doing this because we may be changing |
1354 // the state of connections while sorting. | 1269 // the state of connections while sorting. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 SignalReadPacket(this, data, len, packet_time, 0); | 1334 SignalReadPacket(this, data, len, packet_time, 0); |
1420 } | 1335 } |
1421 | 1336 |
1422 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1337 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1423 if (connection == best_connection_ && writable()) { | 1338 if (connection == best_connection_ && writable()) { |
1424 SignalReadyToSend(this); | 1339 SignalReadyToSend(this); |
1425 } | 1340 } |
1426 } | 1341 } |
1427 | 1342 |
1428 } // namespace cricket | 1343 } // namespace cricket |
OLD | NEW |