Chromium Code Reviews| 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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 95 | 95 |
| 96 // WARNING: Some complexity here about TCP reconnecting. | 96 // WARNING: Some complexity here about TCP reconnecting. |
| 97 // When a TCP connection fails because of a TCP socket disconnecting, the | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 105 // pruning, pinging, and selecting the connection to use, we want to treat the |
| 106 // new connection as "better" than the old one. We could add a method called | 106 // new connection as "better" than the old one. We could add a method called |
| 107 // something like Connection::ImReallyBadEvenThoughImWritable, but that is | 107 // something like Connection::ImReallyBadEvenThoughImWritable, but that is |
| 108 // equivalent to the existing Connection::connected(), which we already have. | 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 | 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 | 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 | 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 | 112 // sure we treat a new writable connection as better than an old disconnected |
| 113 // connection. | 113 // connection. |
| 114 | 114 |
| 115 // In the case where we reconnect TCP connections, the original best | 115 // In the case where we reconnect TCP connections, the original best |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 203 } // unnamed namespace | 203 } // unnamed namespace |
| 204 | 204 |
| 205 namespace cricket { | 205 namespace cricket { |
| 206 | 206 |
| 207 // 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) |
| 208 // 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 |
| 209 // 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 |
| 210 // 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 |
| 211 // quality is reasonable at all. | 211 // quality is reasonable at all. |
| 212 static const int PING_PACKET_SIZE = 60 * 8; | 212 static const int PING_PACKET_SIZE = 60 * 8; |
| 213 // STRONG_PING_INTERVAL (480ms) is applied when the best connection is both | 213 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both |
| 214 // writable and receiving. | 214 // writable and receiving. |
| 215 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; | 215 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; |
| 216 // WEAK_PING_INTERVAL (48ms) is applied when the best connection is either not | 216 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either |
| 217 // writable or not receiving. | 217 // not writable or not receiving. |
| 218 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; | 218 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; |
| 219 | 219 |
| 220 // If the current best connection is both writable and receiving, then we will | 220 // If the current selected connection is both writable and receiving, then we |
| 221 // also try hard to make sure it is pinged at this rate (a little less than | 221 // will also try hard to make sure it is pinged at this rate (a little less |
| 222 // 2 * STRONG_PING_INTERVAL). | 222 // than 2 * STRONG_PING_INTERVAL). |
| 223 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms | 223 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms |
| 224 | 224 |
| 225 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms | 225 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
| 226 | 226 |
| 227 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 227 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
| 228 int component, | 228 int component, |
| 229 P2PTransport* transport, | 229 P2PTransport* transport, |
| 230 PortAllocator* allocator) | 230 PortAllocator* allocator) |
| 231 : P2PTransportChannel(transport_name, component, allocator) {} | 231 : P2PTransportChannel(transport_name, component, allocator) {} |
| 232 | 232 |
| 233 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 233 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
| 234 int component, | 234 int component, |
| 235 PortAllocator* allocator) | 235 PortAllocator* allocator) |
| 236 : TransportChannelImpl(transport_name, component), | 236 : TransportChannelImpl(transport_name, component), |
| 237 allocator_(allocator), | 237 allocator_(allocator), |
| 238 worker_thread_(rtc::Thread::Current()), | 238 worker_thread_(rtc::Thread::Current()), |
| 239 incoming_only_(false), | 239 incoming_only_(false), |
| 240 error_(0), | 240 error_(0), |
| 241 best_connection_(NULL), | |
| 242 pending_best_connection_(NULL), | |
| 243 sort_dirty_(false), | 241 sort_dirty_(false), |
| 244 remote_ice_mode_(ICEMODE_FULL), | 242 remote_ice_mode_(ICEMODE_FULL), |
| 245 ice_role_(ICEROLE_UNKNOWN), | 243 ice_role_(ICEROLE_UNKNOWN), |
| 246 tiebreaker_(0), | 244 tiebreaker_(0), |
| 247 gathering_state_(kIceGatheringNew), | 245 gathering_state_(kIceGatheringNew), |
| 248 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 246 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
| 249 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 247 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
| 250 0 /* backup_connection_ping_interval */, | 248 0 /* backup_connection_ping_interval */, |
| 251 false /* gather_continually */, | 249 false /* gather_continually */, |
| 252 false /* prioritize_most_likely_candidate_pairs */, | 250 false /* prioritize_most_likely_candidate_pairs */, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 connection->SignalReadyToSend.connect( | 292 connection->SignalReadyToSend.connect( |
| 295 this, &P2PTransportChannel::OnReadyToSend); | 293 this, &P2PTransportChannel::OnReadyToSend); |
| 296 connection->SignalStateChange.connect( | 294 connection->SignalStateChange.connect( |
| 297 this, &P2PTransportChannel::OnConnectionStateChange); | 295 this, &P2PTransportChannel::OnConnectionStateChange); |
| 298 connection->SignalDestroyed.connect( | 296 connection->SignalDestroyed.connect( |
| 299 this, &P2PTransportChannel::OnConnectionDestroyed); | 297 this, &P2PTransportChannel::OnConnectionDestroyed); |
| 300 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); | 298 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
| 301 had_connection_ = true; | 299 had_connection_ = true; |
| 302 } | 300 } |
| 303 | 301 |
| 302 // Determines whether we should switch the selected connection to | |
| 303 // |new_connection| based the writable state, the last nominated connection, | |
| 304 // and the last connection receiving data. This is to prevent that the | |
| 305 // controlled side may switch the selected connection too frequently when | |
| 306 // the controlling side is doing aggressive nominations. With this | |
| 307 // implementation, the controlled side will switch the selected connection | |
| 308 // if the new nominated connection is writable, and | |
| 309 // i) the selected connection is nullptr, or | |
| 310 // ii) the selected connection was not nominated, or | |
| 311 // iii) the new connection is nominated and is receiving data, or | |
| 312 // iv) the new connection has lower cost or high priority. | |
| 313 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and | |
| 314 // implement the ice-renomination option. | |
| 315 bool P2PTransportChannel::ShouldSwitchOnNominatedOrDataReceived( | |
| 316 cricket::Connection* new_connection) const { | |
| 317 RTC_CHECK(new_connection != nullptr); | |
| 318 if (!new_connection->writable()) { | |
| 319 return false; | |
| 320 } | |
| 321 if (selected_connection_ == nullptr || !selected_connection_->nominated()) { | |
| 322 return true; | |
| 323 } | |
|
pthatcher1
2016/06/17 00:27:11
As mentioned, I think this is more clear and corre
honghaiz3
2016/06/17 19:18:18
Done.
| |
| 324 if (new_connection == last_nominated_connection_ && | |
|
pthatcher1
2016/06/17 00:27:11
I think we shouldn't change the behavior based on
honghaiz3
2016/06/17 19:18:18
Done.
| |
| 325 new_connection == last_receiving_connection_) { | |
| 326 return true; | |
| 327 } | |
|
pthatcher1
2016/06/17 00:27:11
As mentioned, I think this is more robust:
if (co
honghaiz3
2016/06/17 19:18:18
Done.
| |
| 328 // Lastly, compare the network cost and priority. | |
| 329 return CompareConnectionCandidates(selected_connection_, new_connection) < 0; | |
| 330 } | |
| 331 | |
| 304 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 332 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
| 305 ASSERT(worker_thread_ == rtc::Thread::Current()); | 333 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 306 if (ice_role_ != ice_role) { | 334 if (ice_role_ != ice_role) { |
| 307 ice_role_ = ice_role; | 335 ice_role_ = ice_role; |
| 308 for (std::vector<PortInterface *>::iterator it = ports_.begin(); | 336 for (std::vector<PortInterface *>::iterator it = ports_.begin(); |
| 309 it != ports_.end(); ++it) { | 337 it != ports_.end(); ++it) { |
| 310 (*it)->SetIceRole(ice_role); | 338 (*it)->SetIceRole(ice_role); |
| 311 } | 339 } |
| 312 } | 340 } |
| 313 } | 341 } |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 722 return nullptr; | 750 return nullptr; |
| 723 } | 751 } |
| 724 *generation = params.rend() - it - 1; | 752 *generation = params.rend() - it - 1; |
| 725 return &(*it); | 753 return &(*it); |
| 726 } | 754 } |
| 727 | 755 |
| 728 void P2PTransportChannel::OnNominated(Connection* conn) { | 756 void P2PTransportChannel::OnNominated(Connection* conn) { |
| 729 ASSERT(worker_thread_ == rtc::Thread::Current()); | 757 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 730 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 758 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
| 731 | 759 |
| 732 if (conn->write_state() == Connection::STATE_WRITABLE) { | 760 if (selected_connection_ == conn) { |
| 733 if (best_connection_ != conn) { | 761 return; |
| 734 pending_best_connection_ = NULL; | |
| 735 LOG(LS_INFO) << "Switching best connection on controlled side: " | |
| 736 << conn->ToString(); | |
| 737 SwitchBestConnectionTo(conn); | |
| 738 // Now we have selected the best connection, time to prune other existing | |
| 739 // connections and update the read/write state of the channel. | |
| 740 RequestSort(); | |
| 741 } | |
| 742 } else { | |
| 743 LOG(LS_INFO) << "Not switching the best connection on controlled side yet," | |
| 744 << " because it's not writable: " << conn->ToString(); | |
| 745 pending_best_connection_ = conn; | |
| 746 } | 762 } |
| 763 | |
| 764 last_nominated_connection_ = conn; | |
| 765 if (!ShouldSwitchOnNominatedOrDataReceived(conn)) { | |
| 766 LOG(LS_INFO) | |
| 767 << "Not switching the selected connection on controlled side yet: " | |
| 768 << conn->ToString(); | |
| 769 return; | |
| 770 } | |
| 771 | |
| 772 LOG(LS_INFO) | |
| 773 << "Switching selected connection on controlled side due to nomination: " | |
| 774 << conn->ToString(); | |
| 775 SwitchSelectedConnection(conn); | |
| 776 // Now we have selected the selected connection, time to prune other existing | |
| 777 // connections and update the read/write state of the channel. | |
| 778 RequestSort(); | |
| 747 } | 779 } |
| 748 | 780 |
| 749 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 781 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
| 750 ASSERT(worker_thread_ == rtc::Thread::Current()); | 782 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 751 | 783 |
| 752 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 784 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
| 753 // If a remote candidate with a previous generation arrives, drop it. | 785 // If a remote candidate with a previous generation arrives, drop it. |
| 754 if (generation < remote_ice_generation()) { | 786 if (generation < remote_ice_generation()) { |
| 755 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 787 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
| 756 << candidate.username() | 788 << candidate.username() |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 983 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1015 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 984 | 1016 |
| 985 const auto& found = options_.find(opt); | 1017 const auto& found = options_.find(opt); |
| 986 if (found == options_.end()) { | 1018 if (found == options_.end()) { |
| 987 return false; | 1019 return false; |
| 988 } | 1020 } |
| 989 *value = found->second; | 1021 *value = found->second; |
| 990 return true; | 1022 return true; |
| 991 } | 1023 } |
| 992 | 1024 |
| 993 // Send data to the other side, using our best connection. | 1025 // Send data to the other side, using our selected connection. |
| 994 int P2PTransportChannel::SendPacket(const char *data, size_t len, | 1026 int P2PTransportChannel::SendPacket(const char *data, size_t len, |
| 995 const rtc::PacketOptions& options, | 1027 const rtc::PacketOptions& options, |
| 996 int flags) { | 1028 int flags) { |
| 997 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1029 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 998 if (flags != 0) { | 1030 if (flags != 0) { |
| 999 error_ = EINVAL; | 1031 error_ = EINVAL; |
| 1000 return -1; | 1032 return -1; |
| 1001 } | 1033 } |
| 1002 if (best_connection_ == NULL) { | 1034 if (selected_connection_ == NULL) { |
| 1003 error_ = EWOULDBLOCK; | 1035 error_ = EWOULDBLOCK; |
| 1004 return -1; | 1036 return -1; |
| 1005 } | 1037 } |
| 1006 | 1038 |
| 1007 last_sent_packet_id_ = options.packet_id; | 1039 last_sent_packet_id_ = options.packet_id; |
| 1008 int sent = best_connection_->Send(data, len, options); | 1040 int sent = selected_connection_->Send(data, len, options); |
| 1009 if (sent <= 0) { | 1041 if (sent <= 0) { |
| 1010 ASSERT(sent < 0); | 1042 ASSERT(sent < 0); |
| 1011 error_ = best_connection_->GetError(); | 1043 error_ = selected_connection_->GetError(); |
| 1012 } | 1044 } |
| 1013 return sent; | 1045 return sent; |
| 1014 } | 1046 } |
| 1015 | 1047 |
| 1016 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 1048 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
| 1017 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1049 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1018 // Gather connection infos. | 1050 // Gather connection infos. |
| 1019 infos->clear(); | 1051 infos->clear(); |
| 1020 | 1052 |
| 1021 for (Connection* connection : connections_) { | 1053 for (Connection* connection : connections_) { |
| 1022 ConnectionInfo info = connection->stats(); | 1054 ConnectionInfo info = connection->stats(); |
| 1023 info.best_connection = (best_connection_ == connection); | 1055 info.best_connection = (selected_connection_ == connection); |
| 1024 info.receiving = connection->receiving(); | 1056 info.receiving = connection->receiving(); |
| 1025 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); | 1057 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); |
| 1026 info.timeout = | 1058 info.timeout = |
| 1027 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 1059 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
| 1028 info.new_connection = !connection->reported(); | 1060 info.new_connection = !connection->reported(); |
| 1029 connection->set_reported(true); | 1061 connection->set_reported(true); |
| 1030 info.rtt = connection->rtt(); | 1062 info.rtt = connection->rtt(); |
| 1031 info.local_candidate = connection->local_candidate(); | 1063 info.local_candidate = connection->local_candidate(); |
| 1032 info.remote_candidate = connection->remote_candidate(); | 1064 info.remote_candidate = connection->remote_candidate(); |
| 1033 info.key = connection; | 1065 info.key = connection; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1083 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 1115 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
| 1084 LOG(LS_VERBOSE) << "Sorting " << connections_.size() | 1116 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
| 1085 << " available connections:"; | 1117 << " available connections:"; |
| 1086 for (size_t i = 0; i < connections_.size(); ++i) { | 1118 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1087 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 1119 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
| 1088 } | 1120 } |
| 1089 | 1121 |
| 1090 Connection* top_connection = | 1122 Connection* top_connection = |
| 1091 (connections_.size() > 0) ? connections_[0] : nullptr; | 1123 (connections_.size() > 0) ? connections_[0] : nullptr; |
| 1092 | 1124 |
| 1093 // If necessary, switch to the new choice. | 1125 // If necessary, switch to the new choice. Note that |top_connection| doesn't |
| 1094 // Note that |top_connection| doesn't have to be writable to become the best | 1126 // have to be writable to become the selected connection although it will |
| 1095 // connection although it will have higher priority if it is writable. | 1127 // have higher priority if it is writable. |
| 1096 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { | 1128 if (ShouldSwitch(selected_connection_, top_connection, ice_role_)) { |
| 1097 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 1129 LOG(LS_INFO) << "Switching selected connection after sorting: " |
|
pthatcher1
2016/06/17 00:27:11
Can we please unify the two ShouldSwitch methods i
honghaiz3
2016/06/22 08:03:15
Done.
| |
| 1098 SwitchBestConnectionTo(top_connection); | 1130 << top_connection->ToString(); |
| 1131 SwitchSelectedConnection(top_connection); | |
| 1099 } | 1132 } |
| 1100 | 1133 |
| 1101 // Controlled side can prune only if the best connection has been nominated. | 1134 // Controlled side can prune only if the selected connection has been |
| 1102 // because otherwise it may delete the connection that will be selected by | 1135 // nominated because otherwise it may prune the connection that will be |
| 1103 // the controlling side. | 1136 // selected by the controlling side. |
| 1104 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 1137 // TODO(honghaiz): This is still problematic because with aggressive |
| 1138 // nomination, the controlling side will nominate every connection until it | |
| 1139 // becomes writable. | |
| 1140 if (ice_role_ == ICEROLE_CONTROLLING || selected_nominated_connection()) { | |
| 1105 PruneConnections(); | 1141 PruneConnections(); |
| 1106 } | 1142 } |
| 1107 | 1143 |
| 1108 // Check if all connections are timedout. | 1144 // Check if all connections are timedout. |
| 1109 bool all_connections_timedout = true; | 1145 bool all_connections_timedout = true; |
| 1110 for (size_t i = 0; i < connections_.size(); ++i) { | 1146 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1111 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 1147 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
| 1112 all_connections_timedout = false; | 1148 all_connections_timedout = false; |
| 1113 break; | 1149 break; |
| 1114 } | 1150 } |
| 1115 } | 1151 } |
| 1116 | 1152 |
| 1117 // Now update the writable state of the channel with the information we have | 1153 // Now update the writable state of the channel with the information we have |
| 1118 // so far. | 1154 // so far. |
| 1119 if (all_connections_timedout) { | 1155 if (all_connections_timedout) { |
| 1120 HandleAllTimedOut(); | 1156 HandleAllTimedOut(); |
| 1121 } | 1157 } |
| 1122 | 1158 |
| 1123 // Update the state of this channel. This method is called whenever the | 1159 // Update the state of this channel. This method is called whenever the |
| 1124 // state of any connection changes, so this is a good place to do this. | 1160 // state of any connection changes, so this is a good place to do this. |
| 1125 UpdateState(); | 1161 UpdateState(); |
| 1126 } | 1162 } |
| 1127 | 1163 |
| 1128 Connection* P2PTransportChannel::best_nominated_connection() const { | 1164 Connection* P2PTransportChannel::selected_nominated_connection() const { |
| 1129 return (best_connection_ && best_connection_->nominated()) ? best_connection_ | 1165 return (selected_connection_ && selected_connection_->nominated()) |
| 1130 : nullptr; | 1166 ? selected_connection_ |
| 1167 : nullptr; | |
| 1131 } | 1168 } |
| 1132 | 1169 |
| 1133 void P2PTransportChannel::PruneConnections() { | 1170 void P2PTransportChannel::PruneConnections() { |
| 1134 // We can prune any connection for which there is a connected, writable | 1171 // We can prune any connection for which there is a connected, writable |
| 1135 // connection on the same network with better or equal priority. We leave | 1172 // connection on the same network with better or equal priority. We leave |
| 1136 // those with better priority just in case they become writable later (at | 1173 // those with better priority just in case they become writable later (at |
| 1137 // which point, we would prune out the current best connection). We leave | 1174 // which point, we would prune out the current selected connection). We leave |
| 1138 // connections on other networks because they may not be using the same | 1175 // connections on other networks because they may not be using the same |
| 1139 // resources and they may represent very distinct paths over which we can | 1176 // resources and they may represent very distinct paths over which we can |
| 1140 // switch. If the |premier| connection is not connected, we may be | 1177 // switch. If the |premier| connection is not connected, we may be |
| 1141 // reconnecting a TCP connection and temporarily do not prune connections in | 1178 // reconnecting a TCP connection and temporarily do not prune connections in |
| 1142 // this network. See the big comment in CompareConnections. | 1179 // this network. See the big comment in CompareConnections. |
| 1143 | 1180 |
| 1144 // Get a list of the networks that we are using. | 1181 // Get a list of the networks that we are using. |
| 1145 std::set<rtc::Network*> networks; | 1182 std::set<rtc::Network*> networks; |
| 1146 for (const Connection* conn : connections_) { | 1183 for (const Connection* conn : connections_) { |
| 1147 networks.insert(conn->port()->Network()); | 1184 networks.insert(conn->port()->Network()); |
| 1148 } | 1185 } |
| 1149 for (rtc::Network* network : networks) { | 1186 for (rtc::Network* network : networks) { |
| 1150 Connection* premier = GetBestConnectionOnNetwork(network); | 1187 Connection* premier = GetBestConnectionOnNetwork(network); |
| 1151 // Do not prune connections if the current best connection is weak on this | 1188 // Do not prune connections if the current selected connection is weak on |
| 1152 // network. Otherwise, it may delete connections prematurely. | 1189 // this network. Otherwise, it may delete connections prematurely. |
| 1153 if (!premier || premier->weak()) { | 1190 if (!premier || premier->weak()) { |
| 1154 continue; | 1191 continue; |
| 1155 } | 1192 } |
| 1156 | 1193 |
| 1157 for (Connection* conn : connections_) { | 1194 for (Connection* conn : connections_) { |
| 1158 if ((conn != premier) && (conn->port()->Network() == network) && | 1195 if ((conn != premier) && (conn->port()->Network() == network) && |
| 1159 (CompareConnectionCandidates(premier, conn) >= 0)) { | 1196 (CompareConnectionCandidates(premier, conn) >= 0)) { |
| 1160 conn->Prune(); | 1197 conn->Prune(); |
| 1161 } | 1198 } |
| 1162 } | 1199 } |
| 1163 } | 1200 } |
| 1164 } | 1201 } |
| 1165 | 1202 |
| 1166 // Track the best connection, and let listeners know | 1203 // Track the selected connection, and let listeners know. |
| 1167 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1204 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { |
| 1168 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1205 // Note: if conn is NULL, the previous |selected_connection_| has been |
| 1169 // so don't use it. | 1206 // destroyed, so don't use it. |
| 1170 Connection* old_best_connection = best_connection_; | 1207 Connection* old_selected_connection = selected_connection_; |
| 1171 best_connection_ = conn; | 1208 selected_connection_ = conn; |
| 1172 if (best_connection_) { | 1209 if (selected_connection_) { |
| 1173 if (old_best_connection) { | 1210 if (old_selected_connection) { |
| 1174 LOG_J(LS_INFO, this) << "Previous best connection: " | 1211 LOG_J(LS_INFO, this) << "Previous selected connection: " |
| 1175 << old_best_connection->ToString(); | 1212 << old_selected_connection->ToString(); |
| 1176 } | 1213 } |
| 1177 LOG_J(LS_INFO, this) << "New best connection: " | 1214 LOG_J(LS_INFO, this) << "New selected connection: " |
| 1178 << best_connection_->ToString(); | 1215 << selected_connection_->ToString(); |
| 1179 SignalRouteChange(this, best_connection_->remote_candidate()); | 1216 SignalRouteChange(this, selected_connection_->remote_candidate()); |
| 1180 // This is a temporary, but safe fix to webrtc issue 5705. | 1217 // This is a temporary, but safe fix to webrtc issue 5705. |
| 1181 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport | 1218 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport |
| 1182 // channel so that it knows whether the media channel is allowed to | 1219 // channel so that it knows whether the media channel is allowed to |
| 1183 // send; then it will only signal ready-to-send if the media channel | 1220 // send; then it will only signal ready-to-send if the media channel |
| 1184 // has been disallowed to send. | 1221 // has been disallowed to send. |
| 1185 if (best_connection_->writable()) { | 1222 if (selected_connection_->writable()) { |
| 1186 SignalReadyToSend(this); | 1223 SignalReadyToSend(this); |
| 1187 } | 1224 } |
| 1188 } else { | 1225 } else { |
| 1189 LOG_J(LS_INFO, this) << "No best connection"; | 1226 LOG_J(LS_INFO, this) << "No selected connection"; |
| 1190 } | 1227 } |
| 1191 // TODO(honghaiz): rename best_connection_ with selected_connection_ or | 1228 // TODO(honghaiz): rename selected_connection_ with selected_connection_ or |
| 1192 // selected_candidate pair_. | 1229 // selected_candidate pair_. |
| 1193 SignalSelectedCandidatePairChanged(this, best_connection_, | 1230 SignalSelectedCandidatePairChanged(this, selected_connection_, |
| 1194 last_sent_packet_id_); | 1231 last_sent_packet_id_); |
| 1195 } | 1232 } |
| 1196 | 1233 |
| 1197 // Warning: UpdateState should eventually be called whenever a connection | 1234 // Warning: UpdateState should eventually be called whenever a connection |
| 1198 // is added, deleted, or the write state of any connection changes so that the | 1235 // is added, deleted, or the write state of any connection changes so that the |
| 1199 // transport controller will get the up-to-date channel state. However it | 1236 // transport controller will get the up-to-date channel state. However it |
| 1200 // should not be called too often; in the case that multiple connection states | 1237 // should not be called too often; in the case that multiple connection states |
| 1201 // change, it should be called after all the connection states have changed. For | 1238 // change, it should be called after all the connection states have changed. For |
| 1202 // example, we call this at the end of SortConnections. | 1239 // example, we call this at the end of SortConnections. |
| 1203 void P2PTransportChannel::UpdateState() { | 1240 void P2PTransportChannel::UpdateState() { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1230 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); | 1267 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); |
| 1231 break; | 1268 break; |
| 1232 default: | 1269 default: |
| 1233 RTC_DCHECK(false); | 1270 RTC_DCHECK(false); |
| 1234 break; | 1271 break; |
| 1235 } | 1272 } |
| 1236 state_ = state; | 1273 state_ = state; |
| 1237 SignalStateChanged(this); | 1274 SignalStateChanged(this); |
| 1238 } | 1275 } |
| 1239 | 1276 |
| 1240 bool writable = best_connection_ && best_connection_->writable(); | 1277 bool writable = selected_connection_ && selected_connection_->writable(); |
| 1241 set_writable(writable); | 1278 set_writable(writable); |
| 1242 | 1279 |
| 1243 bool receiving = false; | 1280 bool receiving = false; |
| 1244 for (const Connection* connection : connections_) { | 1281 for (const Connection* connection : connections_) { |
| 1245 if (connection->receiving()) { | 1282 if (connection->receiving()) { |
| 1246 receiving = true; | 1283 receiving = true; |
| 1247 break; | 1284 break; |
| 1248 } | 1285 } |
| 1249 } | 1286 } |
| 1250 set_receiving(receiving); | 1287 set_receiving(receiving); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1270 } | 1307 } |
| 1271 | 1308 |
| 1272 // If all connections timed out, delete them all. | 1309 // If all connections timed out, delete them all. |
| 1273 void P2PTransportChannel::HandleAllTimedOut() { | 1310 void P2PTransportChannel::HandleAllTimedOut() { |
| 1274 for (Connection* connection : connections_) { | 1311 for (Connection* connection : connections_) { |
| 1275 connection->Destroy(); | 1312 connection->Destroy(); |
| 1276 } | 1313 } |
| 1277 } | 1314 } |
| 1278 | 1315 |
| 1279 bool P2PTransportChannel::weak() const { | 1316 bool P2PTransportChannel::weak() const { |
| 1280 return !best_connection_ || best_connection_->weak(); | 1317 return !selected_connection_ || selected_connection_->weak(); |
| 1281 } | 1318 } |
| 1282 | 1319 |
| 1283 // If we have a best connection, return it, otherwise return top one in the | 1320 // If we have a selected connection, return it, otherwise return top one in the |
| 1284 // list (later we will mark it best). | 1321 // list (later we will mark it best). |
| 1285 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | 1322 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
| 1286 rtc::Network* network) const { | 1323 rtc::Network* network) const { |
| 1287 // If the best connection is on this network, then it wins. | 1324 // If the selected connection is on this network, then it wins. |
| 1288 if (best_connection_ && (best_connection_->port()->Network() == network)) | 1325 if (selected_connection_ && |
| 1289 return best_connection_; | 1326 (selected_connection_->port()->Network() == network)) |
| 1327 return selected_connection_; | |
| 1290 | 1328 |
| 1291 // Otherwise, we return the top-most in sorted order. | 1329 // Otherwise, we return the top-most in sorted order. |
| 1292 for (size_t i = 0; i < connections_.size(); ++i) { | 1330 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1293 if (connections_[i]->port()->Network() == network) | 1331 if (connections_[i]->port()->Network() == network) |
| 1294 return connections_[i]; | 1332 return connections_[i]; |
| 1295 } | 1333 } |
| 1296 | 1334 |
| 1297 return NULL; | 1335 return NULL; |
| 1298 } | 1336 } |
| 1299 | 1337 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1316 void P2PTransportChannel::OnSort() { | 1354 void P2PTransportChannel::OnSort() { |
| 1317 // Resort the connections based on the new statistics. | 1355 // Resort the connections based on the new statistics. |
| 1318 SortConnections(); | 1356 SortConnections(); |
| 1319 } | 1357 } |
| 1320 | 1358 |
| 1321 // Handle queued up check-and-ping request | 1359 // Handle queued up check-and-ping request |
| 1322 void P2PTransportChannel::OnCheckAndPing() { | 1360 void P2PTransportChannel::OnCheckAndPing() { |
| 1323 // Make sure the states of the connections are up-to-date (since this affects | 1361 // Make sure the states of the connections are up-to-date (since this affects |
| 1324 // which ones are pingable). | 1362 // which ones are pingable). |
| 1325 UpdateConnectionStates(); | 1363 UpdateConnectionStates(); |
| 1326 // When the best connection is not receiving or not writable, or any active | 1364 // When the selected connection is not receiving or not writable, or any |
| 1327 // connection has not been pinged enough times, use the weak ping interval. | 1365 // active connection has not been pinged enough times, use the weak ping |
| 1366 // interval. | |
| 1328 bool need_more_pings_at_weak_interval = std::any_of( | 1367 bool need_more_pings_at_weak_interval = std::any_of( |
| 1329 connections_.begin(), connections_.end(), [](Connection* conn) { | 1368 connections_.begin(), connections_.end(), [](Connection* conn) { |
| 1330 return conn->active() && | 1369 return conn->active() && |
| 1331 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; | 1370 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; |
| 1332 }); | 1371 }); |
| 1333 int ping_interval = (weak() || need_more_pings_at_weak_interval) | 1372 int ping_interval = (weak() || need_more_pings_at_weak_interval) |
| 1334 ? weak_ping_interval_ | 1373 ? weak_ping_interval_ |
| 1335 : STRONG_PING_INTERVAL; | 1374 : STRONG_PING_INTERVAL; |
| 1336 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { | 1375 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { |
| 1337 Connection* conn = FindNextPingableConnection(); | 1376 Connection* conn = FindNextPingableConnection(); |
| 1338 if (conn) { | 1377 if (conn) { |
| 1339 PingConnection(conn); | 1378 PingConnection(conn); |
| 1340 MarkConnectionPinged(conn); | 1379 MarkConnectionPinged(conn); |
| 1341 } | 1380 } |
| 1342 } | 1381 } |
| 1343 int delay = std::min(ping_interval, check_receiving_interval_); | 1382 int delay = std::min(ping_interval, check_receiving_interval_); |
| 1344 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); | 1383 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); |
| 1345 } | 1384 } |
| 1346 | 1385 |
| 1347 // A connection is considered a backup connection if the channel state | 1386 // A connection is considered a backup connection if the channel state |
| 1348 // is completed, the connection is not the best connection and it is active. | 1387 // is completed, the connection is not the selected connection and it is active. |
| 1349 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1388 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { |
| 1350 return state_ == STATE_COMPLETED && conn != best_connection_ && | 1389 return state_ == STATE_COMPLETED && conn != selected_connection_ && |
| 1351 conn->active(); | 1390 conn->active(); |
| 1352 } | 1391 } |
| 1353 | 1392 |
| 1354 // Is the connection in a state for us to even consider pinging the other side? | 1393 // Is the connection in a state for us to even consider pinging the other side? |
| 1355 // We consider a connection pingable even if it's not connected because that's | 1394 // We consider a connection pingable even if it's not connected because that's |
| 1356 // how a TCP connection is kicked into reconnecting on the active side. | 1395 // how a TCP connection is kicked into reconnecting on the active side. |
| 1357 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { | 1396 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { |
| 1358 const Candidate& remote = conn->remote_candidate(); | 1397 const Candidate& remote = conn->remote_candidate(); |
| 1359 // We should never get this far with an empty remote ufrag. | 1398 // We should never get this far with an empty remote ufrag. |
| 1360 ASSERT(!remote.username().empty()); | 1399 ASSERT(!remote.username().empty()); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1380 if (IsBackupConnection(conn)) { | 1419 if (IsBackupConnection(conn)) { |
| 1381 return (now >= conn->last_ping_response_received() + | 1420 return (now >= conn->last_ping_response_received() + |
| 1382 config_.backup_connection_ping_interval); | 1421 config_.backup_connection_ping_interval); |
| 1383 } | 1422 } |
| 1384 return conn->active(); | 1423 return conn->active(); |
| 1385 } | 1424 } |
| 1386 | 1425 |
| 1387 // Returns the next pingable connection to ping. This will be the oldest | 1426 // Returns the next pingable connection to ping. This will be the oldest |
| 1388 // pingable connection unless we have a connected, writable connection that is | 1427 // pingable connection unless we have a connected, writable connection that is |
| 1389 // past the maximum acceptable ping interval. When reconnecting a TCP | 1428 // past the maximum acceptable ping interval. When reconnecting a TCP |
| 1390 // connection, the best connection is disconnected, although still WRITABLE | 1429 // connection, the selected connection is disconnected, although still WRITABLE |
| 1391 // while reconnecting. The newly created connection should be selected as the | 1430 // while reconnecting. The newly created connection should be selected as the |
| 1392 // ping target to become writable instead. See the big comment in | 1431 // ping target to become writable instead. See the big comment in |
| 1393 // CompareConnections. | 1432 // CompareConnections. |
| 1394 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1433 Connection* P2PTransportChannel::FindNextPingableConnection() { |
| 1395 int64_t now = rtc::TimeMillis(); | 1434 int64_t now = rtc::TimeMillis(); |
| 1396 Connection* conn_to_ping = nullptr; | 1435 Connection* conn_to_ping = nullptr; |
| 1397 if (best_connection_ && best_connection_->connected() && | 1436 if (selected_connection_ && selected_connection_->connected() && |
| 1398 best_connection_->writable() && | 1437 selected_connection_->writable() && |
| 1399 (best_connection_->last_ping_sent() + config_.max_strong_interval <= | 1438 (selected_connection_->last_ping_sent() + config_.max_strong_interval <= |
| 1400 now)) { | 1439 now)) { |
| 1401 conn_to_ping = best_connection_; | 1440 conn_to_ping = selected_connection_; |
| 1402 } else { | 1441 } else { |
| 1403 conn_to_ping = FindConnectionToPing(now); | 1442 conn_to_ping = FindConnectionToPing(now); |
| 1404 } | 1443 } |
| 1405 return conn_to_ping; | 1444 return conn_to_ping; |
| 1406 } | 1445 } |
| 1407 | 1446 |
| 1408 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { | 1447 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
| 1409 if (conn && pinged_connections_.insert(conn).second) { | 1448 if (conn && pinged_connections_.insert(conn).second) { |
| 1410 unpinged_connections_.erase(conn); | 1449 unpinged_connections_.erase(conn); |
| 1411 } | 1450 } |
| 1412 } | 1451 } |
| 1413 | 1452 |
| 1414 // Apart from sending ping from |conn| this method also updates | 1453 // Apart from sending ping from |conn| this method also updates |
| 1415 // |use_candidate_attr| flag. The criteria to update this flag is | 1454 // |use_candidate_attr| flag. The criteria to update this flag is |
| 1416 // explained below. | 1455 // explained below. |
| 1417 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND | 1456 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
| 1418 // a) Channel is in FULL ICE AND | 1457 // a) Channel is in FULL ICE AND |
| 1419 // a.1) |conn| is the best connection OR | 1458 // a.1) |conn| is the selected connection OR |
| 1420 // a.2) there is no best connection OR | 1459 // a.2) there is no selected connection OR |
| 1421 // a.3) the best connection is unwritable OR | 1460 // a.3) the selected connection is unwritable OR |
| 1422 // a.4) |conn| has higher priority than best_connection. | 1461 // a.4) |conn| has higher priority than selected_connection. |
| 1423 // b) we're doing LITE ICE AND | 1462 // b) we're doing LITE ICE AND |
| 1424 // b.1) |conn| is the best_connection AND | 1463 // b.1) |conn| is the selected_connection AND |
| 1425 // b.2) |conn| is writable. | 1464 // b.2) |conn| is writable. |
| 1426 void P2PTransportChannel::PingConnection(Connection* conn) { | 1465 void P2PTransportChannel::PingConnection(Connection* conn) { |
| 1427 bool use_candidate = false; | 1466 bool use_candidate = false; |
| 1428 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1467 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
| 1429 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || | 1468 use_candidate = |
| 1430 (!best_connection_->writable()) || | 1469 (conn == selected_connection_) || (selected_connection_ == NULL) || |
| 1431 (CompareConnectionCandidates(best_connection_, conn) < 0); | 1470 (!selected_connection_->writable()) || |
| 1432 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1471 (CompareConnectionCandidates(selected_connection_, conn) < 0); |
| 1433 use_candidate = best_connection_->writable(); | 1472 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) { |
| 1473 use_candidate = selected_connection_->writable(); | |
| 1434 } | 1474 } |
| 1435 conn->set_use_candidate_attr(use_candidate); | 1475 conn->set_use_candidate_attr(use_candidate); |
| 1436 last_ping_sent_ms_ = rtc::TimeMillis(); | 1476 last_ping_sent_ms_ = rtc::TimeMillis(); |
| 1437 conn->Ping(last_ping_sent_ms_); | 1477 conn->Ping(last_ping_sent_ms_); |
| 1438 } | 1478 } |
| 1439 | 1479 |
| 1440 // When a connection's state changes, we need to figure out who to use as | 1480 // When a connection's state changes, we need to figure out who to use as |
| 1441 // the best connection again. It could have become usable, or become unusable. | 1481 // the selected connection again. It could have become usable, or become |
| 1482 // unusable. | |
| 1442 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1483 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
| 1443 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1484 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1444 | 1485 |
| 1445 // Update the best connection if the state change is from pending best | 1486 // Update the selected connection if the state change is from last nominated |
| 1446 // connection and role is controlled. | 1487 // connection and role is controlled. |
| 1447 if (ice_role_ == ICEROLE_CONTROLLED) { | 1488 if (ice_role_ == ICEROLE_CONTROLLED && |
| 1448 if (connection == pending_best_connection_ && connection->writable()) { | 1489 connection == last_nominated_connection_ && |
| 1449 pending_best_connection_ = NULL; | 1490 connection != selected_connection_ && |
| 1450 LOG(LS_INFO) << "Switching best connection on controlled side" | 1491 ShouldSwitchOnNominatedOrDataReceived(connection)) { |
| 1451 << " because it's now writable: " << connection->ToString(); | 1492 LOG(LS_INFO) << "Switching selected connection on controlled side" |
| 1452 SwitchBestConnectionTo(connection); | 1493 << " because it's now writable: " << connection->ToString(); |
| 1453 } | 1494 SwitchSelectedConnection(connection); |
| 1454 } | 1495 } |
| 1455 | 1496 |
| 1456 // May stop the allocator session when at least one connection becomes | 1497 // May stop the allocator session when at least one connection becomes |
| 1457 // strongly connected after starting to get ports and the local candidate of | 1498 // strongly connected after starting to get ports and the local candidate of |
| 1458 // the connection is at the latest generation. It is not enough to check | 1499 // the connection is at the latest generation. It is not enough to check |
| 1459 // that the connection becomes weakly connected because the connection may be | 1500 // that the connection becomes weakly connected because the connection may be |
| 1460 // changing from (writable, receiving) to (writable, not receiving). | 1501 // changing from (writable, receiving) to (writable, not receiving). |
| 1461 bool strongly_connected = !connection->weak(); | 1502 bool strongly_connected = !connection->weak(); |
| 1462 bool latest_generation = connection->local_candidate().generation() >= | 1503 bool latest_generation = connection->local_candidate().generation() >= |
| 1463 allocator_session()->generation(); | 1504 allocator_session()->generation(); |
| 1464 if (strongly_connected && latest_generation) { | 1505 if (strongly_connected && latest_generation) { |
| 1465 MaybeStopPortAllocatorSessions(); | 1506 MaybeStopPortAllocatorSessions(); |
| 1466 } | 1507 } |
| 1467 | 1508 |
| 1468 // We have to unroll the stack before doing this because we may be changing | 1509 // We have to unroll the stack before doing this because we may be changing |
| 1469 // the state of connections while sorting. | 1510 // the state of connections while sorting. |
| 1470 RequestSort(); | 1511 RequestSort(); |
| 1471 } | 1512 } |
| 1472 | 1513 |
| 1473 // When a connection is removed, edit it out, and then update our best | 1514 // When a connection is removed, edit it out, and then update our best |
| 1474 // connection. | 1515 // connection. |
| 1475 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1516 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
| 1476 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1517 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1477 | 1518 |
| 1478 // Note: the previous best_connection_ may be destroyed by now, so don't | 1519 // Note: the previous selected_connection_ may be destroyed by now, so don't |
| 1479 // use it. | 1520 // use it. |
| 1480 | 1521 |
| 1481 // Remove this connection from the list. | 1522 // Remove this connection from the list. |
| 1482 std::vector<Connection*>::iterator iter = | 1523 std::vector<Connection*>::iterator iter = |
| 1483 std::find(connections_.begin(), connections_.end(), connection); | 1524 std::find(connections_.begin(), connections_.end(), connection); |
| 1484 ASSERT(iter != connections_.end()); | 1525 ASSERT(iter != connections_.end()); |
| 1485 pinged_connections_.erase(*iter); | 1526 pinged_connections_.erase(*iter); |
| 1486 unpinged_connections_.erase(*iter); | 1527 unpinged_connections_.erase(*iter); |
| 1487 connections_.erase(iter); | 1528 connections_.erase(iter); |
| 1488 | 1529 |
| 1489 LOG_J(LS_INFO, this) << "Removed connection (" | 1530 LOG_J(LS_INFO, this) << "Removed connection (" |
| 1490 << static_cast<int>(connections_.size()) << " remaining)"; | 1531 << static_cast<int>(connections_.size()) << " remaining)"; |
| 1491 | 1532 |
| 1492 if (pending_best_connection_ == connection) { | 1533 // If this is currently the selected connection, then we need to pick a new |
| 1493 pending_best_connection_ = NULL; | 1534 // one. The call to SortConnections will pick a new one. It looks at the |
| 1494 } | 1535 // current selected connection in order to avoid switching between fairly |
| 1495 | 1536 // similar ones. Since this connection is no longer an option, we can just |
| 1496 // If this is currently the best connection, then we need to pick a new one. | 1537 // set selected to nullptr and re-choose a best assuming that there was no |
| 1497 // The call to SortConnections will pick a new one. It looks at the current | 1538 // selected connection. |
| 1498 // best connection in order to avoid switching between fairly similar ones. | 1539 if (selected_connection_ == connection) { |
| 1499 // Since this connection is no longer an option, we can just set best to NULL | 1540 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; |
| 1500 // and re-choose a best assuming that there was no best connection. | 1541 SwitchSelectedConnection(nullptr); |
| 1501 if (best_connection_ == connection) { | |
| 1502 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; | |
| 1503 SwitchBestConnectionTo(NULL); | |
| 1504 RequestSort(); | 1542 RequestSort(); |
| 1505 } | 1543 } |
| 1506 | 1544 |
| 1507 UpdateState(); | 1545 UpdateState(); |
| 1508 } | 1546 } |
| 1509 | 1547 |
| 1510 // When a port is destroyed remove it from our list of ports to use for | 1548 // When a port is destroyed remove it from our list of ports to use for |
| 1511 // connection attempts. | 1549 // connection attempts. |
| 1512 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1550 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
| 1513 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1551 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1552 | 1590 |
| 1553 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1591 // Do not deliver, if packet doesn't belong to the correct transport channel. |
| 1554 if (!FindConnection(connection)) | 1592 if (!FindConnection(connection)) |
| 1555 return; | 1593 return; |
| 1556 | 1594 |
| 1557 // Let the client know of an incoming packet | 1595 // Let the client know of an incoming packet |
| 1558 SignalReadPacket(this, data, len, packet_time, 0); | 1596 SignalReadPacket(this, data, len, packet_time, 0); |
| 1559 | 1597 |
| 1560 // May need to switch the sending connection based on the receiving media path | 1598 // May need to switch the sending connection based on the receiving media path |
| 1561 // if this is the controlled side. | 1599 // if this is the controlled side. |
| 1562 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && | 1600 if (ice_role_ != ICEROLE_CONTROLLED || selected_connection_ == connection) { |
| 1563 connection->writable() && best_connection_ != connection) { | 1601 return; |
| 1564 SwitchBestConnectionTo(connection); | 1602 } |
| 1603 | |
| 1604 last_receiving_connection_ = connection; | |
| 1605 if (ShouldSwitchOnNominatedOrDataReceived(connection)) { | |
| 1606 LOG(LS_INFO) | |
| 1607 << "Switching selected connection on controlled side due to receiving: " | |
| 1608 << connection->ToString(); | |
| 1609 SwitchSelectedConnection(connection); | |
| 1565 } | 1610 } |
| 1566 } | 1611 } |
| 1567 | 1612 |
| 1568 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { | 1613 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { |
| 1569 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1614 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1570 | 1615 |
| 1571 SignalSentPacket(this, sent_packet); | 1616 SignalSentPacket(this, sent_packet); |
| 1572 } | 1617 } |
| 1573 | 1618 |
| 1574 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1619 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1575 if (connection == best_connection_ && writable()) { | 1620 if (connection == selected_connection_ && writable()) { |
| 1576 SignalReadyToSend(this); | 1621 SignalReadyToSend(this); |
| 1577 } | 1622 } |
| 1578 } | 1623 } |
| 1579 | 1624 |
| 1580 // Find "triggered checks". We ping first those connections that have | 1625 // Find "triggered checks". We ping first those connections that have |
| 1581 // received a ping but have not sent a ping since receiving it | 1626 // received a ping but have not sent a ping since receiving it |
| 1582 // (last_received_ping > last_sent_ping). But we shouldn't do | 1627 // (last_received_ping > last_sent_ping). But we shouldn't do |
| 1583 // triggered checks if the connection is already writable. | 1628 // triggered checks if the connection is already writable. |
| 1584 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( | 1629 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( |
| 1585 int64_t now) { | 1630 int64_t now) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1688 | 1733 |
| 1689 // During the initial state when nothing has been pinged yet, return the first | 1734 // During the initial state when nothing has been pinged yet, return the first |
| 1690 // one in the ordered |connections_|. | 1735 // one in the ordered |connections_|. |
| 1691 return *(std::find_if(connections_.begin(), connections_.end(), | 1736 return *(std::find_if(connections_.begin(), connections_.end(), |
| 1692 [conn1, conn2](Connection* conn) { | 1737 [conn1, conn2](Connection* conn) { |
| 1693 return conn == conn1 || conn == conn2; | 1738 return conn == conn1 || conn == conn2; |
| 1694 })); | 1739 })); |
| 1695 } | 1740 } |
| 1696 | 1741 |
| 1697 } // namespace cricket | 1742 } // namespace cricket |
| OLD | NEW |