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

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

Issue 1311433009: A few updates on connection states (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Dropping changes on pruning and write_stale state. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
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
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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698