Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(687)

Side by Side Diff: net/quic/quic_packet_generator.cc

Issue 839143002: Roll Chrome into Mojo. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Rebase Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/quic/quic_packet_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_packet_generator.h" 5 #include "net/quic/quic_packet_generator.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "net/quic/quic_ack_notifier.h"
9 #include "net/quic/quic_fec_group.h" 10 #include "net/quic/quic_fec_group.h"
10 #include "net/quic/quic_flags.h" 11 #include "net/quic/quic_flags.h"
11 #include "net/quic/quic_utils.h" 12 #include "net/quic/quic_utils.h"
12 13
13 using base::StringPiece; 14 using base::StringPiece;
14 15
15 namespace net { 16 namespace net {
16 17
17 namespace { 18 namespace {
18 19
19 // We want to put some space between a protected packet and the FEC packet to 20 // We want to put some space between a protected packet and the FEC packet to
20 // avoid losing them both within the same loss episode. On the other hand, 21 // avoid losing them both within the same loss episode. On the other hand,
21 // we expect to be able to recover from any loss in about an RTT. 22 // we expect to be able to recover from any loss in about an RTT.
22 // We resolve this tradeoff by sending an FEC packet atmost half an RTT, 23 // We resolve this tradeoff by sending an FEC packet atmost half an RTT,
23 // or equivalently, half the max number of in-flight packets, the first 24 // or equivalently, half the max number of in-flight packets, the first
24 // protected packet. Since we don't want to delay an FEC packet past half an 25 // protected packet. Since we don't want to delay an FEC packet past half an
25 // RTT, we set the max FEC group size to be half the current congestion window. 26 // RTT, we set the max FEC group size to be half the current congestion window.
26 const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5; 27 const float kMaxPacketsInFlightMultiplierForFecGroupSize = 0.5;
28 const float kRttMultiplierForFecTimeout = 0.5;
27 29
28 } // namespace 30 } // namespace
29 31
30 class QuicAckNotifier; 32 class QuicAckNotifier;
31 33
32 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id, 34 QuicPacketGenerator::QuicPacketGenerator(QuicConnectionId connection_id,
33 QuicFramer* framer, 35 QuicFramer* framer,
34 QuicRandom* random_generator, 36 QuicRandom* random_generator,
35 DelegateInterface* delegate) 37 DelegateInterface* delegate)
36 : delegate_(delegate), 38 : delegate_(delegate),
37 debug_delegate_(nullptr), 39 debug_delegate_(nullptr),
38 packet_creator_(connection_id, framer, random_generator), 40 packet_creator_(connection_id, framer, random_generator),
39 batch_mode_(false), 41 batch_mode_(false),
42 fec_timeout_(QuicTime::Delta::Zero()),
40 should_fec_protect_(false), 43 should_fec_protect_(false),
41 should_send_ack_(false), 44 should_send_ack_(false),
42 should_send_feedback_(false), 45 should_send_feedback_(false),
43 should_send_stop_waiting_(false) {} 46 should_send_stop_waiting_(false) {
47 }
44 48
45 QuicPacketGenerator::~QuicPacketGenerator() { 49 QuicPacketGenerator::~QuicPacketGenerator() {
46 for (QuicFrames::iterator it = queued_control_frames_.begin(); 50 for (QuicFrames::iterator it = queued_control_frames_.begin();
47 it != queued_control_frames_.end(); ++it) { 51 it != queued_control_frames_.end(); ++it) {
48 switch (it->type) { 52 switch (it->type) {
49 case PADDING_FRAME: 53 case PADDING_FRAME:
50 delete it->padding_frame; 54 delete it->padding_frame;
51 break; 55 break;
52 case STREAM_FRAME: 56 case STREAM_FRAME:
53 delete it->stream_frame; 57 delete it->stream_frame;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 } 89 }
86 } 90 }
87 91
88 void QuicPacketGenerator::OnCongestionWindowChange( 92 void QuicPacketGenerator::OnCongestionWindowChange(
89 QuicPacketCount max_packets_in_flight) { 93 QuicPacketCount max_packets_in_flight) {
90 packet_creator_.set_max_packets_per_fec_group( 94 packet_creator_.set_max_packets_per_fec_group(
91 static_cast<size_t>(kMaxPacketsInFlightMultiplierForFecGroupSize * 95 static_cast<size_t>(kMaxPacketsInFlightMultiplierForFecGroupSize *
92 max_packets_in_flight)); 96 max_packets_in_flight));
93 } 97 }
94 98
99 void QuicPacketGenerator::OnRttChange(QuicTime::Delta rtt) {
100 fec_timeout_ = rtt.Multiply(kRttMultiplierForFecTimeout);
101 }
102
95 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback, 103 void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback,
96 bool also_send_stop_waiting) { 104 bool also_send_stop_waiting) {
97 if (FLAGS_quic_disallow_multiple_pending_ack_frames) { 105 if (FLAGS_quic_disallow_multiple_pending_ack_frames) {
98 if (pending_ack_frame_ != nullptr) { 106 if (pending_ack_frame_ != nullptr) {
99 // Ack already queued, nothing to do. 107 // Ack already queued, nothing to do.
100 return; 108 return;
101 } 109 }
102 110
103 if (also_send_feedback && pending_feedback_frame_ != nullptr) { 111 if (also_send_feedback && pending_feedback_frame_ != nullptr) {
104 LOG(DFATAL) << "Should only ever be one pending feedback frame."; 112 LOG(DFATAL) << "Should only ever be one pending feedback frame.";
(...skipping 15 matching lines...) Expand all
120 void QuicPacketGenerator::SetShouldSendStopWaiting() { 128 void QuicPacketGenerator::SetShouldSendStopWaiting() {
121 should_send_stop_waiting_ = true; 129 should_send_stop_waiting_ = true;
122 SendQueuedFrames(false); 130 SendQueuedFrames(false);
123 } 131 }
124 132
125 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) { 133 void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
126 queued_control_frames_.push_back(frame); 134 queued_control_frames_.push_back(frame);
127 SendQueuedFrames(false); 135 SendQueuedFrames(false);
128 } 136 }
129 137
130 QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id, 138 QuicConsumedData QuicPacketGenerator::ConsumeData(
131 const IOVector& data_to_write, 139 QuicStreamId id,
132 QuicStreamOffset offset, 140 const IOVector& data_to_write,
133 bool fin, 141 QuicStreamOffset offset,
134 FecProtection fec_protection, 142 bool fin,
135 QuicAckNotifier* notifier) { 143 FecProtection fec_protection,
144 QuicAckNotifier::DelegateInterface* delegate) {
136 IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE; 145 IsHandshake handshake = id == kCryptoStreamId ? IS_HANDSHAKE : NOT_HANDSHAKE;
137 // To make reasoning about crypto frames easier, we don't combine them with 146 // To make reasoning about crypto frames easier, we don't combine them with
138 // other retransmittable frames in a single packet. 147 // other retransmittable frames in a single packet.
139 const bool flush = handshake == IS_HANDSHAKE && 148 const bool flush = handshake == IS_HANDSHAKE &&
140 packet_creator_.HasPendingRetransmittableFrames(); 149 packet_creator_.HasPendingRetransmittableFrames();
141 SendQueuedFrames(flush); 150 SendQueuedFrames(flush);
142 151
143 size_t total_bytes_consumed = 0; 152 size_t total_bytes_consumed = 0;
144 bool fin_consumed = false; 153 bool fin_consumed = false;
145 154
146 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) { 155 if (!packet_creator_.HasRoomForStreamFrame(id, offset)) {
147 SerializeAndSendPacket(); 156 SerializeAndSendPacket();
148 } 157 }
149 158
150 if (fec_protection == MUST_FEC_PROTECT) { 159 if (fec_protection == MUST_FEC_PROTECT) {
151 MaybeStartFecProtection(); 160 MaybeStartFecProtection();
152 } 161 }
153 162
163 // This notifier will be owned by the AckNotifierManager (or deleted below) if
164 // not attached to a packet.
165 QuicAckNotifier* notifier = nullptr;
166 if (delegate != nullptr) {
167 notifier = new QuicAckNotifier(delegate);
168 }
169
154 IOVector data = data_to_write; 170 IOVector data = data_to_write;
155 size_t data_size = data.TotalBufferSize(); 171 size_t data_size = data.TotalBufferSize();
172 if (FLAGS_quic_empty_data_no_fin_early_return && !fin && (data_size == 0)) {
173 LOG(DFATAL) << "Attempt to consume empty data without FIN.";
174 return QuicConsumedData(0, false);
175 }
176
177 int frames_created = 0;
156 while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION, 178 while (delegate_->ShouldGeneratePacket(NOT_RETRANSMISSION,
157 HAS_RETRANSMITTABLE_DATA, handshake)) { 179 HAS_RETRANSMITTABLE_DATA, handshake)) {
158 QuicFrame frame; 180 QuicFrame frame;
159 size_t bytes_consumed; 181 size_t bytes_consumed = packet_creator_.CreateStreamFrame(
160 if (notifier != nullptr) { 182 id, data, offset + total_bytes_consumed, fin, &frame);
161 // We want to track which packet this stream frame ends up in. 183 ++frames_created;
162 bytes_consumed = packet_creator_.CreateStreamFrameWithNotifier( 184
163 id, data, offset + total_bytes_consumed, fin, notifier, &frame); 185 // We want to track which packet this stream frame ends up in.
164 } else { 186 frame.stream_frame->notifier = notifier;
165 bytes_consumed = packet_creator_.CreateStreamFrame( 187
166 id, data, offset + total_bytes_consumed, fin, &frame);
167 }
168 if (!AddFrame(frame)) { 188 if (!AddFrame(frame)) {
169 LOG(DFATAL) << "Failed to add stream frame."; 189 LOG(DFATAL) << "Failed to add stream frame.";
170 // Inability to add a STREAM frame creates an unrecoverable hole in a 190 // Inability to add a STREAM frame creates an unrecoverable hole in a
171 // the stream, so it's best to close the connection. 191 // the stream, so it's best to close the connection.
172 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false); 192 delegate_->CloseConnection(QUIC_INTERNAL_ERROR, false);
193 delete notifier;
173 return QuicConsumedData(0, false); 194 return QuicConsumedData(0, false);
174 } 195 }
175 196
176 total_bytes_consumed += bytes_consumed; 197 total_bytes_consumed += bytes_consumed;
177 fin_consumed = fin && total_bytes_consumed == data_size; 198 fin_consumed = fin && total_bytes_consumed == data_size;
178 data.Consume(bytes_consumed); 199 data.Consume(bytes_consumed);
179 DCHECK(data.Empty() || packet_creator_.BytesFree() == 0u); 200 DCHECK(data.Empty() || packet_creator_.BytesFree() == 0u);
180 201
181 // TODO(ianswett): Restore packet reordering. 202 // TODO(ianswett): Restore packet reordering.
182 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) { 203 if (!InBatchMode() || !packet_creator_.HasRoomForStreamFrame(id, offset)) {
183 SerializeAndSendPacket(); 204 SerializeAndSendPacket();
184 } 205 }
185 206
186 if (data.Empty()) { 207 if (data.Empty()) {
187 // We're done writing the data. Exit the loop. 208 // We're done writing the data. Exit the loop.
188 // We don't make this a precondition because we could have 0 bytes of data 209 // We don't make this a precondition because we could have 0 bytes of data
189 // if we're simply writing a fin. 210 // if we're simply writing a fin.
190 if (fec_protection == MUST_FEC_PROTECT) { 211 if (fec_protection == MUST_FEC_PROTECT) {
191 // Turn off FEC protection when we're done writing protected data. 212 // Turn off FEC protection when we're done writing protected data.
192 DVLOG(1) << "Turning FEC protection OFF"; 213 DVLOG(1) << "Turning FEC protection OFF";
193 should_fec_protect_ = false; 214 should_fec_protect_ = false;
194 } 215 }
195 break; 216 break;
196 } 217 }
197 } 218 }
198 219
220 if (notifier != nullptr && frames_created == 0) {
221 // Safe to delete the AckNotifer as it was never attached to a packet.
222 delete notifier;
223 }
224
199 // Don't allow the handshake to be bundled with other retransmittable frames. 225 // Don't allow the handshake to be bundled with other retransmittable frames.
200 if (handshake == IS_HANDSHAKE) { 226 if (handshake == IS_HANDSHAKE) {
201 SendQueuedFrames(true); 227 SendQueuedFrames(true);
202 } 228 }
203 229
204 // Try to close FEC group since we've either run out of data to send or we're 230 // Try to close FEC group since we've either run out of data to send or we're
205 // blocked. If not in batch mode, force close the group. 231 // blocked. If not in batch mode, force close the group.
206 // TODO(jri): This method should be called with flush=false here 232 // TODO(jri): This method should be called with flush=false here
207 // once the timer-based FEC sending is done, to separate FEC sending from 233 // once the timer-based FEC sending is done, to separate FEC sending from
208 // the end of batch operations. 234 // the end of batch operations.
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
419 packet_creator_.set_connection_id_length(PACKET_8BYTE_CONNECTION_ID); 445 packet_creator_.set_connection_id_length(PACKET_8BYTE_CONNECTION_ID);
420 } 446 }
421 } 447 }
422 448
423 449
424 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) { 450 void QuicPacketGenerator::set_encryption_level(EncryptionLevel level) {
425 packet_creator_.set_encryption_level(level); 451 packet_creator_.set_encryption_level(level);
426 } 452 }
427 453
428 } // namespace net 454 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/quic_packet_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698