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

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

Issue 1311433009: A few updates on connection states (Closed) Base URL: https://chromium.googlesource.com/external/webrtc@master
Patch Set: Merge with the head Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/p2p/base/p2ptransportchannel.h" 11 #include "webrtc/p2p/base/p2ptransportchannel.h"
12 12
13 #include <algorithm>
13 #include <set> 14 #include <set>
14 #include <algorithm>
15 #include "webrtc/p2p/base/common.h" 15 #include "webrtc/p2p/base/common.h"
16 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE. 16 #include "webrtc/p2p/base/relayport.h" // For RELAY_PORT_TYPE.
17 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE. 17 #include "webrtc/p2p/base/stunport.h" // For STUN_PORT_TYPE.
18 #include "webrtc/base/common.h" 18 #include "webrtc/base/common.h"
19 #include "webrtc/base/crc32.h" 19 #include "webrtc/base/crc32.h"
20 #include "webrtc/base/logging.h" 20 #include "webrtc/base/logging.h"
21 #include "webrtc/base/stringencode.h" 21 #include "webrtc/base/stringencode.h"
22 22
23 namespace { 23 namespace {
24 24
25 // messages for queuing up work for ourselves 25 // messages for queuing up work for ourselves
26 enum { 26 enum { MSG_SORT = 1, MSG_CHECK_AND_PING };
27 MSG_SORT = 1,
28 MSG_PING,
29 MSG_CHECK_RECEIVING
30 };
31 27
32 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) 28 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers)
33 // for pinging. When the socket is writable, we will use only 1 Kbps because 29 // for pinging. When the socket is writable, we will use only 1 Kbps because
34 // we don't want to degrade the quality on a modem. These numbers should work 30 // we don't want to degrade the quality on a modem. These numbers should work
35 // well on a 28.8K modem, which is the slowest connection on which the voice 31 // well on a 28.8K modem, which is the slowest connection on which the voice
36 // quality is reasonable at all. 32 // quality is reasonable at all.
37 static const uint32 PING_PACKET_SIZE = 60 * 8; 33 static const uint32 PING_PACKET_SIZE = 60 * 8;
38 static const uint32 WRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 1000; // 480ms 34 // STRONG_PING_DELAY (480ms) is applied when the best connection is both
39 static const uint32 UNWRITABLE_DELAY = 1000 * PING_PACKET_SIZE / 10000; // 50ms 35 // writable and receiving.
36 static const uint32 STRONG_PING_DELAY = 1000 * PING_PACKET_SIZE / 1000;
37 // WEAK_PING_DELAY (48ms) is applied when the best connection is either not
38 // writable or not receiving.
39 static const uint32 WEAK_PING_DELAY = 1000 * PING_PACKET_SIZE / 10000;
40 40
41 // If there is a current writable connection, then we will also try hard to 41 // If the current best connection is both writable and receiving, then we will
42 // make sure it is pinged at this rate. 42 // also try hard to make sure it is pinged at this rate (a little less than
43 static const uint32 MAX_CURRENT_WRITABLE_DELAY = 900; // 2*WRITABLE_DELAY - bit 43 // 2 * STRONG_PING_DELAY).
44 static const uint32 MAX_CURRENT_STRONG_DELAY = 900;
44 45
45 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms 46 static const int MIN_CHECK_RECEIVING_DELAY = 50; // ms
46 47
47 // The minimum improvement in RTT that justifies a switch. 48 // The minimum improvement in RTT that justifies a switch.
48 static const double kMinImprovement = 10; 49 static const double kMinImprovement = 10;
49 50
50 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port, 51 cricket::PortInterface::CandidateOrigin GetOrigin(cricket::PortInterface* port,
51 cricket::PortInterface* origin_port) { 52 cricket::PortInterface* origin_port) {
52 if (!origin_port) 53 if (!origin_port)
53 return cricket::PortInterface::ORIGIN_MESSAGE; 54 return cricket::PortInterface::ORIGIN_MESSAGE;
(...skipping 10 matching lines...) Expand all
64 if (a->priority() > b->priority()) 65 if (a->priority() > b->priority())
65 return 1; 66 return 1;
66 if (a->priority() < b->priority()) 67 if (a->priority() < b->priority())
67 return -1; 68 return -1;
68 69
69 // If we're still tied at this point, prefer a younger generation. 70 // If we're still tied at this point, prefer a younger generation.
70 return (a->remote_candidate().generation() + a->port()->generation()) - 71 return (a->remote_candidate().generation() + a->port()->generation()) -
71 (b->remote_candidate().generation() + b->port()->generation()); 72 (b->remote_candidate().generation() + b->port()->generation());
72 } 73 }
73 74
74 // Compare two connections based on their connected state, writability and 75 // Compare two connections based on their writing, receiving, and connected
75 // static preferences. 76 // states.
76 int CompareConnections(cricket::Connection *a, cricket::Connection *b) { 77 int CompareConnectionStates(cricket::Connection* a, cricket::Connection* b) {
77 // Sort based on write-state. Better states have lower values. 78 // Sort based on write-state. Better states have lower values.
78 if (a->write_state() < b->write_state()) 79 if (a->write_state() < b->write_state())
79 return 1; 80 return 1;
80 if (a->write_state() > b->write_state()) 81 if (a->write_state() > b->write_state())
81 return -1; 82 return -1;
82 83
84 // We prefer a receiving connection to a non-receiving, higher-priority
85 // connection when sorting connections and choosing which connection to
86 // switch to.
87 if (a->receiving() && !b->receiving())
88 return 1;
89 if (!a->receiving() && b->receiving())
90 return -1;
91
83 // WARNING: Some complexity here about TCP reconnecting. 92 // WARNING: Some complexity here about TCP reconnecting.
84 // When a TCP connection fails because of a TCP socket disconnecting, the 93 // When a TCP connection fails because of a TCP socket disconnecting, the
85 // active side of the connection will attempt to reconnect for 5 seconds while 94 // active side of the connection will attempt to reconnect for 5 seconds while
86 // pretending to be writable (the connection is not set to the unwritable 95 // pretending to be writable (the connection is not set to the unwritable
87 // state). On the passive side, the connection also remains writable even 96 // state). On the passive side, the connection also remains writable even
88 // though it is disconnected, and a new connection is created when the active 97 // though it is disconnected, and a new connection is created when the active
89 // side connects. At that point, there are two TCP connections on the passive 98 // side connects. At that point, there are two TCP connections on the passive
90 // side: 1. the old, disconnected one that is pretending to be writable, and 99 // side: 1. the old, disconnected one that is pretending to be writable, and
91 // 2. the new, connected one that is maybe not yet writable. For purposes of 100 // 2. the new, connected one that is maybe not yet writable. For purposes of
92 // pruning, pinging, and selecting the best connection, we want to treat the 101 // pruning, pinging, and selecting the best connection, we want to treat the
(...skipping 11 matching lines...) Expand all
104 // the new connection, when it becomes writable, should have higher priority. 113 // the new connection, when it becomes writable, should have higher priority.
105 if (a->write_state() == cricket::Connection::STATE_WRITABLE && 114 if (a->write_state() == cricket::Connection::STATE_WRITABLE &&
106 b->write_state() == cricket::Connection::STATE_WRITABLE) { 115 b->write_state() == cricket::Connection::STATE_WRITABLE) {
107 if (a->connected() && !b->connected()) { 116 if (a->connected() && !b->connected()) {
108 return 1; 117 return 1;
109 } 118 }
110 if (!a->connected() && b->connected()) { 119 if (!a->connected() && b->connected()) {
111 return -1; 120 return -1;
112 } 121 }
113 } 122 }
123 return 0;
124 }
114 125
126 int CompareConnections(cricket::Connection* a, cricket::Connection* b) {
127 int state_cmp = CompareConnectionStates(a, b);
128 if (state_cmp != 0) {
129 return state_cmp;
130 }
115 // Compare the candidate information. 131 // Compare the candidate information.
116 return CompareConnectionCandidates(a, b); 132 return CompareConnectionCandidates(a, b);
117 } 133 }
118 134
119 // Wraps the comparison connection into a less than operator that puts higher 135 // Wraps the comparison connection into a less than operator that puts higher
120 // priority writable connections first. 136 // priority writable connections first.
121 class ConnectionCompare { 137 class ConnectionCompare {
122 public: 138 public:
123 bool operator()(const cricket::Connection *ca, 139 bool operator()(const cricket::Connection *ca,
124 const cricket::Connection *cb) { 140 const cricket::Connection *cb) {
(...skipping 17 matching lines...) Expand all
142 // TODO: Yes we should definitely do this. The TCP protocol gains 158 // TODO: Yes we should definitely do this. The TCP protocol gains
143 // efficiency by being used bidirectionally, as opposed to two separate 159 // efficiency by being used bidirectionally, as opposed to two separate
144 // unidirectional streams. This test should probably occur before 160 // unidirectional streams. This test should probably occur before
145 // comparison of local prefs (assuming combined prefs are the same). We 161 // comparison of local prefs (assuming combined prefs are the same). We
146 // need to be careful though, not to bounce back and forth with both sides 162 // need to be careful though, not to bounce back and forth with both sides
147 // trying to rendevous with the other. 163 // trying to rendevous with the other.
148 } 164 }
149 }; 165 };
150 166
151 // Determines whether we should switch between two connections, based first on 167 // Determines whether we should switch between two connections, based first on
152 // static preferences and then (if those are equal) on latency estimates. 168 // connection states, static preferences, and then (if those are equal) on
153 bool ShouldSwitch(cricket::Connection* a_conn, cricket::Connection* b_conn) { 169 // latency estimates.
170 bool ShouldSwitch(cricket::Connection* a_conn,
171 cricket::Connection* b_conn,
172 cricket::IceRole ice_role) {
154 if (a_conn == b_conn) 173 if (a_conn == b_conn)
155 return false; 174 return false;
156 175
157 if (!a_conn || !b_conn) // don't think the latter should happen 176 if (!a_conn || !b_conn) // don't think the latter should happen
158 return true; 177 return true;
159 178
160 int prefs_cmp = CompareConnections(a_conn, b_conn); 179 // We prefer to switch to a writable and receiving connection over a
161 if (prefs_cmp < 0) 180 // non-writable or non-receiving connection, even if the latter has
162 return true; 181 // been nominated by the controlling side.
163 if (prefs_cmp > 0) 182 int state_cmp = CompareConnectionStates(a_conn, b_conn);
183 if (state_cmp != 0) {
184 return state_cmp < 0;
185 }
186 if (ice_role == cricket::ICEROLE_CONTROLLED && a_conn->nominated()) {
187 LOG(LS_VERBOSE) << "Controlled side did not switch due to nominated status";
164 return false; 188 return false;
189 }
190
191 int prefs_cmp = CompareConnectionCandidates(a_conn, b_conn);
192 if (prefs_cmp != 0) {
193 return prefs_cmp < 0;
194 }
165 195
166 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement; 196 return b_conn->rtt() <= a_conn->rtt() + kMinImprovement;
167 } 197 }
168 198
169 } // unnamed namespace 199 } // unnamed namespace
170 200
171 namespace cricket { 201 namespace cricket {
172 202
173 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, 203 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name,
174 int component, 204 int component,
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
343 // Go into the state of processing candidates, and running in general 373 // Go into the state of processing candidates, and running in general
344 void P2PTransportChannel::Connect() { 374 void P2PTransportChannel::Connect() {
345 ASSERT(worker_thread_ == rtc::Thread::Current()); 375 ASSERT(worker_thread_ == rtc::Thread::Current());
346 if (ice_ufrag_.empty() || ice_pwd_.empty()) { 376 if (ice_ufrag_.empty() || ice_pwd_.empty()) {
347 ASSERT(false); 377 ASSERT(false);
348 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " 378 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the "
349 << "ice_pwd_ are not set."; 379 << "ice_pwd_ are not set.";
350 return; 380 return;
351 } 381 }
352 382
353 // Start pinging as the ports come in. 383 // Start checking and pinging as the ports come in.
354 thread()->Post(this, MSG_PING); 384 thread()->Post(this, MSG_CHECK_AND_PING);
355
356 thread()->PostDelayed(
357 check_receiving_delay_, this, MSG_CHECK_RECEIVING);
358 } 385 }
359 386
360 void P2PTransportChannel::MaybeStartGathering() { 387 void P2PTransportChannel::MaybeStartGathering() {
361 // Start gathering if we never started before, or if an ICE restart occurred. 388 // Start gathering if we never started before, or if an ICE restart occurred.
362 if (allocator_sessions_.empty() || 389 if (allocator_sessions_.empty() ||
363 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(), 390 IceCredentialsChanged(allocator_sessions_.back()->ice_ufrag(),
364 allocator_sessions_.back()->ice_pwd(), ice_ufrag_, 391 allocator_sessions_.back()->ice_pwd(), ice_ufrag_,
365 ice_pwd_)) { 392 ice_pwd_)) {
366 if (gathering_state_ != kIceGatheringGathering) { 393 if (gathering_state_ != kIceGatheringGathering) {
367 gathering_state_ = kIceGatheringGathering; 394 gathering_state_ = kIceGatheringGathering;
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after
906 933
907 // Any changes after this point will require a re-sort. 934 // Any changes after this point will require a re-sort.
908 sort_dirty_ = false; 935 sort_dirty_ = false;
909 936
910 // Find the best alternative connection by sorting. It is important to note 937 // Find the best alternative connection by sorting. It is important to note
911 // that amongst equal preference, writable connections, this will choose the 938 // that amongst equal preference, writable connections, this will choose the
912 // one whose estimated latency is lowest. So it is the only one that we 939 // one whose estimated latency is lowest. So it is the only one that we
913 // need to consider switching to. 940 // need to consider switching to.
914 ConnectionCompare cmp; 941 ConnectionCompare cmp;
915 std::stable_sort(connections_.begin(), connections_.end(), cmp); 942 std::stable_sort(connections_.begin(), connections_.end(), cmp);
916 LOG(LS_VERBOSE) << "Sorting available connections:"; 943 LOG(LS_VERBOSE) << "Sorting " << connections_.size()
944 << " available connections:";
917 for (uint32 i = 0; i < connections_.size(); ++i) { 945 for (uint32 i = 0; i < connections_.size(); ++i) {
918 LOG(LS_VERBOSE) << connections_[i]->ToString(); 946 LOG(LS_VERBOSE) << connections_[i]->ToString();
919 } 947 }
920 948
921 Connection* top_connection = 949 Connection* top_connection =
922 (connections_.size() > 0) ? connections_[0] : nullptr; 950 (connections_.size() > 0) ? connections_[0] : nullptr;
923 951
924 // If necessary, switch to the new choice. 952 // If necessary, switch to the new choice.
925 // Note that |top_connection| doesn't have to be writable to become the best 953 // Note that |top_connection| doesn't have to be writable to become the best
926 // connection although it will have higher priority if it is writable. 954 // connection although it will have higher priority if it is writable.
927 // The controlled side can switch the best connection only if the current 955 if (ShouldSwitch(best_connection_, top_connection, ice_role_)) {
928 // |best connection_| has not been nominated by the controlling side yet.
929 if ((ice_role_ == ICEROLE_CONTROLLING || !best_nominated_connection()) &&
930 ShouldSwitch(best_connection_, top_connection)) {
931 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); 956 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString();
932 SwitchBestConnectionTo(top_connection); 957 SwitchBestConnectionTo(top_connection);
933 } 958 }
934 959
935 // Controlled side can prune only if the best connection has been nominated. 960 // Controlled side can prune only if the best connection has been nominated.
936 // because otherwise it may delete the connection that will be selected by 961 // because otherwise it may delete the connection that will be selected by
937 // the controlling side. 962 // the controlling side.
938 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { 963 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) {
939 PruneConnections(); 964 PruneConnections();
940 } 965 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 Connection* old_best_connection = best_connection_; 1031 Connection* old_best_connection = best_connection_;
1007 best_connection_ = conn; 1032 best_connection_ = conn;
1008 if (best_connection_) { 1033 if (best_connection_) {
1009 if (old_best_connection) { 1034 if (old_best_connection) {
1010 LOG_J(LS_INFO, this) << "Previous best connection: " 1035 LOG_J(LS_INFO, this) << "Previous best connection: "
1011 << old_best_connection->ToString(); 1036 << old_best_connection->ToString();
1012 } 1037 }
1013 LOG_J(LS_INFO, this) << "New best connection: " 1038 LOG_J(LS_INFO, this) << "New best connection: "
1014 << best_connection_->ToString(); 1039 << best_connection_->ToString();
1015 SignalRouteChange(this, best_connection_->remote_candidate()); 1040 SignalRouteChange(this, best_connection_->remote_candidate());
1016 set_receiving(best_connection_->receiving());
1017 } else { 1041 } else {
1018 LOG_J(LS_INFO, this) << "No best connection"; 1042 LOG_J(LS_INFO, this) << "No best connection";
1019 } 1043 }
1020 } 1044 }
1021 1045
1022 void P2PTransportChannel::UpdateChannelState() { 1046 void P2PTransportChannel::UpdateChannelState() {
1023 // The Handle* functions already set the writable state. We'll just double- 1047 // The Handle* functions already set the writable state. We'll just double-
1024 // check it here. 1048 // check it here.
1025 bool writable = ((best_connection_ != NULL) && 1049 bool writable = best_connection_ && best_connection_->writable();
1026 (best_connection_->write_state() ==
1027 Connection::STATE_WRITABLE));
1028 ASSERT(writable == this->writable()); 1050 ASSERT(writable == this->writable());
1029 if (writable != this->writable()) 1051 if (writable != this->writable())
1030 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; 1052 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch";
1031 1053
1032 // TODO(honghaiz): The channel receiving state is set in OnCheckReceiving. 1054 bool receiving = false;
1033 // Will revisit in a subsequent code change. 1055 for (const Connection* connection : connections_) {
1056 if (connection->receiving()) {
1057 receiving = true;
1058 break;
1059 }
1060 }
1061 set_receiving(receiving);
1034 } 1062 }
1035 1063
1036 // We checked the status of our connections and we had at least one that 1064 // We checked the status of our connections and we had at least one that
1037 // was writable, go into the writable state. 1065 // was writable, go into the writable state.
1038 void P2PTransportChannel::HandleWritable() { 1066 void P2PTransportChannel::HandleWritable() {
1039 ASSERT(worker_thread_ == rtc::Thread::Current()); 1067 ASSERT(worker_thread_ == rtc::Thread::Current());
1040 if (!writable()) { 1068 if (!writable()) {
1041 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { 1069 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) {
1042 if (allocator_sessions_[i]->IsGettingPorts()) { 1070 if (allocator_sessions_[i]->IsGettingPorts()) {
1043 allocator_sessions_[i]->StopGettingPorts(); 1071 allocator_sessions_[i]->StopGettingPorts();
(...skipping 12 matching lines...) Expand all
1056 was_writable_ = false; 1084 was_writable_ = false;
1057 set_writable(false); 1085 set_writable(false);
1058 } 1086 }
1059 } 1087 }
1060 1088
1061 void P2PTransportChannel::HandleAllTimedOut() { 1089 void P2PTransportChannel::HandleAllTimedOut() {
1062 // Currently we are treating this as channel not writable. 1090 // Currently we are treating this as channel not writable.
1063 HandleNotWritable(); 1091 HandleNotWritable();
1064 } 1092 }
1065 1093
1094 bool P2PTransportChannel::Weak() const {
1095 return !(best_connection_ && best_connection_->receiving() &&
1096 best_connection_->writable());
1097 }
1098
1066 // If we have a best connection, return it, otherwise return top one in the 1099 // If we have a best connection, return it, otherwise return top one in the
1067 // list (later we will mark it best). 1100 // list (later we will mark it best).
1068 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( 1101 Connection* P2PTransportChannel::GetBestConnectionOnNetwork(
1069 rtc::Network* network) const { 1102 rtc::Network* network) const {
1070 // If the best connection is on this network, then it wins. 1103 // If the best connection is on this network, then it wins.
1071 if (best_connection_ && (best_connection_->port()->Network() == network)) 1104 if (best_connection_ && (best_connection_->port()->Network() == network))
1072 return best_connection_; 1105 return best_connection_;
1073 1106
1074 // Otherwise, we return the top-most in sorted order. 1107 // Otherwise, we return the top-most in sorted order.
1075 for (uint32 i = 0; i < connections_.size(); ++i) { 1108 for (uint32 i = 0; i < connections_.size(); ++i) {
1076 if (connections_[i]->port()->Network() == network) 1109 if (connections_[i]->port()->Network() == network)
1077 return connections_[i]; 1110 return connections_[i];
1078 } 1111 }
1079 1112
1080 return NULL; 1113 return NULL;
1081 } 1114 }
1082 1115
1083 // Handle any queued up requests 1116 // Handle any queued up requests
1084 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { 1117 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) {
1085 switch (pmsg->message_id) { 1118 switch (pmsg->message_id) {
1086 case MSG_SORT: 1119 case MSG_SORT:
1087 OnSort(); 1120 OnSort();
1088 break; 1121 break;
1089 case MSG_PING: 1122 case MSG_CHECK_AND_PING:
1090 OnPing(); 1123 OnCheckAndPing();
1091 break;
1092 case MSG_CHECK_RECEIVING:
1093 OnCheckReceiving();
1094 break; 1124 break;
1095 default: 1125 default:
1096 ASSERT(false); 1126 ASSERT(false);
1097 break; 1127 break;
1098 } 1128 }
1099 } 1129 }
1100 1130
1101 // Handle queued up sort request 1131 // Handle queued up sort request
1102 void P2PTransportChannel::OnSort() { 1132 void P2PTransportChannel::OnSort() {
1103 // Resort the connections based on the new statistics. 1133 // Resort the connections based on the new statistics.
1104 SortConnections(); 1134 SortConnections();
1105 } 1135 }
1106 1136
1107 // Handle queued up ping request 1137 // Handle queued up check-and-ping request
1108 void P2PTransportChannel::OnPing() { 1138 void P2PTransportChannel::OnCheckAndPing() {
1109 // Make sure the states of the connections are up-to-date (since this affects 1139 // Make sure the states of the connections are up-to-date (since this affects
1110 // which ones are pingable). 1140 // which ones are pingable).
1111 UpdateConnectionStates(); 1141 UpdateConnectionStates();
1112 1142 // When the best connection is either not receiving or not writable,
1113 // Find the oldest pingable connection and have it do a ping. 1143 // switch to weak ping delay.
1114 Connection* conn = FindNextPingableConnection(); 1144 int ping_delay = Weak() ? WEAK_PING_DELAY : STRONG_PING_DELAY;
1115 if (conn) 1145 if (rtc::Time() >= last_ping_sent_ms_ + ping_delay) {
1116 PingConnection(conn); 1146 Connection* conn = FindNextPingableConnection();
1117 1147 if (conn) {
1118 // Post ourselves a message to perform the next ping. 1148 PingConnection(conn);
1119 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; 1149 }
1120 thread()->PostDelayed(delay, this, MSG_PING);
1121 }
1122
1123 void P2PTransportChannel::OnCheckReceiving() {
1124 if (best_connection_) {
1125 bool receiving = rtc::Time() <=
1126 best_connection_->last_received() + receiving_timeout_;
1127 set_receiving(receiving);
1128 } 1150 }
1129 1151 int check_delay = std::min(ping_delay, check_receiving_delay_);
1130 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); 1152 thread()->PostDelayed(check_delay, this, MSG_CHECK_AND_PING);
1131 } 1153 }
1132 1154
1133 // Is the connection in a state for us to even consider pinging the other side? 1155 // Is the connection in a state for us to even consider pinging the other side?
1134 // We consider a connection pingable even if it's not connected because that's 1156 // We consider a connection pingable even if it's not connected because that's
1135 // how a TCP connection is kicked into reconnecting on the active side. 1157 // how a TCP connection is kicked into reconnecting on the active side.
1136 bool P2PTransportChannel::IsPingable(Connection* conn) { 1158 bool P2PTransportChannel::IsPingable(Connection* conn) {
1137 const Candidate& remote = conn->remote_candidate(); 1159 const Candidate& remote = conn->remote_candidate();
1138 // We should never get this far with an empty remote ufrag. 1160 // We should never get this far with an empty remote ufrag.
1139 ASSERT(!remote.username().empty()); 1161 ASSERT(!remote.username().empty());
1140 if (remote.username().empty() || remote.password().empty()) { 1162 if (remote.username().empty() || remote.password().empty()) {
1141 // If we don't have an ICE ufrag and pwd, there's no way we can ping. 1163 // If we don't have an ICE ufrag and pwd, there's no way we can ping.
1142 return false; 1164 return false;
1143 } 1165 }
1144 1166
1145 // An never connected connection cannot be written to at all, so pinging is 1167 // An never connected connection cannot be written to at all, so pinging is
1146 // out of the question. However, if it has become WRITABLE, it is in the 1168 // out of the question. However, if it has become WRITABLE, it is in the
1147 // reconnecting state so ping is needed. 1169 // reconnecting state so ping is needed.
1148 if (!conn->connected() && !conn->writable()) { 1170 if (!conn->connected() && !conn->writable()) {
1149 return false; 1171 return false;
1150 } 1172 }
1151 1173
1152 // If the channel is not writable, ping all candidates. Otherwise, we only 1174 // If the channel is weak, ping all candidates. Otherwise, we only
1153 // want to ping connections that have not timed out on writing. 1175 // want to ping connections that have not timed out on writing.
1154 return !writable() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; 1176 return Weak() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT;
1155 } 1177 }
1156 1178
1157 // Returns the next pingable connection to ping. This will be the oldest 1179 // Returns the next pingable connection to ping. This will be the oldest
1158 // pingable connection unless we have a connected, writable connection that is 1180 // pingable connection unless we have a connected, writable connection that is
1159 // past the maximum acceptable ping delay. When reconnecting a TCP connection, 1181 // past the maximum acceptable ping delay. When reconnecting a TCP connection,
1160 // the best connection is disconnected, although still WRITABLE while 1182 // the best connection is disconnected, although still WRITABLE while
1161 // reconnecting. The newly created connection should be selected as the ping 1183 // reconnecting. The newly created connection should be selected as the ping
1162 // target to become writable instead. See the big comment in CompareConnections. 1184 // target to become writable instead. See the big comment in CompareConnections.
1163 Connection* P2PTransportChannel::FindNextPingableConnection() { 1185 Connection* P2PTransportChannel::FindNextPingableConnection() {
1164 uint32 now = rtc::Time(); 1186 uint32 now = rtc::Time();
1165 if (best_connection_ && best_connection_->connected() && 1187 if (best_connection_ && best_connection_->connected() &&
1166 (best_connection_->write_state() == Connection::STATE_WRITABLE) && 1188 best_connection_->writable() &&
1167 (best_connection_->last_ping_sent() + MAX_CURRENT_WRITABLE_DELAY <= 1189 (best_connection_->last_ping_sent() + MAX_CURRENT_STRONG_DELAY <= now)) {
1168 now)) {
1169 return best_connection_; 1190 return best_connection_;
1170 } 1191 }
1171 1192
1172 // First, find "triggered checks". We ping first those connections 1193 // First, find "triggered checks". We ping first those connections
1173 // that have received a ping but have not sent a ping since receiving 1194 // that have received a ping but have not sent a ping since receiving
1174 // it (last_received_ping > last_sent_ping). But we shouldn't do 1195 // it (last_received_ping > last_sent_ping). But we shouldn't do
1175 // triggered checks if the connection is already writable. 1196 // triggered checks if the connection is already writable.
1176 Connection* oldest_needing_triggered_check = nullptr; 1197 Connection* oldest_needing_triggered_check = nullptr;
1177 Connection* oldest = nullptr; 1198 Connection* oldest = nullptr;
1178 for (Connection* conn : connections_) { 1199 for (Connection* conn : connections_) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1216 void P2PTransportChannel::PingConnection(Connection* conn) { 1237 void P2PTransportChannel::PingConnection(Connection* conn) {
1217 bool use_candidate = false; 1238 bool use_candidate = false;
1218 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { 1239 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) {
1219 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || 1240 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) ||
1220 (!best_connection_->writable()) || 1241 (!best_connection_->writable()) ||
1221 (conn->priority() > best_connection_->priority()); 1242 (conn->priority() > best_connection_->priority());
1222 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { 1243 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) {
1223 use_candidate = best_connection_->writable(); 1244 use_candidate = best_connection_->writable();
1224 } 1245 }
1225 conn->set_use_candidate_attr(use_candidate); 1246 conn->set_use_candidate_attr(use_candidate);
1226 conn->Ping(rtc::Time()); 1247 last_ping_sent_ms_ = rtc::Time();
1248 conn->Ping(last_ping_sent_ms_);
1227 } 1249 }
1228 1250
1229 // When a connection's state changes, we need to figure out who to use as 1251 // When a connection's state changes, we need to figure out who to use as
1230 // the best connection again. It could have become usable, or become unusable. 1252 // the best connection again. It could have become usable, or become unusable.
1231 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { 1253 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) {
1232 ASSERT(worker_thread_ == rtc::Thread::Current()); 1254 ASSERT(worker_thread_ == rtc::Thread::Current());
1233 1255
1234 // Update the best connection if the state change is from pending best 1256 // Update the best connection if the state change is from pending best
1235 // connection and role is controlled. 1257 // connection and role is controlled.
1236 if (ice_role_ == ICEROLE_CONTROLLED) { 1258 if (ice_role_ == ICEROLE_CONTROLLED) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 } 1341 }
1320 } 1342 }
1321 1343
1322 void P2PTransportChannel::OnReadyToSend(Connection* connection) { 1344 void P2PTransportChannel::OnReadyToSend(Connection* connection) {
1323 if (connection == best_connection_ && writable()) { 1345 if (connection == best_connection_ && writable()) {
1324 SignalReadyToSend(this); 1346 SignalReadyToSend(this);
1325 } 1347 }
1326 } 1348 }
1327 1349
1328 } // namespace cricket 1350 } // namespace cricket
OLDNEW
« no previous file with comments | « webrtc/p2p/base/p2ptransportchannel.h ('k') | webrtc/p2p/base/p2ptransportchannel_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698