Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(489)

Side by Side Diff: webrtc/p2p/base/p2ptransportchannel.cc

Issue 1270613006: First step of passive aggressive nomination. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after
558 558
559 if (port->IceProtocol() == ICEPROTO_RFC5245) { 559 if (port->IceProtocol() == ICEPROTO_RFC5245) {
560 // RFC5245, the agent constructs a pair whose local candidate is equal to 560 // RFC5245, the agent constructs a pair whose local candidate is equal to
561 // the transport address on which the STUN request was received, and a 561 // the transport address on which the STUN request was received, and a
562 // remote candidate equal to the source transport address where the 562 // remote candidate equal to the source transport address where the
563 // request came from. 563 // request came from.
564 564
565 // There shouldn't be an existing connection with this remote address. 565 // There shouldn't be an existing connection with this remote address.
566 // When ports are muxed, this channel might get multiple unknown address 566 // When ports are muxed, this channel might get multiple unknown address
567 // signals. In that case if the connection is already exists, we should 567 // signals. In that case if the connection is already exists, we should
568 // simply ignore the signal othewise send server error. 568 // simply ignore the signal otherwise send server error.
569 if (port->GetConnection(remote_candidate.address())) { 569 if (port->GetConnection(remote_candidate.address())) {
570 if (port_muxed) { 570 if (port_muxed) {
571 LOG(LS_INFO) << "Connection already exists for peer reflexive " 571 LOG(LS_INFO) << "Connection already exists for peer reflexive "
572 << "candidate: " << remote_candidate.ToString(); 572 << "candidate: " << remote_candidate.ToString();
573 return; 573 return;
574 } else { 574 } else {
575 ASSERT(false); 575 ASSERT(false);
576 port->SendBindingErrorResponse(stun_msg, address, 576 port->SendBindingErrorResponse(stun_msg, address,
577 STUN_ERROR_SERVER_ERROR, 577 STUN_ERROR_SERVER_ERROR,
578 STUN_ERROR_REASON_SERVER_ERROR); 578 STUN_ERROR_REASON_SERVER_ERROR);
(...skipping 10 matching lines...) Expand all
589 STUN_ERROR_REASON_SERVER_ERROR); 589 STUN_ERROR_REASON_SERVER_ERROR);
590 return; 590 return;
591 } 591 }
592 592
593 LOG(LS_INFO) << "Adding connection from " 593 LOG(LS_INFO) << "Adding connection from "
594 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") 594 << (remote_candidate_is_new ? "peer reflexive" : "resurrected")
595 << " candidate: " << remote_candidate.ToString(); 595 << " candidate: " << remote_candidate.ToString();
596 AddConnection(connection); 596 AddConnection(connection);
597 connection->ReceivedPing(); 597 connection->ReceivedPing();
598 598
599 bool received_use_candidate =
600 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr;
601 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED &&
602 protocol_type_ == ICEPROTO_RFC5245) {
pthatcher1 2015/08/07 22:50:22 We are already in a "== ICEPROTO_RFC5245" block, s
honghaiz3 2015/08/10 20:15:43 Done.
603 connection->set_nominated(true);
604 OnUseCandidate(connection);
pthatcher1 2015/08/07 22:50:22 Firing OnUseCandidate after we call AddConnection
honghaiz3 2015/08/10 20:15:42 Done. Also changed the SignalUseCandidate to Signa
605 }
606
599 // Send the pinger a successful stun response. 607 // Send the pinger a successful stun response.
600 port->SendBindingResponse(stun_msg, address); 608 port->SendBindingResponse(stun_msg, address);
601 609
602 // Update the list of connections since we just added another. We do this 610 // Update the list of connections since we just added another. We do this
603 // after sending the response since it could (in principle) delete the 611 // after sending the response since it could (in principle) delete the
604 // connection in question. 612 // connection in question.
605 SortConnections(); 613 SortConnections();
606 } else { 614 } else {
607 // Check for connectivity to this address. Create connections 615 // Check for connectivity to this address. Create connections
608 // to this address across all local ports. First, add this as a new remote 616 // to this address across all local ports. First, add this as a new remote
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
992 // is no point in sorting the connections. In hybrid state, ports can have 1000 // is no point in sorting the connections. In hybrid state, ports can have
993 // different protocol than hybrid and protocol may differ from one another. 1001 // different protocol than hybrid and protocol may differ from one another.
994 // Instead just update the state of this channel 1002 // Instead just update the state of this channel
995 UpdateChannelState(); 1003 UpdateChannelState();
996 return; 1004 return;
997 } 1005 }
998 1006
999 // Any changes after this point will require a re-sort. 1007 // Any changes after this point will require a re-sort.
1000 sort_dirty_ = false; 1008 sort_dirty_ = false;
1001 1009
1002 // Get a list of the networks that we are using.
1003 std::set<rtc::Network*> networks;
1004 for (uint32 i = 0; i < connections_.size(); ++i)
1005 networks.insert(connections_[i]->port()->Network());
1006
1007 // Find the best alternative connection by sorting. It is important to note 1010 // Find the best alternative connection by sorting. It is important to note
1008 // that amongst equal preference, writable connections, this will choose the 1011 // that amongst equal preference, writable connections, this will choose the
1009 // one whose estimated latency is lowest. So it is the only one that we 1012 // one whose estimated latency is lowest. So it is the only one that we
1010 // need to consider switching to. 1013 // need to consider switching to.
1011
1012 ConnectionCompare cmp; 1014 ConnectionCompare cmp;
1013 std::stable_sort(connections_.begin(), connections_.end(), cmp); 1015 std::stable_sort(connections_.begin(), connections_.end(), cmp);
1014 LOG(LS_VERBOSE) << "Sorting available connections:"; 1016 LOG(LS_VERBOSE) << "Sorting available connections:";
1015 for (uint32 i = 0; i < connections_.size(); ++i) { 1017 for (uint32 i = 0; i < connections_.size(); ++i) {
1016 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1018 LOG(LS_VERBOSE) << connections_[i]->ToString();
1017 } 1019 }
1018 1020 Connection* top_connection =
1019 Connection* top_connection = NULL; 1021 (connections_.size() > 0) ? connections_[0] : nullptr;
1020 if (connections_.size() > 0)
1021 top_connection = connections_[0];
1022
1023 // We don't want to pick the best connections if channel is using RFC5245
1024 // and it's mode is CONTROLLED, as connections will be selected by the
1025 // CONTROLLING agent.
1026 1022
1027 // If necessary, switch to the new choice. 1023 // If necessary, switch to the new choice.
1028 if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) { 1024 // Note that top_connection doesn't have to be writable to be
pthatcher1 2015/08/07 22:50:22 |top_connection|
honghaiz3 2015/08/10 20:15:43 Done.
1029 if (ShouldSwitch(best_connection_, top_connection)) { 1025 // switched to although it will have higher priority if it is writable.
pthatcher1 2015/08/07 22:50:22 to be switched to => to become the best_connection
honghaiz3 2015/08/10 20:15:42 Done.
1030 LOG(LS_INFO) << "Switching best connection on controlling side: " 1026 // Controlled side can switch the best connection only if the best connection
1031 << top_connection->ToString(); 1027 // was not nominated yet.
pthatcher1 2015/08/07 22:50:22 Controlled side => The controlled side if the best
honghaiz3 2015/08/10 20:15:43 Done.
1032 SwitchBestConnectionTo(top_connection); 1028 if ((protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING ||
1033 } 1029 !best_nominated_connection()) &&
1030 ShouldSwitch(best_connection_, top_connection)) {
1031 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
1032 SwitchBestConnectionTo(top_connection);
1034 } 1033 }
1035 1034
1036 // We can prune any connection for which there is a connected, writable 1035 // Controlled side can prune only if the best connection has been nominated.
1037 // connection on the same network with better or equal priority. We leave 1036 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
1038 // those with better priority just in case they become writable later (at 1037 PruneConnections();
1039 // which point, we would prune out the current best connection). We leave
1040 // connections on other networks because they may not be using the same
1041 // resources and they may represent very distinct paths over which we can
1042 // switch. If the |primier| connection is not connected, we may be
1043 // reconnecting a TCP connection and temporarily do not prune connections in
1044 // this network. See the big comment in CompareConnections.
1045 std::set<rtc::Network*>::iterator network;
1046 for (network = networks.begin(); network != networks.end(); ++network) {
1047 Connection* primier = GetBestConnectionOnNetwork(*network);
1048 if (!primier || (primier->write_state() != Connection::STATE_WRITABLE) ||
1049 !primier->connected())
1050 continue;
1051
1052 for (uint32 i = 0; i < connections_.size(); ++i) {
1053 if ((connections_[i] != primier) &&
1054 (connections_[i]->port()->Network() == *network) &&
1055 (CompareConnectionCandidates(primier, connections_[i]) >= 0)) {
1056 connections_[i]->Prune();
1057 }
1058 }
1059 } 1038 }
1060 1039
1061 // Check if all connections are timedout. 1040 // Check if all connections are timedout.
1062 bool all_connections_timedout = true; 1041 bool all_connections_timedout = true;
1063 for (uint32 i = 0; i < connections_.size(); ++i) { 1042 for (uint32 i = 0; i < connections_.size(); ++i) {
1064 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 1043 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1065 all_connections_timedout = false; 1044 all_connections_timedout = false;
1066 break; 1045 break;
1067 } 1046 }
1068 } 1047 }
1069 1048
1070 // Now update the writable state of the channel with the information we have 1049 // Now update the writable state of the channel with the information we have
1071 // so far. 1050 // so far.
1072 if (best_connection_ && best_connection_->writable()) { 1051 if (best_connection_ && best_connection_->writable()) {
1073 HandleWritable(); 1052 HandleWritable();
1074 } else if (all_connections_timedout) { 1053 } else if (all_connections_timedout) {
1075 HandleAllTimedOut(); 1054 HandleAllTimedOut();
1076 } else { 1055 } else {
1077 HandleNotWritable(); 1056 HandleNotWritable();
1078 } 1057 }
1079 1058
1080 // Update the state of this channel. This method is called whenever the 1059 // Update the state of this channel. This method is called whenever the
1081 // state of any connection changes, so this is a good place to do this. 1060 // state of any connection changes, so this is a good place to do this.
1082 UpdateChannelState(); 1061 UpdateChannelState();
1083 } 1062 }
1084 1063
1064 Connection* P2PTransportChannel::best_nominated_connection() const {
1065 return (best_connection_ && best_connection_->nominated()) ? best_connection_
1066 : nullptr;
1067 }
1068
1069 void P2PTransportChannel::PruneConnections() {
1070 // We can prune any connection for which there is a connected, writable
1071 // connection on the same network with better or equal priority. We leave
1072 // those with better priority just in case they become writable later (at
1073 // which point, we would prune out the current best connection). We leave
1074 // connections on other networks because they may not be using the same
1075 // resources and they may represent very distinct paths over which we can
1076 // switch. If the |primier| connection is not connected, we may be
1077 // reconnecting a TCP connection and temporarily do not prune connections in
1078 // this network. See the big comment in CompareConnections.
1079 // NOTE: If the ICE role is controlled and it has not received requests with
1080 // use_candidate yet, do not prune the connections because it may delete the
pthatcher1 2015/08/07 22:50:22 I'd change "it has not received requests with use_
honghaiz3 2015/08/10 20:15:42 Done.
1081 // connection that will be selected by the controlling side.
pthatcher1 2015/08/07 22:50:22 Shouldn't you move this NOTE to where we call Prun
honghaiz3 2015/08/10 20:15:43 Done. And merged with the comments there.
1082
1083 // Get a list of the networks that we are using.
1084 std::set<rtc::Network*> networks;
1085 for (uint32 i = 0; i < connections_.size(); ++i)
1086 networks.insert(connections_[i]->port()->Network());
pthatcher1 2015/08/07 22:50:22 Might as well switch go c++11: for (const Connect
honghaiz3 2015/08/10 20:15:42 Done.
1087 for (auto network : networks) {
pthatcher1 2015/08/07 22:50:22 I'd prefer "for (const Network* network : networks
honghaiz3 2015/08/10 20:15:43 Done.
1088 Connection* primier = GetBestConnectionOnNetwork(network);
1089 if (!(primier && primier->writable() && primier->connected()))
1090 continue;
pthatcher1 2015/08/07 22:50:22 Can you add some {}s around this?
honghaiz3 2015/08/10 20:15:42 Done.
1091
1092 for (auto connection : connections_) {
pthatcher1 2015/08/07 22:50:22 Same here: for (Connection* conn : connections_)
honghaiz3 2015/08/10 20:15:43 Done.
1093 if ((connection != primier) &&
1094 (connection->port()->Network() == network) &&
1095 (CompareConnectionCandidates(primier, connection) >= 0)) {
1096 connection->Prune();
1097 }
1098 }
1099 }
1100 }
1085 1101
1086 // Track the best connection, and let listeners know 1102 // Track the best connection, and let listeners know
1087 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1103 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1088 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1104 // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1089 // so don't use it. 1105 // so don't use it.
1090 Connection* old_best_connection = best_connection_; 1106 Connection* old_best_connection = best_connection_;
1091 best_connection_ = conn; 1107 best_connection_ = conn;
1092 if (best_connection_) { 1108 if (best_connection_) {
1093 if (old_best_connection) { 1109 if (old_best_connection) {
1094 LOG_J(LS_INFO, this) << "Previous best connection: " 1110 LOG_J(LS_INFO, this) << "Previous best connection: "
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1410 Connection *connection, const char *data, size_t len, 1426 Connection *connection, const char *data, size_t len,
1411 const rtc::PacketTime& packet_time) { 1427 const rtc::PacketTime& packet_time) {
1412 ASSERT(worker_thread_ == rtc::Thread::Current()); 1428 ASSERT(worker_thread_ == rtc::Thread::Current());
1413 1429
1414 // Do not deliver, if packet doesn't belong to the correct transport channel. 1430 // Do not deliver, if packet doesn't belong to the correct transport channel.
1415 if (!FindConnection(connection)) 1431 if (!FindConnection(connection))
1416 return; 1432 return;
1417 1433
1418 // Let the client know of an incoming packet 1434 // Let the client know of an incoming packet
1419 SignalReadPacket(this, data, len, packet_time, 0); 1435 SignalReadPacket(this, data, len, packet_time, 0);
1436
1437 // May need to switch the sending connection based on the receiving media path
1438 // if this is the controlled side.
1439 if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED &&
1440 !best_nominated_connection() && connection->writable()) {
pthatcher1 2015/08/07 22:50:22 I think the order would be a little more clear as:
honghaiz3 2015/08/10 20:15:42 Done. I put it in that order because I thought in
1441 SwitchBestConnectionTo(connection);
1442 }
1420 } 1443 }
1421 1444
1422 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1445 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1423 if (connection == best_connection_ && writable()) { 1446 if (connection == best_connection_ && writable()) {
1424 SignalReadyToSend(this); 1447 SignalReadyToSend(this);
1425 } 1448 }
1426 } 1449 }
1427 1450
1428 } // namespace cricket 1451 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698