| 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 |