Index: webrtc/p2p/base/p2ptransportchannel.cc |
diff --git a/webrtc/p2p/base/p2ptransportchannel.cc b/webrtc/p2p/base/p2ptransportchannel.cc |
index 94eb01754d459111533fa7f9a7c71e9e5e3223d1..6f25223d6a4409e5a3abb1eb2ed2d7ee804988fc 100644 |
--- a/webrtc/p2p/base/p2ptransportchannel.cc |
+++ b/webrtc/p2p/base/p2ptransportchannel.cc |
@@ -565,7 +565,7 @@ void P2PTransportChannel::OnUnknownAddress( |
// There shouldn't be an existing connection with this remote address. |
// When ports are muxed, this channel might get multiple unknown address |
// signals. In that case if the connection is already exists, we should |
- // simply ignore the signal othewise send server error. |
+ // simply ignore the signal otherwise send server error. |
if (port->GetConnection(remote_candidate.address())) { |
if (port_muxed) { |
LOG(LS_INFO) << "Connection already exists for peer reflexive " |
@@ -589,6 +589,15 @@ void P2PTransportChannel::OnUnknownAddress( |
STUN_ERROR_REASON_SERVER_ERROR); |
return; |
} |
+ bool received_use_candidate = |
+ stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr; |
+ if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED && |
+ protocol_type_ == ICEPROTO_RFC5245) { |
+ connection->set_received_use_candidate(true); |
pthatcher1
2015/08/06 01:41:42
I think we should call this set_nominated.
honghaiz3
2015/08/06 18:22:57
Done.
|
+ // Since the connection is not writable yet, it will only set the |
+ // pending_best_connection_ there and will not incur double sorting. |
+ OnUseCandidate(connection); |
pthatcher1
2015/08/06 01:41:42
We can call OnUseCandidate *before* calling AddCon
honghaiz3
2015/08/06 18:22:57
I move this after AddConnection. Plus, hid the cal
|
+ } |
LOG(LS_INFO) << "Adding connection from " |
<< (remote_candidate_is_new ? "peer reflexive" : "resurrected") |
@@ -1020,14 +1029,16 @@ void P2PTransportChannel::SortConnections() { |
if (connections_.size() > 0) |
top_connection = connections_[0]; |
- // We don't want to pick the best connections if channel is using RFC5245 |
- // and it's mode is CONTROLLED, as connections will be selected by the |
- // CONTROLLING agent. |
- |
// If necessary, switch to the new choice. |
- if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) { |
+ // As we are moving toward passive-aggressive nomination, a channel may be |
+ // selected as the best connection even if it is using RFC5245 and its mode |
+ // is CONTROLLED. Note that top_connection don't have to be writable to be |
+ // switched to although it will have higher priority if it is writable. |
+ if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING || |
+ (ice_role_ == ICEROLE_CONTROLLED && |
+ !(best_connection_ && best_connection_->received_use_candidate()))) { |
pthatcher1
2015/08/06 01:41:42
I think a best_nominated_connection() == (best_con
honghaiz3
2015/08/06 18:22:57
Done.
|
if (ShouldSwitch(best_connection_, top_connection)) { |
pthatcher1
2015/08/06 01:41:42
I think we should move all of this logic together
honghaiz3
2015/08/06 18:22:57
ShouldSwitch is defined as a helper function outsi
|
- LOG(LS_INFO) << "Switching best connection on controlling side: " |
+ LOG(LS_INFO) << "Switching best connection: " |
<< top_connection->ToString(); |
SwitchBestConnectionTo(top_connection); |
} |
@@ -1042,18 +1053,23 @@ void P2PTransportChannel::SortConnections() { |
// switch. If the |primier| connection is not connected, we may be |
// reconnecting a TCP connection and temporarily do not prune connections in |
// this network. See the big comment in CompareConnections. |
- std::set<rtc::Network*>::iterator network; |
- for (network = networks.begin(); network != networks.end(); ++network) { |
- Connection* primier = GetBestConnectionOnNetwork(*network); |
- if (!primier || (primier->write_state() != Connection::STATE_WRITABLE) || |
- !primier->connected()) |
- continue; |
- |
- for (uint32 i = 0; i < connections_.size(); ++i) { |
- if ((connections_[i] != primier) && |
- (connections_[i]->port()->Network() == *network) && |
- (CompareConnectionCandidates(primier, connections_[i]) >= 0)) { |
- connections_[i]->Prune(); |
+ // NOTE: If the ICE role is controlled and it has not received requests with |
+ // use_candidate yet, do not prune the connections because it may delete the |
+ // connection that will be selected by the controlling side. |
+ if (ice_role_ != ICEROLE_CONTROLLED || |
+ (best_connection_ && best_connection_->received_use_candidate())) { |
pthatcher1
2015/08/06 01:41:42
I think we want to make this
if (best_connection
honghaiz3
2015/08/06 18:22:57
Done. I think calling it PruneConnections is proba
|
+ std::set<rtc::Network*>::iterator network; |
+ for (network = networks.begin(); network != networks.end(); ++network) { |
+ Connection* primier = GetBestConnectionOnNetwork(*network); |
+ if (!(primier && primier->writable() && primier->connected())) |
+ continue; |
+ |
+ for (uint32 i = 0; i < connections_.size(); ++i) { |
+ if ((connections_[i] != primier) && |
+ (connections_[i]->port()->Network() == *network) && |
+ (CompareConnectionCandidates(primier, connections_[i]) >= 0)) { |
+ connections_[i]->Prune(); |
+ } |
} |
} |
} |
@@ -1417,6 +1433,14 @@ void P2PTransportChannel::OnReadPacket( |
// Let the client know of an incoming packet |
SignalReadPacket(this, data, len, packet_time, 0); |
+ |
+ // May need to switch the sending connection based on the receiving media path |
+ // if this is controlled side. |
+ if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED && |
+ !(best_connection_ && best_connection_->received_use_candidate()) && |
+ connection->writable()) { |
pthatcher1
2015/08/06 01:41:42
I think if this would be easier to read:
if (ice_
honghaiz3
2015/08/06 18:22:57
That is different from what I put.
If the connect
|
+ SwitchBestConnectionTo(connection); |
+ } |
} |
void P2PTransportChannel::OnReadyToSend(Connection* connection) { |