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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 if (!origin_port) | 46 if (!origin_port) |
47 return cricket::PortInterface::ORIGIN_MESSAGE; | 47 return cricket::PortInterface::ORIGIN_MESSAGE; |
48 else if (port == origin_port) | 48 else if (port == origin_port) |
49 return cricket::PortInterface::ORIGIN_THIS_PORT; | 49 return cricket::PortInterface::ORIGIN_THIS_PORT; |
50 else | 50 else |
51 return cricket::PortInterface::ORIGIN_OTHER_PORT; | 51 return cricket::PortInterface::ORIGIN_OTHER_PORT; |
52 } | 52 } |
53 | 53 |
54 // Compares two connections based only on the candidate and network information. | 54 // Compares two connections based only on the candidate and network information. |
55 // Returns positive if |a| is better than |b|. | 55 // Returns positive if |a| is better than |b|. |
56 int CompareConnectionCandidates(cricket::Connection* a, | 56 int CompareConnectionCandidates(const cricket::Connection* a, |
57 cricket::Connection* b) { | 57 const cricket::Connection* b) { |
58 uint32_t a_cost = a->ComputeNetworkCost(); | 58 uint32_t a_cost = a->ComputeNetworkCost(); |
59 uint32_t b_cost = b->ComputeNetworkCost(); | 59 uint32_t b_cost = b->ComputeNetworkCost(); |
60 // Smaller cost is better. | 60 // Smaller cost is better. |
61 if (a_cost < b_cost) { | 61 if (a_cost < b_cost) { |
62 return 1; | 62 return 1; |
63 } | 63 } |
64 if (a_cost > b_cost) { | 64 if (a_cost > b_cost) { |
65 return -1; | 65 return -1; |
66 } | 66 } |
67 | 67 |
68 // Compare connection priority. Lower values get sorted last. | 68 // Compare connection priority. Lower values get sorted last. |
69 if (a->priority() > b->priority()) | 69 if (a->priority() > b->priority()) |
70 return 1; | 70 return 1; |
71 if (a->priority() < b->priority()) | 71 if (a->priority() < b->priority()) |
72 return -1; | 72 return -1; |
73 | 73 |
74 // If we're still tied at this point, prefer a younger generation. | 74 // If we're still tied at this point, prefer a younger generation. |
75 return (a->remote_candidate().generation() + a->port()->generation()) - | 75 return (a->remote_candidate().generation() + a->port()->generation()) - |
76 (b->remote_candidate().generation() + b->port()->generation()); | 76 (b->remote_candidate().generation() + b->port()->generation()); |
77 } | 77 } |
78 | 78 |
79 // Compare two connections based on their writing, receiving, and connected | 79 // Compare two connections based on their writing, receiving, and connected |
80 // states. | 80 // states. |
81 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) { | 81 int CompareConnectionStates(const cricket::Connection* a, |
82 const cricket::Connection* b) { | |
82 // Sort based on write-state. Better states have lower values. | 83 // Sort based on write-state. Better states have lower values. |
83 if (a->write_state() < b->write_state()) | 84 if (a->write_state() < b->write_state()) |
84 return 1; | 85 return 1; |
85 if (a->write_state() > b->write_state()) | 86 if (a->write_state() > b->write_state()) |
86 return -1; | 87 return -1; |
87 | 88 |
88 // We prefer a receiving connection to a non-receiving, higher-priority | 89 // We prefer a receiving connection to a non-receiving, higher-priority |
89 // connection when sorting connections and choosing which connection to | 90 // connection when sorting connections and choosing which connection to |
90 // switch to. | 91 // switch to. |
91 if (a->receiving() && !b->receiving()) | 92 if (a->receiving() && !b->receiving()) |
92 return 1; | 93 return 1; |
93 if (!a->receiving() && b->receiving()) | 94 if (!a->receiving() && b->receiving()) |
94 return -1; | 95 return -1; |
95 | 96 |
96 // WARNING: Some complexity here about TCP reconnecting. | 97 // WARNING: Some complexity here about TCP reconnecting. |
97 // When a TCP connection fails because of a TCP socket disconnecting, the | 98 // When a TCP connection fails because of a TCP socket disconnecting, the |
98 // active side of the connection will attempt to reconnect for 5 seconds while | 99 // active side of the connection will attempt to reconnect for 5 seconds while |
99 // pretending to be writable (the connection is not set to the unwritable | 100 // pretending to be writable (the connection is not set to the unwritable |
100 // state). On the passive side, the connection also remains writable even | 101 // state). On the passive side, the connection also remains writable even |
101 // though it is disconnected, and a new connection is created when the active | 102 // though it is disconnected, and a new connection is created when the active |
102 // side connects. At that point, there are two TCP connections on the passive | 103 // side connects. At that point, there are two TCP connections on the passive |
103 // side: 1. the old, disconnected one that is pretending to be writable, and | 104 // side: 1. the old, disconnected one that is pretending to be writable, and |
104 // 2. the new, connected one that is maybe not yet writable. For purposes of | 105 // 2. the new, connected one that is maybe not yet writable. For purposes of |
105 // pruning, pinging, and selecting the best connection, we want to treat the | 106 // 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 | 107 // new connection as "better" than the old one. We could add a method called |
107 // something like Connection::ImReallyBadEvenThoughImWritable, but that is | 108 // something like Connection::ImReallyBadEvenThoughImWritable, but that is |
108 // equivalent to the existing Connection::connected(), which we already have. | 109 // equivalent to the existing Connection::connected(), which we already have. |
109 // So, in code throughout this file, we'll check whether the connection is | 110 // So, in code throughout this file, we'll check whether the connection is |
110 // connected() or not, and if it is not, treat it as "worse" than a connected | 111 // connected() or not, and if it is not, treat it as "worse" than a connected |
111 // one, even though it's writable. In the code below, we're doing so to make | 112 // one, even though it's writable. In the code below, we're doing so to make |
112 // sure we treat a new writable connection as better than an old disconnected | 113 // sure we treat a new writable connection as better than an old disconnected |
113 // connection. | 114 // connection. |
114 | 115 |
115 // In the case where we reconnect TCP connections, the original best | 116 // In the case where we reconnect TCP connections, the original best |
116 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, | 117 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, |
117 // the new connection, when it becomes writable, should have higher priority. | 118 // the new connection, when it becomes writable, should have higher priority. |
118 if (a->write_state() == cricket::Connection::STATE_WRITABLE && | 119 if (a->write_state() == cricket::Connection::STATE_WRITABLE && |
119 b->write_state() == cricket::Connection::STATE_WRITABLE) { | 120 b->write_state() == cricket::Connection::STATE_WRITABLE) { |
120 if (a->connected() && !b->connected()) { | 121 if (a->connected() && !b->connected()) { |
121 return 1; | 122 return 1; |
122 } | 123 } |
123 if (!a->connected() && b->connected()) { | 124 if (!a->connected() && b->connected()) { |
124 return -1; | 125 return -1; |
125 } | 126 } |
126 } | 127 } |
127 return 0; | 128 return 0; |
128 } | 129 } |
129 | 130 |
130 int CompareConnections(cricket::Connection* a, cricket::Connection* b) { | |
131 int state_cmp = CompareConnectionStates(a, b); | |
132 if (state_cmp != 0) { | |
133 return state_cmp; | |
134 } | |
135 // Compare the candidate information. | |
136 return CompareConnectionCandidates(a, b); | |
137 } | |
138 | |
139 // Wraps the comparison connection into a less than operator that puts higher | |
140 // priority writable connections first. | |
141 class ConnectionCompare { | |
142 public: | |
143 bool operator()(const cricket::Connection *ca, | |
144 const cricket::Connection *cb) { | |
145 cricket::Connection* a = const_cast<cricket::Connection*>(ca); | |
146 cricket::Connection* b = const_cast<cricket::Connection*>(cb); | |
147 | |
148 // Compare first on writability and static preferences. | |
149 int cmp = CompareConnections(a, b); | |
150 if (cmp > 0) | |
151 return true; | |
152 if (cmp < 0) | |
153 return false; | |
154 | |
155 // Otherwise, sort based on latency estimate. | |
156 return a->rtt() < b->rtt(); | |
157 | |
158 // Should we bother checking for the last connection that last received | |
159 // data? It would help rendezvous on the connection that is also receiving | |
160 // packets. | |
161 // | |
162 // TODO: Yes we should definitely do this. The TCP protocol gains | |
163 // efficiency by being used bidirectionally, as opposed to two separate | |
164 // unidirectional streams. This test should probably occur before | |
165 // comparison of local prefs (assuming combined prefs are the same). We | |
166 // need to be careful though, not to bounce back and forth with both sides | |
167 // trying to rendevous with the other. | |
168 } | |
169 }; | |
170 | |
171 // Determines whether we should switch between two connections, based first on | |
172 // connection states, static preferences, and then (if those are equal) on | |
173 // latency estimates. | |
174 bool ShouldSwitch(cricket::Connection* a_conn, | |
175 cricket::Connection* b_conn, | |
176 cricket::IceRole ice_role) { | |
177 if (a_conn == b_conn) | |
178 return false; | |
179 | |
180 if (!a_conn || !b_conn) // don't think the latter should happen | |
181 return true; | |
182 | |
183 // We prefer to switch to a writable and receiving connection over a | |
184 // non-writable or non-receiving connection, even if the latter has | |
185 // been nominated by the controlling side. | |
186 int state_cmp = CompareConnectionStates(a_conn, b_conn); | |
187 if (state_cmp != 0) { | |
188 return state_cmp < 0; | |
189 } | |
190 if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) { | |
191 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status"; | |
192 return false; | |
193 } | |
194 | |
195 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn); | |
196 if (prefs_cmp != 0) { | |
197 return prefs_cmp < 0; | |
198 } | |
199 | |
200 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; | |
201 } | |
202 | |
203 } // unnamed namespace | 131 } // unnamed namespace |
204 | 132 |
205 namespace cricket { | 133 namespace cricket { |
206 | 134 |
207 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 135 // 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 | 136 // 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 | 137 // 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 | 138 // well on a 28.8K modem, which is the slowest connection on which the voice |
211 // quality is reasonable at all. | 139 // quality is reasonable at all. |
212 static const int PING_PACKET_SIZE = 60 * 8; | 140 static const int PING_PACKET_SIZE = 60 * 8; |
213 // STRONG_PING_INTERVAL (480ms) is applied when the best connection is both | 141 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both |
214 // writable and receiving. | 142 // writable and receiving. |
215 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; | 143 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 | 144 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either |
217 // writable or not receiving. | 145 // not writable or not receiving. |
218 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; | 146 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; |
219 | 147 |
220 // If the current best connection is both writable and receiving, then we will | 148 // 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 | 149 // will also try hard to make sure it is pinged at this rate (a little less |
222 // 2 * STRONG_PING_INTERVAL). | 150 // than 2 * STRONG_PING_INTERVAL). |
223 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms | 151 static const int MAX_CURRENT_STRONG_INTERVAL = 900; // ms |
224 | 152 |
225 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms | 153 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
226 | 154 |
227 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 155 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
228 int component, | 156 int component, |
229 P2PTransport* transport, | 157 P2PTransport* transport, |
230 PortAllocator* allocator) | 158 PortAllocator* allocator) |
231 : P2PTransportChannel(transport_name, component, allocator) {} | 159 : P2PTransportChannel(transport_name, component, allocator) {} |
232 | 160 |
233 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 161 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
234 int component, | 162 int component, |
235 PortAllocator* allocator) | 163 PortAllocator* allocator) |
236 : TransportChannelImpl(transport_name, component), | 164 : TransportChannelImpl(transport_name, component), |
237 allocator_(allocator), | 165 allocator_(allocator), |
238 worker_thread_(rtc::Thread::Current()), | 166 worker_thread_(rtc::Thread::Current()), |
239 incoming_only_(false), | 167 incoming_only_(false), |
240 error_(0), | 168 error_(0), |
241 best_connection_(NULL), | |
242 pending_best_connection_(NULL), | |
243 sort_dirty_(false), | 169 sort_dirty_(false), |
244 remote_ice_mode_(ICEMODE_FULL), | 170 remote_ice_mode_(ICEMODE_FULL), |
245 ice_role_(ICEROLE_UNKNOWN), | 171 ice_role_(ICEROLE_UNKNOWN), |
246 tiebreaker_(0), | 172 tiebreaker_(0), |
247 gathering_state_(kIceGatheringNew), | 173 gathering_state_(kIceGatheringNew), |
248 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 174 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
249 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 175 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
250 0 /* backup_connection_ping_interval */, | 176 0 /* backup_connection_ping_interval */, |
251 false /* gather_continually */, | 177 false /* gather_continually */, |
252 false /* prioritize_most_likely_candidate_pairs */, | 178 false /* prioritize_most_likely_candidate_pairs */, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 connection->SignalReadyToSend.connect( | 220 connection->SignalReadyToSend.connect( |
295 this, &P2PTransportChannel::OnReadyToSend); | 221 this, &P2PTransportChannel::OnReadyToSend); |
296 connection->SignalStateChange.connect( | 222 connection->SignalStateChange.connect( |
297 this, &P2PTransportChannel::OnConnectionStateChange); | 223 this, &P2PTransportChannel::OnConnectionStateChange); |
298 connection->SignalDestroyed.connect( | 224 connection->SignalDestroyed.connect( |
299 this, &P2PTransportChannel::OnConnectionDestroyed); | 225 this, &P2PTransportChannel::OnConnectionDestroyed); |
300 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); | 226 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
301 had_connection_ = true; | 227 had_connection_ = true; |
302 } | 228 } |
303 | 229 |
230 int P2PTransportChannel::CompareConnections( | |
pthatcher1
2016/06/21 07:16:53
Can you call this CompareConnectionIncludingStates
honghaiz3
2016/06/22 08:03:16
Done.
| |
231 const cricket::Connection* a, | |
232 const cricket::Connection* b) const { | |
233 RTC_CHECK(a != nullptr); | |
234 RTC_CHECK(b != nullptr); | |
235 | |
236 // We prefer to switch to a writable and receiving connection over a | |
237 // non-writable or non-receiving connection, even if the latter has | |
238 // been nominated by the controlling side. | |
239 int state_cmp = CompareConnectionStates(a, b); | |
240 if (state_cmp != 0) { | |
241 return state_cmp; | |
242 } | |
243 return CompareConnectionsBase(a, b); | |
244 } | |
245 | |
246 int P2PTransportChannel::CompareConnectionsBase( | |
pthatcher1
2016/06/21 07:16:53
Can you call this CompareConnectionsExcludingState
honghaiz3
2016/06/22 08:03:16
Done.
| |
247 const cricket::Connection* a, | |
248 const cricket::Connection* b) const { | |
249 if (ice_role_ == cricket::ICEROLE_CONTROLLED) { | |
250 // Compare the connections based on the nomination states and the last data | |
251 // received time if this is on the controlled side. | |
252 if (a->nominated() != b->nominated()) { | |
253 return b->nominated() ? -1 : 1; | |
254 } | |
255 | |
256 if (a->last_data_received() > b->last_data_received()) { | |
Taylor Brandstetter
2016/06/21 18:33:25
What happens if the controlled side stops sending
pthatcher1
2016/06/22 06:36:34
We could still switch to a higher priority candida
honghaiz3
2016/06/22 08:03:16
If the controlling side stops sending data, the co
honghaiz3
2016/06/22 08:03:16
Acknowledged.
| |
257 return 1; | |
258 } | |
259 if (a->last_data_received() < b->last_data_received()) { | |
260 return -1; | |
261 } | |
262 } | |
263 | |
264 // Compare the network cost and priority. | |
265 return CompareConnectionCandidates(a, b); | |
266 } | |
267 | |
268 // Determines whether we should switch the selected connection to | |
269 // |new_connection| based the writable/receiving state, the nomination state, | |
270 // and the last data received time. This prevents the controlled side from | |
271 // switching the selected connection too frequently when the controlling side | |
272 // is doing aggressive nominations. The precedence of the connection switching | |
273 // criteria is as follows: | |
274 // i) write/receiving/connected states | |
275 // ii) For controlled side, | |
276 // a) nomination state, | |
277 // b) last data received time. | |
278 // iii) Lower cost / higher priority. | |
279 // iv) rtt. | |
280 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and | |
281 // implement the ice-renomination option. | |
282 bool P2PTransportChannel::ShouldSwitchConnection( | |
pthatcher1
2016/06/21 07:16:53
Can you call this ShouldSwitchSelectedConnection?
honghaiz3
2016/06/22 08:03:16
Done.
| |
283 cricket::Connection* new_connection) const { | |
284 RTC_CHECK(new_connection != nullptr); | |
285 RTC_DCHECK(selected_connection_ != new_connection); | |
pthatcher1
2016/06/21 07:16:52
I think it would simply be better to do this:
if
honghaiz3
2016/06/22 08:03:16
Done.
| |
286 | |
287 if (selected_connection_ == nullptr) { | |
288 return true; | |
289 } | |
290 int cmp = CompareConnections(selected_connection_, new_connection); | |
291 if (cmp != 0) { | |
292 return cmp < 0; | |
293 } | |
294 | |
295 // Lastly, switch only if rtt has improved by a margin. | |
Taylor Brandstetter
2016/06/21 18:33:25
Odd to say "lastly" if there's no "firstly". Maybe
pthatcher1
2016/06/22 06:36:34
I think that's what the big comment before the met
honghaiz3
2016/06/22 08:03:16
Acknowledged.
honghaiz3
2016/06/22 08:03:16
Revised the comments.
| |
296 return new_connection->rtt() <= selected_connection_->rtt() + kMinImprovement; | |
297 } | |
298 | |
304 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 299 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
305 ASSERT(worker_thread_ == rtc::Thread::Current()); | 300 ASSERT(worker_thread_ == rtc::Thread::Current()); |
306 if (ice_role_ != ice_role) { | 301 if (ice_role_ != ice_role) { |
307 ice_role_ = ice_role; | 302 ice_role_ = ice_role; |
308 for (std::vector<PortInterface *>::iterator it = ports_.begin(); | 303 for (std::vector<PortInterface *>::iterator it = ports_.begin(); |
309 it != ports_.end(); ++it) { | 304 it != ports_.end(); ++it) { |
310 (*it)->SetIceRole(ice_role); | 305 (*it)->SetIceRole(ice_role); |
311 } | 306 } |
312 } | 307 } |
313 } | 308 } |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
722 return nullptr; | 717 return nullptr; |
723 } | 718 } |
724 *generation = params.rend() - it - 1; | 719 *generation = params.rend() - it - 1; |
725 return &(*it); | 720 return &(*it); |
726 } | 721 } |
727 | 722 |
728 void P2PTransportChannel::OnNominated(Connection* conn) { | 723 void P2PTransportChannel::OnNominated(Connection* conn) { |
729 ASSERT(worker_thread_ == rtc::Thread::Current()); | 724 ASSERT(worker_thread_ == rtc::Thread::Current()); |
730 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 725 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
731 | 726 |
732 if (conn->write_state() == Connection::STATE_WRITABLE) { | 727 if (selected_connection_ == conn) { |
733 if (best_connection_ != conn) { | 728 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 } | 729 } |
730 | |
731 if (!ShouldSwitchConnection(conn)) { | |
732 LOG(LS_INFO) | |
733 << "Not switching the selected connection on controlled side yet: " | |
734 << conn->ToString(); | |
735 return; | |
736 } | |
737 | |
738 LOG(LS_INFO) | |
739 << "Switching selected connection on controlled side due to nomination: " | |
740 << conn->ToString(); | |
741 SwitchSelectedConnection(conn); | |
742 // Now we have selected the selected connection, time to prune other existing | |
Taylor Brandstetter
2016/06/21 18:33:25
"Now that we have selected a connection, it's time
honghaiz3
2016/06/22 08:03:16
Done.
| |
743 // connections and update the read/write state of the channel. | |
744 RequestSort(); | |
747 } | 745 } |
748 | 746 |
749 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 747 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
750 ASSERT(worker_thread_ == rtc::Thread::Current()); | 748 ASSERT(worker_thread_ == rtc::Thread::Current()); |
751 | 749 |
752 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 750 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
753 // If a remote candidate with a previous generation arrives, drop it. | 751 // If a remote candidate with a previous generation arrives, drop it. |
754 if (generation < remote_ice_generation()) { | 752 if (generation < remote_ice_generation()) { |
755 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 753 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
756 << candidate.username() | 754 << candidate.username() |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
983 ASSERT(worker_thread_ == rtc::Thread::Current()); | 981 ASSERT(worker_thread_ == rtc::Thread::Current()); |
984 | 982 |
985 const auto& found = options_.find(opt); | 983 const auto& found = options_.find(opt); |
986 if (found == options_.end()) { | 984 if (found == options_.end()) { |
987 return false; | 985 return false; |
988 } | 986 } |
989 *value = found->second; | 987 *value = found->second; |
990 return true; | 988 return true; |
991 } | 989 } |
992 | 990 |
993 // Send data to the other side, using our best connection. | 991 // Send data to the other side, using our selected connection. |
994 int P2PTransportChannel::SendPacket(const char *data, size_t len, | 992 int P2PTransportChannel::SendPacket(const char *data, size_t len, |
995 const rtc::PacketOptions& options, | 993 const rtc::PacketOptions& options, |
996 int flags) { | 994 int flags) { |
997 ASSERT(worker_thread_ == rtc::Thread::Current()); | 995 ASSERT(worker_thread_ == rtc::Thread::Current()); |
998 if (flags != 0) { | 996 if (flags != 0) { |
999 error_ = EINVAL; | 997 error_ = EINVAL; |
1000 return -1; | 998 return -1; |
1001 } | 999 } |
1002 if (best_connection_ == NULL) { | 1000 if (selected_connection_ == NULL) { |
1003 error_ = EWOULDBLOCK; | 1001 error_ = EWOULDBLOCK; |
1004 return -1; | 1002 return -1; |
1005 } | 1003 } |
1006 | 1004 |
1007 last_sent_packet_id_ = options.packet_id; | 1005 last_sent_packet_id_ = options.packet_id; |
1008 int sent = best_connection_->Send(data, len, options); | 1006 int sent = selected_connection_->Send(data, len, options); |
1009 if (sent <= 0) { | 1007 if (sent <= 0) { |
1010 ASSERT(sent < 0); | 1008 ASSERT(sent < 0); |
1011 error_ = best_connection_->GetError(); | 1009 error_ = selected_connection_->GetError(); |
1012 } | 1010 } |
1013 return sent; | 1011 return sent; |
1014 } | 1012 } |
1015 | 1013 |
1016 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 1014 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
1017 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1015 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1018 // Gather connection infos. | 1016 // Gather connection infos. |
1019 infos->clear(); | 1017 infos->clear(); |
1020 | 1018 |
1021 for (Connection* connection : connections_) { | 1019 for (Connection* connection : connections_) { |
1022 ConnectionInfo info = connection->stats(); | 1020 ConnectionInfo info = connection->stats(); |
1023 info.best_connection = (best_connection_ == connection); | 1021 info.best_connection = (selected_connection_ == connection); |
1024 info.receiving = connection->receiving(); | 1022 info.receiving = connection->receiving(); |
1025 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); | 1023 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); |
1026 info.timeout = | 1024 info.timeout = |
1027 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 1025 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
1028 info.new_connection = !connection->reported(); | 1026 info.new_connection = !connection->reported(); |
1029 connection->set_reported(true); | 1027 connection->set_reported(true); |
1030 info.rtt = connection->rtt(); | 1028 info.rtt = connection->rtt(); |
1031 info.local_candidate = connection->local_candidate(); | 1029 info.local_candidate = connection->local_candidate(); |
1032 info.remote_candidate = connection->remote_candidate(); | 1030 info.remote_candidate = connection->remote_candidate(); |
1033 info.key = connection; | 1031 info.key = connection; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1072 // will be sorted. | 1070 // will be sorted. |
1073 UpdateConnectionStates(); | 1071 UpdateConnectionStates(); |
1074 | 1072 |
1075 // Any changes after this point will require a re-sort. | 1073 // Any changes after this point will require a re-sort. |
1076 sort_dirty_ = false; | 1074 sort_dirty_ = false; |
1077 | 1075 |
1078 // Find the best alternative connection by sorting. It is important to note | 1076 // Find the best alternative connection by sorting. It is important to note |
1079 // that amongst equal preference, writable connections, this will choose the | 1077 // that amongst equal preference, writable connections, this will choose the |
1080 // one whose estimated latency is lowest. So it is the only one that we | 1078 // one whose estimated latency is lowest. So it is the only one that we |
1081 // need to consider switching to. | 1079 // need to consider switching to. |
1082 ConnectionCompare cmp; | 1080 std::stable_sort( |
1083 std::stable_sort(connections_.begin(), connections_.end(), cmp); | 1081 connections_.begin(), connections_.end(), |
1082 [this](const cricket::Connection* a, const cricket::Connection* b) { | |
1083 int cmp = CompareConnections(a, b); | |
1084 if (cmp != 0) { | |
1085 return cmp > 0; | |
1086 } | |
1087 | |
1088 // Otherwise, sort based on latency estimate. | |
1089 return a->rtt() < b->rtt(); | |
1090 }); | |
1084 LOG(LS_VERBOSE) << "Sorting " << connections_.size() | 1091 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
1085 << " available connections:"; | 1092 << " available connections:"; |
1086 for (size_t i = 0; i < connections_.size(); ++i) { | 1093 for (size_t i = 0; i < connections_.size(); ++i) { |
1087 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 1094 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
1088 } | 1095 } |
1089 | 1096 |
1090 Connection* top_connection = | 1097 Connection* top_connection = |
1091 (connections_.size() > 0) ? connections_[0] : nullptr; | 1098 (connections_.size() > 0) ? connections_[0] : nullptr; |
1092 | 1099 |
1093 // If necessary, switch to the new choice. | 1100 // 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 | 1101 // have to be writable to become the selected connection although it will |
1095 // connection although it will have higher priority if it is writable. | 1102 // have higher priority if it is writable. |
1096 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) { | 1103 if (top_connection != selected_connection_ && |
1097 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 1104 ShouldSwitchConnection(top_connection)) { |
pthatcher1
2016/06/21 07:16:53
Can you move this line into ShouldSwitchSelectedCo
honghaiz3
2016/06/22 08:03:16
Done.
| |
1098 SwitchBestConnectionTo(top_connection); | 1105 LOG(LS_INFO) << "Switching selected connection after sorting: " |
1106 << top_connection->ToString(); | |
1107 SwitchSelectedConnection(top_connection); | |
1099 } | 1108 } |
1100 | 1109 |
1101 // Controlled side can prune only if the best connection has been nominated. | 1110 // Controlled side can prune only if the selected connection has been |
pthatcher1
2016/06/21 07:16:53
Controlled side => The controlled side
honghaiz3
2016/06/22 08:03:16
Done.
| |
1102 // because otherwise it may delete the connection that will be selected by | 1111 // nominated because otherwise it may prune the connection that will be |
1103 // the controlling side. | 1112 // selected by the controlling side. |
1104 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 1113 // TODO(honghaiz): This is not enough to prevent a connection from being |
1114 // pruned too early because with aggressive nomination, the controlling side | |
1115 // will nominate every connection until it becomes writable. What we do now | |
1116 // is to un-prune a connection if a ping request comes with a nomination, or | |
1117 // new data is received on a nominated connection. | |
1118 if (ice_role_ == ICEROLE_CONTROLLING || selected_nominated_connection()) { | |
1105 PruneConnections(); | 1119 PruneConnections(); |
1106 } | 1120 } |
1107 | 1121 |
1108 // Check if all connections are timedout. | 1122 // Check if all connections are timedout. |
1109 bool all_connections_timedout = true; | 1123 bool all_connections_timedout = true; |
1110 for (size_t i = 0; i < connections_.size(); ++i) { | 1124 for (size_t i = 0; i < connections_.size(); ++i) { |
1111 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 1125 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
1112 all_connections_timedout = false; | 1126 all_connections_timedout = false; |
1113 break; | 1127 break; |
1114 } | 1128 } |
1115 } | 1129 } |
1116 | 1130 |
1117 // Now update the writable state of the channel with the information we have | 1131 // Now update the writable state of the channel with the information we have |
1118 // so far. | 1132 // so far. |
1119 if (all_connections_timedout) { | 1133 if (all_connections_timedout) { |
1120 HandleAllTimedOut(); | 1134 HandleAllTimedOut(); |
1121 } | 1135 } |
1122 | 1136 |
1123 // Update the state of this channel. This method is called whenever the | 1137 // 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. | 1138 // state of any connection changes, so this is a good place to do this. |
1125 UpdateState(); | 1139 UpdateState(); |
1126 } | 1140 } |
1127 | 1141 |
1128 Connection* P2PTransportChannel::best_nominated_connection() const { | 1142 Connection* P2PTransportChannel::selected_nominated_connection() const { |
pthatcher1
2016/06/21 07:16:53
Since this is only called once, I suggest we inlin
honghaiz3
2016/06/22 08:03:16
Done.
| |
1129 return (best_connection_ && best_connection_->nominated()) ? best_connection_ | 1143 return (selected_connection_ && selected_connection_->nominated()) |
1130 : nullptr; | 1144 ? selected_connection_ |
1145 : nullptr; | |
1131 } | 1146 } |
1132 | 1147 |
1133 void P2PTransportChannel::PruneConnections() { | 1148 void P2PTransportChannel::PruneConnections() { |
1134 // We can prune any connection for which there is a connected, writable | 1149 // 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 | 1150 // 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 | 1151 // 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 | 1152 // 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 | 1153 // 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 | 1154 // resources and they may represent very distinct paths over which we can |
1140 // switch. If the |premier| connection is not connected, we may be | 1155 // switch. If the |premier| connection is not connected, we may be |
1141 // reconnecting a TCP connection and temporarily do not prune connections in | 1156 // reconnecting a TCP connection and temporarily do not prune connections in |
1142 // this network. See the big comment in CompareConnections. | 1157 // this network. See the big comment in CompareConnections. |
1143 | 1158 |
1144 // Get a list of the networks that we are using. | 1159 // Get a list of the networks that we are using. |
1145 std::set<rtc::Network*> networks; | 1160 std::set<rtc::Network*> networks; |
1146 for (const Connection* conn : connections_) { | 1161 for (const Connection* conn : connections_) { |
1147 networks.insert(conn->port()->Network()); | 1162 networks.insert(conn->port()->Network()); |
1148 } | 1163 } |
1149 for (rtc::Network* network : networks) { | 1164 for (rtc::Network* network : networks) { |
1150 Connection* premier = GetBestConnectionOnNetwork(network); | 1165 Connection* premier = GetBestConnectionOnNetwork(network); |
1151 // Do not prune connections if the current best connection is weak on this | 1166 // Do not prune connections if the current selected connection is weak on |
1152 // network. Otherwise, it may delete connections prematurely. | 1167 // this network. Otherwise, it may delete connections prematurely. |
1153 if (!premier || premier->weak()) { | 1168 if (!premier || premier->weak()) { |
1154 continue; | 1169 continue; |
1155 } | 1170 } |
1156 | 1171 |
1157 for (Connection* conn : connections_) { | 1172 for (Connection* conn : connections_) { |
1158 if ((conn != premier) && (conn->port()->Network() == network) && | 1173 if ((conn != premier) && (conn->port()->Network() == network) && |
1159 (CompareConnectionCandidates(premier, conn) >= 0)) { | 1174 (CompareConnectionsBase(premier, conn) >= 0)) { |
Taylor Brandstetter
2016/06/21 18:33:25
Why can't you just use CompareConnections here? Is
pthatcher1
2016/06/22 06:36:33
I think this is so we don't prune a better candida
honghaiz3
2016/06/22 08:03:16
Done. I just use the CompareConnectionCandidates t
honghaiz3
2016/06/22 08:03:16
CompareConnections (now CompareConnectionsIncludin
Taylor Brandstetter
2016/06/22 16:12:22
Ah yes, that's obvious now, my mistake.
| |
1160 conn->Prune(); | 1175 conn->Prune(); |
1161 } | 1176 } |
1162 } | 1177 } |
1163 } | 1178 } |
1164 } | 1179 } |
1165 | 1180 |
1166 // Track the best connection, and let listeners know | 1181 // Track the selected connection, and let listeners know. |
Taylor Brandstetter
2016/06/21 18:33:25
Maybe "Change the" instead of "Track the".
honghaiz3
2016/06/22 08:03:16
Done.
| |
1167 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1182 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { |
1168 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1183 // Note: if conn is NULL, the previous |selected_connection_| has been |
1169 // so don't use it. | 1184 // destroyed, so don't use it. |
1170 Connection* old_best_connection = best_connection_; | 1185 Connection* old_selected_connection = selected_connection_; |
1171 best_connection_ = conn; | 1186 selected_connection_ = conn; |
1172 if (best_connection_) { | 1187 if (selected_connection_) { |
1173 if (old_best_connection) { | 1188 if (old_selected_connection) { |
1174 LOG_J(LS_INFO, this) << "Previous best connection: " | 1189 LOG_J(LS_INFO, this) << "Previous selected connection: " |
1175 << old_best_connection->ToString(); | 1190 << old_selected_connection->ToString(); |
1176 } | 1191 } |
1177 LOG_J(LS_INFO, this) << "New best connection: " | 1192 LOG_J(LS_INFO, this) << "New selected connection: " |
1178 << best_connection_->ToString(); | 1193 << selected_connection_->ToString(); |
1179 SignalRouteChange(this, best_connection_->remote_candidate()); | 1194 SignalRouteChange(this, selected_connection_->remote_candidate()); |
1180 // This is a temporary, but safe fix to webrtc issue 5705. | 1195 // This is a temporary, but safe fix to webrtc issue 5705. |
1181 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport | 1196 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport |
1182 // channel so that it knows whether the media channel is allowed to | 1197 // 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 | 1198 // send; then it will only signal ready-to-send if the media channel |
1184 // has been disallowed to send. | 1199 // has been disallowed to send. |
1185 if (best_connection_->writable()) { | 1200 if (selected_connection_->writable()) { |
1186 SignalReadyToSend(this); | 1201 SignalReadyToSend(this); |
1187 } | 1202 } |
1188 } else { | 1203 } else { |
1189 LOG_J(LS_INFO, this) << "No best connection"; | 1204 LOG_J(LS_INFO, this) << "No selected connection"; |
1190 } | 1205 } |
1191 // TODO(honghaiz): rename best_connection_ with selected_connection_ or | 1206 // TODO(honghaiz): rename selected_connection_ with selected_connection_ or |
1192 // selected_candidate pair_. | 1207 // selected_candidate pair_. |
1193 SignalSelectedCandidatePairChanged(this, best_connection_, | 1208 SignalSelectedCandidatePairChanged(this, selected_connection_, |
1194 last_sent_packet_id_); | 1209 last_sent_packet_id_); |
1195 } | 1210 } |
1196 | 1211 |
1197 // Warning: UpdateState should eventually be called whenever a connection | 1212 // Warning: UpdateState should eventually be called whenever a connection |
1198 // is added, deleted, or the write state of any connection changes so that the | 1213 // 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 | 1214 // 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 | 1215 // 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 | 1216 // change, it should be called after all the connection states have changed. For |
1202 // example, we call this at the end of SortConnections. | 1217 // example, we call this at the end of SortConnections. |
1203 void P2PTransportChannel::UpdateState() { | 1218 void P2PTransportChannel::UpdateState() { |
(...skipping 26 matching lines...) Expand all Loading... | |
1230 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); | 1245 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); |
1231 break; | 1246 break; |
1232 default: | 1247 default: |
1233 RTC_DCHECK(false); | 1248 RTC_DCHECK(false); |
1234 break; | 1249 break; |
1235 } | 1250 } |
1236 state_ = state; | 1251 state_ = state; |
1237 SignalStateChanged(this); | 1252 SignalStateChanged(this); |
1238 } | 1253 } |
1239 | 1254 |
1240 bool writable = best_connection_ && best_connection_->writable(); | 1255 bool writable = selected_connection_ && selected_connection_->writable(); |
1241 set_writable(writable); | 1256 set_writable(writable); |
1242 | 1257 |
1243 bool receiving = false; | 1258 bool receiving = false; |
1244 for (const Connection* connection : connections_) { | 1259 for (const Connection* connection : connections_) { |
1245 if (connection->receiving()) { | 1260 if (connection->receiving()) { |
1246 receiving = true; | 1261 receiving = true; |
1247 break; | 1262 break; |
1248 } | 1263 } |
1249 } | 1264 } |
1250 set_receiving(receiving); | 1265 set_receiving(receiving); |
(...skipping 19 matching lines...) Expand all Loading... | |
1270 } | 1285 } |
1271 | 1286 |
1272 // If all connections timed out, delete them all. | 1287 // If all connections timed out, delete them all. |
1273 void P2PTransportChannel::HandleAllTimedOut() { | 1288 void P2PTransportChannel::HandleAllTimedOut() { |
1274 for (Connection* connection : connections_) { | 1289 for (Connection* connection : connections_) { |
1275 connection->Destroy(); | 1290 connection->Destroy(); |
1276 } | 1291 } |
1277 } | 1292 } |
1278 | 1293 |
1279 bool P2PTransportChannel::weak() const { | 1294 bool P2PTransportChannel::weak() const { |
1280 return !best_connection_ || best_connection_->weak(); | 1295 return !selected_connection_ || selected_connection_->weak(); |
1281 } | 1296 } |
1282 | 1297 |
1283 // If we have a best connection, return it, otherwise return top one in the | 1298 // If we have a selected connection, return it, otherwise return top one in the |
1284 // list (later we will mark it best). | 1299 // list (later we will mark it best). |
1285 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | 1300 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
1286 rtc::Network* network) const { | 1301 rtc::Network* network) const { |
1287 // If the best connection is on this network, then it wins. | 1302 // If the selected connection is on this network, then it wins. |
1288 if (best_connection_ && (best_connection_->port()->Network() == network)) | 1303 if (selected_connection_ && |
1289 return best_connection_; | 1304 (selected_connection_->port()->Network() == network)) |
Taylor Brandstetter
2016/06/21 18:33:25
Nit: As long as you're changing this code, can you
honghaiz3
2016/06/22 08:03:16
Done.
| |
1305 return selected_connection_; | |
1290 | 1306 |
1291 // Otherwise, we return the top-most in sorted order. | 1307 // Otherwise, we return the top-most in sorted order. |
1292 for (size_t i = 0; i < connections_.size(); ++i) { | 1308 for (size_t i = 0; i < connections_.size(); ++i) { |
1293 if (connections_[i]->port()->Network() == network) | 1309 if (connections_[i]->port()->Network() == network) |
1294 return connections_[i]; | 1310 return connections_[i]; |
1295 } | 1311 } |
1296 | 1312 |
1297 return NULL; | 1313 return NULL; |
1298 } | 1314 } |
1299 | 1315 |
(...skipping 16 matching lines...) Expand all Loading... | |
1316 void P2PTransportChannel::OnSort() { | 1332 void P2PTransportChannel::OnSort() { |
1317 // Resort the connections based on the new statistics. | 1333 // Resort the connections based on the new statistics. |
1318 SortConnections(); | 1334 SortConnections(); |
1319 } | 1335 } |
1320 | 1336 |
1321 // Handle queued up check-and-ping request | 1337 // Handle queued up check-and-ping request |
1322 void P2PTransportChannel::OnCheckAndPing() { | 1338 void P2PTransportChannel::OnCheckAndPing() { |
1323 // Make sure the states of the connections are up-to-date (since this affects | 1339 // Make sure the states of the connections are up-to-date (since this affects |
1324 // which ones are pingable). | 1340 // which ones are pingable). |
1325 UpdateConnectionStates(); | 1341 UpdateConnectionStates(); |
1326 // When the best connection is not receiving or not writable, or any active | 1342 // 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. | 1343 // active connection has not been pinged enough times, use the weak ping |
1344 // interval. | |
1328 bool need_more_pings_at_weak_interval = std::any_of( | 1345 bool need_more_pings_at_weak_interval = std::any_of( |
1329 connections_.begin(), connections_.end(), [](Connection* conn) { | 1346 connections_.begin(), connections_.end(), [](Connection* conn) { |
1330 return conn->active() && | 1347 return conn->active() && |
1331 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; | 1348 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; |
1332 }); | 1349 }); |
1333 int ping_interval = (weak() || need_more_pings_at_weak_interval) | 1350 int ping_interval = (weak() || need_more_pings_at_weak_interval) |
1334 ? weak_ping_interval_ | 1351 ? weak_ping_interval_ |
1335 : STRONG_PING_INTERVAL; | 1352 : STRONG_PING_INTERVAL; |
1336 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { | 1353 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { |
1337 Connection* conn = FindNextPingableConnection(); | 1354 Connection* conn = FindNextPingableConnection(); |
1338 if (conn) { | 1355 if (conn) { |
1339 PingConnection(conn); | 1356 PingConnection(conn); |
1340 MarkConnectionPinged(conn); | 1357 MarkConnectionPinged(conn); |
1341 } | 1358 } |
1342 } | 1359 } |
1343 int delay = std::min(ping_interval, check_receiving_interval_); | 1360 int delay = std::min(ping_interval, check_receiving_interval_); |
1344 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); | 1361 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); |
1345 } | 1362 } |
1346 | 1363 |
1347 // A connection is considered a backup connection if the channel state | 1364 // 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. | 1365 // is completed, the connection is not the selected connection and it is active. |
1349 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1366 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { |
1350 return state_ == STATE_COMPLETED && conn != best_connection_ && | 1367 return state_ == STATE_COMPLETED && conn != selected_connection_ && |
1351 conn->active(); | 1368 conn->active(); |
1352 } | 1369 } |
1353 | 1370 |
1354 // Is the connection in a state for us to even consider pinging the other side? | 1371 // 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 | 1372 // 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. | 1373 // how a TCP connection is kicked into reconnecting on the active side. |
1357 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { | 1374 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { |
1358 const Candidate& remote = conn->remote_candidate(); | 1375 const Candidate& remote = conn->remote_candidate(); |
1359 // We should never get this far with an empty remote ufrag. | 1376 // We should never get this far with an empty remote ufrag. |
1360 ASSERT(!remote.username().empty()); | 1377 ASSERT(!remote.username().empty()); |
(...skipping 19 matching lines...) Expand all Loading... | |
1380 if (IsBackupConnection(conn)) { | 1397 if (IsBackupConnection(conn)) { |
1381 return (now >= conn->last_ping_response_received() + | 1398 return (now >= conn->last_ping_response_received() + |
1382 config_.backup_connection_ping_interval); | 1399 config_.backup_connection_ping_interval); |
1383 } | 1400 } |
1384 return conn->active(); | 1401 return conn->active(); |
1385 } | 1402 } |
1386 | 1403 |
1387 // Returns the next pingable connection to ping. This will be the oldest | 1404 // Returns the next pingable connection to ping. This will be the oldest |
1388 // pingable connection unless we have a connected, writable connection that is | 1405 // pingable connection unless we have a connected, writable connection that is |
1389 // past the maximum acceptable ping interval. When reconnecting a TCP | 1406 // past the maximum acceptable ping interval. When reconnecting a TCP |
1390 // connection, the best connection is disconnected, although still WRITABLE | 1407 // connection, the selected connection is disconnected, although still WRITABLE |
1391 // while reconnecting. The newly created connection should be selected as the | 1408 // while reconnecting. The newly created connection should be selected as the |
1392 // ping target to become writable instead. See the big comment in | 1409 // ping target to become writable instead. See the big comment in |
1393 // CompareConnections. | 1410 // CompareConnections. |
1394 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1411 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1395 int64_t now = rtc::TimeMillis(); | 1412 int64_t now = rtc::TimeMillis(); |
1396 Connection* conn_to_ping = nullptr; | 1413 Connection* conn_to_ping = nullptr; |
1397 if (best_connection_ && best_connection_->connected() && | 1414 if (selected_connection_ && selected_connection_->connected() && |
1398 best_connection_->writable() && | 1415 selected_connection_->writable() && |
1399 (best_connection_->last_ping_sent() + config_.max_strong_interval <= | 1416 (selected_connection_->last_ping_sent() + config_.max_strong_interval <= |
1400 now)) { | 1417 now)) { |
1401 conn_to_ping = best_connection_; | 1418 conn_to_ping = selected_connection_; |
1402 } else { | 1419 } else { |
1403 conn_to_ping = FindConnectionToPing(now); | 1420 conn_to_ping = FindConnectionToPing(now); |
1404 } | 1421 } |
1405 return conn_to_ping; | 1422 return conn_to_ping; |
1406 } | 1423 } |
1407 | 1424 |
1408 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { | 1425 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
1409 if (conn && pinged_connections_.insert(conn).second) { | 1426 if (conn && pinged_connections_.insert(conn).second) { |
1410 unpinged_connections_.erase(conn); | 1427 unpinged_connections_.erase(conn); |
1411 } | 1428 } |
1412 } | 1429 } |
1413 | 1430 |
1414 // Apart from sending ping from |conn| this method also updates | 1431 // Apart from sending ping from |conn| this method also updates |
1415 // |use_candidate_attr| flag. The criteria to update this flag is | 1432 // |use_candidate_attr| flag. The criteria to update this flag is |
1416 // explained below. | 1433 // explained below. |
1417 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND | 1434 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
1418 // a) Channel is in FULL ICE AND | 1435 // a) Channel is in FULL ICE AND |
1419 // a.1) |conn| is the best connection OR | 1436 // a.1) |conn| is the selected connection OR |
1420 // a.2) there is no best connection OR | 1437 // a.2) there is no selected connection OR |
1421 // a.3) the best connection is unwritable OR | 1438 // a.3) the selected connection is unwritable OR |
1422 // a.4) |conn| has higher priority than best_connection. | 1439 // a.4) |conn| has higher priority than selected_connection. |
1423 // b) we're doing LITE ICE AND | 1440 // b) we're doing LITE ICE AND |
1424 // b.1) |conn| is the best_connection AND | 1441 // b.1) |conn| is the selected_connection AND |
1425 // b.2) |conn| is writable. | 1442 // b.2) |conn| is writable. |
1426 void P2PTransportChannel::PingConnection(Connection* conn) { | 1443 void P2PTransportChannel::PingConnection(Connection* conn) { |
1427 bool use_candidate = false; | 1444 bool use_candidate = false; |
1428 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1445 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
1429 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || | 1446 use_candidate = |
1430 (!best_connection_->writable()) || | 1447 (conn == selected_connection_) || (selected_connection_ == NULL) || |
1431 (CompareConnectionCandidates(best_connection_, conn) < 0); | 1448 (!selected_connection_->writable()) || |
1432 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1449 (CompareConnectionCandidates(selected_connection_, conn) < 0); |
1433 use_candidate = best_connection_->writable(); | 1450 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) { |
1451 use_candidate = selected_connection_->writable(); | |
1434 } | 1452 } |
1435 conn->set_use_candidate_attr(use_candidate); | 1453 conn->set_use_candidate_attr(use_candidate); |
1436 last_ping_sent_ms_ = rtc::TimeMillis(); | 1454 last_ping_sent_ms_ = rtc::TimeMillis(); |
1437 conn->Ping(last_ping_sent_ms_); | 1455 conn->Ping(last_ping_sent_ms_); |
1438 } | 1456 } |
1439 | 1457 |
1440 // When a connection's state changes, we need to figure out who to use as | 1458 // 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. | 1459 // the selected connection again. It could have become usable, or become |
1460 // unusable. | |
1442 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1461 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
1443 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1462 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1444 | 1463 |
1445 // Update the best connection if the state change is from pending best | |
1446 // connection and role is controlled. | |
1447 if (ice_role_ == ICEROLE_CONTROLLED) { | |
1448 if (connection == pending_best_connection_ && connection->writable()) { | |
1449 pending_best_connection_ = NULL; | |
1450 LOG(LS_INFO) << "Switching best connection on controlled side" | |
1451 << " because it's now writable: " << connection->ToString(); | |
1452 SwitchBestConnectionTo(connection); | |
1453 } | |
1454 } | |
1455 | |
1456 // May stop the allocator session when at least one connection becomes | 1464 // May stop the allocator session when at least one connection becomes |
1457 // strongly connected after starting to get ports and the local candidate of | 1465 // 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 | 1466 // 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 | 1467 // that the connection becomes weakly connected because the connection may be |
1460 // changing from (writable, receiving) to (writable, not receiving). | 1468 // changing from (writable, receiving) to (writable, not receiving). |
1461 bool strongly_connected = !connection->weak(); | 1469 bool strongly_connected = !connection->weak(); |
1462 bool latest_generation = connection->local_candidate().generation() >= | 1470 bool latest_generation = connection->local_candidate().generation() >= |
1463 allocator_session()->generation(); | 1471 allocator_session()->generation(); |
1464 if (strongly_connected && latest_generation) { | 1472 if (strongly_connected && latest_generation) { |
1465 MaybeStopPortAllocatorSessions(); | 1473 MaybeStopPortAllocatorSessions(); |
1466 } | 1474 } |
1467 | 1475 |
1468 // We have to unroll the stack before doing this because we may be changing | 1476 // We have to unroll the stack before doing this because we may be changing |
1469 // the state of connections while sorting. | 1477 // the state of connections while sorting. |
1470 RequestSort(); | 1478 RequestSort(); |
1471 } | 1479 } |
1472 | 1480 |
1473 // When a connection is removed, edit it out, and then update our best | 1481 // When a connection is removed, edit it out, and then update our best |
1474 // connection. | 1482 // connection. |
1475 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1483 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
1476 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1484 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1477 | 1485 |
1478 // Note: the previous best_connection_ may be destroyed by now, so don't | 1486 // Note: the previous selected_connection_ may be destroyed by now, so don't |
1479 // use it. | 1487 // use it. |
1480 | 1488 |
1481 // Remove this connection from the list. | 1489 // Remove this connection from the list. |
1482 std::vector<Connection*>::iterator iter = | 1490 std::vector<Connection*>::iterator iter = |
1483 std::find(connections_.begin(), connections_.end(), connection); | 1491 std::find(connections_.begin(), connections_.end(), connection); |
1484 ASSERT(iter != connections_.end()); | 1492 ASSERT(iter != connections_.end()); |
1485 pinged_connections_.erase(*iter); | 1493 pinged_connections_.erase(*iter); |
1486 unpinged_connections_.erase(*iter); | 1494 unpinged_connections_.erase(*iter); |
1487 connections_.erase(iter); | 1495 connections_.erase(iter); |
1488 | 1496 |
1489 LOG_J(LS_INFO, this) << "Removed connection (" | 1497 LOG_J(LS_INFO, this) << "Removed connection (" |
1490 << static_cast<int>(connections_.size()) << " remaining)"; | 1498 << static_cast<int>(connections_.size()) << " remaining)"; |
1491 | 1499 |
1492 if (pending_best_connection_ == connection) { | 1500 // If this is currently the selected connection, then we need to pick a new |
1493 pending_best_connection_ = NULL; | 1501 // one. The call to SortConnections will pick a new one. It looks at the |
1494 } | 1502 // current selected connection in order to avoid switching between fairly |
1495 | 1503 // 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. | 1504 // 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 | 1505 // selected connection. |
1498 // best connection in order to avoid switching between fairly similar ones. | 1506 if (selected_connection_ == connection) { |
1499 // Since this connection is no longer an option, we can just set best to NULL | 1507 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; |
1500 // and re-choose a best assuming that there was no best connection. | 1508 SwitchSelectedConnection(nullptr); |
1501 if (best_connection_ == connection) { | |
1502 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; | |
1503 SwitchBestConnectionTo(NULL); | |
1504 RequestSort(); | 1509 RequestSort(); |
1505 } | 1510 } |
1506 | 1511 |
1507 UpdateState(); | 1512 UpdateState(); |
1508 } | 1513 } |
1509 | 1514 |
1510 // When a port is destroyed remove it from our list of ports to use for | 1515 // When a port is destroyed remove it from our list of ports to use for |
1511 // connection attempts. | 1516 // connection attempts. |
1512 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1517 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
1513 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1518 ASSERT(worker_thread_ == rtc::Thread::Current()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1552 | 1557 |
1553 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1558 // Do not deliver, if packet doesn't belong to the correct transport channel. |
1554 if (!FindConnection(connection)) | 1559 if (!FindConnection(connection)) |
1555 return; | 1560 return; |
1556 | 1561 |
1557 // Let the client know of an incoming packet | 1562 // Let the client know of an incoming packet |
1558 SignalReadPacket(this, data, len, packet_time, 0); | 1563 SignalReadPacket(this, data, len, packet_time, 0); |
1559 | 1564 |
1560 // May need to switch the sending connection based on the receiving media path | 1565 // May need to switch the sending connection based on the receiving media path |
1561 // if this is the controlled side. | 1566 // if this is the controlled side. |
1562 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && | 1567 if (ice_role_ != ICEROLE_CONTROLLED || selected_connection_ == connection) { |
1563 connection->writable() && best_connection_ != connection) { | 1568 return; |
1564 SwitchBestConnectionTo(connection); | 1569 } |
1570 | |
1571 if (ShouldSwitchConnection(connection)) { | |
pthatcher1
2016/06/21 07:16:53
Can you move this line into ShouldSwitchConnection
honghaiz3
2016/06/22 08:03:16
Done.
| |
1572 LOG(LS_INFO) | |
1573 << "Switching selected connection on controlled side due to receiving: " | |
1574 << connection->ToString(); | |
1575 SwitchSelectedConnection(connection); | |
1565 } | 1576 } |
1566 } | 1577 } |
1567 | 1578 |
1568 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { | 1579 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { |
1569 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1580 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1570 | 1581 |
1571 SignalSentPacket(this, sent_packet); | 1582 SignalSentPacket(this, sent_packet); |
1572 } | 1583 } |
1573 | 1584 |
1574 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1585 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1575 if (connection == best_connection_ && writable()) { | 1586 if (connection == selected_connection_ && writable()) { |
1576 SignalReadyToSend(this); | 1587 SignalReadyToSend(this); |
1577 } | 1588 } |
1578 } | 1589 } |
1579 | 1590 |
1580 // Find "triggered checks". We ping first those connections that have | 1591 // Find "triggered checks". We ping first those connections that have |
1581 // received a ping but have not sent a ping since receiving it | 1592 // received a ping but have not sent a ping since receiving it |
1582 // (last_received_ping > last_sent_ping). But we shouldn't do | 1593 // (last_received_ping > last_sent_ping). But we shouldn't do |
1583 // triggered checks if the connection is already writable. | 1594 // triggered checks if the connection is already writable. |
1584 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( | 1595 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( |
1585 int64_t now) { | 1596 int64_t now) { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1688 | 1699 |
1689 // During the initial state when nothing has been pinged yet, return the first | 1700 // During the initial state when nothing has been pinged yet, return the first |
1690 // one in the ordered |connections_|. | 1701 // one in the ordered |connections_|. |
1691 return *(std::find_if(connections_.begin(), connections_.end(), | 1702 return *(std::find_if(connections_.begin(), connections_.end(), |
1692 [conn1, conn2](Connection* conn) { | 1703 [conn1, conn2](Connection* conn) { |
1693 return conn == conn1 || conn == conn2; | 1704 return conn == conn1 || conn == conn2; |
1694 })); | 1705 })); |
1695 } | 1706 } |
1696 | 1707 |
1697 } // namespace cricket | 1708 } // namespace cricket |
OLD | NEW |