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 <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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |