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 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 session->SignalCandidatesReady.connect( | 214 session->SignalCandidatesReady.connect( |
215 this, &P2PTransportChannel::OnCandidatesReady); | 215 this, &P2PTransportChannel::OnCandidatesReady); |
216 session->SignalCandidatesAllocationDone.connect( | 216 session->SignalCandidatesAllocationDone.connect( |
217 this, &P2PTransportChannel::OnCandidatesAllocationDone); | 217 this, &P2PTransportChannel::OnCandidatesAllocationDone); |
218 session->StartGettingPorts(); | 218 session->StartGettingPorts(); |
219 } | 219 } |
220 | 220 |
221 void P2PTransportChannel::AddConnection(Connection* connection) { | 221 void P2PTransportChannel::AddConnection(Connection* connection) { |
222 connections_.push_back(connection); | 222 connections_.push_back(connection); |
223 connection->set_remote_ice_mode(remote_ice_mode_); | 223 connection->set_remote_ice_mode(remote_ice_mode_); |
224 connection->set_receiving_timeout(receiving_timeout_); | |
225 connection->SignalReadPacket.connect( | 224 connection->SignalReadPacket.connect( |
226 this, &P2PTransportChannel::OnReadPacket); | 225 this, &P2PTransportChannel::OnReadPacket); |
227 connection->SignalReadyToSend.connect( | 226 connection->SignalReadyToSend.connect( |
228 this, &P2PTransportChannel::OnReadyToSend); | 227 this, &P2PTransportChannel::OnReadyToSend); |
229 connection->SignalStateChange.connect( | 228 connection->SignalStateChange.connect( |
230 this, &P2PTransportChannel::OnConnectionStateChange); | 229 this, &P2PTransportChannel::OnConnectionStateChange); |
231 connection->SignalDestroyed.connect( | 230 connection->SignalDestroyed.connect( |
232 this, &P2PTransportChannel::OnConnectionDestroyed); | 231 this, &P2PTransportChannel::OnConnectionDestroyed); |
233 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); | 232 connection->SignalNominated.connect(this, &P2PTransportChannel::OnNominated); |
234 } | 233 } |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 remote_ice_mode_ = mode; | 333 remote_ice_mode_ = mode; |
335 } | 334 } |
336 | 335 |
337 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { | 336 void P2PTransportChannel::SetReceivingTimeout(int receiving_timeout_ms) { |
338 if (receiving_timeout_ms < 0) { | 337 if (receiving_timeout_ms < 0) { |
339 return; | 338 return; |
340 } | 339 } |
341 receiving_timeout_ = receiving_timeout_ms; | 340 receiving_timeout_ = receiving_timeout_ms; |
342 check_receiving_delay_ = | 341 check_receiving_delay_ = |
343 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); | 342 std::max(MIN_CHECK_RECEIVING_DELAY, receiving_timeout_ / 10); |
344 | |
345 for (Connection* connection : connections_) { | |
346 connection->set_receiving_timeout(receiving_timeout_); | |
347 } | |
348 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_ | 343 LOG(LS_VERBOSE) << "Set ICE receiving timeout to " << receiving_timeout_ |
349 << " milliseconds"; | 344 << " milliseconds"; |
350 } | 345 } |
351 | 346 |
352 // Go into the state of processing candidates, and running in general | 347 // Go into the state of processing candidates, and running in general |
353 void P2PTransportChannel::Connect() { | 348 void P2PTransportChannel::Connect() { |
354 ASSERT(worker_thread_ == rtc::Thread::Current()); | 349 ASSERT(worker_thread_ == rtc::Thread::Current()); |
355 if (ice_ufrag_.empty() || ice_pwd_.empty()) { | 350 if (ice_ufrag_.empty() || ice_pwd_.empty()) { |
356 ASSERT(false); | 351 ASSERT(false); |
357 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " | 352 LOG(LS_ERROR) << "P2PTransportChannel::Connect: The ice_ufrag_ and the " |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); | 393 port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed); |
399 port->SignalRoleConflict.connect( | 394 port->SignalRoleConflict.connect( |
400 this, &P2PTransportChannel::OnRoleConflict); | 395 this, &P2PTransportChannel::OnRoleConflict); |
401 | 396 |
402 // Attempt to create a connection from this new port to all of the remote | 397 // Attempt to create a connection from this new port to all of the remote |
403 // candidates that we were given so far. | 398 // candidates that we were given so far. |
404 | 399 |
405 std::vector<RemoteCandidate>::iterator iter; | 400 std::vector<RemoteCandidate>::iterator iter; |
406 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); | 401 for (iter = remote_candidates_.begin(); iter != remote_candidates_.end(); |
407 ++iter) { | 402 ++iter) { |
408 CreateConnection(port, *iter, iter->origin_port()); | 403 CreateConnection(port, *iter, iter->origin_port(), false); |
409 } | 404 } |
410 | 405 |
411 SortConnections(); | 406 SortConnections(); |
412 } | 407 } |
413 | 408 |
414 // A new candidate is available, let listeners know | 409 // A new candidate is available, let listeners know |
415 void P2PTransportChannel::OnCandidatesReady( | 410 void P2PTransportChannel::OnCandidatesReady( |
416 PortAllocatorSession *session, const std::vector<Candidate>& candidates) { | 411 PortAllocatorSession *session, const std::vector<Candidate>& candidates) { |
417 ASSERT(worker_thread_ == rtc::Thread::Current()); | 412 ASSERT(worker_thread_ == rtc::Thread::Current()); |
418 for (size_t i = 0; i < candidates.size(); ++i) { | 413 for (size_t i = 0; i < candidates.size(); ++i) { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 // remote candidate with an older generation arrives, drop it. | 609 // remote candidate with an older generation arrives, drop it. |
615 if (generation != 0 && generation < remote_candidate_generation_) { | 610 if (generation != 0 && generation < remote_candidate_generation_) { |
616 LOG(LS_WARNING) << "Dropping a remote candidate because its generation " | 611 LOG(LS_WARNING) << "Dropping a remote candidate because its generation " |
617 << generation | 612 << generation |
618 << " is lower than the current remote generation " | 613 << " is lower than the current remote generation " |
619 << remote_candidate_generation_; | 614 << remote_candidate_generation_; |
620 return; | 615 return; |
621 } | 616 } |
622 | 617 |
623 // Create connections to this remote candidate. | 618 // Create connections to this remote candidate. |
624 CreateConnections(candidate, NULL); | 619 CreateConnections(candidate, NULL, false); |
625 | 620 |
626 // Resort the connections list, which may have new elements. | 621 // Resort the connections list, which may have new elements. |
627 SortConnections(); | 622 SortConnections(); |
628 } | 623 } |
629 | 624 |
630 // Creates connections from all of the ports that we care about to the given | 625 // Creates connections from all of the ports that we care about to the given |
631 // remote candidate. The return value is true if we created a connection from | 626 // remote candidate. The return value is true if we created a connection from |
632 // the origin port. | 627 // the origin port. |
633 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, | 628 bool P2PTransportChannel::CreateConnections(const Candidate& remote_candidate, |
634 PortInterface* origin_port) { | 629 PortInterface* origin_port, |
| 630 bool readable) { |
635 ASSERT(worker_thread_ == rtc::Thread::Current()); | 631 ASSERT(worker_thread_ == rtc::Thread::Current()); |
636 | 632 |
637 Candidate new_remote_candidate(remote_candidate); | 633 Candidate new_remote_candidate(remote_candidate); |
638 new_remote_candidate.set_generation( | 634 new_remote_candidate.set_generation( |
639 GetRemoteCandidateGeneration(remote_candidate)); | 635 GetRemoteCandidateGeneration(remote_candidate)); |
640 // ICE candidates don't need to have username and password set, but | 636 // ICE candidates don't need to have username and password set, but |
641 // the code below this (specifically, ConnectionRequest::Prepare in | 637 // the code below this (specifically, ConnectionRequest::Prepare in |
642 // port.cc) uses the remote candidates's username. So, we set it | 638 // port.cc) uses the remote candidates's username. So, we set it |
643 // here. | 639 // here. |
644 if (remote_candidate.username().empty()) { | 640 if (remote_candidate.username().empty()) { |
(...skipping 17 matching lines...) Expand all Loading... |
662 } | 658 } |
663 | 659 |
664 // Add a new connection for this candidate to every port that allows such a | 660 // Add a new connection for this candidate to every port that allows such a |
665 // connection (i.e., if they have compatible protocols) and that does not | 661 // connection (i.e., if they have compatible protocols) and that does not |
666 // already have a connection to an equivalent candidate. We must be careful | 662 // already have a connection to an equivalent candidate. We must be careful |
667 // to make sure that the origin port is included, even if it was pruned, | 663 // to make sure that the origin port is included, even if it was pruned, |
668 // since that may be the only port that can create this connection. | 664 // since that may be the only port that can create this connection. |
669 bool created = false; | 665 bool created = false; |
670 std::vector<PortInterface *>::reverse_iterator it; | 666 std::vector<PortInterface *>::reverse_iterator it; |
671 for (it = ports_.rbegin(); it != ports_.rend(); ++it) { | 667 for (it = ports_.rbegin(); it != ports_.rend(); ++it) { |
672 if (CreateConnection(*it, new_remote_candidate, origin_port)) { | 668 if (CreateConnection(*it, new_remote_candidate, origin_port, readable)) { |
673 if (*it == origin_port) | 669 if (*it == origin_port) |
674 created = true; | 670 created = true; |
675 } | 671 } |
676 } | 672 } |
677 | 673 |
678 if ((origin_port != NULL) && | 674 if ((origin_port != NULL) && |
679 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { | 675 std::find(ports_.begin(), ports_.end(), origin_port) == ports_.end()) { |
680 if (CreateConnection(origin_port, new_remote_candidate, origin_port)) | 676 if (CreateConnection( |
| 677 origin_port, new_remote_candidate, origin_port, readable)) |
681 created = true; | 678 created = true; |
682 } | 679 } |
683 | 680 |
684 // Remember this remote candidate so that we can add it to future ports. | 681 // Remember this remote candidate so that we can add it to future ports. |
685 RememberRemoteCandidate(new_remote_candidate, origin_port); | 682 RememberRemoteCandidate(new_remote_candidate, origin_port); |
686 | 683 |
687 return created; | 684 return created; |
688 } | 685 } |
689 | 686 |
690 // Setup a connection object for the local and remote candidate combination. | 687 // Setup a connection object for the local and remote candidate combination. |
691 // And then listen to connection object for changes. | 688 // And then listen to connection object for changes. |
692 bool P2PTransportChannel::CreateConnection(PortInterface* port, | 689 bool P2PTransportChannel::CreateConnection(PortInterface* port, |
693 const Candidate& remote_candidate, | 690 const Candidate& remote_candidate, |
694 PortInterface* origin_port) { | 691 PortInterface* origin_port, |
| 692 bool readable) { |
695 // Look for an existing connection with this remote address. If one is not | 693 // Look for an existing connection with this remote address. If one is not |
696 // found, then we can create a new connection for this address. | 694 // found, then we can create a new connection for this address. |
697 Connection* connection = port->GetConnection(remote_candidate.address()); | 695 Connection* connection = port->GetConnection(remote_candidate.address()); |
698 if (connection != NULL) { | 696 if (connection != NULL) { |
699 connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate); | 697 connection->MaybeUpdatePeerReflexiveCandidate(remote_candidate); |
700 | 698 |
701 // It is not legal to try to change any of the parameters of an existing | 699 // It is not legal to try to change any of the parameters of an existing |
702 // connection; however, the other side can send a duplicate candidate. | 700 // connection; however, the other side can send a duplicate candidate. |
703 if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { | 701 if (!remote_candidate.IsEquivalent(connection->remote_candidate())) { |
704 LOG(INFO) << "Attempt to change a remote candidate." | 702 LOG(INFO) << "Attempt to change a remote candidate." |
(...skipping 14 matching lines...) Expand all Loading... |
719 connection = port->CreateConnection(remote_candidate, origin); | 717 connection = port->CreateConnection(remote_candidate, origin); |
720 if (!connection) | 718 if (!connection) |
721 return false; | 719 return false; |
722 | 720 |
723 AddConnection(connection); | 721 AddConnection(connection); |
724 | 722 |
725 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" | 723 LOG_J(LS_INFO, this) << "Created connection with origin=" << origin << ", (" |
726 << connections_.size() << " total)"; | 724 << connections_.size() << " total)"; |
727 } | 725 } |
728 | 726 |
| 727 // If we are readable, it is because we are creating this in response to a |
| 728 // ping from the other side. This will cause the state to become readable. |
| 729 if (readable) |
| 730 connection->ReceivedPing(); |
| 731 |
729 return true; | 732 return true; |
730 } | 733 } |
731 | 734 |
732 bool P2PTransportChannel::FindConnection( | 735 bool P2PTransportChannel::FindConnection( |
733 cricket::Connection* connection) const { | 736 cricket::Connection* connection) const { |
734 std::vector<Connection*>::const_iterator citer = | 737 std::vector<Connection*>::const_iterator citer = |
735 std::find(connections_.begin(), connections_.end(), connection); | 738 std::find(connections_.begin(), connections_.end(), connection); |
736 return citer != connections_.end(); | 739 return citer != connections_.end(); |
737 } | 740 } |
738 | 741 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
843 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { | 846 bool P2PTransportChannel::GetStats(ConnectionInfos *infos) { |
844 ASSERT(worker_thread_ == rtc::Thread::Current()); | 847 ASSERT(worker_thread_ == rtc::Thread::Current()); |
845 // Gather connection infos. | 848 // Gather connection infos. |
846 infos->clear(); | 849 infos->clear(); |
847 | 850 |
848 std::vector<Connection *>::const_iterator it; | 851 std::vector<Connection *>::const_iterator it; |
849 for (it = connections_.begin(); it != connections_.end(); ++it) { | 852 for (it = connections_.begin(); it != connections_.end(); ++it) { |
850 Connection *connection = *it; | 853 Connection *connection = *it; |
851 ConnectionInfo info; | 854 ConnectionInfo info; |
852 info.best_connection = (best_connection_ == connection); | 855 info.best_connection = (best_connection_ == connection); |
853 info.receiving = connection->receiving(); | 856 info.readable = |
| 857 (connection->read_state() == Connection::STATE_READABLE); |
854 info.writable = | 858 info.writable = |
855 (connection->write_state() == Connection::STATE_WRITABLE); | 859 (connection->write_state() == Connection::STATE_WRITABLE); |
856 info.timeout = | 860 info.timeout = |
857 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); | 861 (connection->write_state() == Connection::STATE_WRITE_TIMEOUT); |
858 info.new_connection = !connection->reported(); | 862 info.new_connection = !connection->reported(); |
859 connection->set_reported(true); | 863 connection->set_reported(true); |
860 info.rtt = connection->rtt(); | 864 info.rtt = connection->rtt(); |
861 info.sent_total_bytes = connection->sent_total_bytes(); | 865 info.sent_total_bytes = connection->sent_total_bytes(); |
862 info.sent_bytes_second = connection->sent_bytes_second(); | 866 info.sent_bytes_second = connection->sent_bytes_second(); |
863 info.sent_discarded_packets = connection->sent_discarded_packets(); | 867 info.sent_discarded_packets = connection->sent_discarded_packets(); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 Connection* old_best_connection = best_connection_; | 1022 Connection* old_best_connection = best_connection_; |
1019 best_connection_ = conn; | 1023 best_connection_ = conn; |
1020 if (best_connection_) { | 1024 if (best_connection_) { |
1021 if (old_best_connection) { | 1025 if (old_best_connection) { |
1022 LOG_J(LS_INFO, this) << "Previous best connection: " | 1026 LOG_J(LS_INFO, this) << "Previous best connection: " |
1023 << old_best_connection->ToString(); | 1027 << old_best_connection->ToString(); |
1024 } | 1028 } |
1025 LOG_J(LS_INFO, this) << "New best connection: " | 1029 LOG_J(LS_INFO, this) << "New best connection: " |
1026 << best_connection_->ToString(); | 1030 << best_connection_->ToString(); |
1027 SignalRouteChange(this, best_connection_->remote_candidate()); | 1031 SignalRouteChange(this, best_connection_->remote_candidate()); |
1028 set_receiving(best_connection_->receiving()); | 1032 // When it just switched to a best connection, set receiving to true. |
| 1033 set_receiving(true); |
1029 } else { | 1034 } else { |
1030 LOG_J(LS_INFO, this) << "No best connection"; | 1035 LOG_J(LS_INFO, this) << "No best connection"; |
1031 } | 1036 } |
1032 } | 1037 } |
1033 | 1038 |
1034 void P2PTransportChannel::UpdateChannelState() { | 1039 void P2PTransportChannel::UpdateChannelState() { |
1035 // The Handle* functions already set the writable state. We'll just double- | 1040 // The Handle* functions already set the writable state. We'll just double- |
1036 // check it here. | 1041 // check it here. |
1037 bool writable = ((best_connection_ != NULL) && | 1042 bool writable = ((best_connection_ != NULL) && |
1038 (best_connection_->write_state() == | 1043 (best_connection_->write_state() == |
1039 Connection::STATE_WRITABLE)); | 1044 Connection::STATE_WRITABLE)); |
1040 ASSERT(writable == this->writable()); | 1045 ASSERT(writable == this->writable()); |
1041 if (writable != this->writable()) | 1046 if (writable != this->writable()) |
1042 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; | 1047 LOG(LS_ERROR) << "UpdateChannelState: writable state mismatch"; |
1043 | 1048 |
1044 // TODO(honghaiz): The channel receiving state is set in OnCheckReceiving. | 1049 bool readable = false; |
1045 // Will revisit in a subsequent code change. | 1050 for (uint32 i = 0; i < connections_.size(); ++i) { |
| 1051 if (connections_[i]->read_state() == Connection::STATE_READABLE) { |
| 1052 readable = true; |
| 1053 break; |
| 1054 } |
| 1055 } |
| 1056 set_readable(readable); |
1046 } | 1057 } |
1047 | 1058 |
1048 // We checked the status of our connections and we had at least one that | 1059 // We checked the status of our connections and we had at least one that |
1049 // was writable, go into the writable state. | 1060 // was writable, go into the writable state. |
1050 void P2PTransportChannel::HandleWritable() { | 1061 void P2PTransportChannel::HandleWritable() { |
1051 ASSERT(worker_thread_ == rtc::Thread::Current()); | 1062 ASSERT(worker_thread_ == rtc::Thread::Current()); |
1052 if (!writable()) { | 1063 if (!writable()) { |
1053 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { | 1064 for (uint32 i = 0; i < allocator_sessions_.size(); ++i) { |
1054 if (allocator_sessions_[i]->IsGettingPorts()) { | 1065 if (allocator_sessions_[i]->IsGettingPorts()) { |
1055 allocator_sessions_[i]->StopGettingPorts(); | 1066 allocator_sessions_[i]->StopGettingPorts(); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 Connection* conn = FindNextPingableConnection(); | 1137 Connection* conn = FindNextPingableConnection(); |
1127 if (conn) | 1138 if (conn) |
1128 PingConnection(conn); | 1139 PingConnection(conn); |
1129 | 1140 |
1130 // Post ourselves a message to perform the next ping. | 1141 // Post ourselves a message to perform the next ping. |
1131 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; | 1142 uint32 delay = writable() ? WRITABLE_DELAY : UNWRITABLE_DELAY; |
1132 thread()->PostDelayed(delay, this, MSG_PING); | 1143 thread()->PostDelayed(delay, this, MSG_PING); |
1133 } | 1144 } |
1134 | 1145 |
1135 void P2PTransportChannel::OnCheckReceiving() { | 1146 void P2PTransportChannel::OnCheckReceiving() { |
1136 if (best_connection_) { | 1147 // Check receiving only if the best connection has received data packets |
| 1148 // because we want to detect not receiving any packets only after the media |
| 1149 // have started flowing. |
| 1150 if (best_connection_ && best_connection_->recv_total_bytes() > 0) { |
1137 bool receiving = rtc::Time() <= | 1151 bool receiving = rtc::Time() <= |
1138 best_connection_->last_received() + receiving_timeout_; | 1152 best_connection_->last_received() + receiving_timeout_; |
1139 set_receiving(receiving); | 1153 set_receiving(receiving); |
1140 } | 1154 } |
1141 | 1155 |
1142 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); | 1156 thread()->PostDelayed(check_receiving_delay_, this, MSG_CHECK_RECEIVING); |
1143 } | 1157 } |
1144 | 1158 |
1145 // Is the connection in a state for us to even consider pinging the other side? | 1159 // Is the connection in a state for us to even consider pinging the other side? |
1146 // We consider a connection pingable even if it's not connected because that's | 1160 // We consider a connection pingable even if it's not connected because that's |
1147 // how a TCP connection is kicked into reconnecting on the active side. | 1161 // how a TCP connection is kicked into reconnecting on the active side. |
1148 bool P2PTransportChannel::IsPingable(Connection* conn) { | 1162 bool P2PTransportChannel::IsPingable(Connection* conn) { |
1149 const Candidate& remote = conn->remote_candidate(); | 1163 const Candidate& remote = conn->remote_candidate(); |
1150 // We should never get this far with an empty remote ufrag. | 1164 // We should never get this far with an empty remote ufrag. |
1151 ASSERT(!remote.username().empty()); | 1165 ASSERT(!remote.username().empty()); |
1152 if (remote.username().empty() || remote.password().empty()) { | 1166 if (remote.username().empty() || remote.password().empty()) { |
1153 // If we don't have an ICE ufrag and pwd, there's no way we can ping. | 1167 // If we don't have an ICE ufrag and pwd, there's no way we can ping. |
1154 return false; | 1168 return false; |
1155 } | 1169 } |
1156 | 1170 |
1157 // An never connected connection cannot be written to at all, so pinging is | 1171 // An never connected connection cannot be written to at all, so pinging is |
1158 // out of the question. However, if it has become WRITABLE, it is in the | 1172 // out of the question. However, if it has become WRITABLE, it is in the |
1159 // reconnecting state so ping is needed. | 1173 // reconnecting state so ping is needed. |
1160 if (!conn->connected() && !conn->writable()) { | 1174 if (!conn->connected() && conn->write_state() != Connection::STATE_WRITABLE) { |
1161 return false; | 1175 return false; |
1162 } | 1176 } |
1163 | 1177 |
1164 // If the channel is not writable, ping all candidates. Otherwise, we only | 1178 if (writable()) { |
1165 // want to ping connections that have not timed out on writing. | 1179 // If we are writable, then we only want to ping connections that could be |
1166 return !writable() || conn->write_state() != Connection::STATE_WRITE_TIMEOUT; | 1180 // better than this one, i.e., the ones that were not pruned. |
| 1181 return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT); |
| 1182 } else { |
| 1183 // If we are not writable, then we need to try everything that might work. |
| 1184 // This includes both connections that do not have write timeout as well as |
| 1185 // ones that do not have read timeout. A connection could be readable but |
| 1186 // be in write-timeout if we pruned it before. Since the other side is |
| 1187 // still pinging it, it very well might still work. |
| 1188 return (conn->write_state() != Connection::STATE_WRITE_TIMEOUT) || |
| 1189 (conn->read_state() != Connection::STATE_READ_TIMEOUT); |
| 1190 } |
1167 } | 1191 } |
1168 | 1192 |
1169 // Returns the next pingable connection to ping. This will be the oldest | 1193 // Returns the next pingable connection to ping. This will be the oldest |
1170 // pingable connection unless we have a connected, writable connection that is | 1194 // pingable connection unless we have a connected, writable connection that is |
1171 // past the maximum acceptable ping delay. When reconnecting a TCP connection, | 1195 // past the maximum acceptable ping delay. When reconnecting a TCP connection, |
1172 // the best connection is disconnected, although still WRITABLE while | 1196 // the best connection is disconnected, although still WRITABLE while |
1173 // reconnecting. The newly created connection should be selected as the ping | 1197 // reconnecting. The newly created connection should be selected as the ping |
1174 // target to become writable instead. See the big comment in CompareConnections. | 1198 // target to become writable instead. See the big comment in CompareConnections. |
1175 Connection* P2PTransportChannel::FindNextPingableConnection() { | 1199 Connection* P2PTransportChannel::FindNextPingableConnection() { |
1176 uint32 now = rtc::Time(); | 1200 uint32 now = rtc::Time(); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 } | 1355 } |
1332 } | 1356 } |
1333 | 1357 |
1334 void P2PTransportChannel::OnReadyToSend(Connection* connection) { | 1358 void P2PTransportChannel::OnReadyToSend(Connection* connection) { |
1335 if (connection == best_connection_ && writable()) { | 1359 if (connection == best_connection_ && writable()) { |
1336 SignalReadyToSend(this); | 1360 SignalReadyToSend(this); |
1337 } | 1361 } |
1338 } | 1362 } |
1339 | 1363 |
1340 } // namespace cricket | 1364 } // namespace cricket |
OLD | NEW |