blob: 094613c7395493b49b49bd9990e82dfde5d18833 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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 "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
6
vasilvv872e7a32019-03-12 16:42:44 -07007#include <string>
8
QUICHE teama6ef0a62019-03-07 20:34:33 -05009#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
10#include "net/third_party/quiche/src/quic/core/crypto/crypto_utils.h"
11#include "net/third_party/quiche/src/quic/core/quic_connection.h"
12#include "net/third_party/quiche/src/quic/core/quic_session.h"
renjietang41a1b412020-02-27 15:05:14 -080013#include "net/third_party/quiche/src/quic/core/quic_types.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050014#include "net/third_party/quiche/src/quic/core/quic_utils.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
16#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
renjietang41a1b412020-02-27 15:05:14 -080018#include "net/third_party/quiche/src/common/platform/api/quiche_optional.h"
dmcardlecf0bfcf2019-12-13 08:08:21 -080019#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050020
21namespace quic {
22
23#define ENDPOINT \
24 (session()->perspective() == Perspective::IS_SERVER ? "Server: " \
25 : "Client:" \
26 " ")
27
28QuicCryptoStream::QuicCryptoStream(QuicSession* session)
renjietangd1d00852019-09-06 10:43:12 -070029 : QuicStream(
30 QuicVersionUsesCryptoFrames(session->transport_version())
31 ? QuicUtils::GetInvalidStreamId(session->transport_version())
32 : QuicUtils::GetCryptoStreamId(session->transport_version()),
33 session,
34 /*is_static=*/true,
35 QuicVersionUsesCryptoFrames(session->transport_version())
36 ? CRYPTO
37 : BIDIRECTIONAL),
bnc5e469412019-12-05 14:16:25 -080038 substreams_{{{this, ENCRYPTION_INITIAL},
39 {this, ENCRYPTION_HANDSHAKE},
40 {this, ENCRYPTION_ZERO_RTT},
renjietang41a1b412020-02-27 15:05:14 -080041 {this, ENCRYPTION_FORWARD_SECURE}}},
42 writevdata_at_level_(GetQuicReloadableFlag(quic_writevdata_at_level)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050043 // The crypto stream is exempt from connection level flow control.
44 DisableConnectionFlowControlForThisStream();
45}
46
47QuicCryptoStream::~QuicCryptoStream() {}
48
49// static
50QuicByteCount QuicCryptoStream::CryptoMessageFramingOverhead(
51 QuicTransportVersion version,
52 QuicConnectionId connection_id) {
53 DCHECK(QuicUtils::IsConnectionIdValidForVersion(connection_id, version));
nharperd43f1d62019-07-01 15:18:20 -070054 QuicVariableLengthIntegerLength retry_token_length_length =
55 VARIABLE_LENGTH_INTEGER_LENGTH_1;
56 QuicVariableLengthIntegerLength length_length =
57 VARIABLE_LENGTH_INTEGER_LENGTH_2;
nharper405f7192019-09-11 08:28:06 -070058 if (!QuicVersionHasLongHeaderLengths(version)) {
nharperd43f1d62019-07-01 15:18:20 -070059 retry_token_length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
60 length_length = VARIABLE_LENGTH_INTEGER_LENGTH_0;
nharperd43f1d62019-07-01 15:18:20 -070061 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 return QuicPacketCreator::StreamFramePacketOverhead(
63 version, static_cast<QuicConnectionIdLength>(connection_id.length()),
64 PACKET_0BYTE_CONNECTION_ID,
65 /*include_version=*/true,
66 /*include_diversification_nonce=*/true,
fayangd4291e42019-05-30 10:31:21 -070067 VersionHasIetfInvariantHeader(version) ? PACKET_4BYTE_PACKET_NUMBER
68 : PACKET_1BYTE_PACKET_NUMBER,
nharperd43f1d62019-07-01 15:18:20 -070069 retry_token_length_length, length_length,
QUICHE teama6ef0a62019-03-07 20:34:33 -050070 /*offset=*/0);
71}
72
73void QuicCryptoStream::OnCryptoFrame(const QuicCryptoFrame& frame) {
renjietangd1d00852019-09-06 10:43:12 -070074 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 << "Versions less than 47 shouldn't receive CRYPTO frames";
76 EncryptionLevel level = session()->connection()->last_decrypted_level();
77 substreams_[level].sequencer.OnCryptoFrame(frame);
renjietang6c2dbdb2020-01-02 11:56:06 -080078 EncryptionLevel frame_level = level;
nharper486a8a92019-08-28 16:25:10 -070079 if (substreams_[level].sequencer.NumBytesBuffered() >
renjietang7cbfe9e2019-11-04 10:44:42 -080080 BufferSizeLimitForLevel(frame_level)) {
renjietang87df0d02020-02-13 11:53:52 -080081 OnUnrecoverableError(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA,
82 "Too much crypto data received");
nharper486a8a92019-08-28 16:25:10 -070083 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050084}
85
86void QuicCryptoStream::OnStreamFrame(const QuicStreamFrame& frame) {
renjietangd1d00852019-09-06 10:43:12 -070087 if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050088 QUIC_PEER_BUG
89 << "Crypto data received in stream frame instead of crypto frame";
renjietang87df0d02020-02-13 11:53:52 -080090 OnUnrecoverableError(QUIC_INVALID_STREAM_DATA, "Unexpected stream frame");
QUICHE teama6ef0a62019-03-07 20:34:33 -050091 }
92 QuicStream::OnStreamFrame(frame);
93}
94
95void QuicCryptoStream::OnDataAvailable() {
96 EncryptionLevel level = session()->connection()->last_decrypted_level();
renjietangd1d00852019-09-06 10:43:12 -070097 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050098 // Versions less than 47 only support QUIC crypto, which ignores the
99 // EncryptionLevel passed into CryptoMessageParser::ProcessInput (and
100 // OnDataAvailableInSequencer).
101 OnDataAvailableInSequencer(sequencer(), level);
102 return;
103 }
104 OnDataAvailableInSequencer(&substreams_[level].sequencer, level);
105}
106
107void QuicCryptoStream::OnDataAvailableInSequencer(
108 QuicStreamSequencer* sequencer,
109 EncryptionLevel level) {
110 struct iovec iov;
111 while (sequencer->GetReadableRegion(&iov)) {
dmcardlecf0bfcf2019-12-13 08:08:21 -0800112 quiche::QuicheStringPiece data(static_cast<char*>(iov.iov_base),
113 iov.iov_len);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500114 if (!crypto_message_parser()->ProcessInput(data, level)) {
renjietang87df0d02020-02-13 11:53:52 -0800115 OnUnrecoverableError(crypto_message_parser()->error(),
116 crypto_message_parser()->error_detail());
QUICHE teama6ef0a62019-03-07 20:34:33 -0500117 return;
118 }
119 sequencer->MarkConsumed(iov.iov_len);
fayang685367a2020-01-14 10:40:15 -0800120 if (one_rtt_keys_available() &&
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 crypto_message_parser()->InputBytesRemaining() == 0) {
122 // If the handshake is complete and the current message has been fully
123 // processed then no more handshake messages are likely to arrive soon
124 // so release the memory in the stream sequencer.
125 sequencer->ReleaseBufferIfEmpty();
126 }
127 }
128}
129
dmcardlecf0bfcf2019-12-13 08:08:21 -0800130bool QuicCryptoStream::ExportKeyingMaterial(quiche::QuicheStringPiece label,
131 quiche::QuicheStringPiece context,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500132 size_t result_len,
vasilvvc48c8712019-03-11 13:38:16 -0700133 std::string* result) const {
fayang685367a2020-01-14 10:40:15 -0800134 if (!one_rtt_keys_available()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500135 QUIC_DLOG(ERROR) << "ExportKeyingMaterial was called before forward-secure"
136 << "encryption was established.";
137 return false;
138 }
139 return CryptoUtils::ExportKeyingMaterial(
140 crypto_negotiated_params().subkey_secret, label, context, result_len,
141 result);
142}
143
144void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
dmcardlecf0bfcf2019-12-13 08:08:21 -0800145 quiche::QuicheStringPiece data) {
renjietangd1d00852019-09-06 10:43:12 -0700146 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500147 // The QUIC crypto handshake takes care of setting the appropriate
148 // encryption level before writing data. Since that is the only handshake
149 // supported in versions less than 47, |level| can be ignored here.
150 WriteOrBufferData(data, /* fin */ false, /* ack_listener */ nullptr);
151 return;
152 }
153 if (data.empty()) {
154 QUIC_BUG << "Empty crypto data being written";
155 return;
156 }
fayangaee31ef2019-08-20 06:47:51 -0700157 const bool had_buffered_data = HasBufferedCryptoFrames();
QUICHE teama6ef0a62019-03-07 20:34:33 -0500158 // Append |data| to the send buffer for this encryption level.
159 struct iovec iov(QuicUtils::MakeIovec(data));
160 QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
161 QuicStreamOffset offset = send_buffer->stream_offset();
162 send_buffer->SaveStreamData(&iov, /*iov_count=*/1, /*iov_offset=*/0,
163 data.length());
164 if (kMaxStreamLength - offset < data.length()) {
165 QUIC_BUG << "Writing too much crypto handshake data";
166 // TODO(nharper): Switch this to an IETF QUIC error code, possibly
167 // INTERNAL_ERROR?
renjietang87df0d02020-02-13 11:53:52 -0800168 OnUnrecoverableError(QUIC_STREAM_LENGTH_OVERFLOW,
169 "Writing too much crypto handshake data");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500170 }
fayangaee31ef2019-08-20 06:47:51 -0700171 if (had_buffered_data) {
172 // Do not try to write if there is buffered data.
173 return;
174 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500175
renjietang0c161c62020-03-05 13:13:53 -0800176 size_t bytes_consumed = stream_delegate()->SendCryptoData(
renjietang4d992bf2020-03-03 13:01:55 -0800177 level, data.length(), offset, NOT_RETRANSMISSION);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500178 send_buffer->OnStreamDataConsumed(bytes_consumed);
179}
180
nharper486a8a92019-08-28 16:25:10 -0700181size_t QuicCryptoStream::BufferSizeLimitForLevel(EncryptionLevel) const {
182 return GetQuicFlag(FLAGS_quic_max_buffered_crypto_bytes);
183}
184
QUICHE teama6ef0a62019-03-07 20:34:33 -0500185bool QuicCryptoStream::OnCryptoFrameAcked(const QuicCryptoFrame& frame,
dschinazi17d42422019-06-18 16:35:07 -0700186 QuicTime::Delta /*ack_delay_time*/) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500187 QuicByteCount newly_acked_length = 0;
188 if (!substreams_[frame.level].send_buffer.OnStreamDataAcked(
189 frame.offset, frame.data_length, &newly_acked_length)) {
renjietang87df0d02020-02-13 11:53:52 -0800190 OnUnrecoverableError(QUIC_INTERNAL_ERROR,
191 "Trying to ack unsent crypto data.");
QUICHE teama6ef0a62019-03-07 20:34:33 -0500192 return false;
193 }
194 return newly_acked_length > 0;
195}
196
renjietang546c7142020-03-05 14:12:10 -0800197void QuicCryptoStream::OnStreamReset(const QuicRstStreamFrame& /*frame*/) {
198 stream_delegate()->OnStreamError(QUIC_INVALID_STREAM_ID,
199 "Attempt to reset crypto stream");
200}
201
QUICHE teama6ef0a62019-03-07 20:34:33 -0500202void QuicCryptoStream::NeuterUnencryptedStreamData() {
renjietangd1d00852019-09-06 10:43:12 -0700203 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE team6987b4a2019-03-15 16:23:04 -0700204 for (const auto& interval : bytes_consumed_[ENCRYPTION_INITIAL]) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500205 QuicByteCount newly_acked_length = 0;
206 send_buffer().OnStreamDataAcked(
207 interval.min(), interval.max() - interval.min(), &newly_acked_length);
208 }
209 return;
210 }
QUICHE team6987b4a2019-03-15 16:23:04 -0700211 QuicStreamSendBuffer* send_buffer =
212 &substreams_[ENCRYPTION_INITIAL].send_buffer;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500213 // TODO(nharper): Consider adding a Clear() method to QuicStreamSendBuffer to
214 // replace the following code.
215 QuicIntervalSet<QuicStreamOffset> to_ack = send_buffer->bytes_acked();
216 to_ack.Complement(0, send_buffer->stream_offset());
217 for (const auto& interval : to_ack) {
218 QuicByteCount newly_acked_length = 0;
219 send_buffer->OnStreamDataAcked(
220 interval.min(), interval.max() - interval.min(), &newly_acked_length);
221 }
222}
223
224void QuicCryptoStream::OnStreamDataConsumed(size_t bytes_consumed) {
renjietangd1d00852019-09-06 10:43:12 -0700225 if (QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500226 QUIC_BUG << "Stream data consumed when CRYPTO frames should be in use";
227 }
228 if (bytes_consumed > 0) {
229 bytes_consumed_[session()->connection()->encryption_level()].Add(
230 stream_bytes_written(), stream_bytes_written() + bytes_consumed);
231 }
232 QuicStream::OnStreamDataConsumed(bytes_consumed);
233}
234
nharper46833c32019-05-15 21:33:05 -0700235bool QuicCryptoStream::HasPendingCryptoRetransmission() const {
renjietangd1d00852019-09-06 10:43:12 -0700236 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500237 return false;
238 }
239 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700240 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500241 if (substreams_[level].send_buffer.HasPendingRetransmission()) {
242 return true;
243 }
244 }
245 return false;
246}
247
248void QuicCryptoStream::WritePendingCryptoRetransmission() {
renjietangd1d00852019-09-06 10:43:12 -0700249 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500250 << "Versions less than 47 don't write CRYPTO frames";
QUICHE teama6ef0a62019-03-07 20:34:33 -0500251 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700252 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500253 QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500254 while (send_buffer->HasPendingRetransmission()) {
255 auto pending = send_buffer->NextPendingRetransmission();
renjietang0c161c62020-03-05 13:13:53 -0800256 size_t bytes_consumed = stream_delegate()->SendCryptoData(
renjietang4d992bf2020-03-03 13:01:55 -0800257 level, pending.length, pending.offset, HANDSHAKE_RETRANSMISSION);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500258 send_buffer->OnStreamDataRetransmitted(pending.offset, bytes_consumed);
fayangd6db04a2019-10-02 14:21:42 -0700259 if (bytes_consumed < pending.length) {
260 break;
261 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500262 }
263 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500264}
265
266void QuicCryptoStream::WritePendingRetransmission() {
267 while (HasPendingRetransmission()) {
268 StreamPendingRetransmission pending =
269 send_buffer().NextPendingRetransmission();
270 QuicIntervalSet<QuicStreamOffset> retransmission(
271 pending.offset, pending.offset + pending.length);
QUICHE team6987b4a2019-03-15 16:23:04 -0700272 EncryptionLevel retransmission_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500273 // Determine the encryption level to write the retransmission
274 // at. The retransmission should be written at the same encryption level
275 // as the original transmission.
276 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
277 if (retransmission.Intersects(bytes_consumed_[i])) {
278 retransmission_encryption_level = static_cast<EncryptionLevel>(i);
279 retransmission.Intersection(bytes_consumed_[i]);
280 break;
281 }
282 }
283 pending.offset = retransmission.begin()->min();
284 pending.length =
285 retransmission.begin()->max() - retransmission.begin()->min();
renjietang41a1b412020-02-27 15:05:14 -0800286 QuicConsumedData consumed(0, false);
287 if (!writevdata_at_level_) {
288 EncryptionLevel current_encryption_level =
289 session()->connection()->encryption_level();
290 // Set appropriate encryption level.
291 session()->connection()->SetDefaultEncryptionLevel(
292 retransmission_encryption_level);
293 consumed = stream_delegate()->WritevData(
294 id(), pending.length, pending.offset, NO_FIN,
renjietang4d992bf2020-03-03 13:01:55 -0800295 HANDSHAKE_RETRANSMISSION, QuicheNullOpt);
renjietang41a1b412020-02-27 15:05:14 -0800296 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
297 << " tries to retransmit stream data [" << pending.offset
298 << ", " << pending.offset + pending.length
299 << ") with encryption level: "
300 << retransmission_encryption_level
301 << ", consumed: " << consumed;
302 OnStreamFrameRetransmitted(pending.offset, consumed.bytes_consumed,
303 consumed.fin_consumed);
304 // Restore encryption level.
305 session()->connection()->SetDefaultEncryptionLevel(
306 current_encryption_level);
307 } else {
308 QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 1, 2);
309 consumed = RetransmitStreamDataAtLevel(pending.offset, pending.length,
renjietang4d992bf2020-03-03 13:01:55 -0800310 retransmission_encryption_level,
311 HANDSHAKE_RETRANSMISSION);
renjietang41a1b412020-02-27 15:05:14 -0800312 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500313 if (consumed.bytes_consumed < pending.length) {
314 // The connection is write blocked.
315 break;
316 }
317 }
318}
319
320bool QuicCryptoStream::RetransmitStreamData(QuicStreamOffset offset,
321 QuicByteCount data_length,
renjietang4d992bf2020-03-03 13:01:55 -0800322 bool /*fin*/,
323 TransmissionType type) {
324 DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500325 QuicIntervalSet<QuicStreamOffset> retransmission(offset,
326 offset + data_length);
327 // Determine the encryption level to send data. This only needs to be once as
328 // [offset, offset + data_length) is guaranteed to be in the same packet.
QUICHE team6987b4a2019-03-15 16:23:04 -0700329 EncryptionLevel send_encryption_level = ENCRYPTION_INITIAL;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500330 for (size_t i = 0; i < NUM_ENCRYPTION_LEVELS; ++i) {
331 if (retransmission.Intersects(bytes_consumed_[i])) {
332 send_encryption_level = static_cast<EncryptionLevel>(i);
333 break;
334 }
335 }
336 retransmission.Difference(bytes_acked());
337 EncryptionLevel current_encryption_level =
338 session()->connection()->encryption_level();
339 for (const auto& interval : retransmission) {
340 QuicStreamOffset retransmission_offset = interval.min();
341 QuicByteCount retransmission_length = interval.max() - interval.min();
renjietang41a1b412020-02-27 15:05:14 -0800342 QuicConsumedData consumed(0, false);
343 if (!writevdata_at_level_) {
344 // Set appropriate encryption level.
345 session()->connection()->SetDefaultEncryptionLevel(send_encryption_level);
renjietang4d992bf2020-03-03 13:01:55 -0800346 consumed = stream_delegate()->WritevData(id(), retransmission_length,
347 retransmission_offset, NO_FIN,
348 type, QuicheNullOpt);
renjietang41a1b412020-02-27 15:05:14 -0800349 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
350 << " is forced to retransmit stream data ["
351 << retransmission_offset << ", "
352 << retransmission_offset + retransmission_length
353 << "), with encryption level: " << send_encryption_level
354 << ", consumed: " << consumed;
355 OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
356 consumed.fin_consumed);
357 // Restore encryption level.
358 session()->connection()->SetDefaultEncryptionLevel(
359 current_encryption_level);
360 } else {
361 QUIC_RELOADABLE_FLAG_COUNT_N(quic_writevdata_at_level, 2, 2);
renjietang4d992bf2020-03-03 13:01:55 -0800362 consumed = RetransmitStreamDataAtLevel(retransmission_offset,
363 retransmission_length,
364 send_encryption_level, type);
renjietang41a1b412020-02-27 15:05:14 -0800365 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500366 if (consumed.bytes_consumed < retransmission_length) {
367 // The connection is write blocked.
368 return false;
369 }
370 }
371
372 return true;
373}
374
renjietang41a1b412020-02-27 15:05:14 -0800375QuicConsumedData QuicCryptoStream::RetransmitStreamDataAtLevel(
376 QuicStreamOffset retransmission_offset,
377 QuicByteCount retransmission_length,
renjietang4d992bf2020-03-03 13:01:55 -0800378 EncryptionLevel encryption_level,
379 TransmissionType type) {
380 DCHECK_EQ(HANDSHAKE_RETRANSMISSION, type);
renjietang41a1b412020-02-27 15:05:14 -0800381 DCHECK(writevdata_at_level_);
382 const auto consumed = stream_delegate()->WritevData(
renjietang4d992bf2020-03-03 13:01:55 -0800383 id(), retransmission_length, retransmission_offset, NO_FIN, type,
384 encryption_level);
renjietang41a1b412020-02-27 15:05:14 -0800385 QUIC_DVLOG(1) << ENDPOINT << "stream " << id()
386 << " is forced to retransmit stream data ["
387 << retransmission_offset << ", "
388 << retransmission_offset + retransmission_length
389 << "), with encryption level: " << encryption_level
390 << ", consumed: " << consumed;
391 OnStreamFrameRetransmitted(retransmission_offset, consumed.bytes_consumed,
392 consumed.fin_consumed);
393
394 return consumed;
395}
396
QUICHE teama6ef0a62019-03-07 20:34:33 -0500397uint64_t QuicCryptoStream::crypto_bytes_read() const {
renjietangd1d00852019-09-06 10:43:12 -0700398 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500399 return stream_bytes_read();
400 }
QUICHE team6987b4a2019-03-15 16:23:04 -0700401 return substreams_[ENCRYPTION_INITIAL].sequencer.NumBytesConsumed() +
QUICHE teama6ef0a62019-03-07 20:34:33 -0500402 substreams_[ENCRYPTION_ZERO_RTT].sequencer.NumBytesConsumed() +
403 substreams_[ENCRYPTION_FORWARD_SECURE].sequencer.NumBytesConsumed();
404}
405
406uint64_t QuicCryptoStream::BytesReadOnLevel(EncryptionLevel level) const {
407 return substreams_[level].sequencer.NumBytesConsumed();
408}
409
410bool QuicCryptoStream::WriteCryptoFrame(EncryptionLevel level,
411 QuicStreamOffset offset,
412 QuicByteCount data_length,
413 QuicDataWriter* writer) {
renjietangd1d00852019-09-06 10:43:12 -0700414 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500415 << "Versions less than 47 don't write CRYPTO frames (2)";
416 return substreams_[level].send_buffer.WriteStreamData(offset, data_length,
417 writer);
418}
419
420void QuicCryptoStream::OnCryptoFrameLost(QuicCryptoFrame* crypto_frame) {
renjietangd1d00852019-09-06 10:43:12 -0700421 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500422 << "Versions less than 47 don't lose CRYPTO frames";
423 substreams_[crypto_frame->level].send_buffer.OnStreamDataLost(
424 crypto_frame->offset, crypto_frame->data_length);
425}
426
renjietang4d992bf2020-03-03 13:01:55 -0800427void QuicCryptoStream::RetransmitData(QuicCryptoFrame* crypto_frame,
428 TransmissionType type) {
renjietangd1d00852019-09-06 10:43:12 -0700429 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
QUICHE teama6ef0a62019-03-07 20:34:33 -0500430 << "Versions less than 47 don't retransmit CRYPTO frames";
431 QuicIntervalSet<QuicStreamOffset> retransmission(
432 crypto_frame->offset, crypto_frame->offset + crypto_frame->data_length);
433 QuicStreamSendBuffer* send_buffer =
434 &substreams_[crypto_frame->level].send_buffer;
435 retransmission.Difference(send_buffer->bytes_acked());
436 if (retransmission.Empty()) {
437 return;
438 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500439 for (const auto& interval : retransmission) {
440 size_t retransmission_offset = interval.min();
441 size_t retransmission_length = interval.max() - interval.min();
renjietang0c161c62020-03-05 13:13:53 -0800442 size_t bytes_consumed = stream_delegate()->SendCryptoData(
renjietang4d992bf2020-03-03 13:01:55 -0800443 crypto_frame->level, retransmission_length, retransmission_offset,
444 type);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500445 send_buffer->OnStreamDataRetransmitted(retransmission_offset,
446 bytes_consumed);
fayangd6db04a2019-10-02 14:21:42 -0700447 if (bytes_consumed < retransmission_length) {
448 break;
449 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500450 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500451}
452
fayangaee31ef2019-08-20 06:47:51 -0700453void QuicCryptoStream::WriteBufferedCryptoFrames() {
renjietangd1d00852019-09-06 10:43:12 -0700454 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
fayangaee31ef2019-08-20 06:47:51 -0700455 << "Versions less than 47 don't use CRYPTO frames";
fayangaee31ef2019-08-20 06:47:51 -0700456 for (EncryptionLevel level :
457 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
458 QuicStreamSendBuffer* send_buffer = &substreams_[level].send_buffer;
459 const size_t data_length =
460 send_buffer->stream_offset() - send_buffer->stream_bytes_written();
461 if (data_length == 0) {
462 // No buffered data for this encryption level.
463 continue;
464 }
renjietang0c161c62020-03-05 13:13:53 -0800465 size_t bytes_consumed = stream_delegate()->SendCryptoData(
renjietang4d992bf2020-03-03 13:01:55 -0800466 level, data_length, send_buffer->stream_bytes_written(),
467 NOT_RETRANSMISSION);
fayangaee31ef2019-08-20 06:47:51 -0700468 send_buffer->OnStreamDataConsumed(bytes_consumed);
469 if (bytes_consumed < data_length) {
470 // Connection is write blocked.
471 break;
472 }
473 }
fayangaee31ef2019-08-20 06:47:51 -0700474}
475
476bool QuicCryptoStream::HasBufferedCryptoFrames() const {
renjietangd1d00852019-09-06 10:43:12 -0700477 QUIC_BUG_IF(!QuicVersionUsesCryptoFrames(session()->transport_version()))
fayangaee31ef2019-08-20 06:47:51 -0700478 << "Versions less than 47 don't use CRYPTO frames";
479 for (EncryptionLevel level :
480 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
481 const QuicStreamSendBuffer& send_buffer = substreams_[level].send_buffer;
482 DCHECK_GE(send_buffer.stream_offset(), send_buffer.stream_bytes_written());
483 if (send_buffer.stream_offset() > send_buffer.stream_bytes_written()) {
484 return true;
485 }
486 }
487 return false;
488}
489
QUICHE teama6ef0a62019-03-07 20:34:33 -0500490bool QuicCryptoStream::IsFrameOutstanding(EncryptionLevel level,
491 size_t offset,
492 size_t length) const {
renjietangd1d00852019-09-06 10:43:12 -0700493 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500494 // This only happens if a client was originally configured for a version
495 // greater than 45, but received a version negotiation packet and is
496 // attempting to retransmit for a version less than 47. Outside of tests,
497 // this is a misconfiguration of the client, and this connection will be
498 // doomed. Return false here to avoid trying to retransmit CRYPTO frames on
499 // the wrong transport version.
500 return false;
501 }
502 return substreams_[level].send_buffer.IsStreamDataOutstanding(offset, length);
503}
504
505bool QuicCryptoStream::IsWaitingForAcks() const {
renjietangd1d00852019-09-06 10:43:12 -0700506 if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500507 return QuicStream::IsWaitingForAcks();
508 }
509 for (EncryptionLevel level :
QUICHE team6987b4a2019-03-15 16:23:04 -0700510 {ENCRYPTION_INITIAL, ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500511 if (substreams_[level].send_buffer.stream_bytes_outstanding()) {
512 return true;
513 }
514 }
515 return false;
516}
517
518QuicCryptoStream::CryptoSubstream::CryptoSubstream(
519 QuicCryptoStream* crypto_stream,
520 EncryptionLevel)
521 : sequencer(crypto_stream),
522 send_buffer(crypto_stream->session()
523 ->connection()
524 ->helper()
525 ->GetStreamSendBufferAllocator()) {}
526
527#undef ENDPOINT // undef for jumbo builds
528} // namespace quic