blob: 1a148709665b48eda0932f9921e0a55bbfeb4eed [file] [log] [blame]
QUICHE teamfd50a402018-12-07 22:54:05 -05001// Copyright 2016 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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "http2/test_tools/frame_parts.h"
QUICHE teamfd50a402018-12-07 22:54:05 -05006
7#include <type_traits>
8
QUICHE team5be974e2020-12-29 18:35:24 -05009#include "http2/http2_structures_test_util.h"
10#include "http2/platform/api/http2_logging.h"
11#include "http2/platform/api/http2_string_utils.h"
12#include "http2/platform/api/http2_test_helpers.h"
13#include "common/platform/api/quiche_test.h"
QUICHE teamfd50a402018-12-07 22:54:05 -050014
15using ::testing::AssertionFailure;
16using ::testing::AssertionResult;
17using ::testing::AssertionSuccess;
18using ::testing::ContainerEq;
19
20namespace http2 {
21namespace test {
22namespace {
23
24static_assert(std::is_base_of<Http2FrameDecoderListener, FrameParts>::value &&
25 !std::is_abstract<FrameParts>::value,
26 "FrameParts needs to implement all of the methods of "
27 "Http2FrameDecoderListener");
28
29// Compare two optional variables of the same type.
30// TODO(jamessynge): Maybe create a ::testing::Matcher for this.
31template <class T>
32AssertionResult VerifyOptionalEq(const T& opt_a, const T& opt_b) {
33 if (opt_a) {
34 if (opt_b) {
35 VERIFY_EQ(opt_a.value(), opt_b.value());
36 } else {
37 return AssertionFailure()
38 << "opt_b is not set; opt_a.value()=" << opt_a.value();
39 }
40 } else if (opt_b) {
41 return AssertionFailure()
42 << "opt_a is not set; opt_b.value()=" << opt_b.value();
43 }
44 return AssertionSuccess();
45}
46
47} // namespace
48
49FrameParts::FrameParts(const Http2FrameHeader& header) : frame_header_(header) {
QUICHE team61940b42019-03-07 23:32:27 -050050 HTTP2_VLOG(1) << "FrameParts, header: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -050051}
52
bnc74646d12019-12-13 09:21:19 -080053FrameParts::FrameParts(const Http2FrameHeader& header,
vasilvv015e16a2020-10-12 23:51:06 -070054 absl::string_view payload)
QUICHE teamfd50a402018-12-07 22:54:05 -050055 : FrameParts(header) {
QUICHE team61940b42019-03-07 23:32:27 -050056 HTTP2_VLOG(1) << "FrameParts with payload.size() = " << payload.size();
QUICHE teamfd50a402018-12-07 22:54:05 -050057 this->payload_.append(payload.data(), payload.size());
58 opt_payload_length_ = payload.size();
59}
60FrameParts::FrameParts(const Http2FrameHeader& header,
vasilvv015e16a2020-10-12 23:51:06 -070061 absl::string_view payload,
QUICHE teamfd50a402018-12-07 22:54:05 -050062 size_t total_pad_length)
63 : FrameParts(header, payload) {
QUICHE team61940b42019-03-07 23:32:27 -050064 HTTP2_VLOG(1) << "FrameParts with total_pad_length=" << total_pad_length;
QUICHE teamfd50a402018-12-07 22:54:05 -050065 SetTotalPadLength(total_pad_length);
66}
67
68FrameParts::FrameParts(const FrameParts& header) = default;
69
70FrameParts::~FrameParts() = default;
71
72AssertionResult FrameParts::VerifyEquals(const FrameParts& that) const {
73#define COMMON_MESSAGE "\n this: " << *this << "\n that: " << that
74
75 VERIFY_EQ(frame_header_, that.frame_header_) << COMMON_MESSAGE;
76 VERIFY_EQ(payload_, that.payload_) << COMMON_MESSAGE;
77 VERIFY_EQ(padding_, that.padding_) << COMMON_MESSAGE;
78 VERIFY_EQ(altsvc_origin_, that.altsvc_origin_) << COMMON_MESSAGE;
79 VERIFY_EQ(altsvc_value_, that.altsvc_value_) << COMMON_MESSAGE;
80 VERIFY_THAT(settings_, ContainerEq(that.settings_)) << COMMON_MESSAGE;
81
82#define VERIFY_OPTIONAL_FIELD(field_name) \
83 VERIFY_SUCCESS(VerifyOptionalEq(field_name, that.field_name))
84
85 VERIFY_OPTIONAL_FIELD(opt_altsvc_origin_length_) << COMMON_MESSAGE;
86 VERIFY_OPTIONAL_FIELD(opt_altsvc_value_length_) << COMMON_MESSAGE;
bncbea13b82021-01-08 08:46:09 -080087 VERIFY_OPTIONAL_FIELD(opt_priority_update_) << COMMON_MESSAGE;
QUICHE teamfd50a402018-12-07 22:54:05 -050088 VERIFY_OPTIONAL_FIELD(opt_goaway_) << COMMON_MESSAGE;
89 VERIFY_OPTIONAL_FIELD(opt_missing_length_) << COMMON_MESSAGE;
90 VERIFY_OPTIONAL_FIELD(opt_pad_length_) << COMMON_MESSAGE;
91 VERIFY_OPTIONAL_FIELD(opt_ping_) << COMMON_MESSAGE;
92 VERIFY_OPTIONAL_FIELD(opt_priority_) << COMMON_MESSAGE;
93 VERIFY_OPTIONAL_FIELD(opt_push_promise_) << COMMON_MESSAGE;
94 VERIFY_OPTIONAL_FIELD(opt_rst_stream_error_code_) << COMMON_MESSAGE;
95 VERIFY_OPTIONAL_FIELD(opt_window_update_increment_) << COMMON_MESSAGE;
96
97#undef VERIFY_OPTIONAL_FIELD
98
99 return AssertionSuccess();
100}
101
102void FrameParts::SetTotalPadLength(size_t total_pad_length) {
103 opt_pad_length_.reset();
104 padding_.clear();
105 if (total_pad_length > 0) {
106 ASSERT_LE(total_pad_length, 256u);
107 ASSERT_TRUE(frame_header_.IsPadded());
108 opt_pad_length_ = total_pad_length - 1;
109 char zero = 0;
110 padding_.append(opt_pad_length_.value(), zero);
111 }
112
113 if (opt_pad_length_) {
QUICHE team61940b42019-03-07 23:32:27 -0500114 HTTP2_VLOG(1) << "SetTotalPadLength: pad_length="
115 << opt_pad_length_.value();
QUICHE teamfd50a402018-12-07 22:54:05 -0500116 } else {
QUICHE team61940b42019-03-07 23:32:27 -0500117 HTTP2_VLOG(1) << "SetTotalPadLength: has no pad length";
QUICHE teamfd50a402018-12-07 22:54:05 -0500118 }
119}
120
vasilvv015e16a2020-10-12 23:51:06 -0700121void FrameParts::SetAltSvcExpected(absl::string_view origin,
122 absl::string_view value) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500123 altsvc_origin_.append(origin.data(), origin.size());
124 altsvc_value_.append(value.data(), value.size());
125 opt_altsvc_origin_length_ = origin.size();
126 opt_altsvc_value_length_ = value.size();
127}
128
129bool FrameParts::OnFrameHeader(const Http2FrameHeader& header) {
130 ADD_FAILURE() << "OnFrameHeader: " << *this;
131 return true;
132}
133
134void FrameParts::OnDataStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500135 HTTP2_VLOG(1) << "OnDataStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500136 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::DATA)) << *this;
137 opt_payload_length_ = header.payload_length;
138}
139
140void FrameParts::OnDataPayload(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500141 HTTP2_VLOG(1) << "OnDataPayload: len=" << len
142 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500143 ASSERT_TRUE(InFrameOfType(Http2FrameType::DATA)) << *this;
vasilvv015e16a2020-10-12 23:51:06 -0700144 ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500145 &opt_payload_length_));
146}
147
148void FrameParts::OnDataEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500149 HTTP2_VLOG(1) << "OnDataEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500150 ASSERT_TRUE(EndFrameOfType(Http2FrameType::DATA)) << *this;
151}
152
153void FrameParts::OnHeadersStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500154 HTTP2_VLOG(1) << "OnHeadersStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500155 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::HEADERS)) << *this;
156 opt_payload_length_ = header.payload_length;
157}
158
159void FrameParts::OnHeadersPriority(const Http2PriorityFields& priority) {
QUICHE team61940b42019-03-07 23:32:27 -0500160 HTTP2_VLOG(1) << "OnHeadersPriority: priority: " << priority
161 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500162 ASSERT_TRUE(InFrameOfType(Http2FrameType::HEADERS)) << *this;
163 ASSERT_FALSE(opt_priority_);
164 opt_priority_ = priority;
165 ASSERT_TRUE(opt_payload_length_);
166 opt_payload_length_ =
167 opt_payload_length_.value() - Http2PriorityFields::EncodedSize();
168}
169
170void FrameParts::OnHpackFragment(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500171 HTTP2_VLOG(1) << "OnHpackFragment: len=" << len
172 << "; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500173 ASSERT_TRUE(got_start_callback_);
174 ASSERT_FALSE(got_end_callback_);
175 ASSERT_TRUE(FrameCanHaveHpackPayload(frame_header_)) << *this;
vasilvv015e16a2020-10-12 23:51:06 -0700176 ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500177 &opt_payload_length_));
178}
179
180void FrameParts::OnHeadersEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500181 HTTP2_VLOG(1) << "OnHeadersEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500182 ASSERT_TRUE(EndFrameOfType(Http2FrameType::HEADERS)) << *this;
183}
184
185void FrameParts::OnPriorityFrame(const Http2FrameHeader& header,
186 const Http2PriorityFields& priority) {
QUICHE team61940b42019-03-07 23:32:27 -0500187 HTTP2_VLOG(1) << "OnPriorityFrame: " << header << "; priority: " << priority;
QUICHE teamfd50a402018-12-07 22:54:05 -0500188 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY)) << *this;
189 ASSERT_FALSE(opt_priority_);
190 opt_priority_ = priority;
191 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY)) << *this;
192}
193
194void FrameParts::OnContinuationStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500195 HTTP2_VLOG(1) << "OnContinuationStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500196 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::CONTINUATION)) << *this;
197 opt_payload_length_ = header.payload_length;
198}
199
200void FrameParts::OnContinuationEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500201 HTTP2_VLOG(1) << "OnContinuationEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500202 ASSERT_TRUE(EndFrameOfType(Http2FrameType::CONTINUATION)) << *this;
203}
204
205void FrameParts::OnPadLength(size_t trailing_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500206 HTTP2_VLOG(1) << "OnPadLength: trailing_length=" << trailing_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500207 ASSERT_TRUE(InPaddedFrame()) << *this;
208 ASSERT_FALSE(opt_pad_length_);
209 ASSERT_TRUE(opt_payload_length_);
210 size_t total_padding_length = trailing_length + 1;
211 ASSERT_GE(opt_payload_length_.value(), total_padding_length);
212 opt_payload_length_ = opt_payload_length_.value() - total_padding_length;
213 opt_pad_length_ = trailing_length;
214}
215
216void FrameParts::OnPadding(const char* pad, size_t skipped_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500217 HTTP2_VLOG(1) << "OnPadding: skipped_length=" << skipped_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500218 ASSERT_TRUE(InPaddedFrame()) << *this;
219 ASSERT_TRUE(opt_pad_length_);
vasilvv015e16a2020-10-12 23:51:06 -0700220 ASSERT_TRUE(AppendString(absl::string_view(pad, skipped_length), &padding_,
221 &opt_pad_length_));
QUICHE teamfd50a402018-12-07 22:54:05 -0500222}
223
224void FrameParts::OnRstStream(const Http2FrameHeader& header,
225 Http2ErrorCode error_code) {
QUICHE team61940b42019-03-07 23:32:27 -0500226 HTTP2_VLOG(1) << "OnRstStream: " << header << "; code=" << error_code;
QUICHE teamfd50a402018-12-07 22:54:05 -0500227 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::RST_STREAM)) << *this;
228 ASSERT_FALSE(opt_rst_stream_error_code_);
229 opt_rst_stream_error_code_ = error_code;
230 ASSERT_TRUE(EndFrameOfType(Http2FrameType::RST_STREAM)) << *this;
231}
232
233void FrameParts::OnSettingsStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500234 HTTP2_VLOG(1) << "OnSettingsStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500235 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
236 ASSERT_EQ(0u, settings_.size());
237 ASSERT_FALSE(header.IsAck()) << header;
238}
239
240void FrameParts::OnSetting(const Http2SettingFields& setting_fields) {
QUICHE team61940b42019-03-07 23:32:27 -0500241 HTTP2_VLOG(1) << "OnSetting: " << setting_fields;
QUICHE teamfd50a402018-12-07 22:54:05 -0500242 ASSERT_TRUE(InFrameOfType(Http2FrameType::SETTINGS)) << *this;
243 settings_.push_back(setting_fields);
244}
245
246void FrameParts::OnSettingsEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500247 HTTP2_VLOG(1) << "OnSettingsEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500248 ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
249}
250
251void FrameParts::OnSettingsAck(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500252 HTTP2_VLOG(1) << "OnSettingsAck: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500253 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::SETTINGS)) << *this;
254 ASSERT_EQ(0u, settings_.size());
255 ASSERT_TRUE(header.IsAck());
256 ASSERT_TRUE(EndFrameOfType(Http2FrameType::SETTINGS)) << *this;
257}
258
259void FrameParts::OnPushPromiseStart(const Http2FrameHeader& header,
260 const Http2PushPromiseFields& promise,
261 size_t total_padding_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500262 HTTP2_VLOG(1) << "OnPushPromiseStart header: " << header
263 << "; promise: " << promise
264 << "; total_padding_length: " << total_padding_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500265 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PUSH_PROMISE)) << *this;
266 ASSERT_GE(header.payload_length, Http2PushPromiseFields::EncodedSize());
267 opt_payload_length_ =
268 header.payload_length - Http2PushPromiseFields::EncodedSize();
269 ASSERT_FALSE(opt_push_promise_);
270 opt_push_promise_ = promise;
271 if (total_padding_length > 0) {
272 ASSERT_GE(opt_payload_length_.value(), total_padding_length);
273 OnPadLength(total_padding_length - 1);
274 } else {
275 ASSERT_FALSE(header.IsPadded());
276 }
277}
278
279void FrameParts::OnPushPromiseEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500280 HTTP2_VLOG(1) << "OnPushPromiseEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500281 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PUSH_PROMISE)) << *this;
282}
283
284void FrameParts::OnPing(const Http2FrameHeader& header,
285 const Http2PingFields& ping) {
QUICHE team61940b42019-03-07 23:32:27 -0500286 HTTP2_VLOG(1) << "OnPing header: " << header << " ping: " << ping;
QUICHE teamfd50a402018-12-07 22:54:05 -0500287 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
288 ASSERT_FALSE(header.IsAck());
289 ASSERT_FALSE(opt_ping_);
290 opt_ping_ = ping;
291 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
292}
293
294void FrameParts::OnPingAck(const Http2FrameHeader& header,
295 const Http2PingFields& ping) {
QUICHE team61940b42019-03-07 23:32:27 -0500296 HTTP2_VLOG(1) << "OnPingAck header: " << header << " ping: " << ping;
QUICHE teamfd50a402018-12-07 22:54:05 -0500297 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PING)) << *this;
298 ASSERT_TRUE(header.IsAck());
299 ASSERT_FALSE(opt_ping_);
300 opt_ping_ = ping;
301 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PING)) << *this;
302}
303
304void FrameParts::OnGoAwayStart(const Http2FrameHeader& header,
305 const Http2GoAwayFields& goaway) {
QUICHE team61940b42019-03-07 23:32:27 -0500306 HTTP2_VLOG(1) << "OnGoAwayStart: " << goaway;
QUICHE teamfd50a402018-12-07 22:54:05 -0500307 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::GOAWAY)) << *this;
308 ASSERT_FALSE(opt_goaway_);
309 opt_goaway_ = goaway;
310 opt_payload_length_ =
311 header.payload_length - Http2GoAwayFields::EncodedSize();
312}
313
314void FrameParts::OnGoAwayOpaqueData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500315 HTTP2_VLOG(1) << "OnGoAwayOpaqueData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500316 ASSERT_TRUE(InFrameOfType(Http2FrameType::GOAWAY)) << *this;
vasilvv015e16a2020-10-12 23:51:06 -0700317 ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500318 &opt_payload_length_));
319}
320
321void FrameParts::OnGoAwayEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500322 HTTP2_VLOG(1) << "OnGoAwayEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500323 ASSERT_TRUE(EndFrameOfType(Http2FrameType::GOAWAY)) << *this;
324}
325
326void FrameParts::OnWindowUpdate(const Http2FrameHeader& header,
327 uint32_t increment) {
QUICHE team61940b42019-03-07 23:32:27 -0500328 HTTP2_VLOG(1) << "OnWindowUpdate header: " << header
329 << " increment=" << increment;
QUICHE teamfd50a402018-12-07 22:54:05 -0500330 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::WINDOW_UPDATE)) << *this;
331 ASSERT_FALSE(opt_window_update_increment_);
332 opt_window_update_increment_ = increment;
333 ASSERT_TRUE(EndFrameOfType(Http2FrameType::WINDOW_UPDATE)) << *this;
334}
335
336void FrameParts::OnAltSvcStart(const Http2FrameHeader& header,
337 size_t origin_length,
338 size_t value_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500339 HTTP2_VLOG(1) << "OnAltSvcStart: " << header
340 << " origin_length: " << origin_length
341 << " value_length: " << value_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500342 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::ALTSVC)) << *this;
343 ASSERT_FALSE(opt_altsvc_origin_length_);
344 opt_altsvc_origin_length_ = origin_length;
345 ASSERT_FALSE(opt_altsvc_value_length_);
346 opt_altsvc_value_length_ = value_length;
347}
348
349void FrameParts::OnAltSvcOriginData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500350 HTTP2_VLOG(1) << "OnAltSvcOriginData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500351 ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
vasilvv015e16a2020-10-12 23:51:06 -0700352 ASSERT_TRUE(AppendString(absl::string_view(data, len), &altsvc_origin_,
353 &opt_altsvc_origin_length_));
QUICHE teamfd50a402018-12-07 22:54:05 -0500354}
355
356void FrameParts::OnAltSvcValueData(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500357 HTTP2_VLOG(1) << "OnAltSvcValueData: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500358 ASSERT_TRUE(InFrameOfType(Http2FrameType::ALTSVC)) << *this;
vasilvv015e16a2020-10-12 23:51:06 -0700359 ASSERT_TRUE(AppendString(absl::string_view(data, len), &altsvc_value_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500360 &opt_altsvc_value_length_));
361}
362
363void FrameParts::OnAltSvcEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500364 HTTP2_VLOG(1) << "OnAltSvcEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500365 ASSERT_TRUE(EndFrameOfType(Http2FrameType::ALTSVC)) << *this;
366}
367
bncbea13b82021-01-08 08:46:09 -0800368void FrameParts::OnPriorityUpdateStart(
369 const Http2FrameHeader& header,
370 const Http2PriorityUpdateFields& priority_update) {
371 HTTP2_VLOG(1) << "OnPriorityUpdateStart: " << header
372 << " prioritized_stream_id: "
373 << priority_update.prioritized_stream_id;
374 ASSERT_TRUE(StartFrameOfType(header, Http2FrameType::PRIORITY_UPDATE))
375 << *this;
376 ASSERT_FALSE(opt_priority_update_);
377 opt_priority_update_ = priority_update;
378 opt_payload_length_ =
379 header.payload_length - Http2PriorityUpdateFields::EncodedSize();
380}
381
382void FrameParts::OnPriorityUpdatePayload(const char* data, size_t len) {
383 HTTP2_VLOG(1) << "OnPriorityUpdatePayload: len=" << len;
384 ASSERT_TRUE(InFrameOfType(Http2FrameType::PRIORITY_UPDATE)) << *this;
bnc9f5ac0f2021-01-11 08:00:56 -0800385 payload_.append(data, len);
bncbea13b82021-01-08 08:46:09 -0800386}
387
388void FrameParts::OnPriorityUpdateEnd() {
389 HTTP2_VLOG(1) << "OnPriorityUpdateEnd; frame_header_: " << frame_header_;
390 ASSERT_TRUE(EndFrameOfType(Http2FrameType::PRIORITY_UPDATE)) << *this;
391}
392
QUICHE teamfd50a402018-12-07 22:54:05 -0500393void FrameParts::OnUnknownStart(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500394 HTTP2_VLOG(1) << "OnUnknownStart: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500395 ASSERT_FALSE(IsSupportedHttp2FrameType(header.type)) << header;
396 ASSERT_FALSE(got_start_callback_);
397 ASSERT_EQ(frame_header_, header);
398 got_start_callback_ = true;
399 opt_payload_length_ = header.payload_length;
400}
401
402void FrameParts::OnUnknownPayload(const char* data, size_t len) {
QUICHE team61940b42019-03-07 23:32:27 -0500403 HTTP2_VLOG(1) << "OnUnknownPayload: len=" << len;
QUICHE teamfd50a402018-12-07 22:54:05 -0500404 ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
405 ASSERT_TRUE(got_start_callback_);
406 ASSERT_FALSE(got_end_callback_);
vasilvv015e16a2020-10-12 23:51:06 -0700407 ASSERT_TRUE(AppendString(absl::string_view(data, len), &payload_,
QUICHE teamfd50a402018-12-07 22:54:05 -0500408 &opt_payload_length_));
409}
410
411void FrameParts::OnUnknownEnd() {
QUICHE team61940b42019-03-07 23:32:27 -0500412 HTTP2_VLOG(1) << "OnUnknownEnd; frame_header_: " << frame_header_;
QUICHE teamfd50a402018-12-07 22:54:05 -0500413 ASSERT_FALSE(IsSupportedHttp2FrameType(frame_header_.type)) << *this;
414 ASSERT_TRUE(got_start_callback_);
415 ASSERT_FALSE(got_end_callback_);
416 got_end_callback_ = true;
417}
418
419void FrameParts::OnPaddingTooLong(const Http2FrameHeader& header,
420 size_t missing_length) {
QUICHE team61940b42019-03-07 23:32:27 -0500421 HTTP2_VLOG(1) << "OnPaddingTooLong: " << header
422 << "; missing_length: " << missing_length;
QUICHE teamfd50a402018-12-07 22:54:05 -0500423 ASSERT_EQ(frame_header_, header);
424 ASSERT_FALSE(got_end_callback_);
425 ASSERT_TRUE(FrameIsPadded(header));
426 ASSERT_FALSE(opt_pad_length_);
427 ASSERT_FALSE(opt_missing_length_);
428 opt_missing_length_ = missing_length;
429 got_start_callback_ = true;
430 got_end_callback_ = true;
431}
432
433void FrameParts::OnFrameSizeError(const Http2FrameHeader& header) {
QUICHE team61940b42019-03-07 23:32:27 -0500434 HTTP2_VLOG(1) << "OnFrameSizeError: " << header;
QUICHE teamfd50a402018-12-07 22:54:05 -0500435 ASSERT_EQ(frame_header_, header);
436 ASSERT_FALSE(got_end_callback_);
437 ASSERT_FALSE(has_frame_size_error_);
438 has_frame_size_error_ = true;
439 got_end_callback_ = true;
440}
441
442void FrameParts::OutputTo(std::ostream& out) const {
443 out << "FrameParts{\n frame_header_: " << frame_header_ << "\n";
444 if (!payload_.empty()) {
445 out << " payload_=\"" << Http2HexEscape(payload_) << "\"\n";
446 }
447 if (!padding_.empty()) {
448 out << " padding_=\"" << Http2HexEscape(padding_) << "\"\n";
449 }
450 if (!altsvc_origin_.empty()) {
451 out << " altsvc_origin_=\"" << Http2HexEscape(altsvc_origin_) << "\"\n";
452 }
453 if (!altsvc_value_.empty()) {
454 out << " altsvc_value_=\"" << Http2HexEscape(altsvc_value_) << "\"\n";
455 }
456 if (opt_priority_) {
457 out << " priority=" << opt_priority_.value() << "\n";
458 }
459 if (opt_rst_stream_error_code_) {
460 out << " rst_stream=" << opt_rst_stream_error_code_.value() << "\n";
461 }
462 if (opt_push_promise_) {
463 out << " push_promise=" << opt_push_promise_.value() << "\n";
464 }
465 if (opt_ping_) {
466 out << " ping=" << opt_ping_.value() << "\n";
467 }
468 if (opt_goaway_) {
469 out << " goaway=" << opt_goaway_.value() << "\n";
470 }
471 if (opt_window_update_increment_) {
472 out << " window_update=" << opt_window_update_increment_.value() << "\n";
473 }
474 if (opt_payload_length_) {
475 out << " payload_length=" << opt_payload_length_.value() << "\n";
476 }
477 if (opt_pad_length_) {
478 out << " pad_length=" << opt_pad_length_.value() << "\n";
479 }
480 if (opt_missing_length_) {
481 out << " missing_length=" << opt_missing_length_.value() << "\n";
482 }
483 if (opt_altsvc_origin_length_) {
484 out << " origin_length=" << opt_altsvc_origin_length_.value() << "\n";
485 }
486 if (opt_altsvc_value_length_) {
487 out << " value_length=" << opt_altsvc_value_length_.value() << "\n";
488 }
bncbea13b82021-01-08 08:46:09 -0800489 if (opt_priority_update_) {
490 out << " prioritized_stream_id_=" << opt_priority_update_.value() << "\n";
491 }
QUICHE teamfd50a402018-12-07 22:54:05 -0500492 if (has_frame_size_error_) {
493 out << " has_frame_size_error\n";
494 }
495 if (got_start_callback_) {
496 out << " got_start_callback\n";
497 }
498 if (got_end_callback_) {
499 out << " got_end_callback\n";
500 }
501 for (size_t ndx = 0; ndx < settings_.size(); ++ndx) {
502 out << " setting[" << ndx << "]=" << settings_[ndx];
503 }
504 out << "}";
505}
506
507AssertionResult FrameParts::StartFrameOfType(
508 const Http2FrameHeader& header,
509 Http2FrameType expected_frame_type) {
510 VERIFY_EQ(header.type, expected_frame_type);
511 VERIFY_FALSE(got_start_callback_);
512 VERIFY_FALSE(got_end_callback_);
513 VERIFY_EQ(frame_header_, header);
514 got_start_callback_ = true;
515 return AssertionSuccess();
516}
517
518AssertionResult FrameParts::InFrameOfType(Http2FrameType expected_frame_type) {
519 VERIFY_TRUE(got_start_callback_);
520 VERIFY_FALSE(got_end_callback_);
521 VERIFY_EQ(frame_header_.type, expected_frame_type);
522 return AssertionSuccess();
523}
524
525AssertionResult FrameParts::EndFrameOfType(Http2FrameType expected_frame_type) {
526 VERIFY_SUCCESS(InFrameOfType(expected_frame_type));
527 got_end_callback_ = true;
528 return AssertionSuccess();
529}
530
531AssertionResult FrameParts::InPaddedFrame() {
532 VERIFY_TRUE(got_start_callback_);
533 VERIFY_FALSE(got_end_callback_);
534 VERIFY_TRUE(FrameIsPadded(frame_header_));
535 return AssertionSuccess();
536}
537
vasilvv7df418b2020-10-13 13:47:09 -0700538AssertionResult FrameParts::AppendString(absl::string_view source,
539 std::string* target,
540 absl::optional<size_t>* opt_length) {
QUICHE teamfd50a402018-12-07 22:54:05 -0500541 target->append(source.data(), source.size());
542 if (opt_length != nullptr) {
543 VERIFY_TRUE(*opt_length) << "Length is not set yet\n" << *this;
544 VERIFY_LE(target->size(), opt_length->value())
545 << "String too large; source.size() = " << source.size() << "\n"
546 << *this;
547 }
548 return ::testing::AssertionSuccess();
549}
550
551std::ostream& operator<<(std::ostream& out, const FrameParts& v) {
552 v.OutputTo(out);
553 return out;
554}
555
556} // namespace test
557} // namespace http2