summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/libjingle/source/talk/p2p/base/p2ptransportchannel.cc
diff options
context:
space:
mode:
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.cc77
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