OLD | NEW |
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 14 matching lines...) Expand all Loading... |
25 #include "webrtc/system_wrappers/include/field_trial.h" | 25 #include "webrtc/system_wrappers/include/field_trial.h" |
26 | 26 |
27 namespace { | 27 namespace { |
28 | 28 |
29 // messages for queuing up work for ourselves | 29 // messages for queuing up work for ourselves |
30 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; | 30 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; |
31 | 31 |
32 // The minimum improvement in RTT that justifies a switch. | 32 // The minimum improvement in RTT that justifies a switch. |
33 static const double kMinImprovement = 10; | 33 static const double kMinImprovement = 10; |
34 | 34 |
35 bool IsRelayRelay(const cricket::Connection* conn) { | 35 bool IsRelayRelay(cricket::Connection* conn) { |
36 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && | 36 return conn->local_candidate().type() == cricket::RELAY_PORT_TYPE && |
37 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; | 37 conn->remote_candidate().type() == cricket::RELAY_PORT_TYPE; |
38 } | 38 } |
39 | 39 |
40 bool IsUdp(cricket::Connection* conn) { | 40 bool IsUdp(cricket::Connection* conn) { |
41 return conn->local_candidate().relay_protocol() == cricket::UDP_PROTOCOL_NAME; | 41 return conn->local_candidate().relay_protocol() == cricket::UDP_PROTOCOL_NAME; |
42 } | 42 } |
43 | 43 |
44 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, | 44 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, |
45 cricket::PortInterface* origin_port) { | 45 cricket::PortInterface* origin_port) { |
46 if (!origin_port) | 46 if (!origin_port) |
47 return cricket::PortInterface::ORIGIN_MESSAGE; | 47 return cricket::PortInterface::ORIGIN_MESSAGE; |
48 else if (port == origin_port) | 48 else if (port == origin_port) |
49 return cricket::PortInterface::ORIGIN_THIS_PORT; | 49 return cricket::PortInterface::ORIGIN_THIS_PORT; |
50 else | 50 else |
51 return cricket::PortInterface::ORIGIN_OTHER_PORT; | 51 return cricket::PortInterface::ORIGIN_OTHER_PORT; |
52 } | 52 } |
53 | 53 |
| 54 // Compares two connections based only on the candidate and network information. |
| 55 // Returns positive if |a| is better than |b|. |
| 56 int CompareConnectionCandidates(cricket::Connection* a, |
| 57 cricket::Connection* b) { |
| 58 uint32_t a_cost = a->ComputeNetworkCost(); |
| 59 uint32_t b_cost = b->ComputeNetworkCost(); |
| 60 // Smaller cost is better. |
| 61 if (a_cost < b_cost) { |
| 62 return 1; |
| 63 } |
| 64 if (a_cost > b_cost) { |
| 65 return -1; |
| 66 } |
| 67 |
| 68 // Compare connection priority. Lower values get sorted last. |
| 69 if (a->priority() > b->priority()) |
| 70 return 1; |
| 71 if (a->priority() < b->priority()) |
| 72 return -1; |
| 73 |
| 74 // If we're still tied at this point, prefer a younger generation. |
| 75 return (a->remote_candidate().generation() + a->port()->generation()) - |
| 76 (b->remote_candidate().generation() + b->port()->generation()); |
| 77 } |
| 78 |
| 79 // Compare two connections based on their writing, receiving, and connected |
| 80 // states. |
| 81 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) { |
| 82 // Sort based on write-state. Better states have lower values. |
| 83 if (a->write_state() < b->write_state()) |
| 84 return 1; |
| 85 if (a->write_state() > b->write_state()) |
| 86 return -1; |
| 87 |
| 88 // We prefer a receiving connection to a non-receiving, higher-priority |
| 89 // connection when sorting connections and choosing which connection to |
| 90 // switch to. |
| 91 if (a->receiving() && !b->receiving()) |
| 92 return 1; |
| 93 if (!a->receiving() && b->receiving()) |
| 94 return -1; |
| 95 |
| 96 // WARNING: Some complexity here about TCP reconnecting. |
| 97 // When a TCP connection fails because of a TCP socket disconnecting, the |
| 98 // active side of the connection will attempt to reconnect for 5 seconds while |
| 99 // pretending to be writable (the connection is not set to the unwritable |
| 100 // state). On the passive side, the connection also remains writable even |
| 101 // though it is disconnected, and a new connection is created when the active |
| 102 // side connects. At that point, there are two TCP connections on the passive |
| 103 // side: 1. the old, disconnected one that is pretending to be writable, and |
| 104 // 2. the new, connected one that is maybe not yet writable. For purposes of |
| 105 // pruning, pinging, and selecting the best connection, we want to treat the |
| 106 // new connection as "better" than the old one. We could add a method called |
| 107 // something like Connection::ImReallyBadEvenThoughImWritable, but that is |
| 108 // equivalent to the existing Connection::connected(), which we already have. |
| 109 // So, in code throughout this file, we'll check whether the connection is |
| 110 // connected() or not, and if it is not, treat it as "worse" than a connected |
| 111 // one, even though it's writable. In the code below, we're doing so to make |
| 112 // sure we treat a new writable connection as better than an old disconnected |
| 113 // connection. |
| 114 |
| 115 // In the case where we reconnect TCP connections, the original best |
| 116 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, |
| 117 // the new connection, when it becomes writable, should have higher priority. |
| 118 if (a->write_state() == cricket::Connection::STATE_WRITABLE && |
| 119 b->write_state() == cricket::Connection::STATE_WRITABLE) { |
| 120 if (a->connected() && !b->connected()) { |
| 121 return 1; |
| 122 } |
| 123 if (!a->connected() && b->connected()) { |
| 124 return -1; |
| 125 } |
| 126 } |
| 127 return 0; |
| 128 } |
| 129 |
| 130 int CompareConnections(cricket::Connection* a, cricket::Connection* b) { |
| 131 int state_cmp = CompareConnectionStates(a, b); |
| 132 if (state_cmp != 0) { |
| 133 return state_cmp; |
| 134 } |
| 135 // Compare the candidate information. |
| 136 return CompareConnectionCandidates(a, b); |
| 137 } |
| 138 |
| 139 // Wraps the comparison connection into a less than operator that puts higher |
| 140 // priority writable connections first. |
| 141 class ConnectionCompare { |
| 142 public: |
| 143 bool operator()(const cricket::Connection *ca, |
| 144 const cricket::Connection *cb) { |
| 145 cricket::Connection* a = const_cast<cricket::Connection*>(ca); |
| 146 cricket::Connection* b = const_cast<cricket::Connection*>(cb); |
| 147 |
| 148 // Compare first on writability and static preferences. |
| 149 int cmp = CompareConnections(a, b); |
| 150 if (cmp > 0) |
| 151 return true; |
| 152 if (cmp < 0) |
| 153 return false; |
| 154 |
| 155 // Otherwise, sort based on latency estimate. |
| 156 return a->rtt() < b->rtt(); |
| 157 |
| 158 // Should we bother checking for the last connection that last received |
| 159 // data? It would help rendezvous on the connection that is also receiving |
| 160 // packets. |
| 161 // |
| 162 // TODO: Yes we should definitely do this. The TCP protocol gains |
| 163 // efficiency by being used bidirectionally, as opposed to two separate |
| 164 // unidirectional streams. This test should probably occur before |
| 165 // comparison of local prefs (assuming combined prefs are the same). We |
| 166 // need to be careful though, not to bounce back and forth with both sides |
| 167 // trying to rendevous with the other. |
| 168 } |
| 169 }; |
| 170 |
| 171 // Determines whether we should switch between two connections, based first on |
| 172 // connection states, static preferences, and then (if those are equal) on |
| 173 // latency estimates. |
| 174 bool ShouldSwitch(cricket::Connection* a_conn, |
| 175 cricket::Connection* b_conn, |
| 176 cricket::IceRole ice_role) { |
| 177 if (a_conn == b_conn) |
| 178 return false; |
| 179 |
| 180 if (!a_conn || !b_conn) // don't think the latter should happen |
| 181 return true; |
| 182 |
| 183 // We prefer to switch to a writable and receiving connection over a |
| 184 // non-writable or non-receiving connection, even if the latter has |
| 185 // been nominated by the controlling side. |
| 186 int state_cmp = CompareConnectionStates(a_conn, b_conn); |
| 187 if (state_cmp != 0) { |
| 188 return state_cmp < 0; |
| 189 } |
| 190 if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) { |
| 191 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status"; |
| 192 return false; |
| 193 } |
| 194 |
| 195 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn); |
| 196 if (prefs_cmp != 0) { |
| 197 return prefs_cmp < 0; |
| 198 } |
| 199 |
| 200 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; |
| 201 } |
| 202 |
54 } // unnamed namespace | 203 } // unnamed namespace |
55 | 204 |
56 namespace cricket { | 205 namespace cricket { |
57 | 206 |
58 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 207 // 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 | 208 // 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 | 209 // 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 | 210 // well on a 28.8K modem, which is the slowest connection on which the voice |
62 // quality is reasonable at all. | 211 // quality is reasonable at all. |
63 static const int PING_PACKET_SIZE = 60 * 8; | 212 static const int PING_PACKET_SIZE = 60 * 8; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 sort_dirty_(false), | 244 sort_dirty_(false), |
96 remote_ice_mode_(ICEMODE_FULL), | 245 remote_ice_mode_(ICEMODE_FULL), |
97 ice_role_(ICEROLE_UNKNOWN), | 246 ice_role_(ICEROLE_UNKNOWN), |
98 tiebreaker_(0), | 247 tiebreaker_(0), |
99 gathering_state_(kIceGatheringNew), | 248 gathering_state_(kIceGatheringNew), |
100 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 249 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
101 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 250 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
102 0 /* backup_connection_ping_interval */, | 251 0 /* backup_connection_ping_interval */, |
103 false /* gather_continually */, | 252 false /* gather_continually */, |
104 false /* prioritize_most_likely_candidate_pairs */, | 253 false /* prioritize_most_likely_candidate_pairs */, |
105 STABLE_WRITABLE_CONNECTION_PING_INTERVAL, | 254 STABLE_WRITABLE_CONNECTION_PING_INTERVAL) { |
106 true /* presume_writable_when_fully_relayed */) { | |
107 uint32_t weak_ping_interval = ::strtoul( | 255 uint32_t weak_ping_interval = ::strtoul( |
108 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), | 256 webrtc::field_trial::FindFullName("WebRTC-StunInterPacketDelay").c_str(), |
109 nullptr, 10); | 257 nullptr, 10); |
110 if (weak_ping_interval) { | 258 if (weak_ping_interval) { |
111 weak_ping_interval_ = static_cast<int>(weak_ping_interval); | 259 weak_ping_interval_ = static_cast<int>(weak_ping_interval); |
112 } | 260 } |
113 } | 261 } |
114 | 262 |
115 P2PTransportChannel::~P2PTransportChannel() { | 263 P2PTransportChannel::~P2PTransportChannel() { |
116 ASSERT(worker_thread_ == rtc::Thread::Current()); | 264 ASSERT(worker_thread_ == rtc::Thread::Current()); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 << config_.prioritize_most_likely_candidate_pairs; | 439 << config_.prioritize_most_likely_candidate_pairs; |
292 | 440 |
293 if (config.stable_writable_connection_ping_interval >= 0 && | 441 if (config.stable_writable_connection_ping_interval >= 0 && |
294 config_.stable_writable_connection_ping_interval != | 442 config_.stable_writable_connection_ping_interval != |
295 config.stable_writable_connection_ping_interval) { | 443 config.stable_writable_connection_ping_interval) { |
296 config_.stable_writable_connection_ping_interval = | 444 config_.stable_writable_connection_ping_interval = |
297 config.stable_writable_connection_ping_interval; | 445 config.stable_writable_connection_ping_interval; |
298 LOG(LS_INFO) << "Set stable_writable_connection_ping_interval to " | 446 LOG(LS_INFO) << "Set stable_writable_connection_ping_interval to " |
299 << config_.stable_writable_connection_ping_interval; | 447 << config_.stable_writable_connection_ping_interval; |
300 } | 448 } |
301 | |
302 if (config.presume_writable_when_fully_relayed != | |
303 config_.presume_writable_when_fully_relayed) { | |
304 if (!connections_.empty()) { | |
305 LOG(LS_ERROR) << "Trying to change 'presume writable' " | |
306 << "while connections already exist!"; | |
307 } else { | |
308 config_.presume_writable_when_fully_relayed = | |
309 config.presume_writable_when_fully_relayed; | |
310 LOG(LS_INFO) << "Set presume writable when fully relayed to " | |
311 << config_.presume_writable_when_fully_relayed; | |
312 } | |
313 } | |
314 } | 449 } |
315 | 450 |
316 const IceConfig& P2PTransportChannel::config() const { | 451 const IceConfig& P2PTransportChannel::config() const { |
317 return config_; | 452 return config_; |
318 } | 453 } |
319 | 454 |
320 // Go into the state of processing candidates, and running in general | 455 // Go into the state of processing candidates, and running in general |
321 void P2PTransportChannel::Connect() { | 456 void P2PTransportChannel::Connect() { |
322 ASSERT(worker_thread_ == rtc::Thread::Current()); | 457 ASSERT(worker_thread_ == rtc::Thread::Current()); |
323 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 458 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 } | 1042 } |
908 | 1043 |
909 // Prepare for best candidate sorting. | 1044 // Prepare for best candidate sorting. |
910 void P2PTransportChannel::RequestSort() { | 1045 void P2PTransportChannel::RequestSort() { |
911 if (!sort_dirty_) { | 1046 if (!sort_dirty_) { |
912 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); | 1047 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); |
913 sort_dirty_ = true; | 1048 sort_dirty_ = true; |
914 } | 1049 } |
915 } | 1050 } |
916 | 1051 |
917 // Compare two connections based on their writing, receiving, and connected | |
918 // states. | |
919 int P2PTransportChannel::CompareConnectionStates(const Connection* a, | |
920 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 | |
925 // one that's not writable. | |
926 bool a_writable = a->writable() || PresumedWritable(a); | |
927 bool b_writable = b->writable() || PresumedWritable(b); | |
928 if (a_writable && !b_writable) { | |
929 return a_is_better; | |
930 } | |
931 if (!a_writable && b_writable) { | |
932 return b_is_better; | |
933 } | |
934 | |
935 // Sort based on write-state. Better states have lower values. | |
936 if (a->write_state() < b->write_state()) { | |
937 return a_is_better; | |
938 } | |
939 if (b->write_state() < a->write_state()) { | |
940 return b_is_better; | |
941 } | |
942 | |
943 // We prefer a receiving connection to a non-receiving, higher-priority | |
944 // connection when sorting connections and choosing which connection to | |
945 // switch to. | |
946 if (a->receiving() && !b->receiving()) { | |
947 return a_is_better; | |
948 } | |
949 if (!a->receiving() && b->receiving()) { | |
950 return b_is_better; | |
951 } | |
952 | |
953 // WARNING: Some complexity here about TCP reconnecting. | |
954 // 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 | |
956 // pretending to be writable (the connection is not set to the unwritable | |
957 // 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 | |
959 // 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 | |
961 // 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 | |
963 // new connection as "better" than the old one. We could add a method called | |
964 // something like Connection::ImReallyBadEvenThoughImWritable, but that is | |
965 // equivalent to the existing Connection::connected(), which we already have. | |
966 // So, in code throughout this file, we'll check whether the connection is | |
967 // connected() or not, and if it is not, treat it as "worse" than a connected | |
968 // one, even though it's writable. In the code below, we're doing so to make | |
969 // sure we treat a new writable connection as better than an old disconnected | |
970 // connection. | |
971 | |
972 // In the case where we reconnect TCP connections, the original best | |
973 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, | |
974 // the new connection, when it becomes writable, should have higher priority. | |
975 if (a->write_state() == Connection::STATE_WRITABLE && | |
976 b->write_state() == Connection::STATE_WRITABLE) { | |
977 if (a->connected() && !b->connected()) { | |
978 return a_is_better; | |
979 } | |
980 if (!a->connected() && b->connected()) { | |
981 return b_is_better; | |
982 } | |
983 } | |
984 return 0; | |
985 } | |
986 | |
987 // Compares two connections based only on the candidate and network information. | |
988 // Returns positive if |a| is better than |b|. | |
989 int P2PTransportChannel::CompareConnectionCandidates( | |
990 const Connection* a, | |
991 const Connection* b) const { | |
992 // Prefer lower network cost. | |
993 uint32_t a_cost = a->ComputeNetworkCost(); | |
994 uint32_t b_cost = b->ComputeNetworkCost(); | |
995 // Smaller cost is better. | |
996 if (a_cost < b_cost) { | |
997 return 1; | |
998 } | |
999 if (a_cost > b_cost) { | |
1000 return -1; | |
1001 } | |
1002 | |
1003 // Compare connection priority. Lower values get sorted last. | |
1004 if (a->priority() > b->priority()) { | |
1005 return 1; | |
1006 } | |
1007 if (a->priority() < b->priority()) { | |
1008 return -1; | |
1009 } | |
1010 | |
1011 // If we're still tied at this point, prefer a younger generation. | |
1012 // (Younger generation means a larger generation number). | |
1013 return (a->remote_candidate().generation() + a->port()->generation()) - | |
1014 (b->remote_candidate().generation() + b->port()->generation()); | |
1015 } | |
1016 | |
1017 int P2PTransportChannel::CompareConnections(const Connection* a, | |
1018 const Connection* b) const { | |
1019 // Compare first on writability and static preferences. | |
1020 int state_cmp = CompareConnectionStates(a, b); | |
1021 if (state_cmp != 0) { | |
1022 return state_cmp; | |
1023 } | |
1024 // Then compare the candidate information. | |
1025 int candidates_cmp = CompareConnectionCandidates(a, b); | |
1026 if (candidates_cmp != 0) { | |
1027 return candidates_cmp; | |
1028 } | |
1029 // Otherwise, compare based on latency estimate. | |
1030 return b->rtt() - a->rtt(); | |
1031 | |
1032 // Should we bother checking for the last connection that last received | |
1033 // data? It would help rendezvous on the connection that is also receiving | |
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 } | |
1043 | |
1044 bool P2PTransportChannel::PresumedWritable( | |
1045 const cricket::Connection* conn) const { | |
1046 return (conn->write_state() == Connection::STATE_WRITE_INIT && | |
1047 config_.presume_writable_when_fully_relayed && | |
1048 conn->local_candidate().type() == RELAY_PORT_TYPE && | |
1049 (conn->remote_candidate().type() == RELAY_PORT_TYPE || | |
1050 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); | |
1051 } | |
1052 | |
1053 // Determines whether we should switch between two connections, based first on | |
1054 // connection states, static preferences, and then (if those are equal) on | |
1055 // latency estimates. | |
1056 bool P2PTransportChannel::ShouldSwitchSelectedConnection( | |
1057 const Connection* selected, | |
1058 const Connection* conn) const { | |
1059 if (selected == conn) { | |
1060 return false; | |
1061 } | |
1062 | |
1063 if (!selected || !conn) { // don't think the latter should happen | |
1064 return true; | |
1065 } | |
1066 | |
1067 // We prefer to switch to a writable and receiving connection over a | |
1068 // non-writable or non-receiving connection, even if the latter has | |
1069 // been nominated by the controlling side. | |
1070 int state_cmp = CompareConnectionStates(selected, conn); | |
1071 if (state_cmp != 0) { | |
1072 return state_cmp < 0; | |
1073 } | |
1074 if (ice_role_ == ICEROLE_CONTROLLED && selected->nominated()) { | |
1075 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status"; | |
1076 return false; | |
1077 } | |
1078 | |
1079 int prefs_cmp = CompareConnectionCandidates(selected, conn); | |
1080 if (prefs_cmp != 0) { | |
1081 return prefs_cmp < 0; | |
1082 } | |
1083 | |
1084 return selected->rtt() - conn->rtt() >= kMinImprovement; | |
1085 } | |
1086 | |
1087 // Sort the available connections to find the best one. We also monitor | 1052 // Sort the available connections to find the best one. We also monitor |
1088 // the number of available connections and the current state. | 1053 // the number of available connections and the current state. |
1089 void P2PTransportChannel::SortConnections() { | 1054 void P2PTransportChannel::SortConnections() { |
1090 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1055 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1091 | 1056 |
1092 // Make sure the connection states are up-to-date since this affects how they | 1057 // Make sure the connection states are up-to-date since this affects how they |
1093 // will be sorted. | 1058 // will be sorted. |
1094 UpdateConnectionStates(); | 1059 UpdateConnectionStates(); |
1095 | 1060 |
1096 // Any changes after this point will require a re-sort. | 1061 // Any changes after this point will require a re-sort. |
1097 sort_dirty_ = false; | 1062 sort_dirty_ = false; |
1098 | 1063 |
1099 // Find the best alternative connection by sorting. It is important to note | 1064 // Find the best alternative connection by sorting. It is important to note |
1100 // that amongst equal preference, writable connections, this will choose the | 1065 // 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 | 1066 // one whose estimated latency is lowest. So it is the only one that we |
1102 // need to consider switching to. | 1067 // need to consider switching to. |
1103 std::stable_sort(connections_.begin(), connections_.end(), | 1068 ConnectionCompare cmp; |
1104 [this](const Connection* a, const Connection* b) { | 1069 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
1105 return CompareConnections(a, b) > 0; | |
1106 }); | |
1107 LOG(LS_VERBOSE) << "Sorting " << connections_.size() | 1070 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
1108 << " available connections:"; | 1071 << " available connections:"; |
1109 for (size_t i = 0; i < connections_.size(); ++i) { | 1072 for (size_t i = 0; i < connections_.size(); ++i) { |
1110 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 1073 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
1111 } | 1074 } |
1112 | 1075 |
1113 Connection* top_connection = | 1076 Connection* top_connection = |
1114 (connections_.size() > 0) ? connections_[0] : nullptr; | 1077 (connections_.size() > 0) ? connections_[0] : nullptr; |
1115 | 1078 |
1116 // If necessary, switch to the new choice. | 1079 // If necessary, switch to the new choice. |
1117 // Note that |top_connection| doesn't have to be writable to become the best | 1080 // Note that |top_connection| doesn't have to be writable to become the best |
1118 // connection although it will have higher priority if it is writable. | 1081 // connection although it will have higher priority if it is writable. |
1119 if (ShouldSwitchSelectedConnection(best_connection_, top_connection)) { | 1082 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { |
1120 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 1083 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); |
1121 SwitchBestConnectionTo(top_connection); | 1084 SwitchBestConnectionTo(top_connection); |
1122 } | 1085 } |
1123 | 1086 |
1124 // Controlled side can prune only if the best connection has been nominated. | 1087 // Controlled side can prune only if the best connection has been nominated. |
1125 // because otherwise it may delete the connection that will be selected by | 1088 // because otherwise it may delete the connection that will be selected by |
1126 // the controlling side. | 1089 // the controlling side. |
1127 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 1090 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
1128 PruneConnections(); | 1091 PruneConnections(); |
1129 } | 1092 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 << old_best_connection->ToString(); | 1161 << old_best_connection->ToString(); |
1199 } | 1162 } |
1200 LOG_J(LS_INFO, this) << "New best connection: " | 1163 LOG_J(LS_INFO, this) << "New best connection: " |
1201 << best_connection_->ToString(); | 1164 << best_connection_->ToString(); |
1202 SignalRouteChange(this, best_connection_->remote_candidate()); | 1165 SignalRouteChange(this, best_connection_->remote_candidate()); |
1203 // This is a temporary, but safe fix to webrtc issue 5705. | 1166 // This is a temporary, but safe fix to webrtc issue 5705. |
1204 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport | 1167 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport |
1205 // channel so that it knows whether the media channel is allowed to | 1168 // 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 | 1169 // send; then it will only signal ready-to-send if the media channel |
1207 // has been disallowed to send. | 1170 // has been disallowed to send. |
1208 if (best_connection_->writable() || PresumedWritable(best_connection_)) { | 1171 if (best_connection_->writable()) { |
1209 SignalReadyToSend(this); | 1172 SignalReadyToSend(this); |
1210 } | 1173 } |
1211 } else { | 1174 } else { |
1212 LOG_J(LS_INFO, this) << "No best connection"; | 1175 LOG_J(LS_INFO, this) << "No best connection"; |
1213 } | 1176 } |
1214 // TODO(honghaiz): rename best_connection_ with selected_connection_ or | 1177 // TODO(honghaiz): rename best_connection_ with selected_connection_ or |
1215 // selected_candidate pair_. | 1178 // selected_candidate pair_. |
1216 SignalSelectedCandidatePairChanged(this, best_connection_, | 1179 SignalSelectedCandidatePairChanged(this, best_connection_, |
1217 last_sent_packet_id_); | 1180 last_sent_packet_id_); |
1218 } | 1181 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); | 1216 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); |
1254 break; | 1217 break; |
1255 default: | 1218 default: |
1256 RTC_DCHECK(false); | 1219 RTC_DCHECK(false); |
1257 break; | 1220 break; |
1258 } | 1221 } |
1259 state_ = state; | 1222 state_ = state; |
1260 SignalStateChanged(this); | 1223 SignalStateChanged(this); |
1261 } | 1224 } |
1262 | 1225 |
1263 // If our best connection is "presumed writable" (TURN-TURN with no | 1226 bool writable = best_connection_ && best_connection_->writable(); |
1264 // CreatePermission required), act like we're already writable to the upper | 1227 set_writable(writable); |
1265 // layers, so they can start media quicker. | |
1266 set_writable(best_connection_ && (best_connection_->writable() || | |
1267 PresumedWritable(best_connection_))); | |
1268 | 1228 |
1269 bool receiving = false; | 1229 bool receiving = false; |
1270 for (const Connection* connection : connections_) { | 1230 for (const Connection* connection : connections_) { |
1271 if (connection->receiving()) { | 1231 if (connection->receiving()) { |
1272 receiving = true; | 1232 receiving = true; |
1273 break; | 1233 break; |
1274 } | 1234 } |
1275 } | 1235 } |
1276 set_receiving(receiving); | 1236 set_receiving(receiving); |
1277 } | 1237 } |
(...skipping 472 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1750 | 1710 |
1751 // During the initial state when nothing has been pinged yet, return the first | 1711 // During the initial state when nothing has been pinged yet, return the first |
1752 // one in the ordered |connections_|. | 1712 // one in the ordered |connections_|. |
1753 return *(std::find_if(connections_.begin(), connections_.end(), | 1713 return *(std::find_if(connections_.begin(), connections_.end(), |
1754 [conn1, conn2](Connection* conn) { | 1714 [conn1, conn2](Connection* conn) { |
1755 return conn == conn1 || conn == conn2; | 1715 return conn == conn1 || conn == conn2; |
1756 })); | 1716 })); |
1757 } | 1717 } |
1758 | 1718 |
1759 } // namespace cricket | 1719 } // namespace cricket |
OLD | NEW |