diff options
Diffstat (limited to 'chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc')
-rw-r--r-- | chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc index 38cc35445ea..887fc45efae 100644 --- a/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc +++ b/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc @@ -167,7 +167,7 @@ P2PTransportChannel::P2PTransportChannel(const std::string& content_name, pending_best_connection_(NULL), sort_dirty_(false), was_writable_(false), - protocol_type_(ICEPROTO_GOOGLE), + protocol_type_(ICEPROTO_HYBRID), remote_ice_mode_(ICEMODE_FULL), ice_role_(ICEROLE_UNKNOWN), tiebreaker_(0), @@ -237,6 +237,11 @@ void P2PTransportChannel::SetIceTiebreaker(uint64 tiebreaker) { tiebreaker_ = tiebreaker; } +bool P2PTransportChannel::GetIceProtocolType(IceProtocolType* type) const { + *type = protocol_type_; + return true; +} + void P2PTransportChannel::SetIceProtocolType(IceProtocolType type) { ASSERT(worker_thread_ == talk_base::Thread::Current()); @@ -465,9 +470,8 @@ void P2PTransportChannel::OnUnknownAddress( } } else { // Create a new candidate with this address. - std::string type; - if (protocol_type_ == ICEPROTO_RFC5245) { + if (port->IceProtocol() == ICEPROTO_RFC5245) { type = PRFLX_PORT_TYPE; } else { // G-ICE doesn't support prflx candidate. @@ -488,10 +492,11 @@ void P2PTransportChannel::OnUnknownAddress( port->Network()->name(), 0U, talk_base::ToString<uint32>(talk_base::ComputeCrc32(id))); new_remote_candidate.set_priority( - new_remote_candidate.GetPriority(ICE_TYPE_PREFERENCE_SRFLX)); + new_remote_candidate.GetPriority(ICE_TYPE_PREFERENCE_SRFLX, + port->Network()->preference())); } - if (protocol_type_ == ICEPROTO_RFC5245) { + if (port->IceProtocol() == ICEPROTO_RFC5245) { // RFC 5245 // If the source transport address of the request does not match any // existing remote candidates, it represents a new peer reflexive remote @@ -623,7 +628,7 @@ void P2PTransportChannel::OnCandidate(const Candidate& candidate) { // Creates connections from all of the ports that we care about to the given // remote candidate. The return value is true if we created a connection from // the origin port. -bool P2PTransportChannel::CreateConnections(const Candidate &remote_candidate, +bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, PortInterface* origin_port, bool readable) { ASSERT(worker_thread_ == talk_base::Thread::Current()); @@ -642,14 +647,25 @@ bool P2PTransportChannel::CreateConnections(const Candidate &remote_candidate, new_remote_candidate.set_password(remote_ice_pwd_); } + // If we've already seen the new remote candidate (in the current candidate + // generation), then we shouldn't try creating connections for it. + // We either already have a connection for it, or we previously created one + // and then later pruned it. If we don't return, the channel will again + // re-create any connections that were previously pruned, which will then + // immediately be re-pruned, churning the network for no purpose. + // This only applies to candidates received over signaling (i.e. origin_port + // is NULL). + if (!origin_port && IsDuplicateRemoteCandidate(new_remote_candidate)) { + // return true to indicate success, without creating any new connections. + return true; + } + // Add a new connection for this candidate to every port that allows such a // connection (i.e., if they have compatible protocols) and that does not // already have a connection to an equivalent candidate. We must be careful // to make sure that the origin port is included, even if it was pruned, // since that may be the only port that can create this connection. - bool created = false; - std::vector<PortInterface *>::reverse_iterator it; for (it = ports_.rbegin(); it != ports_.rend(); ++it) { if (CreateConnection(*it, new_remote_candidate, origin_port, readable)) { @@ -684,7 +700,11 @@ bool P2PTransportChannel::CreateConnection(PortInterface* port, // It is not legal to try to change any of the parameters of an existing // connection; however, the other side can send a duplicate candidate. if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { - LOG(INFO) << "Attempt to change a remote candidate"; + LOG(INFO) << "Attempt to change a remote candidate." + << " Existing remote candidate: " + << connection->remote_candidate().ToString() + << "New remote candidate: " + << remote_candidate.ToString(); return false; } } else { @@ -734,6 +754,17 @@ uint32 P2PTransportChannel::GetRemoteCandidateGeneration( return remote_candidate_generation_; } +// Check if remote candidate is already cached. +bool P2PTransportChannel::IsDuplicateRemoteCandidate( + const Candidate& candidate) { + for (uint32 i = 0; i < remote_candidates_.size(); ++i) { + if (remote_candidates_[i].IsEquivalent(candidate)) { + return true; + } + } + return false; +} + // Maintain our remote candidate list, adding this new remote one. void P2PTransportChannel::RememberRemoteCandidate( const Candidate& remote_candidate, PortInterface* origin_port) { @@ -751,12 +782,9 @@ void P2PTransportChannel::RememberRemoteCandidate( } // Make sure this candidate is not a duplicate. - for (uint32 i = 0; i < remote_candidates_.size(); ++i) { - if (remote_candidates_[i].IsEquivalent(remote_candidate)) { - LOG(INFO) << "Duplicate candidate: " - << remote_candidate.address().ToSensitiveString(); - return; - } + if (IsDuplicateRemoteCandidate(remote_candidate)) { + LOG(INFO) << "Duplicate candidate: " << remote_candidate.ToString(); + return; } // Try this candidate for all future ports. @@ -789,7 +817,7 @@ int P2PTransportChannel::SetOption(talk_base::Socket::Option opt, int value) { // Send data to the other side, using our best connection. int P2PTransportChannel::SendPacket(const char *data, size_t len, - talk_base::DiffServCodePoint dscp, + const talk_base::PacketOptions& options, int flags) { ASSERT(worker_thread_ == talk_base::Thread::Current()); if (flags != 0) { @@ -801,7 +829,7 @@ int P2PTransportChannel::SendPacket(const char *data, size_t len, return -1; } - int sent = best_connection_->Send(data, len, dscp); + int sent = best_connection_->Send(data, len, options); if (sent <= 0) { ASSERT(sent < 0); error_ = best_connection_->GetError(); @@ -884,6 +912,15 @@ void P2PTransportChannel::SortConnections() { // will be sorted. UpdateConnectionStates(); + if (protocol_type_ == ICEPROTO_HYBRID) { + // If we are in hybrid mode, we are not sending any ping requests, so there + // is no point in sorting the connections. In hybrid state, ports can have + // different protocol than hybrid and protocol may differ from one another. + // Instead just update the state of this channel + UpdateChannelState(); + return; + } + // Any changes after this point will require a re-sort. sort_dirty_ = false; @@ -995,8 +1032,10 @@ void P2PTransportChannel::UpdateChannelState() { bool readable = false; for (uint32 i = 0; i < connections_.size(); ++i) { - if (connections_[i]->read_state() == Connection::STATE_READABLE) + if (connections_[i]->read_state() == Connection::STATE_READABLE) { readable = true; + break; + } } set_readable(readable); } @@ -1209,6 +1248,8 @@ void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { SwitchBestConnectionTo(NULL); RequestSort(); } + + SignalConnectionRemoved(this); } // When a port is destroyed remove it from our list of ports to use for |