| 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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   211       allocator_(allocator), |   211       allocator_(allocator), | 
|   212       worker_thread_(rtc::Thread::Current()), |   212       worker_thread_(rtc::Thread::Current()), | 
|   213       incoming_only_(false), |   213       incoming_only_(false), | 
|   214       error_(0), |   214       error_(0), | 
|   215       best_connection_(NULL), |   215       best_connection_(NULL), | 
|   216       pending_best_connection_(NULL), |   216       pending_best_connection_(NULL), | 
|   217       sort_dirty_(false), |   217       sort_dirty_(false), | 
|   218       remote_ice_mode_(ICEMODE_FULL), |   218       remote_ice_mode_(ICEMODE_FULL), | 
|   219       ice_role_(ICEROLE_UNKNOWN), |   219       ice_role_(ICEROLE_UNKNOWN), | 
|   220       tiebreaker_(0), |   220       tiebreaker_(0), | 
|   221       remote_candidate_generation_(0), |  | 
|   222       gathering_state_(kIceGatheringNew), |   221       gathering_state_(kIceGatheringNew), | 
|   223       check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |   222       check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 
|   224       receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), |   223       receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50), | 
|   225       backup_connection_ping_interval_(0) { |   224       backup_connection_ping_interval_(0) { | 
|   226   uint32_t weak_ping_delay = ::strtoul( |   225   uint32_t weak_ping_delay = ::strtoul( | 
|   227       webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |   226       webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 
|   228       nullptr, 10); |   227       nullptr, 10); | 
|   229   if (weak_ping_delay) { |   228   if (weak_ping_delay) { | 
|   230     weak_ping_delay_ =  weak_ping_delay; |   229     weak_ping_delay_ =  weak_ping_delay; | 
|   231   } |   230   } | 
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   340   ASSERT(worker_thread_ == rtc::Thread::Current()); |   339   ASSERT(worker_thread_ == rtc::Thread::Current()); | 
|   341   ice_ufrag_ = ice_ufrag; |   340   ice_ufrag_ = ice_ufrag; | 
|   342   ice_pwd_ = ice_pwd; |   341   ice_pwd_ = ice_pwd; | 
|   343   // Note: Candidate gathering will restart when MaybeStartGathering is next |   342   // Note: Candidate gathering will restart when MaybeStartGathering is next | 
|   344   // called. |   343   // called. | 
|   345 } |   344 } | 
|   346  |   345  | 
|   347 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag, |   346 void P2PTransportChannel::SetRemoteIceCredentials(const std::string& ice_ufrag, | 
|   348                                                   const std::string& ice_pwd) { |   347                                                   const std::string& ice_pwd) { | 
|   349   ASSERT(worker_thread_ == rtc::Thread::Current()); |   348   ASSERT(worker_thread_ == rtc::Thread::Current()); | 
|   350   bool ice_restart = false; |   349   IceParameters* current_ice = remote_ice(); | 
|   351   if (!remote_ice_ufrag_.empty() && !remote_ice_pwd_.empty()) { |   350   IceParameters new_ice(ice_ufrag, ice_pwd); | 
|   352     ice_restart = (remote_ice_ufrag_ != ice_ufrag) || |   351   if (!current_ice || *current_ice != new_ice) { | 
|   353                   (remote_ice_pwd_!= ice_pwd); |   352     // Keep the ICE credentials so that newer connections | 
 |   353     // are prioritized over the older ones. | 
 |   354     remote_ice_parameters_.push_back(new_ice); | 
|   354   } |   355   } | 
|   355  |   356  | 
|   356   remote_ice_ufrag_ = ice_ufrag; |  | 
|   357   remote_ice_pwd_ = ice_pwd; |  | 
|   358  |  | 
|   359   // We need to update the credentials for any peer reflexive candidates. |   357   // We need to update the credentials for any peer reflexive candidates. | 
|   360   std::vector<Connection*>::iterator it = connections_.begin(); |   358   std::vector<Connection*>::iterator it = connections_.begin(); | 
|   361   for (; it != connections_.end(); ++it) { |   359   for (; it != connections_.end(); ++it) { | 
|   362     (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); |   360     (*it)->MaybeSetRemoteIceCredentials(ice_ufrag, ice_pwd); | 
|   363   } |   361   } | 
|   364  |  | 
|   365   if (ice_restart) { |  | 
|   366     // We need to keep track of the remote ice restart so newer |  | 
|   367     // connections are prioritized over the older. |  | 
|   368     ++remote_candidate_generation_; |  | 
|   369   } |  | 
|   370 } |   362 } | 
|   371  |   363  | 
|   372 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |   364 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { | 
|   373   remote_ice_mode_ = mode; |   365   remote_ice_mode_ = mode; | 
|   374 } |   366 } | 
|   375  |   367  | 
|   376 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { |   368 void P2PTransportChannel::SetIceConfig(const IceConfig& config) { | 
|   377   gather_continually_ = config.gather_continually; |   369   gather_continually_ = config.gather_continually; | 
|   378   LOG(LS_INFO) << "Set gather_continually to " << gather_continually_; |   370   LOG(LS_INFO) << "Set gather_continually to " << gather_continually_; | 
|   379  |   371  | 
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   529         break; |   521         break; | 
|   530       } |   522       } | 
|   531       // We don't want to break here because we may find a match of the address |   523       // We don't want to break here because we may find a match of the address | 
|   532       // later. |   524       // later. | 
|   533     } |   525     } | 
|   534   } |   526   } | 
|   535  |   527  | 
|   536   // The STUN binding request may arrive after setRemoteDescription and before |   528   // The STUN binding request may arrive after setRemoteDescription and before | 
|   537   // adding remote candidate, so we need to set the password to the shared |   529   // adding remote candidate, so we need to set the password to the shared | 
|   538   // password if the user name matches. |   530   // password if the user name matches. | 
|   539   if (remote_password.empty() && remote_username == remote_ice_ufrag_) { |   531   if (remote_password.empty()) { | 
|   540     remote_password = remote_ice_pwd_; |   532     IceParameters* current_ice = remote_ice(); | 
 |   533     if (current_ice && remote_username == current_ice->ufrag) { | 
 |   534       remote_password = current_ice->pwd; | 
 |   535     } | 
|   541   } |   536   } | 
|   542  |   537  | 
|   543   Candidate remote_candidate; |   538   Candidate remote_candidate; | 
|   544   bool remote_candidate_is_new = (candidate == nullptr); |   539   bool remote_candidate_is_new = (candidate == nullptr); | 
|   545   if (!remote_candidate_is_new) { |   540   if (!remote_candidate_is_new) { | 
|   546     remote_candidate = *candidate; |   541     remote_candidate = *candidate; | 
|   547     if (ufrag_per_port) { |   542     if (ufrag_per_port) { | 
|   548       remote_candidate.set_address(address); |   543       remote_candidate.set_address(address); | 
|   549     } |   544     } | 
|   550   } else { |   545   } else { | 
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   648   } else { |   643   } else { | 
|   649     LOG(LS_INFO) << "Not switching the best connection on controlled side yet," |   644     LOG(LS_INFO) << "Not switching the best connection on controlled side yet," | 
|   650                  << " because it's not writable: " << conn->ToString(); |   645                  << " because it's not writable: " << conn->ToString(); | 
|   651     pending_best_connection_ = conn; |   646     pending_best_connection_ = conn; | 
|   652   } |   647   } | 
|   653 } |   648 } | 
|   654  |   649  | 
|   655 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |   650 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 
|   656   ASSERT(worker_thread_ == rtc::Thread::Current()); |   651   ASSERT(worker_thread_ == rtc::Thread::Current()); | 
|   657  |   652  | 
|   658   uint32_t generation = candidate.generation(); |   653   uint32_t generation = GetRemoteCandidateGeneration(candidate); | 
|   659   // Network may not guarantee the order of the candidate delivery. If a |   654   // If a remote candidate with a previous generation arrives, drop it. | 
|   660   // remote candidate with an older generation arrives, drop it. |   655   if (generation < remote_ice_generation()) { | 
|   661   if (generation != 0 && generation < remote_candidate_generation_) { |   656     LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 
|   662     LOG(LS_WARNING) << "Dropping a remote candidate because its generation " |   657                     << candidate.username() | 
|   663                     << generation |   658                     << " indicates it was for a previous generation."; | 
|   664                     << " is lower than the current remote generation " |  | 
|   665                     << remote_candidate_generation_; |  | 
|   666     return; |   659     return; | 
|   667   } |   660   } | 
|   668  |   661  | 
 |   662   Candidate new_remote_candidate(candidate); | 
 |   663   new_remote_candidate.set_generation(generation); | 
 |   664   // ICE candidates don't need to have username and password set, but | 
 |   665   // the code below this (specifically, ConnectionRequest::Prepare in | 
 |   666   // port.cc) uses the remote candidates's username.  So, we set it | 
 |   667   // here. | 
 |   668   if (remote_ice()) { | 
 |   669     if (candidate.username().empty()) { | 
 |   670       new_remote_candidate.set_username(remote_ice()->ufrag); | 
 |   671     } | 
 |   672     if (new_remote_candidate.username() == remote_ice()->ufrag) { | 
 |   673       if (candidate.password().empty()) { | 
 |   674         new_remote_candidate.set_password(remote_ice()->pwd); | 
 |   675       } | 
 |   676     } else { | 
 |   677       // The candidate belongs to the next generation. Its pwd will be set | 
 |   678       // when the new remote ICE credentials arrive. | 
 |   679       LOG(LS_WARNING) << "A remote candidate arrives with an unknown ufrag: " | 
 |   680                       << candidate.username(); | 
 |   681     } | 
 |   682   } | 
 |   683  | 
|   669   // Create connections to this remote candidate. |   684   // Create connections to this remote candidate. | 
|   670   CreateConnections(candidate, NULL); |   685   CreateConnections(new_remote_candidate, NULL); | 
|   671  |   686  | 
|   672   // Resort the connections list, which may have new elements. |   687   // Resort the connections list, which may have new elements. | 
|   673   SortConnections(); |   688   SortConnections(); | 
|   674 } |   689 } | 
|   675  |   690  | 
|   676 // Creates connections from all of the ports that we care about to the given |   691 // Creates connections from all of the ports that we care about to the given | 
|   677 // remote candidate.  The return value is true if we created a connection from |   692 // remote candidate.  The return value is true if we created a connection from | 
|   678 // the origin port. |   693 // the origin port. | 
|   679 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, |   694 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, | 
|   680                                             PortInterface* origin_port) { |   695                                             PortInterface* origin_port) { | 
|   681   ASSERT(worker_thread_ == rtc::Thread::Current()); |   696   ASSERT(worker_thread_ == rtc::Thread::Current()); | 
|   682  |   697  | 
|   683   Candidate new_remote_candidate(remote_candidate); |  | 
|   684   new_remote_candidate.set_generation( |  | 
|   685       GetRemoteCandidateGeneration(remote_candidate)); |  | 
|   686   // ICE candidates don't need to have username and password set, but |  | 
|   687   // the code below this (specifically, ConnectionRequest::Prepare in |  | 
|   688   // port.cc) uses the remote candidates's username.  So, we set it |  | 
|   689   // here. |  | 
|   690   if (remote_candidate.username().empty()) { |  | 
|   691     new_remote_candidate.set_username(remote_ice_ufrag_); |  | 
|   692   } |  | 
|   693   if (remote_candidate.password().empty()) { |  | 
|   694     new_remote_candidate.set_password(remote_ice_pwd_); |  | 
|   695   } |  | 
|   696  |  | 
|   697   // If we've already seen the new remote candidate (in the current candidate |   698   // If we've already seen the new remote candidate (in the current candidate | 
|   698   // generation), then we shouldn't try creating connections for it. |   699   // generation), then we shouldn't try creating connections for it. | 
|   699   // We either already have a connection for it, or we previously created one |   700   // We either already have a connection for it, or we previously created one | 
|   700   // and then later pruned it. If we don't return, the channel will again |   701   // and then later pruned it. If we don't return, the channel will again | 
|   701   // re-create any connections that were previously pruned, which will then |   702   // re-create any connections that were previously pruned, which will then | 
|   702   // immediately be re-pruned, churning the network for no purpose. |   703   // immediately be re-pruned, churning the network for no purpose. | 
|   703   // This only applies to candidates received over signaling (i.e. origin_port |   704   // This only applies to candidates received over signaling (i.e. origin_port | 
|   704   // is NULL). |   705   // is NULL). | 
|   705   if (!origin_port && IsDuplicateRemoteCandidate(new_remote_candidate)) { |   706   if (!origin_port && IsDuplicateRemoteCandidate(remote_candidate)) { | 
|   706     // return true to indicate success, without creating any new connections. |   707     // return true to indicate success, without creating any new connections. | 
|   707     return true; |   708     return true; | 
|   708   } |   709   } | 
|   709  |   710  | 
|   710   // Add a new connection for this candidate to every port that allows such a |   711   // Add a new connection for this candidate to every port that allows such a | 
|   711   // connection (i.e., if they have compatible protocols) and that does not |   712   // connection (i.e., if they have compatible protocols) and that does not | 
|   712   // already have a connection to an equivalent candidate.  We must be careful |   713   // already have a connection to an equivalent candidate.  We must be careful | 
|   713   // to make sure that the origin port is included, even if it was pruned, |   714   // to make sure that the origin port is included, even if it was pruned, | 
|   714   // since that may be the only port that can create this connection. |   715   // since that may be the only port that can create this connection. | 
|   715   bool created = false; |   716   bool created = false; | 
|   716   std::vector<PortInterface *>::reverse_iterator it; |   717   std::vector<PortInterface *>::reverse_iterator it; | 
|   717   for (it = ports_.rbegin(); it != ports_.rend(); ++it) { |   718   for (it = ports_.rbegin(); it != ports_.rend(); ++it) { | 
|   718     if (CreateConnection(*it, new_remote_candidate, origin_port)) { |   719     if (CreateConnection(*it, remote_candidate, origin_port)) { | 
|   719       if (*it == origin_port) |   720       if (*it == origin_port) | 
|   720         created = true; |   721         created = true; | 
|   721     } |   722     } | 
|   722   } |   723   } | 
|   723  |   724  | 
|   724   if ((origin_port != NULL) && |   725   if ((origin_port != NULL) && | 
|   725       std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { |   726       std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { | 
|   726     if (CreateConnection(origin_port, new_remote_candidate, origin_port)) |   727     if (CreateConnection(origin_port, remote_candidate, origin_port)) | 
|   727       created = true; |   728       created = true; | 
|   728   } |   729   } | 
|   729  |   730  | 
|   730   // Remember this remote candidate so that we can add it to future ports. |   731   // Remember this remote candidate so that we can add it to future ports. | 
|   731   RememberRemoteCandidate(new_remote_candidate, origin_port); |   732   RememberRemoteCandidate(remote_candidate, origin_port); | 
|   732  |   733  | 
|   733   return created; |   734   return created; | 
|   734 } |   735 } | 
|   735  |   736  | 
|   736 // Setup a connection object for the local and remote candidate combination. |   737 // Setup a connection object for the local and remote candidate combination. | 
|   737 // And then listen to connection object for changes. |   738 // And then listen to connection object for changes. | 
|   738 bool P2PTransportChannel::CreateConnection(PortInterface* port, |   739 bool P2PTransportChannel::CreateConnection(PortInterface* port, | 
|   739                                            const Candidate& remote_candidate, |   740                                            const Candidate& remote_candidate, | 
|   740                                            PortInterface* origin_port) { |   741                                            PortInterface* origin_port) { | 
|   741   // Look for an existing connection with this remote address.  If one is not |   742   // Look for an existing connection with this remote address.  If one is not | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   779     cricket::Connection* connection) const { |   780     cricket::Connection* connection) const { | 
|   780   std::vector<Connection*>::const_iterator citer = |   781   std::vector<Connection*>::const_iterator citer = | 
|   781       std::find(connections_.begin(), connections_.end(), connection); |   782       std::find(connections_.begin(), connections_.end(), connection); | 
|   782   return citer != connections_.end(); |   783   return citer != connections_.end(); | 
|   783 } |   784 } | 
|   784  |   785  | 
|   785 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration( |   786 uint32_t P2PTransportChannel::GetRemoteCandidateGeneration( | 
|   786     const Candidate& candidate) { |   787     const Candidate& candidate) { | 
|   787   // We need to keep track of the remote ice restart so newer |   788   // We need to keep track of the remote ice restart so newer | 
|   788   // connections are prioritized over the older. |   789   // connections are prioritized over the older. | 
|   789   ASSERT(candidate.generation() == 0 || |   790   const auto& params = remote_ice_parameters_; | 
|   790          candidate.generation() == remote_candidate_generation_); |   791   if (!candidate.username().empty()) { | 
|   791   return remote_candidate_generation_; |   792     // If remote side sets the ufrag, we use that to determine the candidate | 
 |   793     // generation. | 
 |   794     // Search backward as it is more likely to find it near the end. | 
 |   795     auto it = std::find_if(params.rbegin(), params.rend(), | 
 |   796                            [candidate](const IceParameters& param) { | 
 |   797                              return param.ufrag == candidate.username(); | 
 |   798                            }); | 
 |   799     if (it == params.rend()) { | 
 |   800       // If not found, assume it is the next (future) generation. | 
 |   801       return static_cast<uint32_t>(remote_ice_parameters_.size()); | 
 |   802     } | 
 |   803     return params.rend() - it - 1; | 
 |   804   } | 
 |   805   // If candidate generation is set, use that. | 
 |   806   if (candidate.generation() > 0) { | 
 |   807     return candidate.generation(); | 
 |   808   } | 
 |   809   // Otherwise, assume the generation from remote ice parameters. | 
 |   810   return remote_ice_generation(); | 
|   792 } |   811 } | 
|   793  |   812  | 
|   794 // Check if remote candidate is already cached. |   813 // Check if remote candidate is already cached. | 
|   795 bool P2PTransportChannel::IsDuplicateRemoteCandidate( |   814 bool P2PTransportChannel::IsDuplicateRemoteCandidate( | 
|   796     const Candidate& candidate) { |   815     const Candidate& candidate) { | 
|   797   for (size_t i = 0; i < remote_candidates_.size(); ++i) { |   816   for (size_t i = 0; i < remote_candidates_.size(); ++i) { | 
|   798     if (remote_candidates_[i].IsEquivalent(candidate)) { |   817     if (remote_candidates_[i].IsEquivalent(candidate)) { | 
|   799       return true; |   818       return true; | 
|   800     } |   819     } | 
|   801   } |   820   } | 
| (...skipping 592 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1394   SignalSentPacket(this, sent_packet); |  1413   SignalSentPacket(this, sent_packet); | 
|  1395 } |  1414 } | 
|  1396  |  1415  | 
|  1397 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |  1416 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 
|  1398   if (connection == best_connection_ && writable()) { |  1417   if (connection == best_connection_ && writable()) { | 
|  1399     SignalReadyToSend(this); |  1418     SignalReadyToSend(this); | 
|  1400   } |  1419   } | 
|  1401 } |  1420 } | 
|  1402  |  1421  | 
|  1403 }  // namespace cricket |  1422 }  // namespace cricket | 
| OLD | NEW |