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

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: Address comments 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) {
603 // This need to be after AddConnection so that the event
604 // SignalUseCandidate is connected to this class.
605 connection->set_nominated(true);
606 }
607
599 // Send the pinger a successful stun response. 608 // Send the pinger a successful stun response.
600 port->SendBindingResponse(stun_msg, address); 609 port->SendBindingResponse(stun_msg, address);
601 610
602 // Update the list of connections since we just added another. We do this 611 // 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 612 // after sending the response since it could (in principle) delete the
604 // connection in question. 613 // connection in question.
605 SortConnections(); 614 SortConnections();
606 } else { 615 } else {
607 // Check for connectivity to this address. Create connections 616 // Check for connectivity to this address. Create connections
608 // to this address across all local ports. First, add this as a new remote 617 // 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 1001 // 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. 1002 // different protocol than hybrid and protocol may differ from one another.
994 // Instead just update the state of this channel 1003 // Instead just update the state of this channel
995 UpdateChannelState(); 1004 UpdateChannelState();
996 return; 1005 return;
997 } 1006 }
998 1007
999 // Any changes after this point will require a re-sort. 1008 // Any changes after this point will require a re-sort.
1000 sort_dirty_ = false; 1009 sort_dirty_ = false;
1001 1010
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 1011 // Find the best alternative connection by sorting. It is important to note
1008 // that amongst equal preference, writable connections, this will choose the 1012 // 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 1013 // one whose estimated latency is lowest. So it is the only one that we
1010 // need to consider switching to. 1014 // need to consider switching to.
1011
1012 ConnectionCompare cmp; 1015 ConnectionCompare cmp;
1013 std::stable_sort(connections_.begin(), connections_.end(), cmp); 1016 std::stable_sort(connections_.begin(), connections_.end(), cmp);
1014 LOG(LS_VERBOSE) << "Sorting available connections:"; 1017 LOG(LS_VERBOSE) << "Sorting available connections:";
1015 for (uint32 i = 0; i < connections_.size(); ++i) { 1018 for (uint32 i = 0; i < connections_.size(); ++i) {
1016 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1019 LOG(LS_VERBOSE) << connections_[i]->ToString();
1017 } 1020 }
1018 1021 Connection* top_connection =
1019 Connection* top_connection = NULL; 1022 (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 1023
1027 // If necessary, switch to the new choice. 1024 // If necessary, switch to the new choice.
1028 if (protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING) { 1025 // Note that top_connection don't have to be writable to be
juberti1 2015/08/07 01:31:19 don't ->doesn't
honghaiz3 2015/08/07 20:42:04 Done.
1029 if (ShouldSwitch(best_connection_, top_connection)) { 1026 // switched to although it will have higher priority if it is writable.
1030 LOG(LS_INFO) << "Switching best connection on controlling side: " 1027 // Controlled side can switch the best connection only if the best connection
1031 << top_connection->ToString(); 1028 // was not nominated yet.
1032 SwitchBestConnectionTo(top_connection); 1029 if ((protocol_type_ != ICEPROTO_RFC5245 || ice_role_ == ICEROLE_CONTROLLING ||
1033 } 1030 !best_nominated_connection()) &&
1031 ShouldSwitch(best_connection_, top_connection)) {
1032 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
1033 SwitchBestConnectionTo(top_connection);
1034 } 1034 }
1035 1035
1036 // We can prune any connection for which there is a connected, writable 1036 // 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 1037 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
1038 // those with better priority just in case they become writable later (at 1038 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 } 1039 }
1060 1040
1061 // Check if all connections are timedout. 1041 // Check if all connections are timedout.
1062 bool all_connections_timedout = true; 1042 bool all_connections_timedout = true;
1063 for (uint32 i = 0; i < connections_.size(); ++i) { 1043 for (uint32 i = 0; i < connections_.size(); ++i) {
1064 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 1044 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1065 all_connections_timedout = false; 1045 all_connections_timedout = false;
1066 break; 1046 break;
1067 } 1047 }
1068 } 1048 }
1069 1049
1070 // Now update the writable state of the channel with the information we have 1050 // Now update the writable state of the channel with the information we have
1071 // so far. 1051 // so far.
1072 if (best_connection_ && best_connection_->writable()) { 1052 if (best_connection_ && best_connection_->writable()) {
1073 HandleWritable(); 1053 HandleWritable();
1074 } else if (all_connections_timedout) { 1054 } else if (all_connections_timedout) {
1075 HandleAllTimedOut(); 1055 HandleAllTimedOut();
1076 } else { 1056 } else {
1077 HandleNotWritable(); 1057 HandleNotWritable();
1078 } 1058 }
1079 1059
1080 // Update the state of this channel. This method is called whenever the 1060 // 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. 1061 // state of any connection changes, so this is a good place to do this.
1082 UpdateChannelState(); 1062 UpdateChannelState();
1083 } 1063 }
1084 1064
1065 Connection* P2PTransportChannel::best_nominated_connection() const {
1066 return (best_connection_ && best_connection_->nominated()) ? best_connection_
1067 : nullptr;
1068 }
1069
1070 void P2PTransportChannel::PruneConnections() {
1071 // We can prune any connection for which there is a connected, writable
1072 // connection on the same network with better or equal priority. We leave
1073 // those with better priority just in case they become writable later (at
1074 // which point, we would prune out the current best connection). We leave
1075 // connections on other networks because they may not be using the same
1076 // resources and they may represent very distinct paths over which we can
1077 // switch. If the |primier| connection is not connected, we may be
1078 // reconnecting a TCP connection and temporarily do not prune connections in
1079 // this network. See the big comment in CompareConnections.
1080 // NOTE: If the ICE role is controlled and it has not received requests with
1081 // use_candidate yet, do not prune the connections because it may delete the
1082 // connection that will be selected by the controlling side.
1083
1084 // Get a list of the networks that we are using.
1085 std::set<rtc::Network*> networks;
1086 for (uint32 i = 0; i < connections_.size(); ++i)
1087 networks.insert(connections_[i]->port()->Network());
1088 for (auto network : networks) {
1089 Connection* primier = GetBestConnectionOnNetwork(network);
1090 if (!(primier && primier->writable() && primier->connected()))
1091 continue;
1092
1093 for (auto connection : connections_) {
1094 if ((connection != primier) &&
1095 (connection->port()->Network() == network) &&
1096 (CompareConnectionCandidates(primier, connection) >= 0)) {
1097 connection->Prune();
1098 }
1099 }
1100 }
1101 }
1085 1102
1086 // Track the best connection, and let listeners know 1103 // Track the best connection, and let listeners know
1087 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1104 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1088 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1105 // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1089 // so don't use it. 1106 // so don't use it.
1090 Connection* old_best_connection = best_connection_; 1107 Connection* old_best_connection = best_connection_;
1091 best_connection_ = conn; 1108 best_connection_ = conn;
1092 if (best_connection_) { 1109 if (best_connection_) {
1093 if (old_best_connection) { 1110 if (old_best_connection) {
1094 LOG_J(LS_INFO, this) << "Previous best connection: " 1111 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, 1427 Connection *connection, const char *data, size_t len,
1411 const rtc::PacketTime& packet_time) { 1428 const rtc::PacketTime& packet_time) {
1412 ASSERT(worker_thread_ == rtc::Thread::Current()); 1429 ASSERT(worker_thread_ == rtc::Thread::Current());
1413 1430
1414 // Do not deliver, if packet doesn't belong to the correct transport channel. 1431 // Do not deliver, if packet doesn't belong to the correct transport channel.
1415 if (!FindConnection(connection)) 1432 if (!FindConnection(connection))
1416 return; 1433 return;
1417 1434
1418 // Let the client know of an incoming packet 1435 // Let the client know of an incoming packet
1419 SignalReadPacket(this, data, len, packet_time, 0); 1436 SignalReadPacket(this, data, len, packet_time, 0);
1437
1438 // May need to switch the sending connection based on the receiving media path
1439 // if this is the controlled side.
1440 if (best_connection_ != connection && ice_role_ == ICEROLE_CONTROLLED &&
1441 !best_nominated_connection() && connection->writable()) {
1442 SwitchBestConnectionTo(connection);
1443 }
1420 } 1444 }
1421 1445
1422 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1446 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1423 if (connection == best_connection_ && writable()) { 1447 if (connection == best_connection_ && writable()) {
1424 SignalReadyToSend(this); 1448 SignalReadyToSend(this);
1425 } 1449 }
1426 } 1450 }
1427 1451
1428 } // namespace cricket 1452 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698