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/quic_connection.h" | 5 #include "net/quic/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 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1098 // SHLO from the server, leading to two different decrypters at the server.) | 1098 // SHLO from the server, leading to two different decrypters at the server.) |
1099 // | 1099 // |
1100 // TODO(jri): Note that ConsumeData may cause a response packet to be sent. | 1100 // TODO(jri): Note that ConsumeData may cause a response packet to be sent. |
1101 // We may end up sending stale ack information if there are undecryptable | 1101 // We may end up sending stale ack information if there are undecryptable |
1102 // packets hanging around and/or there are revivable packets which may get | 1102 // packets hanging around and/or there are revivable packets which may get |
1103 // handled after this packet is sent. Change ScopedPacketBundler to do the | 1103 // handled after this packet is sent. Change ScopedPacketBundler to do the |
1104 // right thing: check ack_queued_, and then check undecryptable packets and | 1104 // right thing: check ack_queued_, and then check undecryptable packets and |
1105 // also if there is possibility of revival. Only bundle an ack if there's no | 1105 // also if there is possibility of revival. Only bundle an ack if there's no |
1106 // processing left that may cause received_info_ to change. | 1106 // processing left that may cause received_info_ to change. |
1107 ScopedRetransmissionScheduler alarm_delayer(this); | 1107 ScopedRetransmissionScheduler alarm_delayer(this); |
1108 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1108 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1109 return packet_generator_.ConsumeData(id, iov, offset, fin, listener); | 1109 return packet_generator_.ConsumeData(id, iov, offset, fin, listener); |
1110 } | 1110 } |
1111 | 1111 |
1112 void QuicConnection::SendRstStream(QuicStreamId id, | 1112 void QuicConnection::SendRstStream(QuicStreamId id, |
1113 QuicRstStreamErrorCode error, | 1113 QuicRstStreamErrorCode error, |
1114 QuicStreamOffset bytes_written) { | 1114 QuicStreamOffset bytes_written) { |
1115 // Opportunistically bundle an ack with this outgoing packet. | 1115 // Opportunistically bundle an ack with this outgoing packet. |
1116 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1116 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1117 packet_generator_.AddControlFrame(QuicFrame(new QuicRstStreamFrame( | 1117 packet_generator_.AddControlFrame(QuicFrame(new QuicRstStreamFrame( |
1118 id, AdjustErrorForVersion(error, version()), bytes_written))); | 1118 id, AdjustErrorForVersion(error, version()), bytes_written))); |
1119 | 1119 |
1120 if (error == QUIC_STREAM_NO_ERROR && version() > QUIC_VERSION_28) { | 1120 if (error == QUIC_STREAM_NO_ERROR && version() > QUIC_VERSION_28) { |
1121 // All data for streams which are reset with QUIC_STREAM_NO_ERROR must | 1121 // All data for streams which are reset with QUIC_STREAM_NO_ERROR must |
1122 // be received by the peer. | 1122 // be received by the peer. |
1123 return; | 1123 return; |
1124 } | 1124 } |
1125 | 1125 |
1126 sent_packet_manager_.CancelRetransmissionsForStream(id); | 1126 sent_packet_manager_.CancelRetransmissionsForStream(id); |
(...skipping 13 matching lines...) Expand all Loading... |
1140 } | 1140 } |
1141 delete[] packet_iterator->encrypted_buffer; | 1141 delete[] packet_iterator->encrypted_buffer; |
1142 QuicUtils::ClearSerializedPacket(&(*packet_iterator)); | 1142 QuicUtils::ClearSerializedPacket(&(*packet_iterator)); |
1143 packet_iterator = queued_packets_.erase(packet_iterator); | 1143 packet_iterator = queued_packets_.erase(packet_iterator); |
1144 } | 1144 } |
1145 } | 1145 } |
1146 | 1146 |
1147 void QuicConnection::SendWindowUpdate(QuicStreamId id, | 1147 void QuicConnection::SendWindowUpdate(QuicStreamId id, |
1148 QuicStreamOffset byte_offset) { | 1148 QuicStreamOffset byte_offset) { |
1149 // Opportunistically bundle an ack with this outgoing packet. | 1149 // Opportunistically bundle an ack with this outgoing packet. |
1150 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1150 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1151 packet_generator_.AddControlFrame( | 1151 packet_generator_.AddControlFrame( |
1152 QuicFrame(new QuicWindowUpdateFrame(id, byte_offset))); | 1152 QuicFrame(new QuicWindowUpdateFrame(id, byte_offset))); |
1153 } | 1153 } |
1154 | 1154 |
1155 void QuicConnection::SendBlocked(QuicStreamId id) { | 1155 void QuicConnection::SendBlocked(QuicStreamId id) { |
1156 // Opportunistically bundle an ack with this outgoing packet. | 1156 // Opportunistically bundle an ack with this outgoing packet. |
1157 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1157 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1158 packet_generator_.AddControlFrame(QuicFrame(new QuicBlockedFrame(id))); | 1158 packet_generator_.AddControlFrame(QuicFrame(new QuicBlockedFrame(id))); |
1159 } | 1159 } |
1160 | 1160 |
1161 void QuicConnection::SendPathClose(QuicPathId path_id) { | 1161 void QuicConnection::SendPathClose(QuicPathId path_id) { |
1162 // Opportunistically bundle an ack with this outgoing packet. | 1162 // Opportunistically bundle an ack with this outgoing packet. |
1163 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1163 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1164 packet_generator_.AddControlFrame(QuicFrame(new QuicPathCloseFrame(path_id))); | 1164 packet_generator_.AddControlFrame(QuicFrame(new QuicPathCloseFrame(path_id))); |
1165 OnPathClosed(path_id); | 1165 OnPathClosed(path_id); |
1166 } | 1166 } |
1167 | 1167 |
1168 const QuicConnectionStats& QuicConnection::GetStats() { | 1168 const QuicConnectionStats& QuicConnection::GetStats() { |
1169 const RttStats* rtt_stats = sent_packet_manager_.GetRttStats(); | 1169 const RttStats* rtt_stats = sent_packet_manager_.GetRttStats(); |
1170 | 1170 |
1171 // Update rtt and estimated bandwidth. | 1171 // Update rtt and estimated bandwidth. |
1172 QuicTime::Delta min_rtt = rtt_stats->min_rtt(); | 1172 QuicTime::Delta min_rtt = rtt_stats->min_rtt(); |
1173 if (min_rtt.IsZero()) { | 1173 if (min_rtt.IsZero()) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1278 WritePendingRetransmissions(); | 1278 WritePendingRetransmissions(); |
1279 | 1279 |
1280 // Sending queued packets may have caused the socket to become write blocked, | 1280 // Sending queued packets may have caused the socket to become write blocked, |
1281 // or the congestion manager to prohibit sending. If we've sent everything | 1281 // or the congestion manager to prohibit sending. If we've sent everything |
1282 // we had queued and we're still not blocked, let the visitor know it can | 1282 // we had queued and we're still not blocked, let the visitor know it can |
1283 // write more. | 1283 // write more. |
1284 if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) { | 1284 if (!CanWrite(HAS_RETRANSMITTABLE_DATA)) { |
1285 return; | 1285 return; |
1286 } | 1286 } |
1287 | 1287 |
1288 { // Limit the scope of the bundler. ACK inclusion happens elsewhere. | 1288 { |
1289 ScopedPacketBundler bundler(this, NO_ACK); | 1289 ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED); |
1290 visitor_->OnCanWrite(); | 1290 visitor_->OnCanWrite(); |
1291 visitor_->PostProcessAfterData(); | 1291 visitor_->PostProcessAfterData(); |
1292 } | 1292 } |
1293 | 1293 |
1294 // After the visitor writes, it may have caused the socket to become write | 1294 // After the visitor writes, it may have caused the socket to become write |
1295 // blocked or the congestion manager to prohibit sending, so check again. | 1295 // blocked or the congestion manager to prohibit sending, so check again. |
1296 if (visitor_->WillingAndAbleToWrite() && !resume_writes_alarm_->IsSet() && | 1296 if (visitor_->WillingAndAbleToWrite() && !resume_writes_alarm_->IsSet() && |
1297 CanWrite(HAS_RETRANSMITTABLE_DATA)) { | 1297 CanWrite(HAS_RETRANSMITTABLE_DATA)) { |
1298 // We're not write blocked, but some stream didn't write out all of its | 1298 // We're not write blocked, but some stream didn't write out all of its |
1299 // bytes. Register for 'immediate' resumption so we'll keep writing after | 1299 // bytes. Register for 'immediate' resumption so we'll keep writing after |
1300 // other connections and events have had a chance to use the thread. | 1300 // other connections and events have had a chance to use the thread. |
1301 resume_writes_alarm_->Set(clock_->ApproximateNow()); | 1301 resume_writes_alarm_->Set(clock_->ApproximateNow()); |
1302 } | 1302 } |
1303 } | 1303 } |
1304 | 1304 |
1305 void QuicConnection::WriteIfNotBlocked() { | 1305 void QuicConnection::WriteIfNotBlocked() { |
1306 if (!writer_->IsWriteBlocked()) { | 1306 if (!writer_->IsWriteBlocked()) { |
1307 OnCanWrite(); | 1307 OnCanWrite(); |
1308 } | 1308 } |
1309 } | 1309 } |
1310 | 1310 |
1311 void QuicConnection::WriteAndBundleAcksIfNotBlocked() { | 1311 void QuicConnection::WriteAndBundleAcksIfNotBlocked() { |
1312 if (!writer_->IsWriteBlocked()) { | 1312 if (!writer_->IsWriteBlocked()) { |
1313 ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK); | 1313 ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED); |
1314 OnCanWrite(); | 1314 OnCanWrite(); |
1315 } | 1315 } |
1316 } | 1316 } |
1317 | 1317 |
1318 bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { | 1318 bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) { |
1319 if (header.fec_flag) { | 1319 if (header.fec_flag) { |
1320 // Drop any FEC packet. | 1320 // Drop any FEC packet. |
1321 return false; | 1321 return false; |
1322 } | 1322 } |
1323 | 1323 |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1753 } | 1753 } |
1754 } | 1754 } |
1755 | 1755 |
1756 void QuicConnection::OnPingTimeout() { | 1756 void QuicConnection::OnPingTimeout() { |
1757 if (!retransmission_alarm_->IsSet()) { | 1757 if (!retransmission_alarm_->IsSet()) { |
1758 SendPing(); | 1758 SendPing(); |
1759 } | 1759 } |
1760 } | 1760 } |
1761 | 1761 |
1762 void QuicConnection::SendPing() { | 1762 void QuicConnection::SendPing() { |
1763 ScopedPacketBundler bundler(this, ack_queued_ ? SEND_ACK : NO_ACK); | 1763 ScopedPacketBundler bundler(this, SEND_ACK_IF_QUEUED); |
1764 packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame())); | 1764 packet_generator_.AddControlFrame(QuicFrame(QuicPingFrame())); |
1765 // Send PING frame immediately, without checking for congestion window bounds. | 1765 // Send PING frame immediately, without checking for congestion window bounds. |
1766 packet_generator_.FlushAllQueuedFrames(); | 1766 packet_generator_.FlushAllQueuedFrames(); |
1767 } | 1767 } |
1768 | 1768 |
1769 void QuicConnection::SendAck() { | 1769 void QuicConnection::SendAck() { |
1770 ack_alarm_->Cancel(); | 1770 ack_alarm_->Cancel(); |
1771 ack_queued_ = false; | 1771 ack_queued_ = false; |
1772 stop_waiting_count_ = 0; | 1772 stop_waiting_count_ = 0; |
1773 num_retransmittable_packets_received_since_last_ack_sent_ = 0; | 1773 num_retransmittable_packets_received_since_last_ack_sent_ = 0; |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1949 const string& reason) { | 1949 const string& reason) { |
1950 if (goaway_sent_) { | 1950 if (goaway_sent_) { |
1951 return; | 1951 return; |
1952 } | 1952 } |
1953 goaway_sent_ = true; | 1953 goaway_sent_ = true; |
1954 | 1954 |
1955 DVLOG(1) << ENDPOINT << "Going away with error " | 1955 DVLOG(1) << ENDPOINT << "Going away with error " |
1956 << QuicUtils::ErrorToString(error) << " (" << error << ")"; | 1956 << QuicUtils::ErrorToString(error) << " (" << error << ")"; |
1957 | 1957 |
1958 // Opportunistically bundle an ack with this outgoing packet. | 1958 // Opportunistically bundle an ack with this outgoing packet. |
1959 ScopedPacketBundler ack_bundler(this, BUNDLE_PENDING_ACK); | 1959 ScopedPacketBundler ack_bundler(this, SEND_ACK_IF_PENDING); |
1960 packet_generator_.AddControlFrame( | 1960 packet_generator_.AddControlFrame( |
1961 QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason))); | 1961 QuicFrame(new QuicGoAwayFrame(error, last_good_stream_id, reason))); |
1962 } | 1962 } |
1963 | 1963 |
1964 QuicByteCount QuicConnection::max_packet_length() const { | 1964 QuicByteCount QuicConnection::max_packet_length() const { |
1965 return packet_generator_.GetCurrentMaxPacketLength(); | 1965 return packet_generator_.GetCurrentMaxPacketLength(); |
1966 } | 1966 } |
1967 | 1967 |
1968 void QuicConnection::SetMaxPacketLength(QuicByteCount length) { | 1968 void QuicConnection::SetMaxPacketLength(QuicByteCount length) { |
1969 return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length)); | 1969 return packet_generator_.SetMaxPacketLength(LimitMaxPacketSize(length)); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2114 | 2114 |
2115 if (packet_number_of_last_sent_packet_ >= next_mtu_probe_at_) { | 2115 if (packet_number_of_last_sent_packet_ >= next_mtu_probe_at_) { |
2116 // Use an alarm to send the MTU probe to ensure that no ScopedPacketBundlers | 2116 // Use an alarm to send the MTU probe to ensure that no ScopedPacketBundlers |
2117 // are active. | 2117 // are active. |
2118 mtu_discovery_alarm_->Set(clock_->ApproximateNow()); | 2118 mtu_discovery_alarm_->Set(clock_->ApproximateNow()); |
2119 } | 2119 } |
2120 } | 2120 } |
2121 | 2121 |
2122 QuicConnection::ScopedPacketBundler::ScopedPacketBundler( | 2122 QuicConnection::ScopedPacketBundler::ScopedPacketBundler( |
2123 QuicConnection* connection, | 2123 QuicConnection* connection, |
2124 AckBundling send_ack) | 2124 AckBundling ack_mode) |
2125 : connection_(connection), | 2125 : connection_(connection), |
2126 already_in_batch_mode_(connection != nullptr && | 2126 already_in_batch_mode_(connection != nullptr && |
2127 connection->packet_generator_.InBatchMode()) { | 2127 connection->packet_generator_.InBatchMode()) { |
2128 if (connection_ == nullptr) { | 2128 if (connection_ == nullptr) { |
2129 return; | 2129 return; |
2130 } | 2130 } |
2131 // Move generator into batch mode. If caller wants us to include an ack, | 2131 // Move generator into batch mode. If caller wants us to include an ack, |
2132 // check the delayed-ack timer to see if there's ack info to be sent. | 2132 // check the delayed-ack timer to see if there's ack info to be sent. |
2133 if (!already_in_batch_mode_) { | 2133 if (!already_in_batch_mode_) { |
2134 DVLOG(1) << "Entering Batch Mode."; | 2134 DVLOG(1) << "Entering Batch Mode."; |
2135 connection_->packet_generator_.StartBatchOperations(); | 2135 connection_->packet_generator_.StartBatchOperations(); |
2136 } | 2136 } |
2137 // Bundle an ack if the alarm is set or with every second packet if we need to | 2137 if (ShouldSendAck(ack_mode)) { |
2138 // raise the peer's least unacked. | |
2139 bool ack_pending = | |
2140 connection_->ack_alarm_->IsSet() || connection_->stop_waiting_count_ > 1; | |
2141 if (send_ack == SEND_ACK || (send_ack == BUNDLE_PENDING_ACK && ack_pending)) { | |
2142 DVLOG(1) << "Bundling ack with outgoing packet."; | 2138 DVLOG(1) << "Bundling ack with outgoing packet."; |
2143 DCHECK(send_ack == SEND_ACK || connection_->ack_frame_updated() || | 2139 DCHECK(ack_mode == SEND_ACK || connection_->ack_frame_updated() || |
2144 connection_->stop_waiting_count_ > 1); | 2140 connection_->stop_waiting_count_ > 1); |
2145 connection_->SendAck(); | 2141 connection_->SendAck(); |
2146 } | 2142 } |
2147 } | 2143 } |
2148 | 2144 |
| 2145 bool QuicConnection::ScopedPacketBundler::ShouldSendAck( |
| 2146 AckBundling ack_mode) const { |
| 2147 switch (ack_mode) { |
| 2148 case SEND_ACK: |
| 2149 return true; |
| 2150 case SEND_ACK_IF_QUEUED: |
| 2151 return connection_->ack_queued(); |
| 2152 case SEND_ACK_IF_PENDING: |
| 2153 return connection_->ack_alarm_->IsSet() || |
| 2154 connection_->stop_waiting_count_ > 1; |
| 2155 } |
| 2156 } |
| 2157 |
2149 QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() { | 2158 QuicConnection::ScopedPacketBundler::~ScopedPacketBundler() { |
2150 if (connection_ == nullptr) { | 2159 if (connection_ == nullptr) { |
2151 return; | 2160 return; |
2152 } | 2161 } |
2153 // If we changed the generator's batch state, restore original batch state. | 2162 // If we changed the generator's batch state, restore original batch state. |
2154 if (!already_in_batch_mode_) { | 2163 if (!already_in_batch_mode_) { |
2155 DVLOG(1) << "Leaving Batch Mode."; | 2164 DVLOG(1) << "Leaving Batch Mode."; |
2156 connection_->packet_generator_.FinishBatchOperations(); | 2165 connection_->packet_generator_.FinishBatchOperations(); |
2157 } | 2166 } |
2158 DCHECK_EQ(already_in_batch_mode_, | 2167 DCHECK_EQ(already_in_batch_mode_, |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2327 } | 2336 } |
2328 | 2337 |
2329 StringPiece QuicConnection::GetCurrentPacket() { | 2338 StringPiece QuicConnection::GetCurrentPacket() { |
2330 if (current_packet_data_ == nullptr) { | 2339 if (current_packet_data_ == nullptr) { |
2331 return StringPiece(); | 2340 return StringPiece(); |
2332 } | 2341 } |
2333 return StringPiece(current_packet_data_, last_size_); | 2342 return StringPiece(current_packet_data_, last_size_); |
2334 } | 2343 } |
2335 | 2344 |
2336 } // namespace net | 2345 } // namespace net |
OLD | NEW |