| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 } // unnamed namespace | 54 } // unnamed namespace |
| 55 | 55 |
| 56 namespace cricket { | 56 namespace cricket { |
| 57 | 57 |
| 58 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) | 58 // When the socket is unwritable, we will use 10 Kbps (ignoring IP+UDP headers) |
| 59 // for pinging. When the socket is writable, we will use only 1 Kbps because | 59 // for pinging. When the socket is writable, we will use only 1 Kbps because |
| 60 // we don't want to degrade the quality on a modem. These numbers should work | 60 // we don't want to degrade the quality on a modem. These numbers should work |
| 61 // well on a 28.8K modem, which is the slowest connection on which the voice | 61 // well on a 28.8K modem, which is the slowest connection on which the voice |
| 62 // quality is reasonable at all. | 62 // quality is reasonable at all. |
| 63 static const int PING_PACKET_SIZE = 60 * 8; | 63 static const int PING_PACKET_SIZE = 60 * 8; |
| 64 // STRONG_PING_INTERVAL (480ms) is applied when the best connection is both | 64 // STRONG_PING_INTERVAL (480ms) is applied when the selected connection is both |
| 65 // writable and receiving. | 65 // writable and receiving. |
| 66 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; | 66 static const int STRONG_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 1000; |
| 67 // WEAK_PING_INTERVAL (48ms) is applied when the best connection is either not | 67 // WEAK_PING_INTERVAL (48ms) is applied when the selected connection is either |
| 68 // writable or not receiving. | 68 // not writable or not receiving. |
| 69 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; | 69 const int WEAK_PING_INTERVAL = 1000 * PING_PACKET_SIZE / 10000; |
| 70 | 70 |
| 71 // Writable connections are pinged at a faster rate while stabilizing. | 71 // Writable connections are pinged at a faster rate while stabilizing. |
| 72 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms | 72 const int STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL = 900; // ms |
| 73 | 73 |
| 74 // Writable connections are pinged at a slower rate once stabilized. | 74 // Writable connections are pinged at a slower rate once stabilized. |
| 75 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms | 75 const int STABLE_WRITABLE_CONNECTION_PING_INTERVAL = 2500; // ms |
| 76 | 76 |
| 77 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms | 77 static const int MIN_CHECK_RECEIVING_INTERVAL = 50; // ms |
| 78 | 78 |
| 79 static constexpr int a_is_better = 1; |
| 80 static constexpr int b_is_better = -1; |
| 81 |
| 79 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 82 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
| 80 int component, | 83 int component, |
| 81 P2PTransport* transport, | 84 P2PTransport* transport, |
| 82 PortAllocator* allocator) | 85 PortAllocator* allocator) |
| 83 : P2PTransportChannel(transport_name, component, allocator) {} | 86 : P2PTransportChannel(transport_name, component, allocator) {} |
| 84 | 87 |
| 85 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, | 88 P2PTransportChannel::P2PTransportChannel(const std::string& transport_name, |
| 86 int component, | 89 int component, |
| 87 PortAllocator* allocator) | 90 PortAllocator* allocator) |
| 88 : TransportChannelImpl(transport_name, component), | 91 : TransportChannelImpl(transport_name, component), |
| 89 allocator_(allocator), | 92 allocator_(allocator), |
| 90 worker_thread_(rtc::Thread::Current()), | 93 worker_thread_(rtc::Thread::Current()), |
| 91 incoming_only_(false), | 94 incoming_only_(false), |
| 92 error_(0), | 95 error_(0), |
| 93 best_connection_(NULL), | |
| 94 pending_best_connection_(NULL), | |
| 95 sort_dirty_(false), | 96 sort_dirty_(false), |
| 96 remote_ice_mode_(ICEMODE_FULL), | 97 remote_ice_mode_(ICEMODE_FULL), |
| 97 ice_role_(ICEROLE_UNKNOWN), | 98 ice_role_(ICEROLE_UNKNOWN), |
| 98 tiebreaker_(0), | 99 tiebreaker_(0), |
| 99 gathering_state_(kIceGatheringNew), | 100 gathering_state_(kIceGatheringNew), |
| 100 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), | 101 check_receiving_interval_(MIN_CHECK_RECEIVING_INTERVAL * 5), |
| 101 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, | 102 config_(MIN_CHECK_RECEIVING_INTERVAL * 50 /* receiving_timeout */, |
| 102 0 /* backup_connection_ping_interval */, | 103 0 /* backup_connection_ping_interval */, |
| 103 false /* gather_continually */, | 104 false /* gather_continually */, |
| 104 false /* prioritize_most_likely_candidate_pairs */, | 105 false /* prioritize_most_likely_candidate_pairs */, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 connection->SignalReadyToSend.connect( | 149 connection->SignalReadyToSend.connect( |
| 149 this, &P2PTransportChannel::OnReadyToSend); | 150 this, &P2PTransportChannel::OnReadyToSend); |
| 150 connection->SignalStateChange.connect( | 151 connection->SignalStateChange.connect( |
| 151 this, &P2PTransportChannel::OnConnectionStateChange); | 152 this, &P2PTransportChannel::OnConnectionStateChange); |
| 152 connection->SignalDestroyed.connect( | 153 connection->SignalDestroyed.connect( |
| 153 this, &P2PTransportChannel::OnConnectionDestroyed); | 154 this, &P2PTransportChannel::OnConnectionDestroyed); |
| 154 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); | 155 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
| 155 had_connection_ = true; | 156 had_connection_ = true; |
| 156 } | 157 } |
| 157 | 158 |
| 159 // Determines whether we should switch the selected connection to |
| 160 // |new_connection| based the writable/receiving state, the nomination state, |
| 161 // and the last data received time. This prevents the controlled side from |
| 162 // switching the selected connection too frequently when the controlling side |
| 163 // is doing aggressive nominations. The precedence of the connection switching |
| 164 // criteria is as follows: |
| 165 // i) write/receiving/connected states |
| 166 // ii) For controlled side, |
| 167 // a) nomination state, |
| 168 // b) last data received time. |
| 169 // iii) Lower cost / higher priority. |
| 170 // iv) rtt. |
| 171 // TODO(honghaiz): Stop the aggressive nomination on the controlling side and |
| 172 // implement the ice-renomination option. |
| 173 bool P2PTransportChannel::ShouldSwitchSelectedConnection( |
| 174 Connection* new_connection) const { |
| 175 if (!new_connection || selected_connection_ == new_connection) { |
| 176 return false; |
| 177 } |
| 178 |
| 179 if (selected_connection_ == nullptr) { |
| 180 return true; |
| 181 } |
| 182 |
| 183 int cmp = CompareConnections(selected_connection_, new_connection); |
| 184 if (cmp != 0) { |
| 185 return cmp < 0; |
| 186 } |
| 187 |
| 188 // If everything else is the same, switch only if rtt has improved by |
| 189 // a margin. |
| 190 return new_connection->rtt() <= selected_connection_->rtt() - kMinImprovement; |
| 191 } |
| 192 |
| 158 void P2PTransportChannel::SetIceRole(IceRole ice_role) { | 193 void P2PTransportChannel::SetIceRole(IceRole ice_role) { |
| 159 ASSERT(worker_thread_ == rtc::Thread::Current()); | 194 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 160 if (ice_role_ != ice_role) { | 195 if (ice_role_ != ice_role) { |
| 161 ice_role_ = ice_role; | 196 ice_role_ = ice_role; |
| 162 for (PortInterface* port : ports_) { | 197 for (PortInterface* port : ports_) { |
| 163 port->SetIceRole(ice_role); | 198 port->SetIceRole(ice_role); |
| 164 } | 199 } |
| 165 // Update role on removed ports as well, because they may still have | 200 // Update role on removed ports as well, because they may still have |
| 166 // connections alive that should be using the correct role. | 201 // connections alive that should be using the correct role. |
| 167 for (PortInterface* port : removed_ports_) { | 202 for (PortInterface* port : removed_ports_) { |
| (...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 return nullptr; | 605 return nullptr; |
| 571 } | 606 } |
| 572 *generation = params.rend() - it - 1; | 607 *generation = params.rend() - it - 1; |
| 573 return &(*it); | 608 return &(*it); |
| 574 } | 609 } |
| 575 | 610 |
| 576 void P2PTransportChannel::OnNominated(Connection* conn) { | 611 void P2PTransportChannel::OnNominated(Connection* conn) { |
| 577 ASSERT(worker_thread_ == rtc::Thread::Current()); | 612 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 578 ASSERT(ice_role_ == ICEROLE_CONTROLLED); | 613 ASSERT(ice_role_ == ICEROLE_CONTROLLED); |
| 579 | 614 |
| 580 if (conn->write_state() == Connection::STATE_WRITABLE) { | 615 if (selected_connection_ == conn) { |
| 581 if (best_connection_ != conn) { | 616 return; |
| 582 pending_best_connection_ = NULL; | |
| 583 LOG(LS_INFO) << "Switching best connection on controlled side: " | |
| 584 << conn->ToString(); | |
| 585 SwitchBestConnectionTo(conn); | |
| 586 // Now we have selected the best connection, time to prune other existing | |
| 587 // connections and update the read/write state of the channel. | |
| 588 RequestSort(); | |
| 589 } | |
| 590 } else { | |
| 591 LOG(LS_INFO) << "Not switching the best connection on controlled side yet," | |
| 592 << " because it's not writable: " << conn->ToString(); | |
| 593 pending_best_connection_ = conn; | |
| 594 } | 617 } |
| 618 |
| 619 if (!ShouldSwitchSelectedConnection(conn)) { |
| 620 LOG(LS_INFO) |
| 621 << "Not switching the selected connection on controlled side yet: " |
| 622 << conn->ToString(); |
| 623 return; |
| 624 } |
| 625 |
| 626 LOG(LS_INFO) |
| 627 << "Switching selected connection on controlled side due to nomination: " |
| 628 << conn->ToString(); |
| 629 SwitchSelectedConnection(conn); |
| 630 // Now that we have selected a connection, it is time to prune other |
| 631 // connections and update the read/write state of the channel. |
| 632 RequestSort(); |
| 595 } | 633 } |
| 596 | 634 |
| 597 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { | 635 void P2PTransportChannel::AddRemoteCandidate(const Candidate& candidate) { |
| 598 ASSERT(worker_thread_ == rtc::Thread::Current()); | 636 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 599 | 637 |
| 600 uint32_t generation = GetRemoteCandidateGeneration(candidate); | 638 uint32_t generation = GetRemoteCandidateGeneration(candidate); |
| 601 // If a remote candidate with a previous generation arrives, drop it. | 639 // If a remote candidate with a previous generation arrives, drop it. |
| 602 if (generation < remote_ice_generation()) { | 640 if (generation < remote_ice_generation()) { |
| 603 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " | 641 LOG(LS_WARNING) << "Dropping a remote candidate because its ufrag " |
| 604 << candidate.username() | 642 << candidate.username() |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 ASSERT(worker_thread_ == rtc::Thread::Current()); | 872 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 835 | 873 |
| 836 const auto& found = options_.find(opt); | 874 const auto& found = options_.find(opt); |
| 837 if (found == options_.end()) { | 875 if (found == options_.end()) { |
| 838 return false; | 876 return false; |
| 839 } | 877 } |
| 840 *value = found->second; | 878 *value = found->second; |
| 841 return true; | 879 return true; |
| 842 } | 880 } |
| 843 | 881 |
| 844 // Send data to the other side, using our best connection. | 882 // Send data to the other side, using our selected connection. |
| 845 int P2PTransportChannel::SendPacket(const char *data, size_t len, | 883 int P2PTransportChannel::SendPacket(const char *data, size_t len, |
| 846 const rtc::PacketOptions& options, | 884 const rtc::PacketOptions& options, |
| 847 int flags) { | 885 int flags) { |
| 848 ASSERT(worker_thread_ == rtc::Thread::Current()); | 886 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 849 if (flags != 0) { | 887 if (flags != 0) { |
| 850 error_ = EINVAL; | 888 error_ = EINVAL; |
| 851 return -1; | 889 return -1; |
| 852 } | 890 } |
| 853 if (best_connection_ == NULL) { | 891 if (selected_connection_ == NULL) { |
| 854 error_ = EWOULDBLOCK; | 892 error_ = EWOULDBLOCK; |
| 855 return -1; | 893 return -1; |
| 856 } | 894 } |
| 857 | 895 |
| 858 last_sent_packet_id_ = options.packet_id; | 896 last_sent_packet_id_ = options.packet_id; |
| 859 int sent = best_connection_->Send(data, len, options); | 897 int sent = selected_connection_->Send(data, len, options); |
| 860 if (sent <= 0) { | 898 if (sent <= 0) { |
| 861 ASSERT(sent < 0); | 899 ASSERT(sent < 0); |
| 862 error_ = best_connection_->GetError(); | 900 error_ = selected_connection_->GetError(); |
| 863 } | 901 } |
| 864 return sent; | 902 return sent; |
| 865 } | 903 } |
| 866 | 904 |
| 867 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 905 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
| 868 ASSERT(worker_thread_ == rtc::Thread::Current()); | 906 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 869 // Gather connection infos. | 907 // Gather connection infos. |
| 870 infos->clear(); | 908 infos->clear(); |
| 871 | 909 |
| 872 for (Connection* connection : connections_) { | 910 for (Connection* connection : connections_) { |
| 873 ConnectionInfo info = connection->stats(); | 911 ConnectionInfo info = connection->stats(); |
| 874 info.best_connection = (best_connection_ == connection); | 912 info.best_connection = (selected_connection_ == connection); |
| 875 info.receiving = connection->receiving(); | 913 info.receiving = connection->receiving(); |
| 876 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); | 914 info.writable = (connection->write_state() == Connection::STATE_WRITABLE); |
| 877 info.timeout = | 915 info.timeout = |
| 878 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 916 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
| 879 info.new_connection = !connection->reported(); | 917 info.new_connection = !connection->reported(); |
| 880 connection->set_reported(true); | 918 connection->set_reported(true); |
| 881 info.rtt = connection->rtt(); | 919 info.rtt = connection->rtt(); |
| 882 info.local_candidate = connection->local_candidate(); | 920 info.local_candidate = connection->local_candidate(); |
| 883 info.remote_candidate = connection->remote_candidate(); | 921 info.remote_candidate = connection->remote_candidate(); |
| 884 info.key = connection; | 922 info.key = connection; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 911 if (!sort_dirty_) { | 949 if (!sort_dirty_) { |
| 912 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); | 950 worker_thread_->Post(RTC_FROM_HERE, this, MSG_SORT); |
| 913 sort_dirty_ = true; | 951 sort_dirty_ = true; |
| 914 } | 952 } |
| 915 } | 953 } |
| 916 | 954 |
| 917 // Compare two connections based on their writing, receiving, and connected | 955 // Compare two connections based on their writing, receiving, and connected |
| 918 // states. | 956 // states. |
| 919 int P2PTransportChannel::CompareConnectionStates(const Connection* a, | 957 int P2PTransportChannel::CompareConnectionStates(const Connection* a, |
| 920 const Connection* b) const { | 958 const Connection* b) const { |
| 921 static constexpr int a_is_better = 1; | |
| 922 static constexpr int b_is_better = -1; | |
| 923 | |
| 924 // First, prefer a connection that's writable or presumed writable over | 959 // First, prefer a connection that's writable or presumed writable over |
| 925 // one that's not writable. | 960 // one that's not writable. |
| 926 bool a_writable = a->writable() || PresumedWritable(a); | 961 bool a_writable = a->writable() || PresumedWritable(a); |
| 927 bool b_writable = b->writable() || PresumedWritable(b); | 962 bool b_writable = b->writable() || PresumedWritable(b); |
| 928 if (a_writable && !b_writable) { | 963 if (a_writable && !b_writable) { |
| 929 return a_is_better; | 964 return a_is_better; |
| 930 } | 965 } |
| 931 if (!a_writable && b_writable) { | 966 if (!a_writable && b_writable) { |
| 932 return b_is_better; | 967 return b_is_better; |
| 933 } | 968 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 952 | 987 |
| 953 // WARNING: Some complexity here about TCP reconnecting. | 988 // WARNING: Some complexity here about TCP reconnecting. |
| 954 // When a TCP connection fails because of a TCP socket disconnecting, the | 989 // When a TCP connection fails because of a TCP socket disconnecting, the |
| 955 // active side of the connection will attempt to reconnect for 5 seconds while | 990 // active side of the connection will attempt to reconnect for 5 seconds while |
| 956 // pretending to be writable (the connection is not set to the unwritable | 991 // pretending to be writable (the connection is not set to the unwritable |
| 957 // state). On the passive side, the connection also remains writable even | 992 // state). On the passive side, the connection also remains writable even |
| 958 // though it is disconnected, and a new connection is created when the active | 993 // though it is disconnected, and a new connection is created when the active |
| 959 // side connects. At that point, there are two TCP connections on the passive | 994 // side connects. At that point, there are two TCP connections on the passive |
| 960 // side: 1. the old, disconnected one that is pretending to be writable, and | 995 // side: 1. the old, disconnected one that is pretending to be writable, and |
| 961 // 2. the new, connected one that is maybe not yet writable. For purposes of | 996 // 2. the new, connected one that is maybe not yet writable. For purposes of |
| 962 // pruning, pinging, and selecting the best connection, we want to treat the | 997 // pruning, pinging, and selecting the selected connection, we want to treat |
| 963 // new connection as "better" than the old one. We could add a method called | 998 // the new connection as "better" than the old one. We could add a method |
| 964 // something like Connection::ImReallyBadEvenThoughImWritable, but that is | 999 // called something like Connection::ImReallyBadEvenThoughImWritable, but that |
| 965 // equivalent to the existing Connection::connected(), which we already have. | 1000 // is equivalent to the existing Connection::connected(), which we already |
| 966 // So, in code throughout this file, we'll check whether the connection is | 1001 // have. So, in code throughout this file, we'll check whether the connection |
| 967 // connected() or not, and if it is not, treat it as "worse" than a connected | 1002 // is connected() or not, and if it is not, treat it as "worse" than a |
| 968 // one, even though it's writable. In the code below, we're doing so to make | 1003 // connected one, even though it's writable. In the code below, we're doing |
| 969 // sure we treat a new writable connection as better than an old disconnected | 1004 // so to make sure we treat a new writable connection as better than an old |
| 970 // connection. | 1005 // disconnected connection. |
| 971 | 1006 |
| 972 // In the case where we reconnect TCP connections, the original best | 1007 // In the case where we reconnect TCP connections, the original best |
| 973 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, | 1008 // connection is disconnected without changing to WRITE_TIMEOUT. In this case, |
| 974 // the new connection, when it becomes writable, should have higher priority. | 1009 // the new connection, when it becomes writable, should have higher priority. |
| 975 if (a->write_state() == Connection::STATE_WRITABLE && | 1010 if (a->write_state() == Connection::STATE_WRITABLE && |
| 976 b->write_state() == Connection::STATE_WRITABLE) { | 1011 b->write_state() == Connection::STATE_WRITABLE) { |
| 977 if (a->connected() && !b->connected()) { | 1012 if (a->connected() && !b->connected()) { |
| 978 return a_is_better; | 1013 return a_is_better; |
| 979 } | 1014 } |
| 980 if (!a->connected() && b->connected()) { | 1015 if (!a->connected() && b->connected()) { |
| 981 return b_is_better; | 1016 return b_is_better; |
| 982 } | 1017 } |
| 983 } | 1018 } |
| 984 return 0; | 1019 return 0; |
| 985 } | 1020 } |
| 986 | 1021 |
| 987 // Compares two connections based only on the candidate and network information. | 1022 // Compares two connections based only on the candidate and network information. |
| 988 // Returns positive if |a| is better than |b|. | 1023 // Returns positive if |a| is better than |b|. |
| 989 int P2PTransportChannel::CompareConnectionCandidates( | 1024 int P2PTransportChannel::CompareConnectionCandidates( |
| 990 const Connection* a, | 1025 const Connection* a, |
| 991 const Connection* b) const { | 1026 const Connection* b) const { |
| 992 // Prefer lower network cost. | 1027 // Prefer lower network cost. |
| 993 uint32_t a_cost = a->ComputeNetworkCost(); | 1028 uint32_t a_cost = a->ComputeNetworkCost(); |
| 994 uint32_t b_cost = b->ComputeNetworkCost(); | 1029 uint32_t b_cost = b->ComputeNetworkCost(); |
| 995 // Smaller cost is better. | 1030 // Smaller cost is better. |
| 996 if (a_cost < b_cost) { | 1031 if (a_cost < b_cost) { |
| 997 return 1; | 1032 return a_is_better; |
| 998 } | 1033 } |
| 999 if (a_cost > b_cost) { | 1034 if (a_cost > b_cost) { |
| 1000 return -1; | 1035 return b_is_better; |
| 1001 } | 1036 } |
| 1002 | 1037 |
| 1003 // Compare connection priority. Lower values get sorted last. | 1038 // Compare connection priority. Lower values get sorted last. |
| 1004 if (a->priority() > b->priority()) { | 1039 if (a->priority() > b->priority()) { |
| 1005 return 1; | 1040 return a_is_better; |
| 1006 } | 1041 } |
| 1007 if (a->priority() < b->priority()) { | 1042 if (a->priority() < b->priority()) { |
| 1008 return -1; | 1043 return b_is_better; |
| 1009 } | 1044 } |
| 1010 | 1045 |
| 1011 // If we're still tied at this point, prefer a younger generation. | 1046 // If we're still tied at this point, prefer a younger generation. |
| 1012 // (Younger generation means a larger generation number). | 1047 // (Younger generation means a larger generation number). |
| 1013 return (a->remote_candidate().generation() + a->port()->generation()) - | 1048 return (a->remote_candidate().generation() + a->port()->generation()) - |
| 1014 (b->remote_candidate().generation() + b->port()->generation()); | 1049 (b->remote_candidate().generation() + b->port()->generation()); |
| 1015 } | 1050 } |
| 1016 | 1051 |
| 1017 int P2PTransportChannel::CompareConnections(const Connection* a, | 1052 int P2PTransportChannel::CompareConnections(const Connection* a, |
| 1018 const Connection* b) const { | 1053 const Connection* b) const { |
| 1019 // Compare first on writability and static preferences. | 1054 RTC_CHECK(a != nullptr); |
| 1055 RTC_CHECK(b != nullptr); |
| 1056 |
| 1057 // We prefer to switch to a writable and receiving connection over a |
| 1058 // non-writable or non-receiving connection, even if the latter has |
| 1059 // been nominated by the controlling side. |
| 1020 int state_cmp = CompareConnectionStates(a, b); | 1060 int state_cmp = CompareConnectionStates(a, b); |
| 1021 if (state_cmp != 0) { | 1061 if (state_cmp != 0) { |
| 1022 return state_cmp; | 1062 return state_cmp; |
| 1023 } | 1063 } |
| 1024 // Then compare the candidate information. | 1064 |
| 1025 int candidates_cmp = CompareConnectionCandidates(a, b); | 1065 if (ice_role_ == ICEROLE_CONTROLLED) { |
| 1026 if (candidates_cmp != 0) { | 1066 // Compare the connections based on the nomination states and the last data |
| 1027 return candidates_cmp; | 1067 // received time if this is on the controlled side. |
| 1068 if (a->nominated() && !b->nominated()) { |
| 1069 return a_is_better; |
| 1070 } |
| 1071 if (!a->nominated() && b->nominated()) { |
| 1072 return b_is_better; |
| 1073 } |
| 1074 |
| 1075 if (a->last_data_received() > b->last_data_received()) { |
| 1076 return a_is_better; |
| 1077 } |
| 1078 if (a->last_data_received() < b->last_data_received()) { |
| 1079 return b_is_better; |
| 1080 } |
| 1028 } | 1081 } |
| 1029 // Otherwise, compare based on latency estimate. | |
| 1030 return b->rtt() - a->rtt(); | |
| 1031 | 1082 |
| 1032 // Should we bother checking for the last connection that last received | 1083 // Compare the network cost and priority. |
| 1033 // data? It would help rendezvous on the connection that is also receiving | 1084 return CompareConnectionCandidates(a, b); |
| 1034 // packets. | |
| 1035 // | |
| 1036 // TODO(deadbeef): Yes we should definitely do this. The TCP protocol gains | |
| 1037 // efficiency by being used bidirectionally, as opposed to two separate | |
| 1038 // unidirectional streams. This test should probably occur before | |
| 1039 // comparison of local prefs (assuming combined prefs are the same). We | |
| 1040 // need to be careful though, not to bounce back and forth with both sides | |
| 1041 // trying to rendevous with the other. | |
| 1042 } | 1085 } |
| 1043 | 1086 |
| 1044 bool P2PTransportChannel::PresumedWritable( | 1087 bool P2PTransportChannel::PresumedWritable(const Connection* conn) const { |
| 1045 const cricket::Connection* conn) const { | |
| 1046 return (conn->write_state() == Connection::STATE_WRITE_INIT && | 1088 return (conn->write_state() == Connection::STATE_WRITE_INIT && |
| 1047 config_.presume_writable_when_fully_relayed && | 1089 config_.presume_writable_when_fully_relayed && |
| 1048 conn->local_candidate().type() == RELAY_PORT_TYPE && | 1090 conn->local_candidate().type() == RELAY_PORT_TYPE && |
| 1049 (conn->remote_candidate().type() == RELAY_PORT_TYPE || | 1091 (conn->remote_candidate().type() == RELAY_PORT_TYPE || |
| 1050 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); | 1092 conn->remote_candidate().type() == PRFLX_PORT_TYPE)); |
| 1051 } | 1093 } |
| 1052 | 1094 |
| 1053 // Determines whether we should switch between two connections, based first on | 1095 // Determines whether we should switch between two connections, based first on |
| 1054 // connection states, static preferences, and then (if those are equal) on | 1096 // connection states, static preferences, and then (if those are equal) on |
| 1055 // latency estimates. | 1097 // latency estimates. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 | 1137 |
| 1096 // Any changes after this point will require a re-sort. | 1138 // Any changes after this point will require a re-sort. |
| 1097 sort_dirty_ = false; | 1139 sort_dirty_ = false; |
| 1098 | 1140 |
| 1099 // Find the best alternative connection by sorting. It is important to note | 1141 // Find the best alternative connection by sorting. It is important to note |
| 1100 // that amongst equal preference, writable connections, this will choose the | 1142 // that amongst equal preference, writable connections, this will choose the |
| 1101 // one whose estimated latency is lowest. So it is the only one that we | 1143 // one whose estimated latency is lowest. So it is the only one that we |
| 1102 // need to consider switching to. | 1144 // need to consider switching to. |
| 1103 std::stable_sort(connections_.begin(), connections_.end(), | 1145 std::stable_sort(connections_.begin(), connections_.end(), |
| 1104 [this](const Connection* a, const Connection* b) { | 1146 [this](const Connection* a, const Connection* b) { |
| 1105 return CompareConnections(a, b) > 0; | 1147 int cmp = CompareConnections(a, b); |
| 1148 if (cmp != 0) { |
| 1149 return cmp > 0; |
| 1150 } |
| 1151 |
| 1152 // Otherwise, sort based on latency estimate. |
| 1153 return a->rtt() < b->rtt(); |
| 1106 }); | 1154 }); |
| 1155 |
| 1107 LOG(LS_VERBOSE) << "Sorting " << connections_.size() | 1156 LOG(LS_VERBOSE) << "Sorting " << connections_.size() |
| 1108 << " available connections:"; | 1157 << " available connections:"; |
| 1109 for (size_t i = 0; i < connections_.size(); ++i) { | 1158 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1110 LOG(LS_VERBOSE) << connections_[i]->ToString(); | 1159 LOG(LS_VERBOSE) << connections_[i]->ToString(); |
| 1111 } | 1160 } |
| 1112 | 1161 |
| 1113 Connection* top_connection = | 1162 Connection* top_connection = |
| 1114 (connections_.size() > 0) ? connections_[0] : nullptr; | 1163 (connections_.size() > 0) ? connections_[0] : nullptr; |
| 1115 | 1164 |
| 1116 // If necessary, switch to the new choice. | 1165 // If necessary, switch to the new choice. Note that |top_connection| doesn't |
| 1117 // Note that |top_connection| doesn't have to be writable to become the best | 1166 // have to be writable to become the selected connection although it will |
| 1118 // connection although it will have higher priority if it is writable. | 1167 // have higher priority if it is writable. |
| 1119 if (ShouldSwitchSelectedConnection(best_connection_, top_connection)) { | 1168 if (ShouldSwitchSelectedConnection(top_connection)) { |
| 1120 LOG(LS_INFO) << "Switching best connection: " << top_connection->ToString(); | 1169 LOG(LS_INFO) << "Switching selected connection after sorting: " |
| 1121 SwitchBestConnectionTo(top_connection); | 1170 << top_connection->ToString(); |
| 1171 SwitchSelectedConnection(top_connection); |
| 1122 } | 1172 } |
| 1123 | 1173 |
| 1124 // Controlled side can prune only if the best connection has been nominated. | 1174 // The controlled side can prune only if the selected connection has been |
| 1125 // because otherwise it may delete the connection that will be selected by | 1175 // nominated because otherwise it may prune the connection that will be |
| 1126 // the controlling side. | 1176 // selected by the controlling side. |
| 1127 if (ice_role_ == ICEROLE_CONTROLLING || best_nominated_connection()) { | 1177 // TODO(honghaiz): This is not enough to prevent a connection from being |
| 1178 // pruned too early because with aggressive nomination, the controlling side |
| 1179 // will nominate every connection until it becomes writable. |
| 1180 if (ice_role_ == ICEROLE_CONTROLLING || |
| 1181 (selected_connection_ && selected_connection_->nominated())) { |
| 1128 PruneConnections(); | 1182 PruneConnections(); |
| 1129 } | 1183 } |
| 1130 | 1184 |
| 1131 // Check if all connections are timedout. | 1185 // Check if all connections are timedout. |
| 1132 bool all_connections_timedout = true; | 1186 bool all_connections_timedout = true; |
| 1133 for (size_t i = 0; i < connections_.size(); ++i) { | 1187 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1134 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { | 1188 if (connections_[i]->write_state() != Connection::STATE_WRITE_TIMEOUT) { |
| 1135 all_connections_timedout = false; | 1189 all_connections_timedout = false; |
| 1136 break; | 1190 break; |
| 1137 } | 1191 } |
| 1138 } | 1192 } |
| 1139 | 1193 |
| 1140 // Now update the writable state of the channel with the information we have | 1194 // Now update the writable state of the channel with the information we have |
| 1141 // so far. | 1195 // so far. |
| 1142 if (all_connections_timedout) { | 1196 if (all_connections_timedout) { |
| 1143 HandleAllTimedOut(); | 1197 HandleAllTimedOut(); |
| 1144 } | 1198 } |
| 1145 | 1199 |
| 1146 // Update the state of this channel. This method is called whenever the | 1200 // Update the state of this channel. This method is called whenever the |
| 1147 // state of any connection changes, so this is a good place to do this. | 1201 // state of any connection changes, so this is a good place to do this. |
| 1148 UpdateState(); | 1202 UpdateState(); |
| 1149 } | 1203 } |
| 1150 | 1204 |
| 1151 Connection* P2PTransportChannel::best_nominated_connection() const { | |
| 1152 return (best_connection_ && best_connection_->nominated()) ? best_connection_ | |
| 1153 : nullptr; | |
| 1154 } | |
| 1155 | |
| 1156 void P2PTransportChannel::PruneConnections() { | 1205 void P2PTransportChannel::PruneConnections() { |
| 1157 // We can prune any connection for which there is a connected, writable | 1206 // We can prune any connection for which there is a connected, writable |
| 1158 // connection on the same network with better or equal priority. We leave | 1207 // connection on the same network with better or equal priority. We leave |
| 1159 // those with better priority just in case they become writable later (at | 1208 // those with better priority just in case they become writable later (at |
| 1160 // which point, we would prune out the current best connection). We leave | 1209 // which point, we would prune out the current selected connection). We leave |
| 1161 // connections on other networks because they may not be using the same | 1210 // connections on other networks because they may not be using the same |
| 1162 // resources and they may represent very distinct paths over which we can | 1211 // resources and they may represent very distinct paths over which we can |
| 1163 // switch. If the |premier| connection is not connected, we may be | 1212 // switch. If the |premier| connection is not connected, we may be |
| 1164 // reconnecting a TCP connection and temporarily do not prune connections in | 1213 // reconnecting a TCP connection and temporarily do not prune connections in |
| 1165 // this network. See the big comment in CompareConnections. | 1214 // this network. See the big comment in CompareConnectionStates. |
| 1166 | 1215 |
| 1167 // Get a list of the networks that we are using. | 1216 // Get a list of the networks that we are using. |
| 1168 std::set<rtc::Network*> networks; | 1217 std::set<rtc::Network*> networks; |
| 1169 for (const Connection* conn : connections_) { | 1218 for (const Connection* conn : connections_) { |
| 1170 networks.insert(conn->port()->Network()); | 1219 networks.insert(conn->port()->Network()); |
| 1171 } | 1220 } |
| 1172 for (rtc::Network* network : networks) { | 1221 for (rtc::Network* network : networks) { |
| 1173 Connection* premier = GetBestConnectionOnNetwork(network); | 1222 Connection* premier = GetBestConnectionOnNetwork(network); |
| 1174 // Do not prune connections if the current best connection is weak on this | 1223 // Do not prune connections if the current selected connection is weak on |
| 1175 // network. Otherwise, it may delete connections prematurely. | 1224 // this network. Otherwise, it may delete connections prematurely. |
| 1176 if (!premier || premier->weak()) { | 1225 if (!premier || premier->weak()) { |
| 1177 continue; | 1226 continue; |
| 1178 } | 1227 } |
| 1179 | 1228 |
| 1180 for (Connection* conn : connections_) { | 1229 for (Connection* conn : connections_) { |
| 1181 if ((conn != premier) && (conn->port()->Network() == network) && | 1230 if ((conn != premier) && (conn->port()->Network() == network) && |
| 1182 (CompareConnectionCandidates(premier, conn) >= 0)) { | 1231 (CompareConnectionCandidates(premier, conn) >= 0)) { |
| 1183 conn->Prune(); | 1232 conn->Prune(); |
| 1184 } | 1233 } |
| 1185 } | 1234 } |
| 1186 } | 1235 } |
| 1187 } | 1236 } |
| 1188 | 1237 |
| 1189 // Track the best connection, and let listeners know | 1238 // Change the selected connection, and let listeners know. |
| 1190 void P2PTransportChannel::SwitchBestConnectionTo(Connection* conn) { | 1239 void P2PTransportChannel::SwitchSelectedConnection(Connection* conn) { |
| 1191 // Note: if conn is NULL, the previous best_connection_ has been destroyed, | 1240 // Note: if conn is NULL, the previous |selected_connection_| has been |
| 1192 // so don't use it. | 1241 // destroyed, so don't use it. |
| 1193 Connection* old_best_connection = best_connection_; | 1242 Connection* old_selected_connection = selected_connection_; |
| 1194 best_connection_ = conn; | 1243 selected_connection_ = conn; |
| 1195 if (best_connection_) { | 1244 if (selected_connection_) { |
| 1196 if (old_best_connection) { | 1245 if (old_selected_connection) { |
| 1197 LOG_J(LS_INFO, this) << "Previous best connection: " | 1246 LOG_J(LS_INFO, this) << "Previous selected connection: " |
| 1198 << old_best_connection->ToString(); | 1247 << old_selected_connection->ToString(); |
| 1199 } | 1248 } |
| 1200 LOG_J(LS_INFO, this) << "New best connection: " | 1249 LOG_J(LS_INFO, this) << "New selected connection: " |
| 1201 << best_connection_->ToString(); | 1250 << selected_connection_->ToString(); |
| 1202 SignalRouteChange(this, best_connection_->remote_candidate()); | 1251 SignalRouteChange(this, selected_connection_->remote_candidate()); |
| 1203 // This is a temporary, but safe fix to webrtc issue 5705. | 1252 // This is a temporary, but safe fix to webrtc issue 5705. |
| 1204 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport | 1253 // TODO(honghaiz): Make all EWOULDBLOCK error routed through the transport |
| 1205 // channel so that it knows whether the media channel is allowed to | 1254 // channel so that it knows whether the media channel is allowed to |
| 1206 // send; then it will only signal ready-to-send if the media channel | 1255 // send; then it will only signal ready-to-send if the media channel |
| 1207 // has been disallowed to send. | 1256 // has been disallowed to send. |
| 1208 if (best_connection_->writable() || PresumedWritable(best_connection_)) { | 1257 if (selected_connection_->writable() || |
| 1258 PresumedWritable(selected_connection_)) { |
| 1209 SignalReadyToSend(this); | 1259 SignalReadyToSend(this); |
| 1210 } | 1260 } |
| 1211 } else { | 1261 } else { |
| 1212 LOG_J(LS_INFO, this) << "No best connection"; | 1262 LOG_J(LS_INFO, this) << "No selected connection"; |
| 1213 } | 1263 } |
| 1214 // TODO(honghaiz): rename best_connection_ with selected_connection_ or | 1264 SignalSelectedCandidatePairChanged(this, selected_connection_, |
| 1215 // selected_candidate pair_. | |
| 1216 SignalSelectedCandidatePairChanged(this, best_connection_, | |
| 1217 last_sent_packet_id_); | 1265 last_sent_packet_id_); |
| 1218 } | 1266 } |
| 1219 | 1267 |
| 1220 // Warning: UpdateState should eventually be called whenever a connection | 1268 // Warning: UpdateState should eventually be called whenever a connection |
| 1221 // is added, deleted, or the write state of any connection changes so that the | 1269 // is added, deleted, or the write state of any connection changes so that the |
| 1222 // transport controller will get the up-to-date channel state. However it | 1270 // transport controller will get the up-to-date channel state. However it |
| 1223 // should not be called too often; in the case that multiple connection states | 1271 // should not be called too often; in the case that multiple connection states |
| 1224 // change, it should be called after all the connection states have changed. For | 1272 // change, it should be called after all the connection states have changed. For |
| 1225 // example, we call this at the end of SortConnections. | 1273 // example, we call this at the end of SortConnections. |
| 1226 void P2PTransportChannel::UpdateState() { | 1274 void P2PTransportChannel::UpdateState() { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1253 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); | 1301 RTC_DCHECK(state == STATE_CONNECTING || state == STATE_COMPLETED); |
| 1254 break; | 1302 break; |
| 1255 default: | 1303 default: |
| 1256 RTC_DCHECK(false); | 1304 RTC_DCHECK(false); |
| 1257 break; | 1305 break; |
| 1258 } | 1306 } |
| 1259 state_ = state; | 1307 state_ = state; |
| 1260 SignalStateChanged(this); | 1308 SignalStateChanged(this); |
| 1261 } | 1309 } |
| 1262 | 1310 |
| 1263 // If our best connection is "presumed writable" (TURN-TURN with no | 1311 // If our selected connection is "presumed writable" (TURN-TURN with no |
| 1264 // CreatePermission required), act like we're already writable to the upper | 1312 // CreatePermission required), act like we're already writable to the upper |
| 1265 // layers, so they can start media quicker. | 1313 // layers, so they can start media quicker. |
| 1266 set_writable(best_connection_ && (best_connection_->writable() || | 1314 bool writable = |
| 1267 PresumedWritable(best_connection_))); | 1315 selected_connection_ && (selected_connection_->writable() || |
| 1316 PresumedWritable(selected_connection_)); |
| 1317 set_writable(writable); |
| 1268 | 1318 |
| 1269 bool receiving = false; | 1319 bool receiving = false; |
| 1270 for (const Connection* connection : connections_) { | 1320 for (const Connection* connection : connections_) { |
| 1271 if (connection->receiving()) { | 1321 if (connection->receiving()) { |
| 1272 receiving = true; | 1322 receiving = true; |
| 1273 break; | 1323 break; |
| 1274 } | 1324 } |
| 1275 } | 1325 } |
| 1276 set_receiving(receiving); | 1326 set_receiving(receiving); |
| 1277 } | 1327 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1296 } | 1346 } |
| 1297 | 1347 |
| 1298 // If all connections timed out, delete them all. | 1348 // If all connections timed out, delete them all. |
| 1299 void P2PTransportChannel::HandleAllTimedOut() { | 1349 void P2PTransportChannel::HandleAllTimedOut() { |
| 1300 for (Connection* connection : connections_) { | 1350 for (Connection* connection : connections_) { |
| 1301 connection->Destroy(); | 1351 connection->Destroy(); |
| 1302 } | 1352 } |
| 1303 } | 1353 } |
| 1304 | 1354 |
| 1305 bool P2PTransportChannel::weak() const { | 1355 bool P2PTransportChannel::weak() const { |
| 1306 return !best_connection_ || best_connection_->weak(); | 1356 return !selected_connection_ || selected_connection_->weak(); |
| 1307 } | 1357 } |
| 1308 | 1358 |
| 1309 // If we have a best connection, return it, otherwise return top one in the | 1359 // If we have a selected connection, return it, otherwise return top one in the |
| 1310 // list (later we will mark it best). | 1360 // list (later we will mark it best). |
| 1311 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( | 1361 Connection* P2PTransportChannel::GetBestConnectionOnNetwork( |
| 1312 rtc::Network* network) const { | 1362 rtc::Network* network) const { |
| 1313 // If the best connection is on this network, then it wins. | 1363 // If the selected connection is on this network, then it wins. |
| 1314 if (best_connection_ && (best_connection_->port()->Network() == network)) | 1364 if (selected_connection_ && |
| 1315 return best_connection_; | 1365 (selected_connection_->port()->Network() == network)) { |
| 1366 return selected_connection_; |
| 1367 } |
| 1316 | 1368 |
| 1317 // Otherwise, we return the top-most in sorted order. | 1369 // Otherwise, we return the top-most in sorted order. |
| 1318 for (size_t i = 0; i < connections_.size(); ++i) { | 1370 for (size_t i = 0; i < connections_.size(); ++i) { |
| 1319 if (connections_[i]->port()->Network() == network) | 1371 if (connections_[i]->port()->Network() == network) { |
| 1320 return connections_[i]; | 1372 return connections_[i]; |
| 1373 } |
| 1321 } | 1374 } |
| 1322 | 1375 |
| 1323 return NULL; | 1376 return NULL; |
| 1324 } | 1377 } |
| 1325 | 1378 |
| 1326 // Handle any queued up requests | 1379 // Handle any queued up requests |
| 1327 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { | 1380 void P2PTransportChannel::OnMessage(rtc::Message *pmsg) { |
| 1328 switch (pmsg->message_id) { | 1381 switch (pmsg->message_id) { |
| 1329 case MSG_SORT: | 1382 case MSG_SORT: |
| 1330 OnSort(); | 1383 OnSort(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1342 void P2PTransportChannel::OnSort() { | 1395 void P2PTransportChannel::OnSort() { |
| 1343 // Resort the connections based on the new statistics. | 1396 // Resort the connections based on the new statistics. |
| 1344 SortConnections(); | 1397 SortConnections(); |
| 1345 } | 1398 } |
| 1346 | 1399 |
| 1347 // Handle queued up check-and-ping request | 1400 // Handle queued up check-and-ping request |
| 1348 void P2PTransportChannel::OnCheckAndPing() { | 1401 void P2PTransportChannel::OnCheckAndPing() { |
| 1349 // Make sure the states of the connections are up-to-date (since this affects | 1402 // Make sure the states of the connections are up-to-date (since this affects |
| 1350 // which ones are pingable). | 1403 // which ones are pingable). |
| 1351 UpdateConnectionStates(); | 1404 UpdateConnectionStates(); |
| 1352 // When the best connection is not receiving or not writable, or any active | 1405 // When the selected connection is not receiving or not writable, or any |
| 1353 // connection has not been pinged enough times, use the weak ping interval. | 1406 // active connection has not been pinged enough times, use the weak ping |
| 1407 // interval. |
| 1354 bool need_more_pings_at_weak_interval = std::any_of( | 1408 bool need_more_pings_at_weak_interval = std::any_of( |
| 1355 connections_.begin(), connections_.end(), [](Connection* conn) { | 1409 connections_.begin(), connections_.end(), [](Connection* conn) { |
| 1356 return conn->active() && | 1410 return conn->active() && |
| 1357 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; | 1411 conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL; |
| 1358 }); | 1412 }); |
| 1359 int ping_interval = (weak() || need_more_pings_at_weak_interval) | 1413 int ping_interval = (weak() || need_more_pings_at_weak_interval) |
| 1360 ? weak_ping_interval_ | 1414 ? weak_ping_interval_ |
| 1361 : STRONG_PING_INTERVAL; | 1415 : STRONG_PING_INTERVAL; |
| 1362 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { | 1416 if (rtc::TimeMillis() >= last_ping_sent_ms_ + ping_interval) { |
| 1363 Connection* conn = FindNextPingableConnection(); | 1417 Connection* conn = FindNextPingableConnection(); |
| 1364 if (conn) { | 1418 if (conn) { |
| 1365 PingConnection(conn); | 1419 PingConnection(conn); |
| 1366 MarkConnectionPinged(conn); | 1420 MarkConnectionPinged(conn); |
| 1367 } | 1421 } |
| 1368 } | 1422 } |
| 1369 int delay = std::min(ping_interval, check_receiving_interval_); | 1423 int delay = std::min(ping_interval, check_receiving_interval_); |
| 1370 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); | 1424 thread()->PostDelayed(RTC_FROM_HERE, delay, this, MSG_CHECK_AND_PING); |
| 1371 } | 1425 } |
| 1372 | 1426 |
| 1373 // A connection is considered a backup connection if the channel state | 1427 // A connection is considered a backup connection if the channel state |
| 1374 // is completed, the connection is not the best connection and it is active. | 1428 // is completed, the connection is not the selected connection and it is active. |
| 1375 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { | 1429 bool P2PTransportChannel::IsBackupConnection(Connection* conn) const { |
| 1376 return state_ == STATE_COMPLETED && conn != best_connection_ && | 1430 return state_ == STATE_COMPLETED && conn != selected_connection_ && |
| 1377 conn->active(); | 1431 conn->active(); |
| 1378 } | 1432 } |
| 1379 | 1433 |
| 1380 // Is the connection in a state for us to even consider pinging the other side? | 1434 // Is the connection in a state for us to even consider pinging the other side? |
| 1381 // We consider a connection pingable even if it's not connected because that's | 1435 // We consider a connection pingable even if it's not connected because that's |
| 1382 // how a TCP connection is kicked into reconnecting on the active side. | 1436 // how a TCP connection is kicked into reconnecting on the active side. |
| 1383 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { | 1437 bool P2PTransportChannel::IsPingable(Connection* conn, int64_t now) { |
| 1384 const Candidate& remote = conn->remote_candidate(); | 1438 const Candidate& remote = conn->remote_candidate(); |
| 1385 // We should never get this far with an empty remote ufrag. | 1439 // We should never get this far with an empty remote ufrag. |
| 1386 ASSERT(!remote.username().empty()); | 1440 ASSERT(!remote.username().empty()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 if (!conn->writable()) { | 1475 if (!conn->writable()) { |
| 1422 return true; | 1476 return true; |
| 1423 } | 1477 } |
| 1424 | 1478 |
| 1425 // Ping writable, active connections if it's been long enough since the last | 1479 // Ping writable, active connections if it's been long enough since the last |
| 1426 // ping. | 1480 // ping. |
| 1427 int ping_interval = CalculateActiveWritablePingInterval(conn, now); | 1481 int ping_interval = CalculateActiveWritablePingInterval(conn, now); |
| 1428 return (now >= conn->last_ping_sent() + ping_interval); | 1482 return (now >= conn->last_ping_sent() + ping_interval); |
| 1429 } | 1483 } |
| 1430 | 1484 |
| 1431 bool P2PTransportChannel::IsBestConnectionPingable(int64_t now) { | 1485 bool P2PTransportChannel::IsSelectedConnectionPingable(int64_t now) { |
| 1432 if (!best_connection_ || !best_connection_->connected() || | 1486 if (!selected_connection_ || !selected_connection_->connected() || |
| 1433 !best_connection_->writable()) { | 1487 !selected_connection_->writable()) { |
| 1434 return false; | 1488 return false; |
| 1435 } | 1489 } |
| 1436 | 1490 |
| 1437 int interval = CalculateActiveWritablePingInterval(best_connection_, now); | 1491 int interval = CalculateActiveWritablePingInterval(selected_connection_, now); |
| 1438 return best_connection_->last_ping_sent() + interval <= now; | 1492 return selected_connection_->last_ping_sent() + interval <= now; |
| 1439 } | 1493 } |
| 1440 | 1494 |
| 1441 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, | 1495 int P2PTransportChannel::CalculateActiveWritablePingInterval(Connection* conn, |
| 1442 int64_t now) { | 1496 int64_t now) { |
| 1443 // Ping each connection at a higher rate at least | 1497 // Ping each connection at a higher rate at least |
| 1444 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. | 1498 // MIN_PINGS_AT_WEAK_PING_INTERVAL times. |
| 1445 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { | 1499 if (conn->num_pings_sent() < MIN_PINGS_AT_WEAK_PING_INTERVAL) { |
| 1446 return weak_ping_interval_; | 1500 return weak_ping_interval_; |
| 1447 } | 1501 } |
| 1448 | 1502 |
| 1449 int stable_interval = config_.stable_writable_connection_ping_interval; | 1503 int stable_interval = config_.stable_writable_connection_ping_interval; |
| 1450 int stablizing_interval = | 1504 int stablizing_interval = |
| 1451 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); | 1505 std::min(stable_interval, STABILIZING_WRITABLE_CONNECTION_PING_INTERVAL); |
| 1452 | 1506 |
| 1453 return conn->stable(now) ? stable_interval : stablizing_interval; | 1507 return conn->stable(now) ? stable_interval : stablizing_interval; |
| 1454 } | 1508 } |
| 1455 | 1509 |
| 1456 // Returns the next pingable connection to ping. This will be the oldest | 1510 // Returns the next pingable connection to ping. This will be the oldest |
| 1457 // pingable connection unless we have a connected, writable connection that is | 1511 // pingable connection unless we have a connected, writable connection that is |
| 1458 // past the writable ping interval. When reconnecting a TCP | 1512 // past the writable ping interval. When reconnecting a TCP |
| 1459 // connection, the best connection is disconnected, although still WRITABLE | 1513 // connection, the selected connection is disconnected, although still WRITABLE |
| 1460 // while reconnecting. The newly created connection should be selected as the | 1514 // while reconnecting. The newly created connection should be selected as the |
| 1461 // ping target to become writable instead. See the big comment in | 1515 // ping target to become writable instead. See the big comment in |
| 1462 // CompareConnections. | 1516 // CompareConnectionStates. |
| 1463 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1517 Connection* P2PTransportChannel::FindNextPingableConnection() { |
| 1464 int64_t now = rtc::TimeMillis(); | 1518 int64_t now = rtc::TimeMillis(); |
| 1465 Connection* conn_to_ping = nullptr; | 1519 Connection* conn_to_ping = nullptr; |
| 1466 if (IsBestConnectionPingable(now)) { | 1520 if (IsSelectedConnectionPingable(now)) { |
| 1467 conn_to_ping = best_connection_; | 1521 conn_to_ping = selected_connection_; |
| 1468 } else { | 1522 } else { |
| 1469 conn_to_ping = FindConnectionToPing(now); | 1523 conn_to_ping = FindConnectionToPing(now); |
| 1470 } | 1524 } |
| 1471 return conn_to_ping; | 1525 return conn_to_ping; |
| 1472 } | 1526 } |
| 1473 | 1527 |
| 1474 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { | 1528 void P2PTransportChannel::MarkConnectionPinged(Connection* conn) { |
| 1475 if (conn && pinged_connections_.insert(conn).second) { | 1529 if (conn && pinged_connections_.insert(conn).second) { |
| 1476 unpinged_connections_.erase(conn); | 1530 unpinged_connections_.erase(conn); |
| 1477 } | 1531 } |
| 1478 } | 1532 } |
| 1479 | 1533 |
| 1480 // Apart from sending ping from |conn| this method also updates | 1534 // Apart from sending ping from |conn| this method also updates |
| 1481 // |use_candidate_attr| flag. The criteria to update this flag is | 1535 // |use_candidate_attr| flag. The criteria to update this flag is |
| 1482 // explained below. | 1536 // explained below. |
| 1483 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND | 1537 // Set USE-CANDIDATE if doing ICE AND this channel is in CONTROLLING AND |
| 1484 // a) Channel is in FULL ICE AND | 1538 // a) Channel is in FULL ICE AND |
| 1485 // a.1) |conn| is the best connection OR | 1539 // a.1) |conn| is the selected connection OR |
| 1486 // a.2) there is no best connection OR | 1540 // a.2) there is no selected connection OR |
| 1487 // a.3) the best connection is unwritable OR | 1541 // a.3) the selected connection is unwritable OR |
| 1488 // a.4) |conn| has higher priority than best_connection. | 1542 // a.4) |conn| has higher priority than selected_connection. |
| 1489 // b) we're doing LITE ICE AND | 1543 // b) we're doing LITE ICE AND |
| 1490 // b.1) |conn| is the best_connection AND | 1544 // b.1) |conn| is the selected_connection AND |
| 1491 // b.2) |conn| is writable. | 1545 // b.2) |conn| is writable. |
| 1492 void P2PTransportChannel::PingConnection(Connection* conn) { | 1546 void P2PTransportChannel::PingConnection(Connection* conn) { |
| 1493 bool use_candidate = false; | 1547 bool use_candidate = false; |
| 1494 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { | 1548 if (remote_ice_mode_ == ICEMODE_FULL && ice_role_ == ICEROLE_CONTROLLING) { |
| 1495 use_candidate = (conn == best_connection_) || (best_connection_ == NULL) || | 1549 use_candidate = |
| 1496 (!best_connection_->writable()) || | 1550 (conn == selected_connection_) || (selected_connection_ == NULL) || |
| 1497 (CompareConnectionCandidates(best_connection_, conn) < 0); | 1551 (!selected_connection_->writable()) || |
| 1498 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == best_connection_) { | 1552 (CompareConnectionCandidates(selected_connection_, conn) < 0); |
| 1499 use_candidate = best_connection_->writable(); | 1553 } else if (remote_ice_mode_ == ICEMODE_LITE && conn == selected_connection_) { |
| 1554 use_candidate = selected_connection_->writable(); |
| 1500 } | 1555 } |
| 1501 conn->set_use_candidate_attr(use_candidate); | 1556 conn->set_use_candidate_attr(use_candidate); |
| 1502 last_ping_sent_ms_ = rtc::TimeMillis(); | 1557 last_ping_sent_ms_ = rtc::TimeMillis(); |
| 1503 conn->Ping(last_ping_sent_ms_); | 1558 conn->Ping(last_ping_sent_ms_); |
| 1504 } | 1559 } |
| 1505 | 1560 |
| 1506 // When a connection's state changes, we need to figure out who to use as | 1561 // When a connection's state changes, we need to figure out who to use as |
| 1507 // the best connection again. It could have become usable, or become unusable. | 1562 // the selected connection again. It could have become usable, or become |
| 1563 // unusable. |
| 1508 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { | 1564 void P2PTransportChannel::OnConnectionStateChange(Connection* connection) { |
| 1509 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1565 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1510 | 1566 |
| 1511 // Update the best connection if the state change is from pending best | |
| 1512 // connection and role is controlled. | |
| 1513 if (ice_role_ == ICEROLE_CONTROLLED) { | |
| 1514 if (connection == pending_best_connection_ && connection->writable()) { | |
| 1515 pending_best_connection_ = NULL; | |
| 1516 LOG(LS_INFO) << "Switching best connection on controlled side" | |
| 1517 << " because it's now writable: " << connection->ToString(); | |
| 1518 SwitchBestConnectionTo(connection); | |
| 1519 } | |
| 1520 } | |
| 1521 | |
| 1522 // May stop the allocator session when at least one connection becomes | 1567 // May stop the allocator session when at least one connection becomes |
| 1523 // strongly connected after starting to get ports and the local candidate of | 1568 // strongly connected after starting to get ports and the local candidate of |
| 1524 // the connection is at the latest generation. It is not enough to check | 1569 // the connection is at the latest generation. It is not enough to check |
| 1525 // that the connection becomes weakly connected because the connection may be | 1570 // that the connection becomes weakly connected because the connection may be |
| 1526 // changing from (writable, receiving) to (writable, not receiving). | 1571 // changing from (writable, receiving) to (writable, not receiving). |
| 1527 bool strongly_connected = !connection->weak(); | 1572 bool strongly_connected = !connection->weak(); |
| 1528 bool latest_generation = connection->local_candidate().generation() >= | 1573 bool latest_generation = connection->local_candidate().generation() >= |
| 1529 allocator_session()->generation(); | 1574 allocator_session()->generation(); |
| 1530 if (strongly_connected && latest_generation) { | 1575 if (strongly_connected && latest_generation) { |
| 1531 MaybeStopPortAllocatorSessions(); | 1576 MaybeStopPortAllocatorSessions(); |
| 1532 } | 1577 } |
| 1533 | 1578 |
| 1534 // We have to unroll the stack before doing this because we may be changing | 1579 // We have to unroll the stack before doing this because we may be changing |
| 1535 // the state of connections while sorting. | 1580 // the state of connections while sorting. |
| 1536 RequestSort(); | 1581 RequestSort(); |
| 1537 } | 1582 } |
| 1538 | 1583 |
| 1539 // When a connection is removed, edit it out, and then update our best | 1584 // When a connection is removed, edit it out, and then update our best |
| 1540 // connection. | 1585 // connection. |
| 1541 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { | 1586 void P2PTransportChannel::OnConnectionDestroyed(Connection* connection) { |
| 1542 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1587 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1543 | 1588 |
| 1544 // Note: the previous best_connection_ may be destroyed by now, so don't | 1589 // Note: the previous selected_connection_ may be destroyed by now, so don't |
| 1545 // use it. | 1590 // use it. |
| 1546 | 1591 |
| 1547 // Remove this connection from the list. | 1592 // Remove this connection from the list. |
| 1548 std::vector<Connection*>::iterator iter = | 1593 std::vector<Connection*>::iterator iter = |
| 1549 std::find(connections_.begin(), connections_.end(), connection); | 1594 std::find(connections_.begin(), connections_.end(), connection); |
| 1550 ASSERT(iter != connections_.end()); | 1595 ASSERT(iter != connections_.end()); |
| 1551 pinged_connections_.erase(*iter); | 1596 pinged_connections_.erase(*iter); |
| 1552 unpinged_connections_.erase(*iter); | 1597 unpinged_connections_.erase(*iter); |
| 1553 connections_.erase(iter); | 1598 connections_.erase(iter); |
| 1554 | 1599 |
| 1555 LOG_J(LS_INFO, this) << "Removed connection (" | 1600 LOG_J(LS_INFO, this) << "Removed connection (" |
| 1556 << static_cast<int>(connections_.size()) << " remaining)"; | 1601 << static_cast<int>(connections_.size()) << " remaining)"; |
| 1557 | 1602 |
| 1558 if (pending_best_connection_ == connection) { | 1603 // If this is currently the selected connection, then we need to pick a new |
| 1559 pending_best_connection_ = NULL; | 1604 // one. The call to SortConnections will pick a new one. It looks at the |
| 1560 } | 1605 // current selected connection in order to avoid switching between fairly |
| 1561 | 1606 // similar ones. Since this connection is no longer an option, we can just |
| 1562 // If this is currently the best connection, then we need to pick a new one. | 1607 // set selected to nullptr and re-choose a best assuming that there was no |
| 1563 // The call to SortConnections will pick a new one. It looks at the current | 1608 // selected connection. |
| 1564 // best connection in order to avoid switching between fairly similar ones. | 1609 if (selected_connection_ == connection) { |
| 1565 // Since this connection is no longer an option, we can just set best to NULL | 1610 LOG(LS_INFO) << "selected connection destroyed. Will choose a new one."; |
| 1566 // and re-choose a best assuming that there was no best connection. | 1611 SwitchSelectedConnection(nullptr); |
| 1567 if (best_connection_ == connection) { | |
| 1568 LOG(LS_INFO) << "Best connection destroyed. Will choose a new one."; | |
| 1569 SwitchBestConnectionTo(NULL); | |
| 1570 RequestSort(); | 1612 RequestSort(); |
| 1571 } | 1613 } |
| 1572 | 1614 |
| 1573 UpdateState(); | 1615 UpdateState(); |
| 1574 } | 1616 } |
| 1575 | 1617 |
| 1576 // When a port is destroyed remove it from our list of ports to use for | 1618 // When a port is destroyed remove it from our list of ports to use for |
| 1577 // connection attempts. | 1619 // connection attempts. |
| 1578 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { | 1620 void P2PTransportChannel::OnPortDestroyed(PortInterface* port) { |
| 1579 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1621 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1619 | 1661 |
| 1620 // Do not deliver, if packet doesn't belong to the correct transport channel. | 1662 // Do not deliver, if packet doesn't belong to the correct transport channel. |
| 1621 if (!FindConnection(connection)) | 1663 if (!FindConnection(connection)) |
| 1622 return; | 1664 return; |
| 1623 | 1665 |
| 1624 // Let the client know of an incoming packet | 1666 // Let the client know of an incoming packet |
| 1625 SignalReadPacket(this, data, len, packet_time, 0); | 1667 SignalReadPacket(this, data, len, packet_time, 0); |
| 1626 | 1668 |
| 1627 // May need to switch the sending connection based on the receiving media path | 1669 // May need to switch the sending connection based on the receiving media path |
| 1628 // if this is the controlled side. | 1670 // if this is the controlled side. |
| 1629 if (ice_role_ == ICEROLE_CONTROLLED && !best_nominated_connection() && | 1671 if (ice_role_ == ICEROLE_CONTROLLED && |
| 1630 connection->writable() && best_connection_ != connection) { | 1672 ShouldSwitchSelectedConnection(connection)) { |
| 1631 SwitchBestConnectionTo(connection); | 1673 LOG(LS_INFO) << "Switching selected connection on controlled side due to " |
| 1674 << "data received: " << connection->ToString(); |
| 1675 SwitchSelectedConnection(connection); |
| 1632 } | 1676 } |
| 1633 } | 1677 } |
| 1634 | 1678 |
| 1635 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { | 1679 void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) { |
| 1636 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1680 ASSERT(worker_thread_ == rtc::Thread::Current()); |
| 1637 | 1681 |
| 1638 SignalSentPacket(this, sent_packet); | 1682 SignalSentPacket(this, sent_packet); |
| 1639 } | 1683 } |
| 1640 | 1684 |
| 1641 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1685 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
| 1642 if (connection == best_connection_ && writable()) { | 1686 if (connection == selected_connection_ && writable()) { |
| 1643 SignalReadyToSend(this); | 1687 SignalReadyToSend(this); |
| 1644 } | 1688 } |
| 1645 } | 1689 } |
| 1646 | 1690 |
| 1647 // Find "triggered checks". We ping first those connections that have | 1691 // Find "triggered checks". We ping first those connections that have |
| 1648 // received a ping but have not sent a ping since receiving it | 1692 // received a ping but have not sent a ping since receiving it |
| 1649 // (last_received_ping > last_sent_ping). But we shouldn't do | 1693 // (last_received_ping > last_sent_ping). But we shouldn't do |
| 1650 // triggered checks if the connection is already writable. | 1694 // triggered checks if the connection is already writable. |
| 1651 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( | 1695 Connection* P2PTransportChannel::FindOldestConnectionNeedingTriggeredCheck( |
| 1652 int64_t now) { | 1696 int64_t now) { |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1755 | 1799 |
| 1756 // During the initial state when nothing has been pinged yet, return the first | 1800 // During the initial state when nothing has been pinged yet, return the first |
| 1757 // one in the ordered |connections_|. | 1801 // one in the ordered |connections_|. |
| 1758 return *(std::find_if(connections_.begin(), connections_.end(), | 1802 return *(std::find_if(connections_.begin(), connections_.end(), |
| 1759 [conn1, conn2](Connection* conn) { | 1803 [conn1, conn2](Connection* conn) { |
| 1760 return conn == conn1 || conn == conn2; | 1804 return conn == conn1 || conn == conn2; |
| 1761 })); | 1805 })); |
| 1762 } | 1806 } |
| 1763 | 1807 |
| 1764 } // namespace cricket | 1808 } // namespace cricket |
| OLD | NEW |