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_RECEIVING |
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 int MIN_CHECK_RECEIVING_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_receiving_delay_(MIN_CHECK_RECEIVING_DELAY * 5), |
| 201 receiving_timeout_(MIN_CHECK_RECEIVING_DELAY * 50) { |
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 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 // Therefore we need to keep track of the remote ice restart so | 352 // Therefore we need to keep track of the remote ice restart so |
348 // newer connections are prioritized over the older. | 353 // newer connections are prioritized over the older. |
349 ++remote_candidate_generation_; | 354 ++remote_candidate_generation_; |
350 } | 355 } |
351 } | 356 } |
352 | 357 |
353 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { | 358 void P2PTransportChannel::SetRemoteIceMode(IceMode mode) { |
354 remote_ice_mode_ = mode; | 359 remote_ice_mode_ = mode; |
355 } | 360 } |
356 | 361 |
| 362 void P2PTransportChannel::set_receiving_timeout(int receiving_timeout_ms) { |
| 363 receiving_timeout_ = receiving_timeout_ms; |
| 364 check_receiving_delay_ = |
| 365 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); |
| 366 } |
| 367 |
357 // Go into the state of processing candidates, and running in general | 368 // Go into the state of processing candidates, and running in general |
358 void P2PTransportChannel::Connect() { | 369 void P2PTransportChannel::Connect() { |
359 ASSERT(worker_thread_ == rtc::Thread::Current()); | 370 ASSERT(worker_thread_ == rtc::Thread::Current()); |
360 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 371 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
361 ASSERT(false); | 372 ASSERT(false); |
362 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 373 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
363 << "ice_pwd_ are not set."; | 374 << "ice_pwd_ are not set."; |
364 return; | 375 return; |
365 } | 376 } |
366 | 377 |
367 // Kick off an allocator session | 378 // Kick off an allocator session |
368 Allocate(); | 379 Allocate(); |
369 | 380 |
370 // Start pinging as the ports come in. | 381 // Start pinging as the ports come in. |
371 thread()->Post(this, MSG_PING); | 382 thread()->Post(this, MSG_PING); |
| 383 |
| 384 thread()->PostDelayed( |
| 385 check_receiving_delay_, this, MSG_CHECK_RECEIVING); |
372 } | 386 } |
373 | 387 |
374 // A new port is available, attempt to make connections for it | 388 // A new port is available, attempt to make connections for it |
375 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, | 389 void P2PTransportChannel::OnPortReady(PortAllocatorSession *session, |
376 PortInterface* port) { | 390 PortInterface* port) { |
377 ASSERT(worker_thread_ == rtc::Thread::Current()); | 391 ASSERT(worker_thread_ == rtc::Thread::Current()); |
378 | 392 |
379 // Set in-effect options on the new port | 393 // Set in-effect options on the new port |
380 for (OptionMap::const_iterator it = options_.begin(); | 394 for (OptionMap::const_iterator it = options_.begin(); |
381 it != options_.end(); | 395 it != options_.end(); |
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1060 Connection* old_best_connection = best_connection_; | 1074 Connection* old_best_connection = best_connection_; |
1061 best_connection_ = conn; | 1075 best_connection_ = conn; |
1062 if (best_connection_) { | 1076 if (best_connection_) { |
1063 if (old_best_connection) { | 1077 if (old_best_connection) { |
1064 LOG_J(LS_INFO, this) << "Previous best connection: " | 1078 LOG_J(LS_INFO, this) << "Previous best connection: " |
1065 << old_best_connection->ToString(); | 1079 << old_best_connection->ToString(); |
1066 } | 1080 } |
1067 LOG_J(LS_INFO, this) << "New best connection: " | 1081 LOG_J(LS_INFO, this) << "New best connection: " |
1068 << best_connection_->ToString(); | 1082 << best_connection_->ToString(); |
1069 SignalRouteChange(this, best_connection_->remote_candidate()); | 1083 SignalRouteChange(this, best_connection_->remote_candidate()); |
| 1084 // When it just switched to a best connection, set receiving to true. |
| 1085 set_receiving(true); |
1070 } else { | 1086 } else { |
1071 LOG_J(LS_INFO, this) << "No best connection"; | 1087 LOG_J(LS_INFO, this) << "No best connection"; |
1072 } | 1088 } |
1073 } | 1089 } |
1074 | 1090 |
1075 void P2PTransportChannel::UpdateChannelState() { | 1091 void P2PTransportChannel::UpdateChannelState() { |
1076 // The Handle* functions already set the writable state. We'll just double- | 1092 // The Handle* functions already set the writable state. We'll just double- |
1077 // check it here. | 1093 // check it here. |
1078 bool writable = ((best_connection_ != NULL) && | 1094 bool writable = ((best_connection_ != NULL) && |
1079 (best_connection_->write_state() == | 1095 (best_connection_->write_state() == |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 | 1157 |
1142 // Handle any queued up requests | 1158 // Handle any queued up requests |
1143 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1159 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
1144 switch (pmsg->message_id) { | 1160 switch (pmsg->message_id) { |
1145 case MSG_SORT: | 1161 case MSG_SORT: |
1146 OnSort(); | 1162 OnSort(); |
1147 break; | 1163 break; |
1148 case MSG_PING: | 1164 case MSG_PING: |
1149 OnPing(); | 1165 OnPing(); |
1150 break; | 1166 break; |
| 1167 case MSG_CHECK_RECEIVING: |
| 1168 OnCheckReceiving(); |
| 1169 break; |
1151 default: | 1170 default: |
1152 ASSERT(false); | 1171 ASSERT(false); |
1153 break; | 1172 break; |
1154 } | 1173 } |
1155 } | 1174 } |
1156 | 1175 |
1157 // Handle queued up sort request | 1176 // Handle queued up sort request |
1158 void P2PTransportChannel::OnSort() { | 1177 void P2PTransportChannel::OnSort() { |
1159 // Resort the connections based on the new statistics. | 1178 // Resort the connections based on the new statistics. |
1160 SortConnections(); | 1179 SortConnections(); |
1161 } | 1180 } |
1162 | 1181 |
1163 // Handle queued up ping request | 1182 // Handle queued up ping request |
1164 void P2PTransportChannel::OnPing() { | 1183 void P2PTransportChannel::OnPing() { |
1165 // Make sure the states of the connections are up-to-date (since this affects | 1184 // Make sure the states of the connections are up-to-date (since this affects |
1166 // which ones are pingable). | 1185 // which ones are pingable). |
1167 UpdateConnectionStates(); | 1186 UpdateConnectionStates(); |
1168 | 1187 |
1169 // Find the oldest pingable connection and have it do a ping. | 1188 // Find the oldest pingable connection and have it do a ping. |
1170 Connection* conn = FindNextPingableConnection(); | 1189 Connection* conn = FindNextPingableConnection(); |
1171 if (conn) | 1190 if (conn) |
1172 PingConnection(conn); | 1191 PingConnection(conn); |
1173 | 1192 |
1174 // Post ourselves a message to perform the next ping. | 1193 // Post ourselves a message to perform the next ping. |
1175 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; | 1194 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; |
1176 thread()->PostDelayed(delay, this, MSG_PING); | 1195 thread()->PostDelayed(delay, this, MSG_PING); |
1177 } | 1196 } |
1178 | 1197 |
| 1198 void P2PTransportChannel::OnCheckReceiving() { |
| 1199 // Check receiving only if the best connection has received data packets |
| 1200 // because we want to detect not receiving any packets only after the media |
| 1201 // have started flowing. |
| 1202 if (best_connection_ && best_connection_->recv_total_bytes() > 0) { |
| 1203 bool receiving = rtc::Time() <= |
| 1204 best_connection_->last_received() + receiving_timeout_; |
| 1205 set_receiving(receiving); |
| 1206 } |
| 1207 |
| 1208 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); |
| 1209 } |
| 1210 |
1179 // Is the connection in a state for us to even consider pinging the other side? | 1211 // 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 | 1212 // 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. | 1213 // how a TCP connection is kicked into reconnecting on the active side. |
1182 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1214 bool P2PTransportChannel::IsPingable(Connection* conn) { |
1183 const Candidate& remote = conn->remote_candidate(); | 1215 const Candidate& remote = conn->remote_candidate(); |
1184 // We should never get this far with an empty remote ufrag. | 1216 // We should never get this far with an empty remote ufrag. |
1185 ASSERT(!remote.username().empty()); | 1217 ASSERT(!remote.username().empty()); |
1186 if (remote.username().empty() || remote.password().empty()) { | 1218 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. | 1219 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1188 return false; | 1220 return false; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1371 SignalReadPacket(this, data, len, packet_time, 0); | 1403 SignalReadPacket(this, data, len, packet_time, 0); |
1372 } | 1404 } |
1373 | 1405 |
1374 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1406 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1375 if (connection == best_connection_ && writable()) { | 1407 if (connection == best_connection_ && writable()) { |
1376 SignalReadyToSend(this); | 1408 SignalReadyToSend(this); |
1377 } | 1409 } |
1378 } | 1410 } |
1379 | 1411 |
1380 } // namespace cricket | 1412 } // namespace cricket |
OLD | NEW |