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

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: Addressed 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 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 connections_.push_back(connection); 222 connections_.push_back(connection);
223 connection->set_remote_ice_mode(remote_ice_mode_); 223 connection->set_remote_ice_mode(remote_ice_mode_);
224 connection->SignalReadPacket.connect( 224 connection->SignalReadPacket.connect(
225 this, &P2PTransportChannel::OnReadPacket); 225 this, &P2PTransportChannel::OnReadPacket);
226 connection->SignalReadyToSend.connect( 226 connection->SignalReadyToSend.connect(
227 this, &P2PTransportChannel::OnReadyToSend); 227 this, &P2PTransportChannel::OnReadyToSend);
228 connection->SignalStateChange.connect( 228 connection->SignalStateChange.connect(
229 this, &P2PTransportChannel::OnConnectionStateChange); 229 this, &P2PTransportChannel::OnConnectionStateChange);
230 connection->SignalDestroyed.connect( 230 connection->SignalDestroyed.connect(
231 this, &P2PTransportChannel::OnConnectionDestroyed); 231 this, &P2PTransportChannel::OnConnectionDestroyed);
232 connection->SignalUseCandidate.connect( 232 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
233 this, &P2PTransportChannel::OnUseCandidate);
234 } 233 }
235 234
236 void P2PTransportChannel::SetIceRole(IceRole ice_role) { 235 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
237 ASSERT(worker_thread_ == rtc::Thread::Current()); 236 ASSERT(worker_thread_ == rtc::Thread::Current());
238 if (ice_role_ != ice_role) { 237 if (ice_role_ != ice_role) {
239 ice_role_ = ice_role; 238 ice_role_ = ice_role;
240 for (std::vector<PortInterface *>::iterator it = ports_.begin(); 239 for (std::vector<PortInterface *>::iterator it = ports_.begin();
241 it != ports_.end(); ++it) { 240 it != ports_.end(); ++it) {
242 (*it)->SetIceRole(ice_role); 241 (*it)->SetIceRole(ice_role);
243 } 242 }
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 } 514 }
516 515
517 // RFC5245, the agent constructs a pair whose local candidate is equal to 516 // RFC5245, the agent constructs a pair whose local candidate is equal to
518 // the transport address on which the STUN request was received, and a 517 // the transport address on which the STUN request was received, and a
519 // remote candidate equal to the source transport address where the 518 // remote candidate equal to the source transport address where the
520 // request came from. 519 // request came from.
521 520
522 // There shouldn't be an existing connection with this remote address. 521 // There shouldn't be an existing connection with this remote address.
523 // When ports are muxed, this channel might get multiple unknown address 522 // When ports are muxed, this channel might get multiple unknown address
524 // signals. In that case if the connection is already exists, we should 523 // signals. In that case if the connection is already exists, we should
525 // simply ignore the signal othewise send server error. 524 // simply ignore the signal otherwise send server error.
526 if (port->GetConnection(remote_candidate.address())) { 525 if (port->GetConnection(remote_candidate.address())) {
527 if (port_muxed) { 526 if (port_muxed) {
528 LOG(LS_INFO) << "Connection already exists for peer reflexive " 527 LOG(LS_INFO) << "Connection already exists for peer reflexive "
529 << "candidate: " << remote_candidate.ToString(); 528 << "candidate: " << remote_candidate.ToString();
530 return; 529 return;
531 } else { 530 } else {
532 ASSERT(false); 531 ASSERT(false);
533 port->SendBindingErrorResponse(stun_msg, address, 532 port->SendBindingErrorResponse(stun_msg, address,
534 STUN_ERROR_SERVER_ERROR, 533 STUN_ERROR_SERVER_ERROR,
535 STUN_ERROR_REASON_SERVER_ERROR); 534 STUN_ERROR_REASON_SERVER_ERROR);
(...skipping 10 matching lines...) Expand all
546 STUN_ERROR_REASON_SERVER_ERROR); 545 STUN_ERROR_REASON_SERVER_ERROR);
547 return; 546 return;
548 } 547 }
549 548
550 LOG(LS_INFO) << "Adding connection from " 549 LOG(LS_INFO) << "Adding connection from "
551 << (remote_candidate_is_new ? "peer reflexive" : "resurrected") 550 << (remote_candidate_is_new ? "peer reflexive" : "resurrected")
552 << " candidate: " << remote_candidate.ToString(); 551 << " candidate: " << remote_candidate.ToString();
553 AddConnection(connection); 552 AddConnection(connection);
554 connection->ReceivedPing(); 553 connection->ReceivedPing();
555 554
555 bool received_use_candidate =
556 stun_msg->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr;
557 if (received_use_candidate && ice_role_ == ICEROLE_CONTROLLED) {
558 connection->set_nominated(true);
559 OnNominated(connection);
560 }
561
556 // Update the list of connections since we just added another. We do this 562 // Update the list of connections since we just added another. We do this
557 // after sending the response since it could (in principle) delete the 563 // after sending the response since it could (in principle) delete the
558 // connection in question. 564 // connection in question.
559 SortConnections(); 565 SortConnections();
560 } 566 }
561 567
562 void P2PTransportChannel::OnRoleConflict(PortInterface* port) { 568 void P2PTransportChannel::OnRoleConflict(PortInterface* port) {
563 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called 569 SignalRoleConflict(this); // STUN ping will be sent when SetRole is called
564 // from Transport. 570 // from Transport.
565 } 571 }
566 572
567 // When the signalling channel is ready, we can really kick off the allocator 573 // When the signalling channel is ready, we can really kick off the allocator
568 void P2PTransportChannel::OnSignalingReady() { 574 void P2PTransportChannel::OnSignalingReady() {
569 ASSERT(worker_thread_ == rtc::Thread::Current()); 575 ASSERT(worker_thread_ == rtc::Thread::Current());
570 if (waiting_for_signaling_) { 576 if (waiting_for_signaling_) {
571 waiting_for_signaling_ = false; 577 waiting_for_signaling_ = false;
572 AddAllocatorSession(allocator_->CreateSession( 578 AddAllocatorSession(allocator_->CreateSession(
573 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_)); 579 SessionId(), content_name(), component(), ice_ufrag_, ice_pwd_));
574 } 580 }
575 } 581 }
576 582
577 void P2PTransportChannel::OnUseCandidate(Connection* conn) { 583 void P2PTransportChannel::OnNominated(Connection* conn) {
578 ASSERT(worker_thread_ == rtc::Thread::Current()); 584 ASSERT(worker_thread_ == rtc::Thread::Current());
579 ASSERT(ice_role_ == ICEROLE_CONTROLLED); 585 ASSERT(ice_role_ == ICEROLE_CONTROLLED);
580 586
581 if (conn->write_state() == Connection::STATE_WRITABLE) { 587 if (conn->write_state() == Connection::STATE_WRITABLE) {
582 if (best_connection_ != conn) { 588 if (best_connection_ != conn) {
583 pending_best_connection_ = NULL; 589 pending_best_connection_ = NULL;
584 LOG(LS_INFO) << "Switching best connection on controlled side: " 590 LOG(LS_INFO) << "Switching best connection on controlled side: "
585 << conn->ToString(); 591 << conn->ToString();
586 SwitchBestConnectionTo(conn); 592 SwitchBestConnectionTo(conn);
587 // Now we have selected the best connection, time to prune other existing 593 // Now we have selected the best connection, time to prune other existing
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 void P2PTransportChannel::SortConnections() { 916 void P2PTransportChannel::SortConnections() {
911 ASSERT(worker_thread_ == rtc::Thread::Current()); 917 ASSERT(worker_thread_ == rtc::Thread::Current());
912 918
913 // Make sure the connection states are up-to-date since this affects how they 919 // Make sure the connection states are up-to-date since this affects how they
914 // will be sorted. 920 // will be sorted.
915 UpdateConnectionStates(); 921 UpdateConnectionStates();
916 922
917 // Any changes after this point will require a re-sort. 923 // Any changes after this point will require a re-sort.
918 sort_dirty_ = false; 924 sort_dirty_ = false;
919 925
920 // Get a list of the networks that we are using.
921 std::set<rtc::Network*> networks;
922 for (uint32 i = 0; i < connections_.size(); ++i)
923 networks.insert(connections_[i]->port()->Network());
924
925 // Find the best alternative connection by sorting. It is important to note 926 // Find the best alternative connection by sorting. It is important to note
926 // that amongst equal preference, writable connections, this will choose the 927 // that amongst equal preference, writable connections, this will choose the
927 // one whose estimated latency is lowest. So it is the only one that we 928 // one whose estimated latency is lowest. So it is the only one that we
928 // need to consider switching to. 929 // need to consider switching to.
929
930 ConnectionCompare cmp; 930 ConnectionCompare cmp;
931 std::stable_sort(connections_.begin(), connections_.end(), cmp); 931 std::stable_sort(connections_.begin(), connections_.end(), cmp);
932 LOG(LS_VERBOSE) << "Sorting available connections:"; 932 LOG(LS_VERBOSE) << "Sorting available connections:";
933 for (uint32 i = 0; i < connections_.size(); ++i) { 933 for (uint32 i = 0; i < connections_.size(); ++i) {
934 LOG(LS_VERBOSE) << connections_[i]->ToString(); 934 LOG(LS_VERBOSE) << connections_[i]->ToString();
935 } 935 }
936 936
937 Connection* top_connection = NULL; 937 Connection* top_connection =
938 if (connections_.size() > 0) 938 (connections_.size() > 0) ? connections_[0] : nullptr;
939 top_connection = connections_[0];
940
941 // We don't want to pick the best connections if channel is
942 // CONTROLLED, as connections will be selected by the CONTROLLING
943 // agent.
944 939
945 // If necessary, switch to the new choice. 940 // If necessary, switch to the new choice.
946 if (ice_role_ == ICEROLE_CONTROLLING) { 941 // Note that |top_connection| doesn't have to be writable to become the best
947 if (ShouldSwitch(best_connection_, top_connection)) { 942 // connection although it will have higher priority if it is writable.
948 LOG(LS_INFO) << "Switching best connection on controlling side: " 943 // The controlled side can switch the best connection only if the current
949 << top_connection->ToString(); 944 // |best connection_| has not been nominated by the controlling side yet.
950 SwitchBestConnectionTo(top_connection); 945 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) &&
951 } 946 ShouldSwitch(best_connection_, top_connection)) {
947 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
948 SwitchBestConnectionTo(top_connection);
952 } 949 }
953 950
954 // We can prune any connection for which there is a connected, writable 951 // Controlled side can prune only if the best connection has been nominated.
955 // connection on the same network with better or equal priority. We leave 952 // because otherwise it may delete the connection that will be selected by
956 // those with better priority just in case they become writable later (at 953 // the controlling side.
957 // which point, we would prune out the current best connection). We leave 954 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
958 // connections on other networks because they may not be using the same 955 PruneConnections();
959 // resources and they may represent very distinct paths over which we can
960 // switch. If the |primier| connection is not connected, we may be
961 // reconnecting a TCP connection and temporarily do not prune connections in
962 // this network. See the big comment in CompareConnections.
963 std::set<rtc::Network*>::iterator network;
964 for (network = networks.begin(); network != networks.end(); ++network) {
965 Connection* primier = GetBestConnectionOnNetwork(*network);
966 if (!primier || (primier->write_state() != Connection::STATE_WRITABLE) ||
967 !primier->connected())
968 continue;
969
970 for (uint32 i = 0; i < connections_.size(); ++i) {
971 if ((connections_[i] != primier) &&
972 (connections_[i]->port()->Network() == *network) &&
973 (CompareConnectionCandidates(primier, connections_[i]) >= 0)) {
974 connections_[i]->Prune();
975 }
976 }
977 } 956 }
978 957
979 // Check if all connections are timedout. 958 // Check if all connections are timedout.
980 bool all_connections_timedout = true; 959 bool all_connections_timedout = true;
981 for (uint32 i = 0; i < connections_.size(); ++i) { 960 for (uint32 i = 0; i < connections_.size(); ++i) {
982 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 961 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
983 all_connections_timedout = false; 962 all_connections_timedout = false;
984 break; 963 break;
985 } 964 }
986 } 965 }
987 966
988 // Now update the writable state of the channel with the information we have 967 // Now update the writable state of the channel with the information we have
989 // so far. 968 // so far.
990 if (best_connection_ && best_connection_->writable()) { 969 if (best_connection_ && best_connection_->writable()) {
991 HandleWritable(); 970 HandleWritable();
992 } else if (all_connections_timedout) { 971 } else if (all_connections_timedout) {
993 HandleAllTimedOut(); 972 HandleAllTimedOut();
994 } else { 973 } else {
995 HandleNotWritable(); 974 HandleNotWritable();
996 } 975 }
997 976
998 // Update the state of this channel. This method is called whenever the 977 // Update the state of this channel. This method is called whenever the
999 // state of any connection changes, so this is a good place to do this. 978 // state of any connection changes, so this is a good place to do this.
1000 UpdateChannelState(); 979 UpdateChannelState();
1001 } 980 }
1002 981
982 Connection* P2PTransportChannel::best_nominated_connection() const {
983 return (best_connection_ && best_connection_->nominated()) ? best_connection_
984 : nullptr;
985 }
986
987 void P2PTransportChannel::PruneConnections() {
988 // We can prune any connection for which there is a connected, writable
989 // connection on the same network with better or equal priority. We leave
990 // those with better priority just in case they become writable later (at
991 // which point, we would prune out the current best connection). We leave
992 // connections on other networks because they may not be using the same
993 // resources and they may represent very distinct paths over which we can
994 // switch. If the |primier| connection is not connected, we may be
995 // reconnecting a TCP connection and temporarily do not prune connections in
996 // this network. See the big comment in CompareConnections.
997
998 // Get a list of the networks that we are using.
999 std::set<rtc::Network*> networks;
1000 for (const Connection* conn : connections_) {
1001 networks.insert(conn->port()->Network());
1002 }
1003 for (rtc::Network* network : networks) {
1004 Connection* primier = GetBestConnectionOnNetwork(network);
1005 if (!(primier && primier->writable() && primier->connected())) {
1006 continue;
1007 }
1008
1009 for (Connection* conn : connections_) {
1010 if ((conn != primier) && (conn->port()->Network() == network) &&
1011 (CompareConnectionCandidates(primier, conn) >= 0)) {
1012 conn->Prune();
1013 }
1014 }
1015 }
1016 }
1003 1017
1004 // Track the best connection, and let listeners know 1018 // Track the best connection, and let listeners know
1005 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1019 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) {
1006 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1020 // Note: if conn is NULL, the previous best_connection_ has been destroyed,
1007 // so don't use it. 1021 // so don't use it.
1008 Connection* old_best_connection = best_connection_; 1022 Connection* old_best_connection = best_connection_;
1009 best_connection_ = conn; 1023 best_connection_ = conn;
1010 if (best_connection_) { 1024 if (best_connection_) {
1011 if (old_best_connection) { 1025 if (old_best_connection) {
1012 LOG_J(LS_INFO, this) << "Previous best connection: " 1026 LOG_J(LS_INFO, this) << "Previous best connection: "
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 Connection *connection, const char *data, size_t len, 1339 Connection *connection, const char *data, size_t len,
1326 const rtc::PacketTime& packet_time) { 1340 const rtc::PacketTime& packet_time) {
1327 ASSERT(worker_thread_ == rtc::Thread::Current()); 1341 ASSERT(worker_thread_ == rtc::Thread::Current());
1328 1342
1329 // Do not deliver, if packet doesn't belong to the correct transport channel. 1343 // Do not deliver, if packet doesn't belong to the correct transport channel.
1330 if (!FindConnection(connection)) 1344 if (!FindConnection(connection))
1331 return; 1345 return;
1332 1346
1333 // Let the client know of an incoming packet 1347 // Let the client know of an incoming packet
1334 SignalReadPacket(this, data, len, packet_time, 0); 1348 SignalReadPacket(this, data, len, packet_time, 0);
1349
1350 // May need to switch the sending connection based on the receiving media path
1351 // if this is the controlled side.
1352 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() &&
1353 connection->writable() && best_connection_ != connection) {
1354 SwitchBestConnectionTo(connection);
1355 }
1335 } 1356 }
1336 1357
1337 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1338 if (connection == best_connection_ && writable()) { 1359 if (connection == best_connection_ && writable()) {
1339 SignalReadyToSend(this); 1360 SignalReadyToSend(this);
1340 } 1361 }
1341 } 1362 }
1342 1363
1343 } // namespace cricket 1364 } // namespace cricket
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698