OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/quic/core/quic_connection.h" | 5 #include "net/quic/core/quic_connection.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 #include <sys/types.h> | 8 #include <sys/types.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 672 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
683 } | 683 } |
684 | 684 |
685 // Only migrate connection to a new peer address if a change is not underway. | 685 // Only migrate connection to a new peer address if a change is not underway. |
686 PeerAddressChangeType peer_migration_type = | 686 PeerAddressChangeType peer_migration_type = |
687 QuicUtils::DetermineAddressChangeType(peer_address_, | 687 QuicUtils::DetermineAddressChangeType(peer_address_, |
688 last_packet_source_address_); | 688 last_packet_source_address_); |
689 // Do not migrate connection if the changed address packet is a reordered | 689 // Do not migrate connection if the changed address packet is a reordered |
690 // packet. | 690 // packet. |
691 if (active_peer_migration_type_ == NO_CHANGE && | 691 if (active_peer_migration_type_ == NO_CHANGE && |
692 peer_migration_type != NO_CHANGE && | 692 peer_migration_type != NO_CHANGE && |
693 (!FLAGS_quic_do_not_migrate_on_old_packet || | 693 header.packet_number > received_packet_manager_.GetLargestObserved()) { |
694 header.packet_number > received_packet_manager_.GetLargestObserved())) { | |
695 StartPeerMigration(header.path_id, peer_migration_type); | 694 StartPeerMigration(header.path_id, peer_migration_type); |
696 } | 695 } |
697 | 696 |
698 --stats_.packets_dropped; | 697 --stats_.packets_dropped; |
699 DVLOG(1) << ENDPOINT << "Received packet header: " << header; | 698 DVLOG(1) << ENDPOINT << "Received packet header: " << header; |
700 last_header_ = header; | 699 last_header_ = header; |
701 DCHECK(connected_); | 700 DCHECK(connected_); |
702 return true; | 701 return true; |
703 } | 702 } |
704 | 703 |
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 // Now that we have received an ack, we might be able to send packets which | 1160 // Now that we have received an ack, we might be able to send packets which |
1162 // are queued locally, or drain streams which are blocked. | 1161 // are queued locally, or drain streams which are blocked. |
1163 if (defer_send_in_response_to_packets_) { | 1162 if (defer_send_in_response_to_packets_) { |
1164 send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero()); | 1163 send_alarm_->Update(clock_->ApproximateNow(), QuicTime::Delta::Zero()); |
1165 } else { | 1164 } else { |
1166 WriteAndBundleAcksIfNotBlocked(); | 1165 WriteAndBundleAcksIfNotBlocked(); |
1167 } | 1166 } |
1168 } | 1167 } |
1169 | 1168 |
1170 void QuicConnection::SendVersionNegotiationPacket() { | 1169 void QuicConnection::SendVersionNegotiationPacket() { |
1171 // TODO(alyssar): implement zero server state negotiation. | |
1172 pending_version_negotiation_packet_ = true; | 1170 pending_version_negotiation_packet_ = true; |
1173 if (writer_->IsWriteBlocked()) { | 1171 if (writer_->IsWriteBlocked()) { |
1174 visitor_->OnWriteBlocked(); | 1172 visitor_->OnWriteBlocked(); |
1175 return; | 1173 return; |
1176 } | 1174 } |
1177 DVLOG(1) << ENDPOINT << "Sending version negotiation packet: {" | 1175 DVLOG(1) << ENDPOINT << "Sending version negotiation packet: {" |
1178 << QuicVersionVectorToString(framer_.supported_versions()) << "}"; | 1176 << QuicVersionVectorToString(framer_.supported_versions()) << "}"; |
1179 std::unique_ptr<QuicEncryptedPacket> version_packet( | 1177 std::unique_ptr<QuicEncryptedPacket> version_packet( |
1180 packet_generator_.SerializeVersionNegotiationPacket( | 1178 packet_generator_.SerializeVersionNegotiationPacket( |
1181 framer_.supported_versions())); | 1179 framer_.supported_versions())); |
(...skipping 1118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2300 } | 2298 } |
2301 | 2299 |
2302 QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() { | 2300 QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() { |
2303 if (connection_ == nullptr) { | 2301 if (connection_ == nullptr) { |
2304 return; | 2302 return; |
2305 } | 2303 } |
2306 // If we changed the generator's batch state, restore original batch state. | 2304 // If we changed the generator's batch state, restore original batch state. |
2307 if (!already_in_batch_mode_) { | 2305 if (!already_in_batch_mode_) { |
2308 DVLOG(2) << "Leaving Batch Mode."; | 2306 DVLOG(2) << "Leaving Batch Mode."; |
2309 connection_->packet_generator_.FinishBatchOperations(); | 2307 connection_->packet_generator_.FinishBatchOperations(); |
| 2308 |
| 2309 // Once all transmissions are done, check if there is any outstanding data |
| 2310 // to send and notify the congestion controller if not. |
| 2311 // |
| 2312 // Note that this means that the application limited check will happen as |
| 2313 // soon as the last bundler gets destroyed, which is typically after a |
| 2314 // single stream write is finished. This means that if all the data from a |
| 2315 // single write goes through the connection, the application-limited signal |
| 2316 // will fire even if the caller does a write operation immediately after. |
| 2317 // There are two important approaches to remedy this situation: |
| 2318 // (1) Instantiate ScopedPacketBundler before performing multiple subsequent |
| 2319 // writes, thus deferring this check until all writes are done. |
| 2320 // (2) Write data in chunks sufficiently large so that they cause the |
| 2321 // connection to be limited by the congestion control. Typically, this |
| 2322 // would mean writing chunks larger than the product of the current |
| 2323 // pacing rate and the pacer granularity. So, for instance, if the |
| 2324 // pacing rate of the connection is 1 Gbps, and the pacer granularity is |
| 2325 // 1 ms, the caller should send at least 125k bytes in order to not |
| 2326 // be marked as application-limited. |
| 2327 if (FLAGS_quic_enable_app_limited_check) { |
| 2328 connection_->CheckIfApplicationLimited(); |
| 2329 } |
2310 } | 2330 } |
2311 DCHECK_EQ(already_in_batch_mode_, | 2331 DCHECK_EQ(already_in_batch_mode_, |
2312 connection_->packet_generator_.InBatchMode()); | 2332 connection_->packet_generator_.InBatchMode()); |
2313 } | 2333 } |
2314 | 2334 |
2315 QuicConnection::ScopedRetransmissionScheduler::ScopedRetransmissionScheduler( | 2335 QuicConnection::ScopedRetransmissionScheduler::ScopedRetransmissionScheduler( |
2316 QuicConnection* connection) | 2336 QuicConnection* connection) |
2317 : connection_(connection), | 2337 : connection_(connection), |
2318 already_delayed_(connection_->delay_setting_retransmission_alarm_) { | 2338 already_delayed_(connection_->delay_setting_retransmission_alarm_) { |
2319 connection_->delay_setting_retransmission_alarm_ = true; | 2339 connection_->delay_setting_retransmission_alarm_ = true; |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2516 // There may be a value in making this delay adaptive with the help of | 2536 // There may be a value in making this delay adaptive with the help of |
2517 // the sender and a signaling mechanism -- if the sender uses a | 2537 // the sender and a signaling mechanism -- if the sender uses a |
2518 // different MinRTO, we may get spurious retransmissions. May not have | 2538 // different MinRTO, we may get spurious retransmissions. May not have |
2519 // any benefits, but if the delayed ack becomes a significant source | 2539 // any benefits, but if the delayed ack becomes a significant source |
2520 // of (likely, tail) latency, then consider such a mechanism. | 2540 // of (likely, tail) latency, then consider such a mechanism. |
2521 const QuicTime::Delta QuicConnection::DelayedAckTime() { | 2541 const QuicTime::Delta QuicConnection::DelayedAckTime() { |
2522 return QuicTime::Delta::FromMilliseconds( | 2542 return QuicTime::Delta::FromMilliseconds( |
2523 min(kMaxDelayedAckTimeMs, kMinRetransmissionTimeMs / 2)); | 2543 min(kMaxDelayedAckTimeMs, kMinRetransmissionTimeMs / 2)); |
2524 } | 2544 } |
2525 | 2545 |
| 2546 void QuicConnection::CheckIfApplicationLimited() { |
| 2547 if (queued_packets_.empty() && |
| 2548 !sent_packet_manager_->HasPendingRetransmissions() && |
| 2549 !visitor_->WillingAndAbleToWrite()) { |
| 2550 sent_packet_manager_->OnApplicationLimited(); |
| 2551 } |
| 2552 } |
| 2553 |
2526 } // namespace net | 2554 } // namespace net |
OLD | NEW |