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
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/quic_crypto_stream.h"
6
7 #include <string>
8
9 #include "absl/strings/str_cat.h"
10 #include "absl/strings/string_view.h"
11 #include "absl/types/optional.h"
12 #include "quiche/quic/core/crypto/crypto_handshake.h"
13 #include "quiche/quic/core/frames/quic_crypto_frame.h"
14 #include "quiche/quic/core/quic_connection.h"
15 #include "quiche/quic/core/quic_error_codes.h"
16 #include "quiche/quic/core/quic_session.h"
17 #include "quiche/quic/core/quic_types.h"
18 #include "quiche/quic/core/quic_utils.h"
19 #include "quiche/quic/platform/api/quic_flag_utils.h"
20 #include "quiche/quic/platform/api/quic_flags.h"
21 #include "quiche/quic/platform/api/quic_logging.h"
22
23 namespace quic {
24
25 #define ENDPOINT \
26 (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
27 : "Client:" \
28 " ")
29
QuicCryptoStream(QuicSession * session)30 QuicCryptoStream::QuicCryptoStream(QuicSession* session)
31 : QuicStream(
32 QuicVersionUsesCryptoFrames(session->transport_version())
33 ? QuicUtils::GetInvalidStreamId(session->transport_version())
34 : QuicUtils::GetCryptoStreamId(session->transport_version()),
35 session,
36 /*is_static=*/true,
37 QuicVersionUsesCryptoFrames(session->transport_version())
38 ? CRYPTO
39 : BIDIRECTIONAL),
40 substreams_{{{this}, {this}, {this}}} {
41 // The crypto stream is exempt from connection level flow control.
42 DisableConnectionFlowControlForThisStream();
43 }
44
~QuicCryptoStream()45 QuicCryptoStream::~QuicCryptoStream() {}
46
47 // static
CryptoMessageFramingOverhead(QuicTransportVersion version,QuicConnectionId connection_id)48 QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
49 QuicTransportVersion version, QuicConnectionId connection_id) {
50 QUICHE_DCHECK(
51 QuicUtils::IsConnectionIdValidForVersion(connection_id, version));
52 quiche::QuicheVariableLengthIntegerLength retry_token_length_length =
53 quiche::VARIABLE_LENGTH_INTEGER_LENGTH_1;
54 quiche::QuicheVariableLengthIntegerLength length_length =
55 quiche::VARIABLE_LENGTH_INTEGER_LENGTH_2;
56 if (!QuicVersionHasLongHeaderLengths(version)) {
57 retry_token_length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
58 length_length = quiche::VARIABLE_LENGTH_INTEGER_LENGTH_0;
59 }
60 return QuicPacketCreator::StreamFramePacketOverhead(
61 version, connection_id.length(), 0, /*include_version=*/true,
62 /*include_diversification_nonce=*/true,
63 VersionHasIetfInvariantHeader(version) ? PACKET_4BYTE_PACKET_NUMBER
64 : PACKET_1BYTE_PACKET_NUMBER,
65 retry_token_length_length, length_length,
66 /*offset=*/0);
67 }
68
OnCryptoFrame(const QuicCryptoFrame & frame)69 void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
70 QUIC_BUG_IF(quic_bug_12573_1,
71 !QuicVersionUsesCryptoFrames(session()->transport_version()))
72 << "Versions less than 47 shouldn't receive CRYPTO frames";
73 EncryptionLevel level = session()->connection()->last_decrypted_level();
74 if (!IsCryptoFrameExpectedForEncryptionLevel(level)) {
75 OnUnrecoverableError(
76 IETF_QUIC_PROTOCOL_VIOLATION,
77 absl::StrCat("CRYPTO_FRAME is unexpectedly received at level ", level));
78 return;
79 }
80 CryptoSubstream& substream =
81 substreams_[QuicUtils::GetPacketNumberSpace(level)];
82 substream.sequencer.OnCryptoFrame(frame);
83 EncryptionLevel frame_level = level;
84 if (substream.sequencer.NumBytesBuffered() >
85 BufferSizeLimitForLevel(frame_level)) {
86 OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
87 "Too much crypto data received");
88 }
89 }
90
OnStreamFrame(const QuicStreamFrame & frame)91 void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
92 if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
93 QUIC_PEER_BUG(quic_peer_bug_12573_2)
94 << "Crypto data received in stream frame instead of crypto frame";
95 OnUnrecoverableError(QUIC_INVALID_STREAM_DATA, "Unexpected stream frame");
96 }
97 QuicStream::OnStreamFrame(frame);
98 }
99
OnDataAvailable()100 void QuicCryptoStream::OnDataAvailable() {
101 EncryptionLevel level = session()->connection()->last_decrypted_level();
102 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
103 // Versions less than 47 only support QUIC crypto, which ignores the
104 // EncryptionLevel passed into CryptoMessageParser::ProcessInput (and
105 // OnDataAvailableInSequencer).
106 OnDataAvailableInSequencer(sequencer(), level);
107 return;
108 }
109 OnDataAvailableInSequencer(
110 &substreams_[QuicUtils::GetPacketNumberSpace(level)].sequencer, level);
111 }
112
OnDataAvailableInSequencer(QuicStreamSequencer * sequencer,EncryptionLevel level)113 void QuicCryptoStream::OnDataAvailableInSequencer(
114 QuicStreamSequencer* sequencer, EncryptionLevel level) {
115 struct iovec iov;
116 while (sequencer->GetReadableRegion(&iov)) {
117 absl::string_view data(static_cast<char*>(iov.iov_base), iov.iov_len);
118 if (!crypto_message_parser()->ProcessInput(data, level)) {
119 OnUnrecoverableError(crypto_message_parser()->error(),
120 crypto_message_parser()->error_detail());
121 return;
122 }
123 sequencer->MarkConsumed(iov.iov_len);
124 if (one_rtt_keys_available() &&
125 crypto_message_parser()->InputBytesRemaining() == 0) {
126 // If the handshake is complete and the current message has been fully
127 // processed then no more handshake messages are likely to arrive soon
128 // so release the memory in the stream sequencer.
129 sequencer->ReleaseBufferIfEmpty();
130 }
131 }
132 }
133
WriteCryptoData(EncryptionLevel level,absl::string_view data)134 void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
135 absl::string_view data) {
136 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
137 WriteOrBufferDataAtLevel(data, /*fin=*/false, level,
138 /*ack_listener=*/nullptr);
139 return;
140 }
141 if (data.empty()) {
142 QUIC_BUG(quic_bug_10322_1) << "Empty crypto data being written";
143 return;
144 }
145 const bool had_buffered_data = HasBufferedCryptoFrames();
146 QuicStreamSendBuffer* send_buffer =
147 &substreams_[QuicUtils::GetPacketNumberSpace(level)].send_buffer;
148 QuicStreamOffset offset = send_buffer->stream_offset();
149
150 // Ensure this data does not cause the send buffer for this encryption level
151 // to exceed its size limit.
152 if (GetQuicFlag(quic_bounded_crypto_send_buffer)) {
153 QUIC_BUG_IF(quic_crypto_stream_offset_lt_bytes_written,
154 offset < send_buffer->stream_bytes_written());
155 uint64_t current_buffer_size =
156 offset - std::min(offset, send_buffer->stream_bytes_written());
157 if (current_buffer_size > 0) {
158 QUIC_CODE_COUNT(quic_received_crypto_data_with_non_empty_send_buffer);
159 if (BufferSizeLimitForLevel(level) <
160 (current_buffer_size + data.length())) {
161 QUIC_BUG(quic_crypto_send_buffer_overflow)
162 << absl::StrCat("Too much data for crypto send buffer with level: ",
163 EncryptionLevelToString(level),
164 ", current_buffer_size: ", current_buffer_size,
165 ", data length: ", data.length(),
166 ", SNI: ", crypto_negotiated_params().sni);
167 OnUnrecoverableError(QUIC_INTERNAL_ERROR,
168 "Too much data for crypto send buffer");
169 return;
170 }
171 }
172 }
173
174 // Append |data| to the send buffer for this encryption level.
175 send_buffer->SaveStreamData(data);
176 if (kMaxStreamLength - offset < data.length()) {
177 QUIC_BUG(quic_bug_10322_2) << "Writing too much crypto handshake data";
178 OnUnrecoverableError(QUIC_INTERNAL_ERROR,
179 "Writing too much crypto handshake data");
180 return;
181 }
182 if (had_buffered_data) {
183 // Do not try to write if there is buffered data.
184 return;
185 }
186
187 size_t bytes_consumed = stream_delegate()->SendCryptoData(
188 level, data.length(), offset, NOT_RETRANSMISSION);
189 send_buffer->OnStreamDataConsumed(bytes_consumed);
190 }
191
BufferSizeLimitForLevel(EncryptionLevel) const192 size_t QuicCryptoStream::BufferSizeLimitForLevel(EncryptionLevel) const {
193 return GetQuicFlag(quic_max_buffered_crypto_bytes);
194 }
195
OnCryptoFrameAcked(const QuicCryptoFrame & frame,QuicTime::Delta)196 bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame,
197 QuicTime::Delta /*ack_delay_time*/) {
198 QuicByteCount newly_acked_length = 0;
199 if (!substreams_[QuicUtils::GetPacketNumberSpace(frame.level)]
200 .send_buffer.OnStreamDataAcked(frame.offset, frame.data_length,
201 &newly_acked_length)) {
202 OnUnrecoverableError(QUIC_INTERNAL_ERROR,
203 "Trying to ack unsent crypto data.");
204 return false;
205 }
206 return newly_acked_length > 0;
207 }
208
OnStreamReset(const QuicRstStreamFrame &)209 void QuicCryptoStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
210 stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
211 "Attempt to reset crypto stream");
212 }
213
NeuterUnencryptedStreamData()214 void QuicCryptoStream::NeuterUnencryptedStreamData() {
215 NeuterStreamDataOfEncryptionLevel(ENCRYPTION_INITIAL);
216 }
217
NeuterStreamDataOfEncryptionLevel(EncryptionLevel level)218 void QuicCryptoStream::NeuterStreamDataOfEncryptionLevel(
219 EncryptionLevel level) {
220 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
221 for (const auto& interval : bytes_consumed_[level]) {
222 QuicByteCount newly_acked_length = 0;
223 send_buffer().OnStreamDataAcked(
224 interval.min(), interval.max() - interval.min(), &newly_acked_length);
225 }
226 return;
227 }
228 QuicStreamSendBuffer* send_buffer =
229 &substreams_[QuicUtils::GetPacketNumberSpace(level)].send_buffer;
230 // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer
231 // to replace the following code.
232 QuicIntervalSet<QuicStreamOffset> to_ack = send_buffer->bytes_acked();
233 to_ack.Complement(0, send_buffer->stream_offset());
234 for (const auto& interval : to_ack) {
235 QuicByteCount newly_acked_length = 0;
236 send_buffer->OnStreamDataAcked(
237 interval.min(), interval.max() - interval.min(), &newly_acked_length);
238 }
239 }
240
OnStreamDataConsumed(QuicByteCount bytes_consumed)241 void QuicCryptoStream::OnStreamDataConsumed(QuicByteCount bytes_consumed) {
242 if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
243 QUIC_BUG(quic_bug_10322_3)
244 << "Stream data consumed when CRYPTO frames should be in use";
245 }
246 if (bytes_consumed > 0) {
247 bytes_consumed_[session()->connection()->encryption_level()].Add(
248 stream_bytes_written(), stream_bytes_written() + bytes_consumed);
249 }
250 QuicStream::OnStreamDataConsumed(bytes_consumed);
251 }
252
HasPendingCryptoRetransmission() const253 bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
254 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
255 return false;
256 }
257 for (const auto& substream : substreams_) {
258 if (substream.send_buffer.HasPendingRetransmission()) {
259 return true;
260 }
261 }
262 return false;
263 }
264
WritePendingCryptoRetransmission()265 void QuicCryptoStream::WritePendingCryptoRetransmission() {
266 QUIC_BUG_IF(quic_bug_12573_3,
267 !QuicVersionUsesCryptoFrames(session()->transport_version()))
268 << "Versions less than 47 don't write CRYPTO frames";
269 for (uint8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) {
270 auto packet_number_space = static_cast<PacketNumberSpace>(i);
271 QuicStreamSendBuffer* send_buffer =
272 &substreams_[packet_number_space].send_buffer;
273 while (send_buffer->HasPendingRetransmission()) {
274 auto pending = send_buffer->NextPendingRetransmission();
275 size_t bytes_consumed = stream_delegate()->SendCryptoData(
276 GetEncryptionLevelToSendCryptoDataOfSpace(packet_number_space),
277 pending.length, pending.offset, HANDSHAKE_RETRANSMISSION);
278 send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
279 if (bytes_consumed < pending.length) {
280 return;
281 }
282 }
283 }
284 }
285
WritePendingRetransmission()286 void QuicCryptoStream::WritePendingRetransmission() {
287 while (HasPendingRetransmission()) {
288 StreamPendingRetransmission pending =
289 send_buffer().NextPendingRetransmission();
290 QuicIntervalSet<QuicStreamOffset> retransmission(
291 pending.offset, pending.offset + pending.length);
292 EncryptionLevel retransmission_encryption_level = ENCRYPTION_INITIAL;
293 // Determine the encryption level to write the retransmission
294 // at. The retransmission should be written at the same encryption level
295 // as the original transmission.
296 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
297 if (retransmission.Intersects(bytes_consumed_[i])) {
298 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
299 retransmission.Intersection(bytes_consumed_[i]);
300 break;
301 }
302 }
303 pending.offset = retransmission.begin()->min();
304 pending.length =
305 retransmission.begin()->max() - retransmission.begin()->min();
306 QuicConsumedData consumed = RetransmitStreamDataAtLevel(
307 pending.offset, pending.length, retransmission_encryption_level,
308 HANDSHAKE_RETRANSMISSION);
309 if (consumed.bytes_consumed < pending.length) {
310 // The connection is write blocked.
311 break;
312 }
313 }
314 }
315
RetransmitStreamData(QuicStreamOffset offset,QuicByteCount data_length,bool,TransmissionType type)316 bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
317 QuicByteCount data_length,
318 bool /*fin*/,
319 TransmissionType type) {
320 QUICHE_DCHECK(type == HANDSHAKE_RETRANSMISSION || type == PTO_RETRANSMISSION);
321 QuicIntervalSet<QuicStreamOffset> retransmission(offset,
322 offset + data_length);
323 // Determine the encryption level to send data. This only needs to be once as
324 // [offset, offset + data_length) is guaranteed to be in the same packet.
325 EncryptionLevel send_encryption_level = ENCRYPTION_INITIAL;
326 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
327 if (retransmission.Intersects(bytes_consumed_[i])) {
328 send_encryption_level = static_cast<EncryptionLevel>(i);
329 break;
330 }
331 }
332 retransmission.Difference(bytes_acked());
333 for (const auto& interval : retransmission) {
334 QuicStreamOffset retransmission_offset = interval.min();
335 QuicByteCount retransmission_length = interval.max() - interval.min();
336 QuicConsumedData consumed = RetransmitStreamDataAtLevel(
337 retransmission_offset, retransmission_length, send_encryption_level,
338 type);
339 if (consumed.bytes_consumed < retransmission_length) {
340 // The connection is write blocked.
341 return false;
342 }
343 }
344
345 return true;
346 }
347
RetransmitStreamDataAtLevel(QuicStreamOffset retransmission_offset,QuicByteCount retransmission_length,EncryptionLevel encryption_level,TransmissionType type)348 QuicConsumedData QuicCryptoStream::RetransmitStreamDataAtLevel(
349 QuicStreamOffset retransmission_offset, QuicByteCount retransmission_length,
350 EncryptionLevel encryption_level, TransmissionType type) {
351 QUICHE_DCHECK(type == HANDSHAKE_RETRANSMISSION || type == PTO_RETRANSMISSION);
352 const auto consumed = stream_delegate()->WritevData(
353 id(), retransmission_length, retransmission_offset, NO_FIN, type,
354 encryption_level);
355 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
356 << " is forced to retransmit stream data ["
357 << retransmission_offset << ", "
358 << retransmission_offset + retransmission_length
359 << "), with encryption level: " << encryption_level
360 << ", consumed: " << consumed;
361 OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
362 consumed.fin_consumed);
363
364 return consumed;
365 }
366
crypto_bytes_read() const367 uint64_t QuicCryptoStream::crypto_bytes_read() const {
368 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
369 return stream_bytes_read();
370 }
371 uint64_t bytes_read = 0;
372 for (const CryptoSubstream& substream : substreams_) {
373 bytes_read += substream.sequencer.NumBytesConsumed();
374 }
375 return bytes_read;
376 }
377
378 // TODO(haoyuewang) Move this test-only method under
379 // quiche/quic/test_tools.
BytesReadOnLevel(EncryptionLevel level) const380 uint64_t QuicCryptoStream::BytesReadOnLevel(EncryptionLevel level) const {
381 return substreams_[QuicUtils::GetPacketNumberSpace(level)]
382 .sequencer.NumBytesConsumed();
383 }
384
BytesSentOnLevel(EncryptionLevel level) const385 uint64_t QuicCryptoStream::BytesSentOnLevel(EncryptionLevel level) const {
386 return substreams_[QuicUtils::GetPacketNumberSpace(level)]
387 .send_buffer.stream_bytes_written();
388 }
389
WriteCryptoFrame(EncryptionLevel level,QuicStreamOffset offset,QuicByteCount data_length,QuicDataWriter * writer)390 bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level,
391 QuicStreamOffset offset,
392 QuicByteCount data_length,
393 QuicDataWriter* writer) {
394 QUIC_BUG_IF(quic_bug_12573_4,
395 !QuicVersionUsesCryptoFrames(session()->transport_version()))
396 << "Versions less than 47 don't write CRYPTO frames (2)";
397 return substreams_[QuicUtils::GetPacketNumberSpace(level)]
398 .send_buffer.WriteStreamData(offset, data_length, writer);
399 }
400
OnCryptoFrameLost(QuicCryptoFrame * crypto_frame)401 void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
402 QUIC_BUG_IF(quic_bug_12573_5,
403 !QuicVersionUsesCryptoFrames(session()->transport_version()))
404 << "Versions less than 47 don't lose CRYPTO frames";
405 substreams_[QuicUtils::GetPacketNumberSpace(crypto_frame->level)]
406 .send_buffer.OnStreamDataLost(crypto_frame->offset,
407 crypto_frame->data_length);
408 }
409
RetransmitData(QuicCryptoFrame * crypto_frame,TransmissionType type)410 bool QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
411 TransmissionType type) {
412 QUIC_BUG_IF(quic_bug_12573_6,
413 !QuicVersionUsesCryptoFrames(session()->transport_version()))
414 << "Versions less than 47 don't retransmit CRYPTO frames";
415 QuicIntervalSet<QuicStreamOffset> retransmission(
416 crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length);
417 QuicStreamSendBuffer* send_buffer =
418 &substreams_[QuicUtils::GetPacketNumberSpace(crypto_frame->level)]
419 .send_buffer;
420 retransmission.Difference(send_buffer->bytes_acked());
421 if (retransmission.Empty()) {
422 return true;
423 }
424 for (const auto& interval : retransmission) {
425 size_t retransmission_offset = interval.min();
426 size_t retransmission_length = interval.max() - interval.min();
427 EncryptionLevel retransmission_encryption_level =
428 GetEncryptionLevelToSendCryptoDataOfSpace(
429 QuicUtils::GetPacketNumberSpace(crypto_frame->level));
430 size_t bytes_consumed = stream_delegate()->SendCryptoData(
431 retransmission_encryption_level, retransmission_length,
432 retransmission_offset, type);
433 send_buffer->OnStreamDataRetransmitted(retransmission_offset,
434 bytes_consumed);
435 if (bytes_consumed < retransmission_length) {
436 return false;
437 }
438 }
439 return true;
440 }
441
WriteBufferedCryptoFrames()442 void QuicCryptoStream::WriteBufferedCryptoFrames() {
443 QUIC_BUG_IF(quic_bug_12573_7,
444 !QuicVersionUsesCryptoFrames(session()->transport_version()))
445 << "Versions less than 47 don't use CRYPTO frames";
446 for (uint8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) {
447 auto packet_number_space = static_cast<PacketNumberSpace>(i);
448 QuicStreamSendBuffer* send_buffer =
449 &substreams_[packet_number_space].send_buffer;
450 const size_t data_length =
451 send_buffer->stream_offset() - send_buffer->stream_bytes_written();
452 if (data_length == 0) {
453 // No buffered data for this encryption level.
454 continue;
455 }
456 size_t bytes_consumed = stream_delegate()->SendCryptoData(
457 GetEncryptionLevelToSendCryptoDataOfSpace(packet_number_space),
458 data_length, send_buffer->stream_bytes_written(), NOT_RETRANSMISSION);
459 send_buffer->OnStreamDataConsumed(bytes_consumed);
460 if (bytes_consumed < data_length) {
461 // Connection is write blocked.
462 break;
463 }
464 }
465 }
466
HasBufferedCryptoFrames() const467 bool QuicCryptoStream::HasBufferedCryptoFrames() const {
468 QUIC_BUG_IF(quic_bug_12573_8,
469 !QuicVersionUsesCryptoFrames(session()->transport_version()))
470 << "Versions less than 47 don't use CRYPTO frames";
471 for (const CryptoSubstream& substream : substreams_) {
472 const QuicStreamSendBuffer& send_buffer = substream.send_buffer;
473 QUICHE_DCHECK_GE(send_buffer.stream_offset(),
474 send_buffer.stream_bytes_written());
475 if (send_buffer.stream_offset() > send_buffer.stream_bytes_written()) {
476 return true;
477 }
478 }
479 return false;
480 }
481
IsFrameOutstanding(EncryptionLevel level,size_t offset,size_t length) const482 bool QuicCryptoStream::IsFrameOutstanding(EncryptionLevel level, size_t offset,
483 size_t length) const {
484 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
485 // This only happens if a client was originally configured for a version
486 // greater than 45, but received a version negotiation packet and is
487 // attempting to retransmit for a version less than 47. Outside of tests,
488 // this is a misconfiguration of the client, and this connection will be
489 // doomed. Return false here to avoid trying to retransmit CRYPTO frames on
490 // the wrong transport version.
491 return false;
492 }
493 return substreams_[QuicUtils::GetPacketNumberSpace(level)]
494 .send_buffer.IsStreamDataOutstanding(offset, length);
495 }
496
IsWaitingForAcks() const497 bool QuicCryptoStream::IsWaitingForAcks() const {
498 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
499 return QuicStream::IsWaitingForAcks();
500 }
501 for (const CryptoSubstream& substream : substreams_) {
502 if (substream.send_buffer.stream_bytes_outstanding()) {
503 return true;
504 }
505 }
506 return false;
507 }
508
CryptoSubstream(QuicCryptoStream * crypto_stream)509 QuicCryptoStream::CryptoSubstream::CryptoSubstream(
510 QuicCryptoStream* crypto_stream)
511 : sequencer(crypto_stream),
512 send_buffer(crypto_stream->session()
513 ->connection()
514 ->helper()
515 ->GetStreamSendBufferAllocator()) {}
516
517 #undef ENDPOINT // undef for jumbo builds
518 } // namespace quic
519