blob: 1e6cc54043a1c5743d60ead6831d6f71640e4dd6 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2018 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/tools/quic_tcp_like_trace_converter.h"
6
7#include "net/third_party/quiche/src/quic/core/quic_constants.h"
fayangf921a932020-05-29 14:39:11 -07008#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05009
10namespace quic {
11
12QuicTcpLikeTraceConverter::QuicTcpLikeTraceConverter()
13 : largest_observed_control_frame_id_(kInvalidControlFrameId),
14 connection_offset_(0) {}
15
16QuicTcpLikeTraceConverter::StreamOffsetSegment::StreamOffsetSegment()
17 : connection_offset(0) {}
18
19QuicTcpLikeTraceConverter::StreamOffsetSegment::StreamOffsetSegment(
20 QuicStreamOffset stream_offset,
21 uint64_t connection_offset,
22 QuicByteCount data_length)
23 : stream_data(stream_offset, stream_offset + data_length),
24 connection_offset(connection_offset) {}
25
26QuicTcpLikeTraceConverter::StreamInfo::StreamInfo() : fin(false) {}
27
fayangf921a932020-05-29 14:39:11 -070028QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnCryptoFrameSent(
29 EncryptionLevel level,
30 QuicStreamOffset offset,
31 QuicByteCount data_length) {
32 if (level >= NUM_ENCRYPTION_LEVELS) {
33 QUIC_BUG << "Invalid encryption level";
34 return {};
35 }
36 return OnFrameSent(offset, data_length, /*fin=*/false,
37 &crypto_frames_info_[level]);
38}
39
QUICHE teama6ef0a62019-03-07 20:34:33 -050040QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnStreamFrameSent(
41 QuicStreamId stream_id,
42 QuicStreamOffset offset,
43 QuicByteCount data_length,
44 bool fin) {
fayangf921a932020-05-29 14:39:11 -070045 return OnFrameSent(
46 offset, data_length, fin,
47 &streams_info_.emplace(stream_id, StreamInfo()).first->second);
48}
49
50QuicIntervalSet<uint64_t> QuicTcpLikeTraceConverter::OnFrameSent(
51 QuicStreamOffset offset,
52 QuicByteCount data_length,
53 bool fin,
54 StreamInfo* info) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050055 QuicIntervalSet<uint64_t> connection_offsets;
56 if (fin) {
57 // Stream fin consumes a connection offset.
58 ++data_length;
59 }
QUICHE teama6ef0a62019-03-07 20:34:33 -050060 // Get connection offsets of retransmission data in this frame.
fayangf921a932020-05-29 14:39:11 -070061 for (const auto& segment : info->segments) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050062 QuicInterval<QuicStreamOffset> retransmission(offset, offset + data_length);
63 retransmission.IntersectWith(segment.stream_data);
64 if (retransmission.Empty()) {
65 continue;
66 }
67 const uint64_t connection_offset = segment.connection_offset +
68 retransmission.min() -
69 segment.stream_data.min();
70 connection_offsets.Add(connection_offset,
71 connection_offset + retransmission.Length());
72 }
73
fayangf921a932020-05-29 14:39:11 -070074 if (info->fin) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050075 return connection_offsets;
76 }
77
78 // Get connection offsets of new data in this frame.
79 QuicStreamOffset least_unsent_offset =
fayangf921a932020-05-29 14:39:11 -070080 info->segments.empty() ? 0 : info->segments.back().stream_data.max();
QUICHE teama6ef0a62019-03-07 20:34:33 -050081 if (least_unsent_offset >= offset + data_length) {
82 return connection_offsets;
83 }
84 // Ignore out-of-order stream data so that as connection offset increases,
85 // stream offset increases.
86 QuicStreamOffset new_data_offset = std::max(least_unsent_offset, offset);
87 QuicByteCount new_data_length = offset + data_length - new_data_offset;
88 connection_offsets.Add(connection_offset_,
89 connection_offset_ + new_data_length);
fayangf921a932020-05-29 14:39:11 -070090 if (!info->segments.empty() && new_data_offset == least_unsent_offset &&
91 connection_offset_ == info->segments.back().connection_offset +
92 info->segments.back().stream_data.Length()) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050093 // Extend the last segment if both stream and connection offsets are
94 // contiguous.
fayangf921a932020-05-29 14:39:11 -070095 info->segments.back().stream_data.SetMax(new_data_offset + new_data_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 } else {
fayangf921a932020-05-29 14:39:11 -070097 info->segments.emplace_back(new_data_offset, connection_offset_,
98 new_data_length);
QUICHE teama6ef0a62019-03-07 20:34:33 -050099 }
fayangf921a932020-05-29 14:39:11 -0700100 info->fin = fin;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 connection_offset_ += new_data_length;
102
103 return connection_offsets;
104}
105
106QuicInterval<uint64_t> QuicTcpLikeTraceConverter::OnControlFrameSent(
107 QuicControlFrameId control_frame_id,
108 QuicByteCount control_frame_length) {
109 if (control_frame_id > largest_observed_control_frame_id_) {
110 // New control frame.
111 QuicInterval<uint64_t> connection_offset = QuicInterval<uint64_t>(
112 connection_offset_, connection_offset_ + control_frame_length);
113 connection_offset_ += control_frame_length;
fayang03e0cec2019-04-22 12:34:56 -0700114 control_frames_info_[control_frame_id] = connection_offset;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500115 largest_observed_control_frame_id_ = control_frame_id;
116 return connection_offset;
117 }
118 const auto iter = control_frames_info_.find(control_frame_id);
119 if (iter == control_frames_info_.end()) {
120 // Ignore out of order control frames.
121 return {};
122 }
123 return iter->second;
124}
125
126} // namespace quic