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 |
| 11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
| 12 | 12 |
| 13 #include <algorithm> | |
| 13 #include <set> | 14 #include <set> |
| 14 #include "webrtc/p2p/base/common.h" | 15 #include "webrtc/p2p/base/common.h" |
| 15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 16 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
| 16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 17 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
| 17 #include "webrtc/base/common.h" | 18 #include "webrtc/base/common.h" |
| 18 #include "webrtc/base/crc32.h" | 19 #include "webrtc/base/crc32.h" |
| 19 #include "webrtc/base/logging.h" | 20 #include "webrtc/base/logging.h" |
| 20 #include "webrtc/base/stringencode.h" | 21 #include "webrtc/base/stringencode.h" |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 // messages for queuing up work for ourselves | 25 // messages for queuing up work for ourselves |
| 25 enum { | 26 enum { MSG_SORT = 1, MSG_CHECK_AND_PING }; |
| 26 MSG_SORT = 1, | |
| 27 MSG_PING, | |
| 28 MSG_CHECK_RECEIVING | |
| 29 }; | |
| 30 | 27 |
| 31 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 28 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) |
| 32 // for pinging. When the socket is writable, we will use only 1 Kbps because | 29 // for pinging. When the socket is writable, we will use only 1 Kbps because |
| 33 // we don't want to degrade the quality on a modem. These numbers should work | 30 // we don't want to degrade the quality on a modem. These numbers should work |
| 34 // well on a 28.8K modem, which is the slowest connection on which the voice | 31 // well on a 28.8K modem, which is the slowest connection on which the voice |
| 35 // quality is reasonable at all. | 32 // quality is reasonable at all. |
| 36 static const uint32 PING_PACKET_SIZE = 60 * 8; | 33 static const uint32 PING_PACKET_SIZE = 60 * 8; |
| 37 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms | 34 // STRONG_PING_DELAY (480ms) is applied when the best connection is both |
| 38 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms | 35 // writable and receiving. |
| 36 static const uint32 STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000; | |
| 37 // WEAK_PING_DELAY (48ms) is applied when the best connection is either not | |
| 38 // writable or not receiving. | |
| 39 static const uint32 WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000; | |
| 39 | 40 |
| 40 // If there is a current writable connection, then we will also try hard to | 41 // If the current best connection is both writable and receiving, then we will |
| 41 // make sure it is pinged at this rate. | 42 // also try hard to make sure it is pinged at this rate (a little less than |
| 42 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit | 43 // 2 * STRONG_PING_DELAY). |
| 44 static const uint32 MAX_CURRENT_STRONG_DELAY = 900; | |
| 43 | 45 |
| 44 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms | 46 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms |
| 45 | 47 |
| 46 // The minimum improvement in RTT that justifies a switch. | 48 // The minimum improvement in RTT that justifies a switch. |
| 47 static const double kMinImprovement = 10; | 49 static const double kMinImprovement = 10; |
| 48 | 50 |
| 49 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, | 51 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, |
| 50 cricket::PortInterface* origin_port) { | 52 cricket::PortInterface* origin_port) { |
| 51 if (!origin_port) | 53 if (!origin_port) |
| 52 return cricket::PortInterface::ORIGIN_MESSAGE; | 54 return cricket::PortInterface::ORIGIN_MESSAGE; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 63 if (a->priority() > b->priority()) | 65 if (a->priority() > b->priority()) |
| 64 return 1; | 66 return 1; |
| 65 if (a->priority() < b->priority()) | 67 if (a->priority() < b->priority()) |
| 66 return -1; | 68 return -1; |
| 67 | 69 |
| 68 // If we're still tied at this point, prefer a younger generation. | 70 // If we're still tied at this point, prefer a younger generation. |
| 69 return (a->remote_candidate().generation() + a->port()->generation()) - | 71 return (a->remote_candidate().generation() + a->port()->generation()) - |
| 70 (b->remote_candidate().generation() + b->port()->generation()); | 72 (b->remote_candidate().generation() + b->port()->generation()); |
| 71 } | 73 } |
| 72 | 74 |
| 73 // Compare two connections based on their connected state, writability and | 75 // Compare two connections based on their writing, receiving, and connected |
| 74 // static preferences. | 76 // states. |
| 75 int CompareConnections(cricket::Connection *a, cricket::Connection *b) { | 77 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) { |
| 76 // Sort based on write-state. Better states have lower values. | 78 // Sort based on write-state. Better states have lower values. |
| 77 if (a->write_state() < b->write_state()) | 79 if (a->write_state() < b->write_state()) |
| 78 return 1; | 80 return 1; |
| 79 if (a->write_state() > b->write_state()) | 81 if (a->write_state() > b->write_state()) |
| 80 return -1; | 82 return -1; |
| 81 | 83 |
| 84 if (a->receiving() && !b->receiving()) | |
| 85 return 1; | |
| 86 if (!a->receiving() && b->receiving()) | |
| 87 return -1; | |
|
pthatcher1
2015/09/22 23:41:46
Can you put a comment along the lines of "We prefe
honghaiz3
2015/09/23 03:16:10
Done. I do not see that the pinging order is relat
| |
| 88 | |
| 82 // WARNING: Some complexity here about TCP reconnecting. | 89 // WARNING: Some complexity here about TCP reconnecting. |
| 83 // When a TCP connection fails because of a TCP socket disconnecting, the | 90 // When a TCP connection fails because of a TCP socket disconnecting, the |
| 84 // active side of the connection will attempt to reconnect for 5 seconds while | 91 // active side of the connection will attempt to reconnect for 5 seconds while |
| 85 // pretending to be writable (the connection is not set to the unwritable | 92 // pretending to be writable (the connection is not set to the unwritable |
| 86 // state). On the passive side, the connection also remains writable even | 93 // state). On the passive side, the connection also remains writable even |
| 87 // though it is disconnected, and a new connection is created when the active | 94 // though it is disconnected, and a new connection is created when the active |
| 88 // side connects. At that point, there are two TCP connections on the passive | 95 // side connects. At that point, there are two TCP connections on the passive |
| 89 // side: 1. the old, disconnected one that is pretending to be writable, and | 96 // side: 1. the old, disconnected one that is pretending to be writable, and |
| 90 // 2. the new, connected one that is maybe not yet writable. For purposes of | 97 // 2. the new, connected one that is maybe not yet writable. For purposes of |
| 91 // pruning, pinging, and selecting the best connection, we want to treat the | 98 // pruning, pinging, and selecting the best connection, we want to treat the |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 103 // the new connection, when it becomes writable, should have higher priority. | 110 // the new connection, when it becomes writable, should have higher priority. |
| 104 if (a->write_state() == cricket::Connection::STATE_WRITABLE && | 111 if (a->write_state() == cricket::Connection::STATE_WRITABLE && |
| 105 b->write_state() == cricket::Connection::STATE_WRITABLE) { | 112 b->write_state() == cricket::Connection::STATE_WRITABLE) { |
| 106 if (a->connected() && !b->connected()) { | 113 if (a->connected() && !b->connected()) { |
| 107 return 1; | 114 return 1; |
| 108 } | 115 } |
| 109 if (!a->connected() && b->connected()) { | 116 if (!a->connected() && b->connected()) { |
| 110 return -1; | 117 return -1; |
| 111 } | 118 } |
| 112 } | 119 } |
| 120 return 0; | |
| 121 } | |
| 113 | 122 |
| 123 int CompareConnections(cricket::Connection* a, cricket::Connection* b) { | |
| 124 int state_cmp = CompareConnectionStates(a, b); | |
| 125 if (state_cmp != 0) { | |
| 126 return state_cmp; | |
| 127 } | |
| 114 // Compare the candidate information. | 128 // Compare the candidate information. |
| 115 return CompareConnectionCandidates(a, b); | 129 return CompareConnectionCandidates(a, b); |
| 116 } | 130 } |
| 117 | 131 |
| 118 // Wraps the comparison connection into a less than operator that puts higher | 132 // Wraps the comparison connection into a less than operator that puts higher |
| 119 // priority writable connections first. | 133 // priority writable connections first. |
| 120 class ConnectionCompare { | 134 class ConnectionCompare { |
| 121 public: | 135 public: |
| 122 bool operator()(const cricket::Connection *ca, | 136 bool operator()(const cricket::Connection *ca, |
| 123 const cricket::Connection *cb) { | 137 const cricket::Connection *cb) { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 141 // TODO: Yes we should definitely do this. The TCP protocol gains | 155 // TODO: Yes we should definitely do this. The TCP protocol gains |
| 142 // efficiency by being used bidirectionally, as opposed to two separate | 156 // efficiency by being used bidirectionally, as opposed to two separate |
| 143 // unidirectional streams. This test should probably occur before | 157 // unidirectional streams. This test should probably occur before |
| 144 // comparison of local prefs (assuming combined prefs are the same). We | 158 // comparison of local prefs (assuming combined prefs are the same). We |
| 145 // need to be careful though, not to bounce back and forth with both sides | 159 // need to be careful though, not to bounce back and forth with both sides |
| 146 // trying to rendevous with the other. | 160 // trying to rendevous with the other. |
| 147 } | 161 } |
| 148 }; | 162 }; |
| 149 | 163 |
| 150 // Determines whether we should switch between two connections, based first on | 164 // Determines whether we should switch between two connections, based first on |
| 151 // static preferences and then (if those are equal) on latency estimates. | 165 // connection states, static preferences, and then (if those are equal) on |
| 152 bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) { | 166 // latency estimates. |
| 167 bool ShouldSwitch(cricket::Connection* a_conn, | |
| 168 cricket::Connection* b_conn, | |
| 169 cricket::IceRole ice_role) { | |
| 153 if (a_conn == b_conn) | 170 if (a_conn == b_conn) |
| 154 return false; | 171 return false; |
| 155 | 172 |
| 156 if (!a_conn || !b_conn) // don't think the latter should happen | 173 if (!a_conn || !b_conn) // don't think the latter should happen |
| 157 return true; | 174 return true; |
| 158 | 175 |
| 159 int prefs_cmp = CompareConnections(a_conn, b_conn); | 176 // If the connection states (WRITE/RECEIVING/CONNECT) are different, we should |
| 160 if (prefs_cmp < 0) | 177 // switch regardless of the nominated state. Otherwise, do not switch if |
| 161 return true; | 178 // |a_conn| is nominated on the controlled side. |
|
pthatcher1
2015/09/22 23:41:46
Can you reword this as something like "We prefer t
honghaiz3
2015/09/23 03:16:10
Done.
| |
| 162 if (prefs_cmp > 0) | 179 int state_cmp = CompareConnectionStates(a_conn, b_conn); |
| 180 if (state_cmp != 0) { | |
| 181 return state_cmp < 0; | |
| 182 } | |
| 183 if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) { | |
| 184 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status"; | |
| 163 return false; | 185 return false; |
| 186 } | |
| 187 | |
| 188 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn); | |
| 189 if (prefs_cmp != 0) { | |
| 190 return prefs_cmp < 0; | |
| 191 } | |
| 164 | 192 |
| 165 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; | 193 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; |
| 166 } | 194 } |
| 167 | 195 |
| 168 } // unnamed namespace | 196 } // unnamed namespace |
| 169 | 197 |
| 170 namespace cricket { | 198 namespace cricket { |
| 171 | 199 |
| 172 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, | 200 P2PTransportChannel::P2PTransportChannel(const std::string& content_name, |
| 173 int component, | 201 int component, |
| 174 P2PTransport* transport, | 202 P2PTransport* transport, |
| 175 PortAllocator *allocator) : | 203 PortAllocator* allocator) |
| 176 TransportChannelImpl(content_name, component), | 204 : TransportChannelImpl(content_name, component), |
| 177 transport_(transport), | 205 transport_(transport), |
| 178 allocator_(allocator), | 206 allocator_(allocator), |
| 179 worker_thread_(rtc::Thread::Current()), | 207 worker_thread_(rtc::Thread::Current()), |
| 180 incoming_only_(false), | 208 incoming_only_(false), |
| 181 waiting_for_signaling_(false), | 209 waiting_for_signaling_(false), |
| 182 error_(0), | 210 error_(0), |
| 183 best_connection_(NULL), | 211 best_connection_(nullptr), |
| 184 pending_best_connection_(NULL), | 212 pending_best_connection_(nullptr), |
| 185 sort_dirty_(false), | 213 sort_dirty_(false), |
| 186 was_writable_(false), | 214 was_writable_(false), |
| 187 remote_ice_mode_(ICEMODE_FULL), | 215 remote_ice_mode_(ICEMODE_FULL), |
| 188 ice_role_(ICEROLE_UNKNOWN), | 216 ice_role_(ICEROLE_UNKNOWN), |
| 189 tiebreaker_(0), | 217 tiebreaker_(0), |
| 190 remote_candidate_generation_(0), | 218 remote_candidate_generation_(0), |
| 191 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), | 219 check_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
| 192 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { | 220 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) {} |
| 193 } | |
| 194 | 221 |
| 195 P2PTransportChannel::~P2PTransportChannel() { | 222 P2PTransportChannel::~P2PTransportChannel() { |
| 196 ASSERT(worker_thread_ == rtc::Thread::Current()); | 223 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 197 | 224 |
| 198 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) | 225 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) |
| 199 delete allocator_sessions_[i]; | 226 delete allocator_sessions_[i]; |
| 200 } | 227 } |
| 201 | 228 |
| 202 // Add the allocator session to our list so that we know which sessions | 229 // Add the allocator session to our list so that we know which sessions |
| 203 // are still active. | 230 // are still active. |
| (...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 355 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 382 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
| 356 ASSERT(false); | 383 ASSERT(false); |
| 357 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 384 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
| 358 << "ice_pwd_ are not set."; | 385 << "ice_pwd_ are not set."; |
| 359 return; | 386 return; |
| 360 } | 387 } |
| 361 | 388 |
| 362 // Kick off an allocator session | 389 // Kick off an allocator session |
| 363 Allocate(); | 390 Allocate(); |
| 364 | 391 |
| 365 // Start pinging as the ports come in. | 392 // Start checking and pinging as the ports come in. |
| 366 thread()->Post(this, MSG_PING); | 393 thread()->Post(this, MSG_CHECK_AND_PING); |
| 367 | |
| 368 thread()->PostDelayed( | |
| 369 check_receiving_delay_, this, MSG_CHECK_RECEIVING); | |
| 370 } | 394 } |
| 371 | 395 |
| 372 // A new port is available, attempt to make connections for it | 396 // A new port is available, attempt to make connections for it |
| 373 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 397 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
| 374 PortInterface* port) { | 398 PortInterface* port) { |
| 375 ASSERT(worker_thread_ == rtc::Thread::Current()); | 399 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 376 | 400 |
| 377 // Set in-effect options on the new port | 401 // Set in-effect options on the new port |
| 378 for (OptionMap::const_iterator it = options_.begin(); | 402 for (OptionMap::const_iterator it = options_.begin(); |
| 379 it != options_.end(); | 403 it != options_.end(); |
| (...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 918 | 942 |
| 919 // Any changes after this point will require a re-sort. | 943 // Any changes after this point will require a re-sort. |
| 920 sort_dirty_ = false; | 944 sort_dirty_ = false; |
| 921 | 945 |
| 922 // Find the best alternative connection by sorting. It is important to note | 946 // Find the best alternative connection by sorting. It is important to note |
| 923 // that amongst equal preference, writable connections, this will choose the | 947 // that amongst equal preference, writable connections, this will choose the |
| 924 // one whose estimated latency is lowest. So it is the only one that we | 948 // one whose estimated latency is lowest. So it is the only one that we |
| 925 // need to consider switching to. | 949 // need to consider switching to. |
| 926 ConnectionCompare cmp; | 950 ConnectionCompare cmp; |
| 927 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 951 std::stable_sort(connections_.begin(), connections_.end(), cmp); |
| 928 LOG(LS_VERBOSE) << "Sorting available connections:"; | 952 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
| 953 << " available connections:"; | |
| 929 for (uint32 i = 0; i < connections_.size(); ++i) { | 954 for (uint32 i = 0; i < connections_.size(); ++i) { |
| 930 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 955 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
| 931 } | 956 } |
| 932 | 957 |
| 933 Connection* top_connection = | 958 Connection* top_connection = |
| 934 (connections_.size() > 0) ? connections_[0] : nullptr; | 959 (connections_.size() > 0) ? connections_[0] : nullptr; |
| 935 | 960 |
| 936 // If necessary, switch to the new choice. | 961 // If necessary, switch to the new choice. |
| 937 // Note that |top_connection| doesn't have to be writable to become the best | 962 // Note that |top_connection| doesn't have to be writable to become the best |
| 938 // connection although it will have higher priority if it is writable. | 963 // connection although it will have higher priority if it is writable. |
| 939 // The controlled side can switch the best connection only if the current | 964 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { |
| 940 // |best connection_| has not been nominated by the controlling side yet. | |
| 941 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) && | |
| 942 ShouldSwitch(best_connection_, top_connection)) { | |
| 943 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 965 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); |
| 944 SwitchBestConnectionTo(top_connection); | 966 SwitchBestConnectionTo(top_connection); |
| 945 } | 967 } |
| 946 | 968 |
| 947 // Controlled side can prune only if the best connection has been nominated. | 969 // Controlled side can prune only if the best connection has been nominated. |
| 948 // because otherwise it may delete the connection that will be selected by | 970 // because otherwise it may delete the connection that will be selected by |
| 949 // the controlling side. | 971 // the controlling side. |
| 950 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 972 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { |
| 951 PruneConnections(); | 973 PruneConnections(); |
| 952 } | 974 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1018 Connection* old_best_connection = best_connection_; | 1040 Connection* old_best_connection = best_connection_; |
| 1019 best_connection_ = conn; | 1041 best_connection_ = conn; |
| 1020 if (best_connection_) { | 1042 if (best_connection_) { |
| 1021 if (old_best_connection) { | 1043 if (old_best_connection) { |
| 1022 LOG_J(LS_INFO, this) << "Previous best connection: " | 1044 LOG_J(LS_INFO, this) << "Previous best connection: " |
| 1023 << old_best_connection->ToString(); | 1045 << old_best_connection->ToString(); |
| 1024 } | 1046 } |
| 1025 LOG_J(LS_INFO, this) << "New best connection: " | 1047 LOG_J(LS_INFO, this) << "New best connection: " |
| 1026 << best_connection_->ToString(); | 1048 << best_connection_->ToString(); |
| 1027 SignalRouteChange(this, best_connection_->remote_candidate()); | 1049 SignalRouteChange(this, best_connection_->remote_candidate()); |
| 1028 set_receiving(best_connection_->receiving()); | |
| 1029 } else { | 1050 } else { |
| 1030 LOG_J(LS_INFO, this) << "No best connection"; | 1051 LOG_J(LS_INFO, this) << "No best connection"; |
| 1031 } | 1052 } |
| 1032 } | 1053 } |
| 1033 | 1054 |
| 1034 void P2PTransportChannel::UpdateChannelState() { | 1055 void P2PTransportChannel::UpdateChannelState() { |
| 1035 // The Handle* functions already set the writable state. We'll just double- | 1056 // The Handle* functions already set the writable state. We'll just double- |
| 1036 // check it here. | 1057 // check it here. |
| 1037 bool writable = ((best_connection_ != NULL) && | 1058 bool writable = best_connection_ && best_connection_->writable(); |
| 1038 (best_connection_->write_state() == | |
| 1039 Connection::STATE_WRITABLE)); | |
| 1040 ASSERT(writable == this->writable()); | 1059 ASSERT(writable == this->writable()); |
| 1041 if (writable != this->writable()) | 1060 if (writable != this->writable()) |
| 1042 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; | 1061 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; |
| 1043 | 1062 |
| 1044 // TODO(honghaiz): The channel receiving state is set in OnCheckReceiving. | 1063 bool receiving = false; |
| 1045 // Will revisit in a subsequent code change. | 1064 for (const Connection* connection : connections_) { |
| 1065 if (connection->receiving()) { | |
| 1066 receiving = true; | |
| 1067 break; | |
| 1068 } | |
| 1069 } | |
|
pthatcher1
2015/09/22 23:41:46
I thought this was more readable using std::any_of
honghaiz3
2015/09/23 03:16:10
Using that caused the compiling to break on some M
| |
| 1070 set_receiving(receiving); | |
| 1046 } | 1071 } |
| 1047 | 1072 |
| 1048 // We checked the status of our connections and we had at least one that | 1073 // We checked the status of our connections and we had at least one that |
| 1049 // was writable, go into the writable state. | 1074 // was writable, go into the writable state. |
| 1050 void P2PTransportChannel::HandleWritable() { | 1075 void P2PTransportChannel::HandleWritable() { |
| 1051 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1076 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1052 if (!writable()) { | 1077 if (!writable()) { |
| 1053 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { | 1078 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { |
| 1054 if (allocator_sessions_[i]->IsGettingPorts()) { | 1079 if (allocator_sessions_[i]->IsGettingPorts()) { |
| 1055 allocator_sessions_[i]->StopGettingPorts(); | 1080 allocator_sessions_[i]->StopGettingPorts(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 1068 was_writable_ = false; | 1093 was_writable_ = false; |
| 1069 set_writable(false); | 1094 set_writable(false); |
| 1070 } | 1095 } |
| 1071 } | 1096 } |
| 1072 | 1097 |
| 1073 void P2PTransportChannel::HandleAllTimedOut() { | 1098 void P2PTransportChannel::HandleAllTimedOut() { |
| 1074 // Currently we are treating this as channel not writable. | 1099 // Currently we are treating this as channel not writable. |
| 1075 HandleNotWritable(); | 1100 HandleNotWritable(); |
| 1076 } | 1101 } |
| 1077 | 1102 |
| 1103 bool P2PTransportChannel::Weak() const { | |
| 1104 return !(best_connection_ && best_connection_->receiving() && writable()); | |
|
pthatcher1
2015/09/22 23:41:46
Isn't the same as "!(best_connection_ && best_conn
honghaiz3
2015/09/23 03:16:10
Done.
| |
| 1105 } | |
| 1106 | |
| 1078 // If we have a best connection, return it, otherwise return top one in the | 1107 // If we have a best connection, return it, otherwise return top one in the |
| 1079 // list (later we will mark it best). | 1108 // list (later we will mark it best). |
| 1080 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | 1109 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
| 1081 rtc::Network* network) const { | 1110 rtc::Network* network) const { |
| 1082 // If the best connection is on this network, then it wins. | 1111 // If the best connection is on this network, then it wins. |
| 1083 if (best_connection_ && (best_connection_->port()->Network() == network)) | 1112 if (best_connection_ && (best_connection_->port()->Network() == network)) |
| 1084 return best_connection_; | 1113 return best_connection_; |
| 1085 | 1114 |
| 1086 // Otherwise, we return the top-most in sorted order. | 1115 // Otherwise, we return the top-most in sorted order. |
| 1087 for (uint32 i = 0; i < connections_.size(); ++i) { | 1116 for (uint32 i = 0; i < connections_.size(); ++i) { |
| 1088 if (connections_[i]->port()->Network() == network) | 1117 if (connections_[i]->port()->Network() == network) |
| 1089 return connections_[i]; | 1118 return connections_[i]; |
| 1090 } | 1119 } |
| 1091 | 1120 |
| 1092 return NULL; | 1121 return NULL; |
| 1093 } | 1122 } |
| 1094 | 1123 |
| 1095 // Handle any queued up requests | 1124 // Handle any queued up requests |
| 1096 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1125 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
| 1097 switch (pmsg->message_id) { | 1126 switch (pmsg->message_id) { |
| 1098 case MSG_SORT: | 1127 case MSG_SORT: |
| 1099 OnSort(); | 1128 OnSort(); |
| 1100 break; | 1129 break; |
| 1101 case MSG_PING: | 1130 case MSG_CHECK_AND_PING: |
| 1102 OnPing(); | 1131 OnCheckAndPing(); |
| 1103 break; | |
| 1104 case MSG_CHECK_RECEIVING: | |
| 1105 OnCheckReceiving(); | |
| 1106 break; | 1132 break; |
| 1107 default: | 1133 default: |
| 1108 ASSERT(false); | 1134 ASSERT(false); |
| 1109 break; | 1135 break; |
| 1110 } | 1136 } |
| 1111 } | 1137 } |
| 1112 | 1138 |
| 1113 // Handle queued up sort request | 1139 // Handle queued up sort request |
| 1114 void P2PTransportChannel::OnSort() { | 1140 void P2PTransportChannel::OnSort() { |
| 1115 // Resort the connections based on the new statistics. | 1141 // Resort the connections based on the new statistics. |
| 1116 SortConnections(); | 1142 SortConnections(); |
| 1117 } | 1143 } |
| 1118 | 1144 |
| 1119 // Handle queued up ping request | 1145 // Handle queued up check-and-ping request |
| 1120 void P2PTransportChannel::OnPing() { | 1146 void P2PTransportChannel::OnCheckAndPing() { |
| 1121 // Make sure the states of the connections are up-to-date (since this affects | 1147 // Make sure the states of the connections are up-to-date (since this affects |
| 1122 // which ones are pingable). | 1148 // which ones are pingable). |
| 1123 UpdateConnectionStates(); | 1149 UpdateConnectionStates(); |
| 1124 | 1150 // When the best connection is either not receiving or not writable, |
| 1125 // Find the oldest pingable connection and have it do a ping. | 1151 // switch to weak ping delay. |
| 1126 Connection* conn = FindNextPingableConnection(); | 1152 int ping_delay = Weak() ? WEAK_PING_DELAY : STRONG_PING_DELAY; |
| 1127 if (conn) | 1153 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) { |
| 1128 PingConnection(conn); | 1154 Connection* conn = FindNextPingableConnection(); |
| 1129 | 1155 if (conn) { |
| 1130 // Post ourselves a message to perform the next ping. | 1156 PingConnection(conn); |
| 1131 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; | 1157 } |
| 1132 thread()->PostDelayed(delay, this, MSG_PING); | |
| 1133 } | |
| 1134 | |
| 1135 void P2PTransportChannel::OnCheckReceiving() { | |
| 1136 if (best_connection_) { | |
| 1137 bool receiving = rtc::Time() <= | |
| 1138 best_connection_->last_received() + receiving_timeout_; | |
| 1139 set_receiving(receiving); | |
| 1140 } | 1158 } |
| 1141 | 1159 int check_delay = std::min(ping_delay, check_receiving_delay_); |
| 1142 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); | 1160 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING); |
| 1143 } | 1161 } |
|
pthatcher1
2015/09/22 23:41:46
So we only check for receiving() every 500ms? Doe
honghaiz3
2015/09/23 03:16:10
We took the minimum of the ping_delay and check_re
| |
| 1144 | 1162 |
| 1145 // Is the connection in a state for us to even consider pinging the other side? | 1163 // Is the connection in a state for us to even consider pinging the other side? |
| 1146 // We consider a connection pingable even if it's not connected because that's | 1164 // We consider a connection pingable even if it's not connected because that's |
| 1147 // how a TCP connection is kicked into reconnecting on the active side. | 1165 // how a TCP connection is kicked into reconnecting on the active side. |
| 1148 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1166 bool P2PTransportChannel::IsPingable(Connection* conn) { |
| 1149 const Candidate& remote = conn->remote_candidate(); | 1167 const Candidate& remote = conn->remote_candidate(); |
| 1150 // We should never get this far with an empty remote ufrag. | 1168 // We should never get this far with an empty remote ufrag. |
| 1151 ASSERT(!remote.username().empty()); | 1169 ASSERT(!remote.username().empty()); |
| 1152 if (remote.username().empty() || remote.password().empty()) { | 1170 if (remote.username().empty() || remote.password().empty()) { |
| 1153 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1171 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
| 1154 return false; | 1172 return false; |
| 1155 } | 1173 } |
| 1156 | 1174 |
| 1157 // An never connected connection cannot be written to at all, so pinging is | 1175 // An never connected connection cannot be written to at all, so pinging is |
| 1158 // out of the question. However, if it has become WRITABLE, it is in the | 1176 // out of the question. However, if it has become WRITABLE, it is in the |
| 1159 // reconnecting state so ping is needed. | 1177 // reconnecting state so ping is needed. |
| 1160 if (!conn->connected() && !conn->writable()) { | 1178 if (!conn->connected() && !conn->writable()) { |
| 1161 return false; | 1179 return false; |
| 1162 } | 1180 } |
| 1163 | 1181 |
| 1164 // If the channel is not writable, ping all candidates. Otherwise, we only | 1182 // If the channel is weak, ping all candidates. Otherwise, we only |
| 1165 // want to ping connections that have not timed out on writing. | 1183 // want to ping connections that have not timed out on writing. |
| 1166 return !writable() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; | 1184 return Weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; |
| 1167 } | 1185 } |
| 1168 | 1186 |
| 1169 // Returns the next pingable connection to ping. This will be the oldest | 1187 // Returns the next pingable connection to ping. This will be the oldest |
| 1170 // pingable connection unless we have a connected, writable connection that is | 1188 // pingable connection unless we have a connected, writable connection that is |
| 1171 // past the maximum acceptable ping delay. When reconnecting a TCP connection, | 1189 // past the maximum acceptable ping delay. When reconnecting a TCP connection, |
| 1172 // the best connection is disconnected, although still WRITABLE while | 1190 // the best connection is disconnected, although still WRITABLE while |
| 1173 // reconnecting. The newly created connection should be selected as the ping | 1191 // reconnecting. The newly created connection should be selected as the ping |
| 1174 // target to become writable instead. See the big comment in CompareConnections. | 1192 // target to become writable instead. See the big comment in CompareConnections. |
| 1175 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1193 Connection* P2PTransportChannel::FindNextPingableConnection() { |
| 1176 uint32 now = rtc::Time(); | 1194 uint32 now = rtc::Time(); |
| 1177 if (best_connection_ && best_connection_->connected() && | 1195 if (best_connection_ && best_connection_->connected() && |
| 1178 (best_connection_->write_state() == Connection::STATE_WRITABLE) && | 1196 best_connection_->writable() && |
| 1179 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <= | 1197 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) { |
| 1180 now)) { | |
| 1181 return best_connection_; | 1198 return best_connection_; |
| 1182 } | 1199 } |
| 1183 | 1200 |
| 1184 // First, find "triggered checks". We ping first those connections | 1201 // First, find "triggered checks". We ping first those connections |
| 1185 // that have received a ping but have not sent a ping since receiving | 1202 // that have received a ping but have not sent a ping since receiving |
| 1186 // it (last_received_ping > last_sent_ping). But we shouldn't do | 1203 // it (last_received_ping > last_sent_ping). But we shouldn't do |
| 1187 // triggered checks if the connection is already writable. | 1204 // triggered checks if the connection is already writable. |
| 1188 Connection* oldest_needing_triggered_check = nullptr; | 1205 Connection* oldest_needing_triggered_check = nullptr; |
| 1189 Connection* oldest = nullptr; | 1206 Connection* oldest = nullptr; |
| 1190 for (Connection* conn : connections_) { | 1207 for (Connection* conn : connections_) { |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1229 bool use_candidate = false; | 1246 bool use_candidate = false; |
| 1230 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1247 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
| 1231 use_candidate = (conn == best_connection_) || | 1248 use_candidate = (conn == best_connection_) || |
| 1232 (best_connection_ == NULL) || | 1249 (best_connection_ == NULL) || |
| 1233 (!best_connection_->writable()) || | 1250 (!best_connection_->writable()) || |
| 1234 (conn->priority() > best_connection_->priority()); | 1251 (conn->priority() > best_connection_->priority()); |
| 1235 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1252 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { |
| 1236 use_candidate = best_connection_->writable(); | 1253 use_candidate = best_connection_->writable(); |
| 1237 } | 1254 } |
| 1238 conn->set_use_candidate_attr(use_candidate); | 1255 conn->set_use_candidate_attr(use_candidate); |
| 1239 conn->Ping(rtc::Time()); | 1256 last_ping_sent_ms_ = rtc::Time(); |
| 1257 conn->Ping(last_ping_sent_ms_); | |
| 1240 } | 1258 } |
| 1241 | 1259 |
| 1242 // When a connection's state changes, we need to figure out who to use as | 1260 // When a connection's state changes, we need to figure out who to use as |
| 1243 // the best connection again. It could have become usable, or become unusable. | 1261 // the best connection again. It could have become usable, or become unusable. |
| 1244 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1262 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
| 1245 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1263 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1246 | 1264 |
| 1247 // Update the best connection if the state change is from pending best | 1265 // Update the best connection if the state change is from pending best |
| 1248 // connection and role is controlled. | 1266 // connection and role is controlled. |
| 1249 if (ice_role_ == ICEROLE_CONTROLLED) { | 1267 if (ice_role_ == ICEROLE_CONTROLLED) { |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1331 } | 1349 } |
| 1332 } | 1350 } |
| 1333 | 1351 |
| 1334 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1352 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1335 if (connection == best_connection_ && writable()) { | 1353 if (connection == best_connection_ && writable()) { |
| 1336 SignalReadyToSend(this); | 1354 SignalReadyToSend(this); |
| 1337 } | 1355 } |
| 1338 } | 1356 } |
| 1339 | 1357 |
| 1340 } // namespace cricket | 1358 } // namespace cricket |
| OLD | NEW |