OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/p2p/base/p2ptransportchannel.h" | 11 #include "webrtc/p2p/base/p2ptransportchannel.h" |
12 | 12 |
13 #include <set> | 13 #include <set> |
14 #include "webrtc/p2p/base/common.h" | 14 #include "webrtc/p2p/base/common.h" |
15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. | 15 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. |
16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. | 16 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. |
17 #include "webrtc/base/common.h" | 17 #include "webrtc/base/common.h" |
18 #include "webrtc/base/crc32.h" | 18 #include "webrtc/base/crc32.h" |
19 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" |
20 #include "webrtc/base/stringencode.h" | 20 #include "webrtc/base/stringencode.h" |
21 | 21 |
22 namespace { | 22 namespace { |
23 | 23 |
24 // messages for queuing up work for ourselves | 24 // messages for queuing up work for ourselves |
25 enum { | 25 enum { |
26 MSG_SORT = 1, | 26 MSG_SORT = 1, |
27 MSG_PING, | 27 MSG_PING, |
28 MSG_CHECK_FLAKINESS | |
pthatcher1
2015/06/26 19:24:02
MSG_CHECK_RECEIVING
honghaiz3
2015/08/05 23:56:56
Done.
| |
28 }; | 29 }; |
29 | 30 |
30 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 31 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) |
31 // for pinging. When the socket is writable, we will use only 1 Kbps because | 32 // for pinging. When the socket is writable, we will use only 1 Kbps because |
32 // we don't want to degrade the quality on a modem. These numbers should work | 33 // we don't want to degrade the quality on a modem. These numbers should work |
33 // well on a 28.8K modem, which is the slowest connection on which the voice | 34 // well on a 28.8K modem, which is the slowest connection on which the voice |
34 // quality is reasonable at all. | 35 // quality is reasonable at all. |
35 static const uint32 PING_PACKET_SIZE = 60 * 8; | 36 static const uint32 PING_PACKET_SIZE = 60 * 8; |
36 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms | 37 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms |
37 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms | 38 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms |
38 | 39 |
39 // If there is a current writable connection, then we will also try hard to | 40 // If there is a current writable connection, then we will also try hard to |
40 // make sure it is pinged at this rate. | 41 // make sure it is pinged at this rate. |
41 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit | 42 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit |
42 | 43 |
44 static const uint32 MIN_CHECK_FLAKINESS_DELAY = 50; // ms | |
45 | |
43 // The minimum improvement in RTT that justifies a switch. | 46 // The minimum improvement in RTT that justifies a switch. |
44 static const double kMinImprovement = 10; | 47 static const double kMinImprovement = 10; |
45 | 48 |
46 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, | 49 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, |
47 cricket::PortInterface* origin_port) { | 50 cricket::PortInterface* origin_port) { |
48 if (!origin_port) | 51 if (!origin_port) |
49 return cricket::PortInterface::ORIGIN_MESSAGE; | 52 return cricket::PortInterface::ORIGIN_MESSAGE; |
50 else if (port == origin_port) | 53 else if (port == origin_port) |
51 return cricket::PortInterface::ORIGIN_THIS_PORT; | 54 return cricket::PortInterface::ORIGIN_THIS_PORT; |
52 else | 55 else |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
186 waiting_for_signaling_(false), | 189 waiting_for_signaling_(false), |
187 error_(0), | 190 error_(0), |
188 best_connection_(NULL), | 191 best_connection_(NULL), |
189 pending_best_connection_(NULL), | 192 pending_best_connection_(NULL), |
190 sort_dirty_(false), | 193 sort_dirty_(false), |
191 was_writable_(false), | 194 was_writable_(false), |
192 protocol_type_(ICEPROTO_HYBRID), | 195 protocol_type_(ICEPROTO_HYBRID), |
193 remote_ice_mode_(ICEMODE_FULL), | 196 remote_ice_mode_(ICEMODE_FULL), |
194 ice_role_(ICEROLE_UNKNOWN), | 197 ice_role_(ICEROLE_UNKNOWN), |
195 tiebreaker_(0), | 198 tiebreaker_(0), |
196 remote_candidate_generation_(0) { | 199 remote_candidate_generation_(0), |
200 check_flakiness_delay_(MIN_CHECK_FLAKINESS_DELAY * 2), | |
201 check_flakiness_timeout_(MIN_CHECK_FLAKINESS_DELAY * 20) { | |
197 } | 202 } |
198 | 203 |
199 P2PTransportChannel::~P2PTransportChannel() { | 204 P2PTransportChannel::~P2PTransportChannel() { |
200 ASSERT(worker_thread_ == rtc::Thread::Current()); | 205 ASSERT(worker_thread_ == rtc::Thread::Current()); |
201 | 206 |
202 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) | 207 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) |
203 delete allocator_sessions_[i]; | 208 delete allocator_sessions_[i]; |
204 } | 209 } |
205 | 210 |
206 // Add the allocator session to our list so that we know which sessions | 211 // Add the allocator session to our list so that we know which sessions |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 367 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
363 << "ice_pwd_ are not set."; | 368 << "ice_pwd_ are not set."; |
364 return; | 369 return; |
365 } | 370 } |
366 | 371 |
367 // Kick off an allocator session | 372 // Kick off an allocator session |
368 Allocate(); | 373 Allocate(); |
369 | 374 |
370 // Start pinging as the ports come in. | 375 // Start pinging as the ports come in. |
371 thread()->Post(this, MSG_PING); | 376 thread()->Post(this, MSG_PING); |
377 | |
378 thread()->PostDelayed( | |
379 check_flakiness_delay_, this, MSG_CHECK_FLAKINESS); | |
372 } | 380 } |
373 | 381 |
374 // A new port is available, attempt to make connections for it | 382 // A new port is available, attempt to make connections for it |
375 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 383 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
376 PortInterface* port) { | 384 PortInterface* port) { |
377 ASSERT(worker_thread_ == rtc::Thread::Current()); | 385 ASSERT(worker_thread_ == rtc::Thread::Current()); |
378 | 386 |
379 // Set in-effect options on the new port | 387 // Set in-effect options on the new port |
380 for (OptionMap::const_iterator it = options_.begin(); | 388 for (OptionMap::const_iterator it = options_.begin(); |
381 it != options_.end(); | 389 it != options_.end(); |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1060 Connection* old_best_connection = best_connection_; | 1068 Connection* old_best_connection = best_connection_; |
1061 best_connection_ = conn; | 1069 best_connection_ = conn; |
1062 if (best_connection_) { | 1070 if (best_connection_) { |
1063 if (old_best_connection) { | 1071 if (old_best_connection) { |
1064 LOG_J(LS_INFO, this) << "Previous best connection: " | 1072 LOG_J(LS_INFO, this) << "Previous best connection: " |
1065 << old_best_connection->ToString(); | 1073 << old_best_connection->ToString(); |
1066 } | 1074 } |
1067 LOG_J(LS_INFO, this) << "New best connection: " | 1075 LOG_J(LS_INFO, this) << "New best connection: " |
1068 << best_connection_->ToString(); | 1076 << best_connection_->ToString(); |
1069 SignalRouteChange(this, best_connection_->remote_candidate()); | 1077 SignalRouteChange(this, best_connection_->remote_candidate()); |
1078 // When it just switched to a best connection, set the channel state to | |
1079 // unflaky. | |
1080 set_flaky(false); | |
1070 } else { | 1081 } else { |
1071 LOG_J(LS_INFO, this) << "No best connection"; | 1082 LOG_J(LS_INFO, this) << "No best connection"; |
1072 } | 1083 } |
1073 } | 1084 } |
1074 | 1085 |
1075 void P2PTransportChannel::UpdateChannelState() { | 1086 void P2PTransportChannel::UpdateChannelState() { |
1076 // The Handle* functions already set the writable state. We'll just double- | 1087 // The Handle* functions already set the writable state. We'll just double- |
1077 // check it here. | 1088 // check it here. |
1078 bool writable = ((best_connection_ != NULL) && | 1089 bool writable = ((best_connection_ != NULL) && |
1079 (best_connection_->write_state() == | 1090 (best_connection_->write_state() == |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1141 | 1152 |
1142 // Handle any queued up requests | 1153 // Handle any queued up requests |
1143 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1154 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1144 switch (pmsg->message_id) { | 1155 switch (pmsg->message_id) { |
1145 case MSG_SORT: | 1156 case MSG_SORT: |
1146 OnSort(); | 1157 OnSort(); |
1147 break; | 1158 break; |
1148 case MSG_PING: | 1159 case MSG_PING: |
1149 OnPing(); | 1160 OnPing(); |
1150 break; | 1161 break; |
1162 case MSG_CHECK_FLAKINESS: | |
1163 OnCheckFlakiness(); | |
pthatcher1
2015/06/26 19:24:02
OnCheckReceiving
honghaiz3
2015/08/05 23:56:56
Done.
| |
1164 break; | |
1151 default: | 1165 default: |
1152 ASSERT(false); | 1166 ASSERT(false); |
1153 break; | 1167 break; |
1154 } | 1168 } |
1155 } | 1169 } |
1156 | 1170 |
1157 // Handle queued up sort request | 1171 // Handle queued up sort request |
1158 void P2PTransportChannel::OnSort() { | 1172 void P2PTransportChannel::OnSort() { |
1159 // Resort the connections based on the new statistics. | 1173 // Resort the connections based on the new statistics. |
1160 SortConnections(); | 1174 SortConnections(); |
1161 } | 1175 } |
1162 | 1176 |
1163 // Handle queued up ping request | 1177 // Handle queued up ping request |
1164 void P2PTransportChannel::OnPing() { | 1178 void P2PTransportChannel::OnPing() { |
1165 // Make sure the states of the connections are up-to-date (since this affects | 1179 // Make sure the states of the connections are up-to-date (since this affects |
1166 // which ones are pingable). | 1180 // which ones are pingable). |
1167 UpdateConnectionStates(); | 1181 UpdateConnectionStates(); |
1168 | 1182 |
1169 // Find the oldest pingable connection and have it do a ping. | 1183 // Find the oldest pingable connection and have it do a ping. |
1170 Connection* conn = FindNextPingableConnection(); | 1184 Connection* conn = FindNextPingableConnection(); |
1171 if (conn) | 1185 if (conn) |
1172 PingConnection(conn); | 1186 PingConnection(conn); |
1173 | 1187 |
1174 // Post ourselves a message to perform the next ping. | 1188 // Post ourselves a message to perform the next ping. |
1175 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; | 1189 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; |
1176 thread()->PostDelayed(delay, this, MSG_PING); | 1190 thread()->PostDelayed(delay, this, MSG_PING); |
1177 } | 1191 } |
1178 | 1192 |
1193 void P2PTransportChannel::OnCheckFlakiness() { | |
1194 // Check flakiness only if the best connection has received packets. | |
1195 if (best_connection_ && best_connection_->recv_total_bytes() > 0) { | |
1196 bool flaky = !best_connection_->CheckReceiving(check_flakiness_timeout_); | |
1197 set_flaky(flaky); | |
1198 } | |
1199 | |
1200 thread()->PostDelayed(check_flakiness_delay_, this, MSG_CHECK_FLAKINESS); | |
1201 } | |
1202 | |
1179 // Is the connection in a state for us to even consider pinging the other side? | 1203 // Is the connection in a state for us to even consider pinging the other side? |
1180 // We consider a connection pingable even if it's not connected because that's | 1204 // We consider a connection pingable even if it's not connected because that's |
1181 // how a TCP connection is kicked into reconnecting on the active side. | 1205 // how a TCP connection is kicked into reconnecting on the active side. |
1182 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1206 bool P2PTransportChannel::IsPingable(Connection* conn) { |
1183 const Candidate& remote = conn->remote_candidate(); | 1207 const Candidate& remote = conn->remote_candidate(); |
1184 // We should never get this far with an empty remote ufrag. | 1208 // We should never get this far with an empty remote ufrag. |
1185 ASSERT(!remote.username().empty()); | 1209 ASSERT(!remote.username().empty()); |
1186 if (remote.username().empty() || remote.password().empty()) { | 1210 if (remote.username().empty() || remote.password().empty()) { |
1187 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1211 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1188 return false; | 1212 return false; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1371 SignalReadPacket(this, data, len, packet_time, 0); | 1395 SignalReadPacket(this, data, len, packet_time, 0); |
1372 } | 1396 } |
1373 | 1397 |
1374 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1398 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1375 if (connection == best_connection_ && writable()) { | 1399 if (connection == best_connection_ && writable()) { |
1376 SignalReadyToSend(this); | 1400 SignalReadyToSend(this); |
1377 } | 1401 } |
1378 } | 1402 } |
1379 | 1403 |
1380 } // namespace cricket | 1404 } // namespace cricket |
OLD | NEW |