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