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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 << network->ToString() | 277 << network->ToString() |
287 << " has more than 1 connection."; | 278 << " has more than 1 connection."; |
288 return TransportChannelState::STATE_CONNECTING; | 279 return TransportChannelState::STATE_CONNECTING; |
289 } | 280 } |
290 } | 281 } |
291 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; | 282 LOG_J(LS_VERBOSE, this) << "Ice is completed for this channel."; |
292 | 283 |
293 return TransportChannelState::STATE_COMPLETED; | 284 return TransportChannelState::STATE_COMPLETED; |
294 } | 285 } |
295 | 286 |
296 bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const { | |
297 *type = protocol_type_; | |
298 return true; | |
299 } | |
300 | |
301 void P2PTransportChannel::SetIceProtocolType(IceProtocolType type) { | |
302 ASSERT(worker_thread_ == rtc::Thread::Current()); | |
303 | |
304 protocol_type_ = type; | |
305 for (std::vector<PortInterface *>::iterator it = ports_.begin(); | |
306 it != ports_.end(); ++it) { | |
307 (*it)->SetIceProtocolType(protocol_type_); | |
308 } | |
309 } | |
310 | |
311 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, | 287 void P2PTransportChannel::SetIceCredentials(const std::string& ice_ufrag, |
312 const std::string& ice_pwd) { | 288 const std::string& ice_pwd) { |
313 ASSERT(worker_thread_ == rtc::Thread::Current()); | 289 ASSERT(worker_thread_ == rtc::Thread::Current()); |
314 bool ice_restart = false; | 290 bool ice_restart = false; |
315 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { | 291 if (!ice_ufrag_.empty() && !ice_pwd_.empty()) { |
316 // Restart candidate allocation if there is any change in either | 292 // Restart candidate allocation if there is any change in either |
317 // ice ufrag or password. | 293 // ice ufrag or password. |
318 ice_restart = | 294 ice_restart = |
319 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); | 295 IceCredentialsChanged(ice_ufrag_, ice_pwd_, ice_ufrag, ice_pwd); |
320 } | 296 } |
(...skipping 19 matching lines...) Expand all Loading... |
340 remote_ice_ufrag_ = ice_ufrag; | 316 remote_ice_ufrag_ = ice_ufrag; |
341 remote_ice_pwd_ = ice_pwd; | 317 remote_ice_pwd_ = ice_pwd; |
342 | 318 |
343 // We need to update the credentials for any peer reflexive candidates. | 319 // We need to update the credentials for any peer reflexive candidates. |
344 std::vector<Connection*>::iterator it = connections_.begin(); | 320 std::vector<Connection*>::iterator it = connections_.begin(); |
345 for (; it != connections_.end(); ++it) { | 321 for (; it != connections_.end(); ++it) { |
346 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); | 322 (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); |
347 } | 323 } |
348 | 324 |
349 if (ice_restart) { | 325 if (ice_restart) { |
350 // |candidate.generation()| is not signaled in ICEPROTO_RFC5245. | 326 // We need to keep track of the remote ice restart so newer |
351 // Therefore we need to keep track of the remote ice restart so | 327 // connections are prioritized over the older. |
352 // newer connections are prioritized over the older. | |
353 ++remote_candidate_generation_; | 328 ++remote_candidate_generation_; |
354 } | 329 } |
355 } | 330 } |
356 | 331 |
357 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { | 332 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |
358 remote_ice_mode_ = mode; | 333 remote_ice_mode_ = mode; |
359 } | 334 } |
360 | 335 |
361 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { | 336 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { |
362 if (receiving_timeout_ms < 0) { | 337 if (receiving_timeout_ms < 0) { |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 LOG_J(LS_WARNING, port) << "SetOption(" << it->first | 378 LOG_J(LS_WARNING, port) << "SetOption(" << it->first |
404 << ", " << it->second | 379 << ", " << it->second |
405 << ") failed: " << port->GetError(); | 380 << ") failed: " << port->GetError(); |
406 } | 381 } |
407 } | 382 } |
408 | 383 |
409 // Remember the ports and candidates, and signal that candidates are ready. | 384 // Remember the ports and candidates, and signal that candidates are ready. |
410 // The session will handle this, and send an initiate/accept/modify message | 385 // The session will handle this, and send an initiate/accept/modify message |
411 // if one is pending. | 386 // if one is pending. |
412 | 387 |
413 port->SetIceProtocolType(protocol_type_); | |
414 port->SetIceRole(ice_role_); | 388 port->SetIceRole(ice_role_); |
415 port->SetIceTiebreaker(tiebreaker_); | 389 port->SetIceTiebreaker(tiebreaker_); |
416 ports_.push_back(port); | 390 ports_.push_back(port); |
417 port->SignalUnknownAddress.connect( | 391 port->SignalUnknownAddress.connect( |
418 this, &P2PTransportChannel::OnUnknownAddress); | 392 this, &P2PTransportChannel::OnUnknownAddress); |
419 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); | 393 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); |
420 port->SignalRoleConflict.connect( | 394 port->SignalRoleConflict.connect( |
421 this, &P2PTransportChannel::OnRoleConflict); | 395 this, &P2PTransportChannel::OnRoleConflict); |
422 | 396 |
423 // Attempt to create a connection from this new port to all of the remote | 397 // 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... |
498 | 472 |
499 Candidate remote_candidate; | 473 Candidate remote_candidate; |
500 bool remote_candidate_is_new = (candidate == nullptr); | 474 bool remote_candidate_is_new = (candidate == nullptr); |
501 if (!remote_candidate_is_new) { | 475 if (!remote_candidate_is_new) { |
502 remote_candidate = *candidate; | 476 remote_candidate = *candidate; |
503 if (ufrag_per_port) { | 477 if (ufrag_per_port) { |
504 remote_candidate.set_address(address); | 478 remote_candidate.set_address(address); |
505 } | 479 } |
506 } else { | 480 } else { |
507 // Create a new candidate with this address. | 481 // Create a new candidate with this address. |
508 std::string type; | |
509 int remote_candidate_priority; | 482 int remote_candidate_priority; |
510 if (port->IceProtocol() == ICEPROTO_RFC5245) { | |
511 // RFC 5245 | |
512 // If the source transport address of the request does not match any | |
513 // existing remote candidates, it represents a new peer reflexive remote | |
514 // candidate. | |
515 type = PRFLX_PORT_TYPE; | |
516 | 483 |
517 // The priority of the candidate is set to the PRIORITY attribute | 484 // The priority of the candidate is set to the PRIORITY attribute |
518 // from the request. | 485 // from the request. |
519 const StunUInt32Attribute* priority_attr = | 486 const StunUInt32Attribute* priority_attr = |
520 stun_msg->GetUInt32(STUN_ATTR_PRIORITY); | 487 stun_msg->GetUInt32(STUN_ATTR_PRIORITY); |
521 if (!priority_attr) { | 488 if (!priority_attr) { |
522 LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - " | 489 LOG(LS_WARNING) << "P2PTransportChannel::OnUnknownAddress - " |
523 << "No STUN_ATTR_PRIORITY found in the " | 490 << "No STUN_ATTR_PRIORITY found in the " |
524 << "stun request message"; | 491 << "stun request message"; |
525 port->SendBindingErrorResponse(stun_msg, address, | 492 port->SendBindingErrorResponse(stun_msg, address, |
526 STUN_ERROR_BAD_REQUEST, | 493 STUN_ERROR_BAD_REQUEST, |
527 STUN_ERROR_REASON_BAD_REQUEST); | 494 STUN_ERROR_REASON_BAD_REQUEST); |
528 return; | 495 return; |
529 } | |
530 remote_candidate_priority = priority_attr->value(); | |
531 } else { | |
532 // G-ICE doesn't support prflx candidate. | |
533 // We set candidate type to STUN_PORT_TYPE if the binding request comes | |
534 // from a relay port or the shared socket is used. Otherwise we use the | |
535 // port's type as the candidate type. | |
536 if (port->Type() == RELAY_PORT_TYPE || port->SharedSocket()) { | |
537 type = STUN_PORT_TYPE; | |
538 } else { | |
539 type = port->Type(); | |
540 } | |
541 remote_candidate_priority = remote_candidate.GetPriority( | |
542 ICE_TYPE_PREFERENCE_PRFLX, port->Network()->preference(), 0); | |
543 } | 496 } |
| 497 remote_candidate_priority = priority_attr->value(); |
544 | 498 |
| 499 // RFC 5245 |
| 500 // If the source transport address of the request does not match any |
| 501 // existing remote candidates, it represents a new peer reflexive remote |
| 502 // candidate. |
545 remote_candidate = | 503 remote_candidate = |
546 Candidate(component(), ProtoToString(proto), address, 0, | 504 Candidate(component(), ProtoToString(proto), address, 0, |
547 remote_username, remote_password, type, 0U, ""); | 505 remote_username, remote_password, PRFLX_PORT_TYPE, 0U, ""); |
548 | 506 |
549 // From RFC 5245, section-7.2.1.3: | 507 // From RFC 5245, section-7.2.1.3: |
550 // The foundation of the candidate is set to an arbitrary value, different | 508 // The foundation of the candidate is set to an arbitrary value, different |
551 // from the foundation for all other remote candidates. | 509 // from the foundation for all other remote candidates. |
552 remote_candidate.set_foundation( | 510 remote_candidate.set_foundation( |
553 rtc::ToString<uint32>(rtc::ComputeCrc32(remote_candidate.id()))); | 511 rtc::ToString<uint32>(rtc::ComputeCrc32(remote_candidate.id()))); |
554 | 512 |
555 remote_candidate.set_priority(remote_candidate_priority); | 513 remote_candidate.set_priority(remote_candidate_priority); |
556 } | 514 } |
557 | 515 |
558 if (port->IceProtocol() == ICEPROTO_RFC5245) { | 516 // RFC5245, the agent constructs a pair whose local candidate is equal to |
559 // RFC5245, the agent constructs a pair whose local candidate is equal to | 517 // the transport address on which the STUN request was received, and a |
560 // the transport address on which the STUN request was received, and a | 518 // remote candidate equal to the source transport address where the |
561 // remote candidate equal to the source transport address where the | 519 // request came from. |
562 // request came from. | |
563 | 520 |
564 // There shouldn't be an existing connection with this remote address. | 521 // There shouldn't be an existing connection with this remote address. |
565 // When ports are muxed, this channel might get multiple unknown address | 522 // When ports are muxed, this channel might get multiple unknown address |
566 // signals. In that case if the connection is already exists, we should | 523 // signals. In that case if the connection is already exists, we should |
567 // simply ignore the signal otherwise send server error. | 524 // simply ignore the signal otherwise send server error. |
568 if (port->GetConnection(remote_candidate.address())) { | 525 if (port->GetConnection(remote_candidate.address())) { |
569 if (port_muxed) { | 526 if (port_muxed) { |
570 LOG(LS_INFO) << "Connection already exists for peer reflexive " | 527 LOG(LS_INFO) << "Connection already exists for peer reflexive " |
571 << "candidate: " << remote_candidate.ToString(); | 528 << "candidate: " << remote_candidate.ToString(); |
572 return; | 529 return; |
573 } else { | 530 } else { |
574 ASSERT(false); | |
575 port->SendBindingErrorResponse(stun_msg, address, | |
576 STUN_ERROR_SERVER_ERROR, | |
577 STUN_ERROR_REASON_SERVER_ERROR); | |
578 return; | |
579 } | |
580 } | |
581 | |
582 Connection* connection = port->CreateConnection( | |
583 remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT); | |
584 if (!connection) { | |
585 ASSERT(false); | 531 ASSERT(false); |
586 port->SendBindingErrorResponse(stun_msg, address, | 532 port->SendBindingErrorResponse(stun_msg, address, |
587 STUN_ERROR_SERVER_ERROR, | 533 STUN_ERROR_SERVER_ERROR, |
588 STUN_ERROR_REASON_SERVER_ERROR); | 534 STUN_ERROR_REASON_SERVER_ERROR); |
589 return; | 535 return; |
590 } | 536 } |
| 537 } |
591 | 538 |
592 LOG(LS_INFO) << "Adding connection from " | 539 Connection* connection = port->CreateConnection( |
593 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") | 540 remote_candidate, cricket::PortInterface::ORIGIN_THIS_PORT); |
594 << " candidate: " << remote_candidate.ToString(); | 541 if (!connection) { |
595 AddConnection(connection); | 542 ASSERT(false); |
596 connection->ReceivedPing(); | 543 port->SendBindingErrorResponse(stun_msg, address, |
| 544 STUN_ERROR_SERVER_ERROR, |
| 545 STUN_ERROR_REASON_SERVER_ERROR); |
| 546 return; |
| 547 } |
597 | 548 |
598 // Send the pinger a successful stun response. | 549 LOG(LS_INFO) << "Adding connection from " |
599 port->SendBindingResponse(stun_msg, address); | 550 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
| 551 << " candidate: " << remote_candidate.ToString(); |
| 552 AddConnection(connection); |
| 553 connection->ReceivedPing(); |
600 | 554 |
601 bool received_use_candidate = | 555 bool received_use_candidate = |
602 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr; | 556 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr; |
603 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED) { | 557 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED) { |
604 connection->set_nominated(true); | 558 connection->set_nominated(true); |
605 OnNominated(connection); | 559 OnNominated(connection); |
606 } | 560 } |
607 | 561 |
608 // Update the list of connections since we just added another. We do this | 562 // Update the list of connections since we just added another. We do this |
609 // after sending the response since it could (in principle) delete the | 563 // after sending the response since it could (in principle) delete the |
610 // connection in question. | 564 // connection in question. |
611 SortConnections(); | 565 SortConnections(); |
612 } else { | |
613 // Check for connectivity to this address. Create connections | |
614 // to this address across all local ports. First, add this as a new remote | |
615 // address | |
616 if (!CreateConnections(remote_candidate, port, true)) { | |
617 // Hopefully this won't occur, because changing a destination address | |
618 // shouldn't cause a new connection to fail | |
619 ASSERT(false); | |
620 port->SendBindingErrorResponse(stun_msg, address, STUN_ERROR_SERVER_ERROR, | |
621 STUN_ERROR_REASON_SERVER_ERROR); | |
622 return; | |
623 } | |
624 | |
625 // Send the pinger a successful stun response. | |
626 port->SendBindingResponse(stun_msg, address); | |
627 | |
628 // Update the list of connections since we just added another. We do this | |
629 // after sending the response since it could (in principle) delete the | |
630 // connection in question. | |
631 SortConnections(); | |
632 } | |
633 } | 566 } |
634 | 567 |
635 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { | 568 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { |
636 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called | 569 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called |
637 // from Transport. | 570 // from Transport. |
638 } | 571 } |
639 | 572 |
640 // When the signalling channel is ready, we can really kick off the allocator | 573 // When the signalling channel is ready, we can really kick off the allocator |
641 void P2PTransportChannel::OnSignalingReady() { | 574 void P2PTransportChannel::OnSignalingReady() { |
642 ASSERT(worker_thread_ == rtc::Thread::Current()); | 575 ASSERT(worker_thread_ == rtc::Thread::Current()); |
643 if (waiting_for_signaling_) { | 576 if (waiting_for_signaling_) { |
644 waiting_for_signaling_ = false; | 577 waiting_for_signaling_ = false; |
645 AddAllocatorSession(allocator_->CreateSession( | 578 AddAllocatorSession(allocator_->CreateSession( |
646 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); | 579 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); |
647 } | 580 } |
648 } | 581 } |
649 | 582 |
650 void P2PTransportChannel::OnNominated(Connection* conn) { | 583 void P2PTransportChannel::OnNominated(Connection* conn) { |
651 ASSERT(worker_thread_ == rtc::Thread::Current()); | 584 ASSERT(worker_thread_ == rtc::Thread::Current()); |
652 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 585 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
653 ASSERT(protocol_type_ == ICEPROTO_RFC5245); | |
654 | 586 |
655 if (conn->write_state() == Connection::STATE_WRITABLE) { | 587 if (conn->write_state() == Connection::STATE_WRITABLE) { |
656 if (best_connection_ != conn) { | 588 if (best_connection_ != conn) { |
657 pending_best_connection_ = NULL; | 589 pending_best_connection_ = NULL; |
658 LOG(LS_INFO) << "Switching best connection on controlled side: " | 590 LOG(LS_INFO) << "Switching best connection on controlled side: " |
659 << conn->ToString(); | 591 << conn->ToString(); |
660 SwitchBestConnectionTo(conn); | 592 SwitchBestConnectionTo(conn); |
661 // Now we have selected the best connection, time to prune other existing | 593 // Now we have selected the best connection, time to prune other existing |
662 // connections and update the read/write state of the channel. | 594 // connections and update the read/write state of the channel. |
663 RequestSort(); | 595 RequestSort(); |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 | 734 |
803 bool P2PTransportChannel::FindConnection( | 735 bool P2PTransportChannel::FindConnection( |
804 cricket::Connection* connection) const { | 736 cricket::Connection* connection) const { |
805 std::vector<Connection*>::const_iterator citer = | 737 std::vector<Connection*>::const_iterator citer = |
806 std::find(connections_.begin(), connections_.end(), connection); | 738 std::find(connections_.begin(), connections_.end(), connection); |
807 return citer != connections_.end(); | 739 return citer != connections_.end(); |
808 } | 740 } |
809 | 741 |
810 uint32 P2PTransportChannel::GetRemoteCandidateGeneration( | 742 uint32 P2PTransportChannel::GetRemoteCandidateGeneration( |
811 const Candidate& candidate) { | 743 const Candidate& candidate) { |
812 if (protocol_type_ == ICEPROTO_GOOGLE) { | 744 // We need to keep track of the remote ice restart so newer |
813 // The Candidate.generation() can be trusted. Nothing needs to be done. | 745 // connections are prioritized over the older. |
814 return candidate.generation(); | |
815 } | |
816 // |candidate.generation()| is not signaled in ICEPROTO_RFC5245. | |
817 // Therefore we need to keep track of the remote ice restart so | |
818 // newer connections are prioritized over the older. | |
819 ASSERT(candidate.generation() == 0 || | 746 ASSERT(candidate.generation() == 0 || |
820 candidate.generation() == remote_candidate_generation_); | 747 candidate.generation() == remote_candidate_generation_); |
821 return remote_candidate_generation_; | 748 return remote_candidate_generation_; |
822 } | 749 } |
823 | 750 |
824 // Check if remote candidate is already cached. | 751 // Check if remote candidate is already cached. |
825 bool P2PTransportChannel::IsDuplicateRemoteCandidate( | 752 bool P2PTransportChannel::IsDuplicateRemoteCandidate( |
826 const Candidate& candidate) { | 753 const Candidate& candidate) { |
827 for (uint32 i = 0; i < remote_candidates_.size(); ++i) { | 754 for (uint32 i = 0; i < remote_candidates_.size(); ++i) { |
828 if (remote_candidates_[i].IsEquivalent(candidate)) { | 755 if (remote_candidates_[i].IsEquivalent(candidate)) { |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
986 | 913 |
987 // Sort the available connections to find the best one. We also monitor | 914 // Sort the available connections to find the best one. We also monitor |
988 // the number of available connections and the current state. | 915 // the number of available connections and the current state. |
989 void P2PTransportChannel::SortConnections() { | 916 void P2PTransportChannel::SortConnections() { |
990 ASSERT(worker_thread_ == rtc::Thread::Current()); | 917 ASSERT(worker_thread_ == rtc::Thread::Current()); |
991 | 918 |
992 // Make sure the connection states are up-to-date since this affects how they | 919 // Make sure the connection states are up-to-date since this affects how they |
993 // will be sorted. | 920 // will be sorted. |
994 UpdateConnectionStates(); | 921 UpdateConnectionStates(); |
995 | 922 |
996 if (protocol_type_ == ICEPROTO_HYBRID) { | |
997 // If we are in hybrid mode, we are not sending any ping requests, so there | |
998 // is no point in sorting the connections. In hybrid state, ports can have | |
999 // different protocol than hybrid and protocol may differ from one another. | |
1000 // Instead just update the state of this channel | |
1001 UpdateChannelState(); | |
1002 return; | |
1003 } | |
1004 | |
1005 // Any changes after this point will require a re-sort. | 923 // Any changes after this point will require a re-sort. |
1006 sort_dirty_ = false; | 924 sort_dirty_ = false; |
1007 | 925 |
1008 // Find the best alternative connection by sorting. It is important to note | 926 // Find the best alternative connection by sorting. It is important to note |
1009 // that amongst equal preference, writable connections, this will choose the | 927 // that amongst equal preference, writable connections, this will choose the |
1010 // one whose estimated latency is lowest. So it is the only one that we | 928 // one whose estimated latency is lowest. So it is the only one that we |
1011 // need to consider switching to. | 929 // need to consider switching to. |
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 = | 937 Connection* top_connection = |
1020 (connections_.size() > 0) ? connections_[0] : nullptr; | 938 (connections_.size() > 0) ? connections_[0] : nullptr; |
1021 | 939 |
1022 // If necessary, switch to the new choice. | 940 // If necessary, switch to the new choice. |
1023 // Note that |top_connection| doesn't have to be writable to become the best | 941 // Note that |top_connection| doesn't have to be writable to become the best |
1024 // connection although it will have higher priority if it is writable. | 942 // connection although it will have higher priority if it is writable. |
1025 // The controlled side can switch the best connection only if the current | 943 // The controlled side can switch the best connection only if the current |
1026 // |best connection_| has not been nominated by the controlling side yet. | 944 // |best connection_| has not been nominated by the controlling side yet. |
1027 | 945 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) && |
1028 // We don't want to pick the best connections if channel is using RFC5245. | |
1029 if ((protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING || | |
1030 !best_nominated_connection()) && | |
1031 ShouldSwitch(best_connection_, top_connection)) { | 946 ShouldSwitch(best_connection_, top_connection)) { |
1032 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 947 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); |
1033 SwitchBestConnectionTo(top_connection); | 948 SwitchBestConnectionTo(top_connection); |
1034 } | 949 } |
1035 | 950 |
1036 // Controlled side can prune only if the best connection has been nominated. | 951 // Controlled side can prune only if the best connection has been nominated. |
1037 // because otherwise it may delete the connection that will be selected by | 952 // because otherwise it may delete the connection that will be selected by |
1038 // the controlling side. | 953 // the controlling side. |
1039 if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING || | 954 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
1040 best_nominated_connection()) { | |
1041 PruneConnections(); | 955 PruneConnections(); |
1042 } | 956 } |
1043 | 957 |
1044 // Check if all connections are timedout. | 958 // Check if all connections are timedout. |
1045 bool all_connections_timedout = true; | 959 bool all_connections_timedout = true; |
1046 for (uint32 i = 0; i < connections_.size(); ++i) { | 960 for (uint32 i = 0; i < connections_.size(); ++i) { |
1047 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 961 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
1048 all_connections_timedout = false; | 962 all_connections_timedout = false; |
1049 break; | 963 break; |
1050 } | 964 } |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1295 // that have received a ping but have not sent a ping since receiving | 1209 // that have received a ping but have not sent a ping since receiving |
1296 // it (last_received_ping > last_sent_ping). But we shouldn't do | 1210 // it (last_received_ping > last_sent_ping). But we shouldn't do |
1297 // triggered checks if the connection is already writable. | 1211 // triggered checks if the connection is already writable. |
1298 Connection* oldest_needing_triggered_check = nullptr; | 1212 Connection* oldest_needing_triggered_check = nullptr; |
1299 Connection* oldest = nullptr; | 1213 Connection* oldest = nullptr; |
1300 for (Connection* conn : connections_) { | 1214 for (Connection* conn : connections_) { |
1301 if (!IsPingable(conn)) { | 1215 if (!IsPingable(conn)) { |
1302 continue; | 1216 continue; |
1303 } | 1217 } |
1304 bool needs_triggered_check = | 1218 bool needs_triggered_check = |
1305 (protocol_type_ == ICEPROTO_RFC5245 && | 1219 (!conn->writable() && |
1306 !conn->writable() && | |
1307 conn->last_ping_received() > conn->last_ping_sent()); | 1220 conn->last_ping_received() > conn->last_ping_sent()); |
1308 if (needs_triggered_check && | 1221 if (needs_triggered_check && |
1309 (!oldest_needing_triggered_check || | 1222 (!oldest_needing_triggered_check || |
1310 (conn->last_ping_received() < | 1223 (conn->last_ping_received() < |
1311 oldest_needing_triggered_check->last_ping_received()))) { | 1224 oldest_needing_triggered_check->last_ping_received()))) { |
1312 oldest_needing_triggered_check = conn; | 1225 oldest_needing_triggered_check = conn; |
1313 } | 1226 } |
1314 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { | 1227 if (!oldest || (conn->last_ping_sent() < oldest->last_ping_sent())) { |
1315 oldest = conn; | 1228 oldest = conn; |
1316 } | 1229 } |
(...skipping 14 matching lines...) Expand all Loading... |
1331 // a) Channel is in FULL ICE AND | 1244 // a) Channel is in FULL ICE AND |
1332 // a.1) |conn| is the best connection OR | 1245 // a.1) |conn| is the best connection OR |
1333 // a.2) there is no best connection OR | 1246 // a.2) there is no best connection OR |
1334 // a.3) the best connection is unwritable OR | 1247 // a.3) the best connection is unwritable OR |
1335 // a.4) |conn| has higher priority than best_connection. | 1248 // a.4) |conn| has higher priority than best_connection. |
1336 // b) we're doing LITE ICE AND | 1249 // b) we're doing LITE ICE AND |
1337 // b.1) |conn| is the best_connection AND | 1250 // b.1) |conn| is the best_connection AND |
1338 // b.2) |conn| is writable. | 1251 // b.2) |conn| is writable. |
1339 void P2PTransportChannel::PingConnection(Connection* conn) { | 1252 void P2PTransportChannel::PingConnection(Connection* conn) { |
1340 bool use_candidate = false; | 1253 bool use_candidate = false; |
1341 if (protocol_type_ == ICEPROTO_RFC5245) { | 1254 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
1342 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1255 use_candidate = (conn == best_connection_) || |
1343 use_candidate = (conn == best_connection_) || | 1256 (best_connection_ == NULL) || |
1344 (best_connection_ == NULL) || | 1257 (!best_connection_->writable()) || |
1345 (!best_connection_->writable()) || | 1258 (conn->priority() > best_connection_->priority()); |
1346 (conn->priority() > best_connection_->priority()); | 1259 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { |
1347 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1260 use_candidate = best_connection_->writable(); |
1348 use_candidate = best_connection_->writable(); | |
1349 } | |
1350 } | 1261 } |
1351 conn->set_use_candidate_attr(use_candidate); | 1262 conn->set_use_candidate_attr(use_candidate); |
1352 conn->Ping(rtc::Time()); | 1263 conn->Ping(rtc::Time()); |
1353 } | 1264 } |
1354 | 1265 |
1355 // When a connection's state changes, we need to figure out who to use as | 1266 // When a connection's state changes, we need to figure out who to use as |
1356 // the best connection again. It could have become usable, or become unusable. | 1267 // the best connection again. It could have become usable, or become unusable. |
1357 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1268 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
1358 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1269 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1359 | 1270 |
1360 // Update the best connection if the state change is from pending best | 1271 // Update the best connection if the state change is from pending best |
1361 // connection and role is controlled. | 1272 // connection and role is controlled. |
1362 if (protocol_type_ == ICEPROTO_RFC5245 && ice_role_ == ICEROLE_CONTROLLED) { | 1273 if (ice_role_ == ICEROLE_CONTROLLED) { |
1363 if (connection == pending_best_connection_ && connection->writable()) { | 1274 if (connection == pending_best_connection_ && connection->writable()) { |
1364 pending_best_connection_ = NULL; | 1275 pending_best_connection_ = NULL; |
1365 LOG(LS_INFO) << "Switching best connection on controlled side" | 1276 LOG(LS_INFO) << "Switching best connection on controlled side" |
1366 << " because it's now writable: " << connection->ToString(); | 1277 << " because it's now writable: " << connection->ToString(); |
1367 SwitchBestConnectionTo(connection); | 1278 SwitchBestConnectionTo(connection); |
1368 } | 1279 } |
1369 } | 1280 } |
1370 | 1281 |
1371 // We have to unroll the stack before doing this because we may be changing | 1282 // We have to unroll the stack before doing this because we may be changing |
1372 // the state of connections while sorting. | 1283 // the state of connections while sorting. |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1444 } | 1355 } |
1445 } | 1356 } |
1446 | 1357 |
1447 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1448 if (connection == best_connection_ && writable()) { | 1359 if (connection == best_connection_ && writable()) { |
1449 SignalReadyToSend(this); | 1360 SignalReadyToSend(this); |
1450 } | 1361 } |
1451 } | 1362 } |
1452 | 1363 |
1453 } // namespace cricket | 1364 } // namespace cricket |
OLD | NEW |