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

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

Issue 2069493002: Do not switch best connection on the controlled side too frequently (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Merge branch 'master' into nominate_on_controlled_side Created 4 years, 5 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
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
54 } // unnamed namespace 54 } // unnamed namespace
55 55
56 namespace cricket { 56 namespace cricket {
57 57
58 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) 58 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
59 // for pinging. When the socket is writable, we will use only 1 Kbps because 59 // for pinging. When the socket is writable, we will use only 1 Kbps because
60 // we don't want to degrade the quality on a modem. These numbers should work 60 // we don't want to degrade the quality on a modem. These numbers should work
61 // well on a 28.8K modem, which is the slowest connection on which the voice 61 // well on a 28.8K modem, which is the slowest connection on which the voice
62 // quality is reasonable at all. 62 // quality is reasonable at all.
63 static const int PING_PACKET_SIZE = 60 * 8; 63 static const int PING_PACKET_SIZE = 60 * 8;
64 // STRONG_PING_INTERVAL (480ms) is applied when the best connection is both 64 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both
65 // writable and receiving. 65 // writable and receiving.
66 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; 66 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000;
67 // WEAK_PING_INTERVAL (48ms) is applied when the best connection is either not 67 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either
68 // writable or not receiving. 68 // not writable or not receiving.
69 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; 69 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000;
70 70
71 // Writable connections are pinged at a faster rate while stabilizing. 71 // Writable connections are pinged at a faster rate while stabilizing.
72 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms 72 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms
73 73
74 // Writable connections are pinged at a slower rate once stabilized. 74 // Writable connections are pinged at a slower rate once stabilized.
75 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms 75 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms
76 76
77 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms 77 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms
78 78
79 static constexpr int a_is_better = 1;
80 static constexpr int b_is_better = -1;
81
79 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 82 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
80 int component, 83 int component,
81 P2PTransport* transport, 84 P2PTransport* transport,
82 PortAllocator* allocator) 85 PortAllocator* allocator)
83 : P2PTransportChannel(transport_name, component, allocator) {} 86 : P2PTransportChannel(transport_name, component, allocator) {}
84 87
85 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 88 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
86 int component, 89 int component,
87 PortAllocator* allocator) 90 PortAllocator* allocator)
88 : TransportChannelImpl(transport_name, component), 91 : TransportChannelImpl(transport_name, component),
89 allocator_(allocator), 92 allocator_(allocator),
90 worker_thread_(rtc::Thread::Current()), 93 worker_thread_(rtc::Thread::Current()),
91 incoming_only_(false), 94 incoming_only_(false),
92 error_(0), 95 error_(0),
93 best_connection_(NULL),
94 pending_best_connection_(NULL),
95 sort_dirty_(false), 96 sort_dirty_(false),
96 remote_ice_mode_(ICEMODE_FULL), 97 remote_ice_mode_(ICEMODE_FULL),
97 ice_role_(ICEROLE_UNKNOWN), 98 ice_role_(ICEROLE_UNKNOWN),
98 tiebreaker_(0), 99 tiebreaker_(0),
99 gathering_state_(kIceGatheringNew), 100 gathering_state_(kIceGatheringNew),
100 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), 101 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5),
101 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, 102 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */,
102 0 /* backup_connection_ping_interval */, 103 0 /* backup_connection_ping_interval */,
103 false /* gather_continually */, 104 false /* gather_continually */,
104 false /* prioritize_most_likely_candidate_pairs */, 105 false /* prioritize_most_likely_candidate_pairs */,
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 connection->SignalReadyToSend.connect( 149 connection->SignalReadyToSend.connect(
149 this, &P2PTransportChannel::OnReadyToSend); 150 this, &P2PTransportChannel::OnReadyToSend);
150 connection->SignalStateChange.connect( 151 connection->SignalStateChange.connect(
151 this, &P2PTransportChannel::OnConnectionStateChange); 152 this, &P2PTransportChannel::OnConnectionStateChange);
152 connection->SignalDestroyed.connect( 153 connection->SignalDestroyed.connect(
153 this, &P2PTransportChannel::OnConnectionDestroyed); 154 this, &P2PTransportChannel::OnConnectionDestroyed);
154 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); 155 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated);
155 had_connection_ = true; 156 had_connection_ = true;
156 } 157 }
157 158
159 // Determines whether we should switch the selected connection to
160 // |new_connection| based the writable/receiving state, the nomination state,
161 // and the last data received time. This prevents the controlled side from
162 // switching the selected connection too frequently when the controlling side
163 // is doing aggressive nominations. The precedence of the connection switching
164 // criteria is as follows:
165 // i) write/receiving/connected states
166 // ii) For controlled side,
167 // a) nomination state,
168 // b) last data received time.
169 // iii) Lower cost / higher priority.
170 // iv) rtt.
171 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and
172 // implement the ice-renomination option.
173 bool P2PTransportChannel::ShouldSwitchSelectedConnection(
174 Connection* new_connection) const {
175 if (!new_connection || selected_connection_ == new_connection) {
176 return false;
177 }
178
179 if (selected_connection_ == nullptr) {
180 return true;
181 }
182
183 int cmp = CompareConnections(selected_connection_, new_connection);
184 if (cmp != 0) {
185 return cmp < 0;
186 }
187
188 // If everything else is the same, switch only if rtt has improved by
189 // a margin.
190 return new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement;
191 }
192
158 void P2PTransportChannel::SetIceRole(IceRole ice_role) { 193 void P2PTransportChannel::SetIceRole(IceRole ice_role) {
159 ASSERT(worker_thread_ == rtc::Thread::Current()); 194 ASSERT(worker_thread_ == rtc::Thread::Current());
160 if (ice_role_ != ice_role) { 195 if (ice_role_ != ice_role) {
161 ice_role_ = ice_role; 196 ice_role_ = ice_role;
162 for (PortInterface* port : ports_) { 197 for (PortInterface* port : ports_) {
163 port->SetIceRole(ice_role); 198 port->SetIceRole(ice_role);
164 } 199 }
165 // Update role on removed ports as well, because they may still have 200 // Update role on removed ports as well, because they may still have
166 // connections alive that should be using the correct role. 201 // connections alive that should be using the correct role.
167 for (PortInterface* port : removed_ports_) { 202 for (PortInterface* port : removed_ports_) {
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
570 return nullptr; 605 return nullptr;
571 } 606 }
572 *generation = params.rend() - it - 1; 607 *generation = params.rend() - it - 1;
573 return &(*it); 608 return &(*it);
574 } 609 }
575 610
576 void P2PTransportChannel::OnNominated(Connection* conn) { 611 void P2PTransportChannel::OnNominated(Connection* conn) {
577 ASSERT(worker_thread_ == rtc::Thread::Current()); 612 ASSERT(worker_thread_ == rtc::Thread::Current());
578 ASSERT(ice_role_ == ICEROLE_CONTROLLED); 613 ASSERT(ice_role_ == ICEROLE_CONTROLLED);
579 614
580 if (conn->write_state() == Connection::STATE_WRITABLE) { 615 if (selected_connection_ == conn) {
581 if (best_connection_ != conn) { 616 return;
582 pending_best_connection_ = NULL;
583 LOG(LS_INFO) << "Switching best connection on controlled side: "
584 << conn->ToString();
585 SwitchBestConnectionTo(conn);
586 // Now we have selected the best connection, time to prune other existing
587 // connections and update the read/write state of the channel.
588 RequestSort();
589 }
590 } else {
591 LOG(LS_INFO) << "Not switching the best connection on controlled side yet,"
592 << " because it's not writable: " << conn->ToString();
593 pending_best_connection_ = conn;
594 } 617 }
618
619 if (!ShouldSwitchSelectedConnection(conn)) {
620 LOG(LS_INFO)
621 << "Not switching the selected connection on controlled side yet: "
622 << conn->ToString();
623 return;
624 }
625
626 LOG(LS_INFO)
627 << "Switching selected connection on controlled side due to nomination: "
628 << conn->ToString();
629 SwitchSelectedConnection(conn);
630 // Now that we have selected a connection, it is time to prune other
631 // connections and update the read/write state of the channel.
632 RequestSort();
595 } 633 }
596 634
597 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { 635 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) {
598 ASSERT(worker_thread_ == rtc::Thread::Current()); 636 ASSERT(worker_thread_ == rtc::Thread::Current());
599 637
600 uint32_t generation = GetRemoteCandidateGeneration(candidate); 638 uint32_t generation = GetRemoteCandidateGeneration(candidate);
601 // If a remote candidate with a previous generation arrives, drop it. 639 // If a remote candidate with a previous generation arrives, drop it.
602 if (generation < remote_ice_generation()) { 640 if (generation < remote_ice_generation()) {
603 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " 641 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag "
604 << candidate.username() 642 << candidate.username()
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 ASSERT(worker_thread_ == rtc::Thread::Current()); 872 ASSERT(worker_thread_ == rtc::Thread::Current());
835 873
836 const auto& found = options_.find(opt); 874 const auto& found = options_.find(opt);
837 if (found == options_.end()) { 875 if (found == options_.end()) {
838 return false; 876 return false;
839 } 877 }
840 *value = found->second; 878 *value = found->second;
841 return true; 879 return true;
842 } 880 }
843 881
844 // Send data to the other side, using our best connection. 882 // Send data to the other side, using our selected connection.
845 int P2PTransportChannel::SendPacket(const char *data, size_t len, 883 int P2PTransportChannel::SendPacket(const char *data, size_t len,
846 const rtc::PacketOptions& options, 884 const rtc::PacketOptions& options,
847 int flags) { 885 int flags) {
848 ASSERT(worker_thread_ == rtc::Thread::Current()); 886 ASSERT(worker_thread_ == rtc::Thread::Current());
849 if (flags != 0) { 887 if (flags != 0) {
850 error_ = EINVAL; 888 error_ = EINVAL;
851 return -1; 889 return -1;
852 } 890 }
853 if (best_connection_ == NULL) { 891 if (selected_connection_ == NULL) {
854 error_ = EWOULDBLOCK; 892 error_ = EWOULDBLOCK;
855 return -1; 893 return -1;
856 } 894 }
857 895
858 last_sent_packet_id_ = options.packet_id; 896 last_sent_packet_id_ = options.packet_id;
859 int sent = best_connection_->Send(data, len, options); 897 int sent = selected_connection_->Send(data, len, options);
860 if (sent <= 0) { 898 if (sent <= 0) {
861 ASSERT(sent < 0); 899 ASSERT(sent < 0);
862 error_ = best_connection_->GetError(); 900 error_ = selected_connection_->GetError();
863 } 901 }
864 return sent; 902 return sent;
865 } 903 }
866 904
867 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { 905 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) {
868 ASSERT(worker_thread_ == rtc::Thread::Current()); 906 ASSERT(worker_thread_ == rtc::Thread::Current());
869 // Gather connection infos. 907 // Gather connection infos.
870 infos->clear(); 908 infos->clear();
871 909
872 for (Connection* connection : connections_) { 910 for (Connection* connection : connections_) {
873 ConnectionInfo info = connection->stats(); 911 ConnectionInfo info = connection->stats();
874 info.best_connection = (best_connection_ == connection); 912 info.best_connection = (selected_connection_ == connection);
875 info.receiving = connection->receiving(); 913 info.receiving = connection->receiving();
876 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); 914 info.writable = (connection->write_state() == Connection::STATE_WRITABLE);
877 info.timeout = 915 info.timeout =
878 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); 916 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT);
879 info.new_connection = !connection->reported(); 917 info.new_connection = !connection->reported();
880 connection->set_reported(true); 918 connection->set_reported(true);
881 info.rtt = connection->rtt(); 919 info.rtt = connection->rtt();
882 info.local_candidate = connection->local_candidate(); 920 info.local_candidate = connection->local_candidate();
883 info.remote_candidate = connection->remote_candidate(); 921 info.remote_candidate = connection->remote_candidate();
884 info.key = connection; 922 info.key = connection;
(...skipping 26 matching lines...) Expand all
911 if (!sort_dirty_) { 949 if (!sort_dirty_) {
912 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); 950 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT);
913 sort_dirty_ = true; 951 sort_dirty_ = true;
914 } 952 }
915 } 953 }
916 954
917 // Compare two connections based on their writing, receiving, and connected 955 // Compare two connections based on their writing, receiving, and connected
918 // states. 956 // states.
919 int P2PTransportChannel::CompareConnectionStates(const Connection* a, 957 int P2PTransportChannel::CompareConnectionStates(const Connection* a,
920 const Connection* b) const { 958 const Connection* b) const {
921 static constexpr int a_is_better = 1;
922 static constexpr int b_is_better = -1;
923
924 // First, prefer a connection that's writable or presumed writable over 959 // First, prefer a connection that's writable or presumed writable over
925 // one that's not writable. 960 // one that's not writable.
926 bool a_writable = a->writable() || PresumedWritable(a); 961 bool a_writable = a->writable() || PresumedWritable(a);
927 bool b_writable = b->writable() || PresumedWritable(b); 962 bool b_writable = b->writable() || PresumedWritable(b);
928 if (a_writable && !b_writable) { 963 if (a_writable && !b_writable) {
929 return a_is_better; 964 return a_is_better;
930 } 965 }
931 if (!a_writable && b_writable) { 966 if (!a_writable && b_writable) {
932 return b_is_better; 967 return b_is_better;
933 } 968 }
(...skipping 18 matching lines...) Expand all
952 987
953 // WARNING: Some complexity here about TCP reconnecting. 988 // WARNING: Some complexity here about TCP reconnecting.
954 // When a TCP connection fails because of a TCP socket disconnecting, the 989 // When a TCP connection fails because of a TCP socket disconnecting, the
955 // active side of the connection will attempt to reconnect for 5 seconds while 990 // active side of the connection will attempt to reconnect for 5 seconds while
956 // pretending to be writable (the connection is not set to the unwritable 991 // pretending to be writable (the connection is not set to the unwritable
957 // state). On the passive side, the connection also remains writable even 992 // state). On the passive side, the connection also remains writable even
958 // though it is disconnected, and a new connection is created when the active 993 // though it is disconnected, and a new connection is created when the active
959 // side connects. At that point, there are two TCP connections on the passive 994 // side connects. At that point, there are two TCP connections on the passive
960 // side: 1. the old, disconnected one that is pretending to be writable, and 995 // side: 1. the old, disconnected one that is pretending to be writable, and
961 // 2. the new, connected one that is maybe not yet writable. For purposes of 996 // 2. the new, connected one that is maybe not yet writable. For purposes of
962 // pruning, pinging, and selecting the best connection, we want to treat the 997 // pruning, pinging, and selecting the selected connection, we want to treat
963 // new connection as "better" than the old one. We could add a method called 998 // the new connection as "better" than the old one. We could add a method
964 // something like Connection::ImReallyBadEvenThoughImWritable, but that is 999 // called something like Connection::ImReallyBadEvenThoughImWritable, but that
965 // equivalent to the existing Connection::connected(), which we already have. 1000 // is equivalent to the existing Connection::connected(), which we already
966 // So, in code throughout this file, we'll check whether the connection is 1001 // have. So, in code throughout this file, we'll check whether the connection
967 // connected() or not, and if it is not, treat it as "worse" than a connected 1002 // is connected() or not, and if it is not, treat it as "worse" than a
968 // one, even though it's writable. In the code below, we're doing so to make 1003 // connected one, even though it's writable. In the code below, we're doing
969 // sure we treat a new writable connection as better than an old disconnected 1004 // so to make sure we treat a new writable connection as better than an old
970 // connection. 1005 // disconnected connection.
971 1006
972 // In the case where we reconnect TCP connections, the original best 1007 // In the case where we reconnect TCP connections, the original best
973 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, 1008 // connection is disconnected without changing to WRITE_TIMEOUT. In this case,
974 // the new connection, when it becomes writable, should have higher priority. 1009 // the new connection, when it becomes writable, should have higher priority.
975 if (a->write_state() == Connection::STATE_WRITABLE && 1010 if (a->write_state() == Connection::STATE_WRITABLE &&
976 b->write_state() == Connection::STATE_WRITABLE) { 1011 b->write_state() == Connection::STATE_WRITABLE) {
977 if (a->connected() && !b->connected()) { 1012 if (a->connected() && !b->connected()) {
978 return a_is_better; 1013 return a_is_better;
979 } 1014 }
980 if (!a->connected() && b->connected()) { 1015 if (!a->connected() && b->connected()) {
981 return b_is_better; 1016 return b_is_better;
982 } 1017 }
983 } 1018 }
984 return 0; 1019 return 0;
985 } 1020 }
986 1021
987 // Compares two connections based only on the candidate and network information. 1022 // Compares two connections based only on the candidate and network information.
988 // Returns positive if |a| is better than |b|. 1023 // Returns positive if |a| is better than |b|.
989 int P2PTransportChannel::CompareConnectionCandidates( 1024 int P2PTransportChannel::CompareConnectionCandidates(
990 const Connection* a, 1025 const Connection* a,
991 const Connection* b) const { 1026 const Connection* b) const {
992 // Prefer lower network cost. 1027 // Prefer lower network cost.
993 uint32_t a_cost = a->ComputeNetworkCost(); 1028 uint32_t a_cost = a->ComputeNetworkCost();
994 uint32_t b_cost = b->ComputeNetworkCost(); 1029 uint32_t b_cost = b->ComputeNetworkCost();
995 // Smaller cost is better. 1030 // Smaller cost is better.
996 if (a_cost < b_cost) { 1031 if (a_cost < b_cost) {
997 return 1; 1032 return a_is_better;
998 } 1033 }
999 if (a_cost > b_cost) { 1034 if (a_cost > b_cost) {
1000 return -1; 1035 return b_is_better;
1001 } 1036 }
1002 1037
1003 // Compare connection priority. Lower values get sorted last. 1038 // Compare connection priority. Lower values get sorted last.
1004 if (a->priority() > b->priority()) { 1039 if (a->priority() > b->priority()) {
1005 return 1; 1040 return a_is_better;
1006 } 1041 }
1007 if (a->priority() < b->priority()) { 1042 if (a->priority() < b->priority()) {
1008 return -1; 1043 return b_is_better;
1009 } 1044 }
1010 1045
1011 // If we're still tied at this point, prefer a younger generation. 1046 // If we're still tied at this point, prefer a younger generation.
1012 // (Younger generation means a larger generation number). 1047 // (Younger generation means a larger generation number).
1013 return (a->remote_candidate().generation() + a->port()->generation()) - 1048 return (a->remote_candidate().generation() + a->port()->generation()) -
1014 (b->remote_candidate().generation() + b->port()->generation()); 1049 (b->remote_candidate().generation() + b->port()->generation());
1015 } 1050 }
1016 1051
1017 int P2PTransportChannel::CompareConnections(const Connection* a, 1052 int P2PTransportChannel::CompareConnections(const Connection* a,
1018 const Connection* b) const { 1053 const Connection* b) const {
1019 // Compare first on writability and static preferences. 1054 RTC_CHECK(a != nullptr);
1055 RTC_CHECK(b != nullptr);
1056
1057 // We prefer to switch to a writable and receiving connection over a
1058 // non-writable or non-receiving connection, even if the latter has
1059 // been nominated by the controlling side.
1020 int state_cmp = CompareConnectionStates(a, b); 1060 int state_cmp = CompareConnectionStates(a, b);
1021 if (state_cmp != 0) { 1061 if (state_cmp != 0) {
1022 return state_cmp; 1062 return state_cmp;
1023 } 1063 }
1024 // Then compare the candidate information. 1064
1025 int candidates_cmp = CompareConnectionCandidates(a, b); 1065 if (ice_role_ == ICEROLE_CONTROLLED) {
1026 if (candidates_cmp != 0) { 1066 // Compare the connections based on the nomination states and the last data
1027 return candidates_cmp; 1067 // received time if this is on the controlled side.
1068 if (a->nominated() && !b->nominated()) {
1069 return a_is_better;
1070 }
1071 if (!a->nominated() && b->nominated()) {
1072 return b_is_better;
1073 }
1074
1075 if (a->last_data_received() > b->last_data_received()) {
1076 return a_is_better;
1077 }
1078 if (a->last_data_received() < b->last_data_received()) {
1079 return b_is_better;
1080 }
1028 } 1081 }
1029 // Otherwise, compare based on latency estimate.
1030 return b->rtt() - a->rtt();
1031 1082
1032 // Should we bother checking for the last connection that last received 1083 // Compare the network cost and priority.
1033 // data? It would help rendezvous on the connection that is also receiving 1084 return CompareConnectionCandidates(a, b);
1034 // packets.
1035 //
1036 // TODO(deadbeef): Yes we should definitely do this. The TCP protocol gains
1037 // efficiency by being used bidirectionally, as opposed to two separate
1038 // unidirectional streams. This test should probably occur before
1039 // comparison of local prefs (assuming combined prefs are the same). We
1040 // need to be careful though, not to bounce back and forth with both sides
1041 // trying to rendevous with the other.
1042 } 1085 }
1043 1086
1044 bool P2PTransportChannel::PresumedWritable( 1087 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const {
1045 const cricket::Connection* conn) const {
1046 return (conn->write_state() == Connection::STATE_WRITE_INIT && 1088 return (conn->write_state() == Connection::STATE_WRITE_INIT &&
1047 config_.presume_writable_when_fully_relayed && 1089 config_.presume_writable_when_fully_relayed &&
1048 conn->local_candidate().type() == RELAY_PORT_TYPE && 1090 conn->local_candidate().type() == RELAY_PORT_TYPE &&
1049 (conn->remote_candidate().type() == RELAY_PORT_TYPE || 1091 (conn->remote_candidate().type() == RELAY_PORT_TYPE ||
1050 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); 1092 conn->remote_candidate().type() == PRFLX_PORT_TYPE));
1051 } 1093 }
1052 1094
1053 // Determines whether we should switch between two connections, based first on 1095 // Determines whether we should switch between two connections, based first on
1054 // connection states, static preferences, and then (if those are equal) on 1096 // connection states, static preferences, and then (if those are equal) on
1055 // latency estimates. 1097 // latency estimates.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 1137
1096 // Any changes after this point will require a re-sort. 1138 // Any changes after this point will require a re-sort.
1097 sort_dirty_ = false; 1139 sort_dirty_ = false;
1098 1140
1099 // Find the best alternative connection by sorting. It is important to note 1141 // Find the best alternative connection by sorting. It is important to note
1100 // that amongst equal preference, writable connections, this will choose the 1142 // that amongst equal preference, writable connections, this will choose the
1101 // one whose estimated latency is lowest. So it is the only one that we 1143 // one whose estimated latency is lowest. So it is the only one that we
1102 // need to consider switching to. 1144 // need to consider switching to.
1103 std::stable_sort(connections_.begin(), connections_.end(), 1145 std::stable_sort(connections_.begin(), connections_.end(),
1104 [this](const Connection* a, const Connection* b) { 1146 [this](const Connection* a, const Connection* b) {
1105 return CompareConnections(a, b) > 0; 1147 int cmp = CompareConnections(a, b);
1148 if (cmp != 0) {
1149 return cmp > 0;
1150 }
1151
1152 // Otherwise, sort based on latency estimate.
1153 return a->rtt() < b->rtt();
1106 }); 1154 });
1155
1107 LOG(LS_VERBOSE) << "Sorting " << connections_.size() 1156 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
1108 << " available connections:"; 1157 << " available connections:";
1109 for (size_t i = 0; i < connections_.size(); ++i) { 1158 for (size_t i = 0; i < connections_.size(); ++i) {
1110 LOG(LS_VERBOSE) << connections_[i]->ToString(); 1159 LOG(LS_VERBOSE) << connections_[i]->ToString();
1111 } 1160 }
1112 1161
1113 Connection* top_connection = 1162 Connection* top_connection =
1114 (connections_.size() > 0) ? connections_[0] : nullptr; 1163 (connections_.size() > 0) ? connections_[0] : nullptr;
1115 1164
1116 // If necessary, switch to the new choice. 1165 // If necessary, switch to the new choice. Note that |top_connection| doesn't
1117 // Note that |top_connection| doesn't have to be writable to become the best 1166 // have to be writable to become the selected connection although it will
1118 // connection although it will have higher priority if it is writable. 1167 // have higher priority if it is writable.
1119 if (ShouldSwitchSelectedConnection(best_connection_, top_connection)) { 1168 if (ShouldSwitchSelectedConnection(top_connection)) {
1120 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); 1169 LOG(LS_INFO) << "Switching selected connection after sorting: "
1121 SwitchBestConnectionTo(top_connection); 1170 << top_connection->ToString();
1171 SwitchSelectedConnection(top_connection);
1122 } 1172 }
1123 1173
1124 // Controlled side can prune only if the best connection has been nominated. 1174 // The controlled side can prune only if the selected connection has been
1125 // because otherwise it may delete the connection that will be selected by 1175 // nominated because otherwise it may prune the connection that will be
1126 // the controlling side. 1176 // selected by the controlling side.
1127 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { 1177 // TODO(honghaiz): This is not enough to prevent a connection from being
1178 // pruned too early because with aggressive nomination, the controlling side
1179 // will nominate every connection until it becomes writable.
1180 if (ice_role_ == ICEROLE_CONTROLLING ||
1181 (selected_connection_ && selected_connection_->nominated())) {
1128 PruneConnections(); 1182 PruneConnections();
1129 } 1183 }
1130 1184
1131 // Check if all connections are timedout. 1185 // Check if all connections are timedout.
1132 bool all_connections_timedout = true; 1186 bool all_connections_timedout = true;
1133 for (size_t i = 0; i < connections_.size(); ++i) { 1187 for (size_t i = 0; i < connections_.size(); ++i) {
1134 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { 1188 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) {
1135 all_connections_timedout = false; 1189 all_connections_timedout = false;
1136 break; 1190 break;
1137 } 1191 }
1138 } 1192 }
1139 1193
1140 // Now update the writable state of the channel with the information we have 1194 // Now update the writable state of the channel with the information we have
1141 // so far. 1195 // so far.
1142 if (all_connections_timedout) { 1196 if (all_connections_timedout) {
1143 HandleAllTimedOut(); 1197 HandleAllTimedOut();
1144 } 1198 }
1145 1199
1146 // Update the state of this channel. This method is called whenever the 1200 // Update the state of this channel. This method is called whenever the
1147 // state of any connection changes, so this is a good place to do this. 1201 // state of any connection changes, so this is a good place to do this.
1148 UpdateState(); 1202 UpdateState();
1149 } 1203 }
1150 1204
1151 Connection* P2PTransportChannel::best_nominated_connection() const {
1152 return (best_connection_ && best_connection_->nominated()) ? best_connection_
1153 : nullptr;
1154 }
1155
1156 void P2PTransportChannel::PruneConnections() { 1205 void P2PTransportChannel::PruneConnections() {
1157 // We can prune any connection for which there is a connected, writable 1206 // We can prune any connection for which there is a connected, writable
1158 // connection on the same network with better or equal priority. We leave 1207 // connection on the same network with better or equal priority. We leave
1159 // those with better priority just in case they become writable later (at 1208 // those with better priority just in case they become writable later (at
1160 // which point, we would prune out the current best connection). We leave 1209 // which point, we would prune out the current selected connection). We leave
1161 // connections on other networks because they may not be using the same 1210 // connections on other networks because they may not be using the same
1162 // resources and they may represent very distinct paths over which we can 1211 // resources and they may represent very distinct paths over which we can
1163 // switch. If the |premier| connection is not connected, we may be 1212 // switch. If the |premier| connection is not connected, we may be
1164 // reconnecting a TCP connection and temporarily do not prune connections in 1213 // reconnecting a TCP connection and temporarily do not prune connections in
1165 // this network. See the big comment in CompareConnections. 1214 // this network. See the big comment in CompareConnectionStates.
1166 1215
1167 // Get a list of the networks that we are using. 1216 // Get a list of the networks that we are using.
1168 std::set<rtc::Network*> networks; 1217 std::set<rtc::Network*> networks;
1169 for (const Connection* conn : connections_) { 1218 for (const Connection* conn : connections_) {
1170 networks.insert(conn->port()->Network()); 1219 networks.insert(conn->port()->Network());
1171 } 1220 }
1172 for (rtc::Network* network : networks) { 1221 for (rtc::Network* network : networks) {
1173 Connection* premier = GetBestConnectionOnNetwork(network); 1222 Connection* premier = GetBestConnectionOnNetwork(network);
1174 // Do not prune connections if the current best connection is weak on this 1223 // Do not prune connections if the current selected connection is weak on
1175 // network. Otherwise, it may delete connections prematurely. 1224 // this network. Otherwise, it may delete connections prematurely.
1176 if (!premier || premier->weak()) { 1225 if (!premier || premier->weak()) {
1177 continue; 1226 continue;
1178 } 1227 }
1179 1228
1180 for (Connection* conn : connections_) { 1229 for (Connection* conn : connections_) {
1181 if ((conn != premier) && (conn->port()->Network() == network) && 1230 if ((conn != premier) && (conn->port()->Network() == network) &&
1182 (CompareConnectionCandidates(premier, conn) >= 0)) { 1231 (CompareConnectionCandidates(premier, conn) >= 0)) {
1183 conn->Prune(); 1232 conn->Prune();
1184 } 1233 }
1185 } 1234 }
1186 } 1235 }
1187 } 1236 }
1188 1237
1189 // Track the best connection, and let listeners know 1238 // Change the selected connection, and let listeners know.
1190 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { 1239 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) {
1191 // Note: if conn is NULL, the previous best_connection_ has been destroyed, 1240 // Note: if conn is NULL, the previous |selected_connection_| has been
1192 // so don't use it. 1241 // destroyed, so don't use it.
1193 Connection* old_best_connection = best_connection_; 1242 Connection* old_selected_connection = selected_connection_;
1194 best_connection_ = conn; 1243 selected_connection_ = conn;
1195 if (best_connection_) { 1244 if (selected_connection_) {
1196 if (old_best_connection) { 1245 if (old_selected_connection) {
1197 LOG_J(LS_INFO, this) << "Previous best connection: " 1246 LOG_J(LS_INFO, this) << "Previous selected connection: "
1198 << old_best_connection->ToString(); 1247 << old_selected_connection->ToString();
1199 } 1248 }
1200 LOG_J(LS_INFO, this) << "New best connection: " 1249 LOG_J(LS_INFO, this) << "New selected connection: "
1201 << best_connection_->ToString(); 1250 << selected_connection_->ToString();
1202 SignalRouteChange(this, best_connection_->remote_candidate()); 1251 SignalRouteChange(this, selected_connection_->remote_candidate());
1203 // This is a temporary, but safe fix to webrtc issue 5705. 1252 // This is a temporary, but safe fix to webrtc issue 5705.
1204 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport 1253 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport
1205 // channel so that it knows whether the media channel is allowed to 1254 // channel so that it knows whether the media channel is allowed to
1206 // send; then it will only signal ready-to-send if the media channel 1255 // send; then it will only signal ready-to-send if the media channel
1207 // has been disallowed to send. 1256 // has been disallowed to send.
1208 if (best_connection_->writable() || PresumedWritable(best_connection_)) { 1257 if (selected_connection_->writable() ||
1258 PresumedWritable(selected_connection_)) {
1209 SignalReadyToSend(this); 1259 SignalReadyToSend(this);
1210 } 1260 }
1211 } else { 1261 } else {
1212 LOG_J(LS_INFO, this) << "No best connection"; 1262 LOG_J(LS_INFO, this) << "No selected connection";
1213 } 1263 }
1214 // TODO(honghaiz): rename best_connection_ with selected_connection_ or 1264 SignalSelectedCandidatePairChanged(this, selected_connection_,
1215 // selected_candidate pair_.
1216 SignalSelectedCandidatePairChanged(this, best_connection_,
1217 last_sent_packet_id_); 1265 last_sent_packet_id_);
1218 } 1266 }
1219 1267
1220 // Warning: UpdateState should eventually be called whenever a connection 1268 // Warning: UpdateState should eventually be called whenever a connection
1221 // is added, deleted, or the write state of any connection changes so that the 1269 // is added, deleted, or the write state of any connection changes so that the
1222 // transport controller will get the up-to-date channel state. However it 1270 // transport controller will get the up-to-date channel state. However it
1223 // should not be called too often; in the case that multiple connection states 1271 // should not be called too often; in the case that multiple connection states
1224 // change, it should be called after all the connection states have changed. For 1272 // change, it should be called after all the connection states have changed. For
1225 // example, we call this at the end of SortConnections. 1273 // example, we call this at the end of SortConnections.
1226 void P2PTransportChannel::UpdateState() { 1274 void P2PTransportChannel::UpdateState() {
(...skipping 26 matching lines...) Expand all
1253 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); 1301 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED);
1254 break; 1302 break;
1255 default: 1303 default:
1256 RTC_DCHECK(false); 1304 RTC_DCHECK(false);
1257 break; 1305 break;
1258 } 1306 }
1259 state_ = state; 1307 state_ = state;
1260 SignalStateChanged(this); 1308 SignalStateChanged(this);
1261 } 1309 }
1262 1310
1263 // If our best connection is "presumed writable" (TURN-TURN with no 1311 // If our selected connection is "presumed writable" (TURN-TURN with no
1264 // CreatePermission required), act like we're already writable to the upper 1312 // CreatePermission required), act like we're already writable to the upper
1265 // layers, so they can start media quicker. 1313 // layers, so they can start media quicker.
1266 set_writable(best_connection_ && (best_connection_->writable() || 1314 bool writable =
1267 PresumedWritable(best_connection_))); 1315 selected_connection_ && (selected_connection_->writable() ||
1316 PresumedWritable(selected_connection_));
1317 set_writable(writable);
1268 1318
1269 bool receiving = false; 1319 bool receiving = false;
1270 for (const Connection* connection : connections_) { 1320 for (const Connection* connection : connections_) {
1271 if (connection->receiving()) { 1321 if (connection->receiving()) {
1272 receiving = true; 1322 receiving = true;
1273 break; 1323 break;
1274 } 1324 }
1275 } 1325 }
1276 set_receiving(receiving); 1326 set_receiving(receiving);
1277 } 1327 }
(...skipping 18 matching lines...) Expand all
1296 } 1346 }
1297 1347
1298 // If all connections timed out, delete them all. 1348 // If all connections timed out, delete them all.
1299 void P2PTransportChannel::HandleAllTimedOut() { 1349 void P2PTransportChannel::HandleAllTimedOut() {
1300 for (Connection* connection : connections_) { 1350 for (Connection* connection : connections_) {
1301 connection->Destroy(); 1351 connection->Destroy();
1302 } 1352 }
1303 } 1353 }
1304 1354
1305 bool P2PTransportChannel::weak() const { 1355 bool P2PTransportChannel::weak() const {
1306 return !best_connection_ || best_connection_->weak(); 1356 return !selected_connection_ || selected_connection_->weak();
1307 } 1357 }
1308 1358
1309 // If we have a best connection, return it, otherwise return top one in the 1359 // If we have a selected connection, return it, otherwise return top one in the
1310 // list (later we will mark it best). 1360 // list (later we will mark it best).
1311 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( 1361 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1312 rtc::Network* network) const { 1362 rtc::Network* network) const {
1313 // If the best connection is on this network, then it wins. 1363 // If the selected connection is on this network, then it wins.
1314 if (best_connection_ && (best_connection_->port()->Network() == network)) 1364 if (selected_connection_ &&
1315 return best_connection_; 1365 (selected_connection_->port()->Network() == network)) {
1366 return selected_connection_;
1367 }
1316 1368
1317 // Otherwise, we return the top-most in sorted order. 1369 // Otherwise, we return the top-most in sorted order.
1318 for (size_t i = 0; i < connections_.size(); ++i) { 1370 for (size_t i = 0; i < connections_.size(); ++i) {
1319 if (connections_[i]->port()->Network() == network) 1371 if (connections_[i]->port()->Network() == network) {
1320 return connections_[i]; 1372 return connections_[i];
1373 }
1321 } 1374 }
1322 1375
1323 return NULL; 1376 return NULL;
1324 } 1377 }
1325 1378
1326 // Handle any queued up requests 1379 // Handle any queued up requests
1327 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { 1380 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1328 switch (pmsg->message_id) { 1381 switch (pmsg->message_id) {
1329 case MSG_SORT: 1382 case MSG_SORT:
1330 OnSort(); 1383 OnSort();
(...skipping 11 matching lines...) Expand all
1342 void P2PTransportChannel::OnSort() { 1395 void P2PTransportChannel::OnSort() {
1343 // Resort the connections based on the new statistics. 1396 // Resort the connections based on the new statistics.
1344 SortConnections(); 1397 SortConnections();
1345 } 1398 }
1346 1399
1347 // Handle queued up check-and-ping request 1400 // Handle queued up check-and-ping request
1348 void P2PTransportChannel::OnCheckAndPing() { 1401 void P2PTransportChannel::OnCheckAndPing() {
1349 // Make sure the states of the connections are up-to-date (since this affects 1402 // Make sure the states of the connections are up-to-date (since this affects
1350 // which ones are pingable). 1403 // which ones are pingable).
1351 UpdateConnectionStates(); 1404 UpdateConnectionStates();
1352 // When the best connection is not receiving or not writable, or any active 1405 // When the selected connection is not receiving or not writable, or any
1353 // connection has not been pinged enough times, use the weak ping interval. 1406 // active connection has not been pinged enough times, use the weak ping
1407 // interval.
1354 bool need_more_pings_at_weak_interval = std::any_of( 1408 bool need_more_pings_at_weak_interval = std::any_of(
1355 connections_.begin(), connections_.end(), [](Connection* conn) { 1409 connections_.begin(), connections_.end(), [](Connection* conn) {
1356 return conn->active() && 1410 return conn->active() &&
1357 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; 1411 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL;
1358 }); 1412 });
1359 int ping_interval = (weak() || need_more_pings_at_weak_interval) 1413 int ping_interval = (weak() || need_more_pings_at_weak_interval)
1360 ? weak_ping_interval_ 1414 ? weak_ping_interval_
1361 : STRONG_PING_INTERVAL; 1415 : STRONG_PING_INTERVAL;
1362 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { 1416 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) {
1363 Connection* conn = FindNextPingableConnection(); 1417 Connection* conn = FindNextPingableConnection();
1364 if (conn) { 1418 if (conn) {
1365 PingConnection(conn); 1419 PingConnection(conn);
1366 MarkConnectionPinged(conn); 1420 MarkConnectionPinged(conn);
1367 } 1421 }
1368 } 1422 }
1369 int delay = std::min(ping_interval, check_receiving_interval_); 1423 int delay = std::min(ping_interval, check_receiving_interval_);
1370 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); 1424 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING);
1371 } 1425 }
1372 1426
1373 // A connection is considered a backup connection if the channel state 1427 // A connection is considered a backup connection if the channel state
1374 // is completed, the connection is not the best connection and it is active. 1428 // is completed, the connection is not the selected connection and it is active.
1375 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { 1429 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const {
1376 return state_ == STATE_COMPLETED && conn != best_connection_ && 1430 return state_ == STATE_COMPLETED && conn != selected_connection_ &&
1377 conn->active(); 1431 conn->active();
1378 } 1432 }
1379 1433
1380 // Is the connection in a state for us to even consider pinging the other side? 1434 // Is the connection in a state for us to even consider pinging the other side?
1381 // We consider a connection pingable even if it's not connected because that's 1435 // We consider a connection pingable even if it's not connected because that's
1382 // how a TCP connection is kicked into reconnecting on the active side. 1436 // how a TCP connection is kicked into reconnecting on the active side.
1383 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { 1437 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) {
1384 const Candidate& remote = conn->remote_candidate(); 1438 const Candidate& remote = conn->remote_candidate();
1385 // We should never get this far with an empty remote ufrag. 1439 // We should never get this far with an empty remote ufrag.
1386 ASSERT(!remote.username().empty()); 1440 ASSERT(!remote.username().empty());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1421 if (!conn->writable()) { 1475 if (!conn->writable()) {
1422 return true; 1476 return true;
1423 } 1477 }
1424 1478
1425 // Ping writable, active connections if it's been long enough since the last 1479 // Ping writable, active connections if it's been long enough since the last
1426 // ping. 1480 // ping.
1427 int ping_interval = CalculateActiveWritablePingInterval(conn, now); 1481 int ping_interval = CalculateActiveWritablePingInterval(conn, now);
1428 return (now >= conn->last_ping_sent() + ping_interval); 1482 return (now >= conn->last_ping_sent() + ping_interval);
1429 } 1483 }
1430 1484
1431 bool P2PTransportChannel::IsBestConnectionPingable(int64_t now) { 1485 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) {
1432 if (!best_connection_ || !best_connection_->connected() || 1486 if (!selected_connection_ || !selected_connection_->connected() ||
1433 !best_connection_->writable()) { 1487 !selected_connection_->writable()) {
1434 return false; 1488 return false;
1435 } 1489 }
1436 1490
1437 int interval = CalculateActiveWritablePingInterval(best_connection_, now); 1491 int interval = CalculateActiveWritablePingInterval(selected_connection_, now);
1438 return best_connection_->last_ping_sent() + interval <= now; 1492 return selected_connection_->last_ping_sent() + interval <= now;
1439 } 1493 }
1440 1494
1441 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, 1495 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn,
1442 int64_t now) { 1496 int64_t now) {
1443 // Ping each connection at a higher rate at least 1497 // Ping each connection at a higher rate at least
1444 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. 1498 // MIN_PINGS_AT_WEAK_PING_INTERVAL times.
1445 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { 1499 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) {
1446 return weak_ping_interval_; 1500 return weak_ping_interval_;
1447 } 1501 }
1448 1502
1449 int stable_interval = config_.stable_writable_connection_ping_interval; 1503 int stable_interval = config_.stable_writable_connection_ping_interval;
1450 int stablizing_interval = 1504 int stablizing_interval =
1451 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); 1505 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL);
1452 1506
1453 return conn->stable(now) ? stable_interval : stablizing_interval; 1507 return conn->stable(now) ? stable_interval : stablizing_interval;
1454 } 1508 }
1455 1509
1456 // Returns the next pingable connection to ping. This will be the oldest 1510 // Returns the next pingable connection to ping. This will be the oldest
1457 // pingable connection unless we have a connected, writable connection that is 1511 // pingable connection unless we have a connected, writable connection that is
1458 // past the writable ping interval. When reconnecting a TCP 1512 // past the writable ping interval. When reconnecting a TCP
1459 // connection, the best connection is disconnected, although still WRITABLE 1513 // connection, the selected connection is disconnected, although still WRITABLE
1460 // while reconnecting. The newly created connection should be selected as the 1514 // while reconnecting. The newly created connection should be selected as the
1461 // ping target to become writable instead. See the big comment in 1515 // ping target to become writable instead. See the big comment in
1462 // CompareConnections. 1516 // CompareConnectionStates.
1463 Connection* P2PTransportChannel::FindNextPingableConnection() { 1517 Connection* P2PTransportChannel::FindNextPingableConnection() {
1464 int64_t now = rtc::TimeMillis(); 1518 int64_t now = rtc::TimeMillis();
1465 Connection* conn_to_ping = nullptr; 1519 Connection* conn_to_ping = nullptr;
1466 if (IsBestConnectionPingable(now)) { 1520 if (IsSelectedConnectionPingable(now)) {
1467 conn_to_ping = best_connection_; 1521 conn_to_ping = selected_connection_;
1468 } else { 1522 } else {
1469 conn_to_ping = FindConnectionToPing(now); 1523 conn_to_ping = FindConnectionToPing(now);
1470 } 1524 }
1471 return conn_to_ping; 1525 return conn_to_ping;
1472 } 1526 }
1473 1527
1474 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { 1528 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) {
1475 if (conn && pinged_connections_.insert(conn).second) { 1529 if (conn && pinged_connections_.insert(conn).second) {
1476 unpinged_connections_.erase(conn); 1530 unpinged_connections_.erase(conn);
1477 } 1531 }
1478 } 1532 }
1479 1533
1480 // Apart from sending ping from |conn| this method also updates 1534 // Apart from sending ping from |conn| this method also updates
1481 // |use_candidate_attr| flag. The criteria to update this flag is 1535 // |use_candidate_attr| flag. The criteria to update this flag is
1482 // explained below. 1536 // explained below.
1483 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND 1537 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND
1484 // a) Channel is in FULL ICE AND 1538 // a) Channel is in FULL ICE AND
1485 // a.1) |conn| is the best connection OR 1539 // a.1) |conn| is the selected connection OR
1486 // a.2) there is no best connection OR 1540 // a.2) there is no selected connection OR
1487 // a.3) the best connection is unwritable OR 1541 // a.3) the selected connection is unwritable OR
1488 // a.4) |conn| has higher priority than best_connection. 1542 // a.4) |conn| has higher priority than selected_connection.
1489 // b) we're doing LITE ICE AND 1543 // b) we're doing LITE ICE AND
1490 // b.1) |conn| is the best_connection AND 1544 // b.1) |conn| is the selected_connection AND
1491 // b.2) |conn| is writable. 1545 // b.2) |conn| is writable.
1492 void P2PTransportChannel::PingConnection(Connection* conn) { 1546 void P2PTransportChannel::PingConnection(Connection* conn) {
1493 bool use_candidate = false; 1547 bool use_candidate = false;
1494 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { 1548 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1495 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || 1549 use_candidate =
1496 (!best_connection_->writable()) || 1550 (conn == selected_connection_) || (selected_connection_ == NULL) ||
1497 (CompareConnectionCandidates(best_connection_, conn) < 0); 1551 (!selected_connection_->writable()) ||
1498 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { 1552 (CompareConnectionCandidates(selected_connection_, conn) < 0);
1499 use_candidate = best_connection_->writable(); 1553 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) {
1554 use_candidate = selected_connection_->writable();
1500 } 1555 }
1501 conn->set_use_candidate_attr(use_candidate); 1556 conn->set_use_candidate_attr(use_candidate);
1502 last_ping_sent_ms_ = rtc::TimeMillis(); 1557 last_ping_sent_ms_ = rtc::TimeMillis();
1503 conn->Ping(last_ping_sent_ms_); 1558 conn->Ping(last_ping_sent_ms_);
1504 } 1559 }
1505 1560
1506 // When a connection's state changes, we need to figure out who to use as 1561 // When a connection's state changes, we need to figure out who to use as
1507 // the best connection again. It could have become usable, or become unusable. 1562 // the selected connection again. It could have become usable, or become
1563 // unusable.
1508 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { 1564 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1509 ASSERT(worker_thread_ == rtc::Thread::Current()); 1565 ASSERT(worker_thread_ == rtc::Thread::Current());
1510 1566
1511 // Update the best connection if the state change is from pending best
1512 // connection and role is controlled.
1513 if (ice_role_ == ICEROLE_CONTROLLED) {
1514 if (connection == pending_best_connection_ && connection->writable()) {
1515 pending_best_connection_ = NULL;
1516 LOG(LS_INFO) << "Switching best connection on controlled side"
1517 << " because it's now writable: " << connection->ToString();
1518 SwitchBestConnectionTo(connection);
1519 }
1520 }
1521
1522 // May stop the allocator session when at least one connection becomes 1567 // May stop the allocator session when at least one connection becomes
1523 // strongly connected after starting to get ports and the local candidate of 1568 // strongly connected after starting to get ports and the local candidate of
1524 // the connection is at the latest generation. It is not enough to check 1569 // the connection is at the latest generation. It is not enough to check
1525 // that the connection becomes weakly connected because the connection may be 1570 // that the connection becomes weakly connected because the connection may be
1526 // changing from (writable, receiving) to (writable, not receiving). 1571 // changing from (writable, receiving) to (writable, not receiving).
1527 bool strongly_connected = !connection->weak(); 1572 bool strongly_connected = !connection->weak();
1528 bool latest_generation = connection->local_candidate().generation() >= 1573 bool latest_generation = connection->local_candidate().generation() >=
1529 allocator_session()->generation(); 1574 allocator_session()->generation();
1530 if (strongly_connected && latest_generation) { 1575 if (strongly_connected && latest_generation) {
1531 MaybeStopPortAllocatorSessions(); 1576 MaybeStopPortAllocatorSessions();
1532 } 1577 }
1533 1578
1534 // We have to unroll the stack before doing this because we may be changing 1579 // We have to unroll the stack before doing this because we may be changing
1535 // the state of connections while sorting. 1580 // the state of connections while sorting.
1536 RequestSort(); 1581 RequestSort();
1537 } 1582 }
1538 1583
1539 // When a connection is removed, edit it out, and then update our best 1584 // When a connection is removed, edit it out, and then update our best
1540 // connection. 1585 // connection.
1541 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { 1586 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) {
1542 ASSERT(worker_thread_ == rtc::Thread::Current()); 1587 ASSERT(worker_thread_ == rtc::Thread::Current());
1543 1588
1544 // Note: the previous best_connection_ may be destroyed by now, so don't 1589 // Note: the previous selected_connection_ may be destroyed by now, so don't
1545 // use it. 1590 // use it.
1546 1591
1547 // Remove this connection from the list. 1592 // Remove this connection from the list.
1548 std::vector<Connection*>::iterator iter = 1593 std::vector<Connection*>::iterator iter =
1549 std::find(connections_.begin(), connections_.end(), connection); 1594 std::find(connections_.begin(), connections_.end(), connection);
1550 ASSERT(iter != connections_.end()); 1595 ASSERT(iter != connections_.end());
1551 pinged_connections_.erase(*iter); 1596 pinged_connections_.erase(*iter);
1552 unpinged_connections_.erase(*iter); 1597 unpinged_connections_.erase(*iter);
1553 connections_.erase(iter); 1598 connections_.erase(iter);
1554 1599
1555 LOG_J(LS_INFO, this) << "Removed connection (" 1600 LOG_J(LS_INFO, this) << "Removed connection ("
1556 << static_cast<int>(connections_.size()) << " remaining)"; 1601 << static_cast<int>(connections_.size()) << " remaining)";
1557 1602
1558 if (pending_best_connection_ == connection) { 1603 // If this is currently the selected connection, then we need to pick a new
1559 pending_best_connection_ = NULL; 1604 // one. The call to SortConnections will pick a new one. It looks at the
1560 } 1605 // current selected connection in order to avoid switching between fairly
1561 1606 // similar ones. Since this connection is no longer an option, we can just
1562 // If this is currently the best connection, then we need to pick a new one. 1607 // set selected to nullptr and re-choose a best assuming that there was no
1563 // The call to SortConnections will pick a new one. It looks at the current 1608 // selected connection.
1564 // best connection in order to avoid switching between fairly similar ones. 1609 if (selected_connection_ == connection) {
1565 // Since this connection is no longer an option, we can just set best to NULL 1610 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one.";
1566 // and re-choose a best assuming that there was no best connection. 1611 SwitchSelectedConnection(nullptr);
1567 if (best_connection_ == connection) {
1568 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one.";
1569 SwitchBestConnectionTo(NULL);
1570 RequestSort(); 1612 RequestSort();
1571 } 1613 }
1572 1614
1573 UpdateState(); 1615 UpdateState();
1574 } 1616 }
1575 1617
1576 // When a port is destroyed remove it from our list of ports to use for 1618 // When a port is destroyed remove it from our list of ports to use for
1577 // connection attempts. 1619 // connection attempts.
1578 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { 1620 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) {
1579 ASSERT(worker_thread_ == rtc::Thread::Current()); 1621 ASSERT(worker_thread_ == rtc::Thread::Current());
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1619 1661
1620 // Do not deliver, if packet doesn't belong to the correct transport channel. 1662 // Do not deliver, if packet doesn't belong to the correct transport channel.
1621 if (!FindConnection(connection)) 1663 if (!FindConnection(connection))
1622 return; 1664 return;
1623 1665
1624 // Let the client know of an incoming packet 1666 // Let the client know of an incoming packet
1625 SignalReadPacket(this, data, len, packet_time, 0); 1667 SignalReadPacket(this, data, len, packet_time, 0);
1626 1668
1627 // May need to switch the sending connection based on the receiving media path 1669 // May need to switch the sending connection based on the receiving media path
1628 // if this is the controlled side. 1670 // if this is the controlled side.
1629 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && 1671 if (ice_role_ == ICEROLE_CONTROLLED &&
1630 connection->writable() && best_connection_ != connection) { 1672 ShouldSwitchSelectedConnection(connection)) {
1631 SwitchBestConnectionTo(connection); 1673 LOG(LS_INFO) << "Switching selected connection on controlled side due to "
1674 << "data received: " << connection->ToString();
1675 SwitchSelectedConnection(connection);
1632 } 1676 }
1633 } 1677 }
1634 1678
1635 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { 1679 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
1636 ASSERT(worker_thread_ == rtc::Thread::Current()); 1680 ASSERT(worker_thread_ == rtc::Thread::Current());
1637 1681
1638 SignalSentPacket(this, sent_packet); 1682 SignalSentPacket(this, sent_packet);
1639 } 1683 }
1640 1684
1641 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1685 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1642 if (connection == best_connection_ && writable()) { 1686 if (connection == selected_connection_ && writable()) {
1643 SignalReadyToSend(this); 1687 SignalReadyToSend(this);
1644 } 1688 }
1645 } 1689 }
1646 1690
1647 // Find "triggered checks". We ping first those connections that have 1691 // Find "triggered checks". We ping first those connections that have
1648 // received a ping but have not sent a ping since receiving it 1692 // received a ping but have not sent a ping since receiving it
1649 // (last_received_ping > last_sent_ping). But we shouldn't do 1693 // (last_received_ping > last_sent_ping). But we shouldn't do
1650 // triggered checks if the connection is already writable. 1694 // triggered checks if the connection is already writable.
1651 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( 1695 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck(
1652 int64_t now) { 1696 int64_t now) {
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1755 1799
1756 // During the initial state when nothing has been pinged yet, return the first 1800 // During the initial state when nothing has been pinged yet, return the first
1757 // one in the ordered |connections_|. 1801 // one in the ordered |connections_|.
1758 return *(std::find_if(connections_.begin(), connections_.end(), 1802 return *(std::find_if(connections_.begin(), connections_.end(),
1759 [conn1, conn2](Connection* conn) { 1803 [conn1, conn2](Connection* conn) {
1760 return conn == conn1 || conn == conn2; 1804 return conn == conn1 || conn == conn2;
1761 })); 1805 }));
1762 } 1806 }
1763 1807
1764 } // namespace cricket 1808 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698