blob: 10e5e858a9cb5cab1ccf825432bd8a22a7d6ea9d [file] [log] [blame]
QUICHE team82dee2f2019-01-18 12:35:12 -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
5#include "net/third_party/quiche/src/spdy/core/spdy_deframer_visitor.h"
6
7#include <stdlib.h>
8
9#include <algorithm>
10#include <cstdint>
11#include <limits>
12#include <memory>
13
QUICHE team82dee2f2019-01-18 12:35:12 -050014#include "net/third_party/quiche/src/http2/platform/api/http2_macros.h"
bnc7f82d042020-01-03 12:18:53 -080015#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
QUICHE team82dee2f2019-01-18 12:35:12 -050016#include "net/third_party/quiche/src/spdy/core/hpack/hpack_constants.h"
17#include "net/third_party/quiche/src/spdy/core/mock_spdy_framer_visitor.h"
18#include "net/third_party/quiche/src/spdy/core/spdy_frame_reader.h"
19#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
20#include "net/third_party/quiche/src/spdy/core/spdy_test_utils.h"
21#include "net/third_party/quiche/src/spdy/platform/api/spdy_flags.h"
QUICHE teamded03512019-03-07 14:45:11 -080022#include "net/third_party/quiche/src/spdy/platform/api/spdy_logging.h"
QUICHE team82dee2f2019-01-18 12:35:12 -050023
24using ::testing::AssertionFailure;
25using ::testing::AssertionResult;
26using ::testing::AssertionSuccess;
27
28namespace spdy {
29namespace test {
30
31// Specify whether to process headers as request or response in visitor-related
32// params.
33enum class HeaderDirection { REQUEST, RESPONSE };
34
35// Types of HTTP/2 frames, per RFC 7540.
36// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
37enum Http2FrameType {
38 DATA = 0,
39 HEADERS = 1,
40 PRIORITY = 2,
41 RST_STREAM = 3,
42 SETTINGS = 4,
43 PUSH_PROMISE = 5,
44 PING = 6,
45 GOAWAY = 7,
46 WINDOW_UPDATE = 8,
47 CONTINUATION = 9,
48 ALTSVC = 10,
49
50 // Not a frame type.
51 UNSET = -1,
52 UNKNOWN = -2,
53};
54
55// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
56const char* Http2FrameTypeToString(Http2FrameType v) {
57 switch (v) {
58 case DATA:
59 return "DATA";
60 case HEADERS:
61 return "HEADERS";
62 case PRIORITY:
63 return "PRIORITY";
64 case RST_STREAM:
65 return "RST_STREAM";
66 case SETTINGS:
67 return "SETTINGS";
68 case PUSH_PROMISE:
69 return "PUSH_PROMISE";
70 case PING:
71 return "PING";
72 case GOAWAY:
73 return "GOAWAY";
74 case WINDOW_UPDATE:
75 return "WINDOW_UPDATE";
76 case CONTINUATION:
77 return "CONTINUATION";
78 case ALTSVC:
79 return "ALTSVC";
80 case UNSET:
81 return "UNSET";
82 case UNKNOWN:
83 return "UNKNOWN";
84 default:
85 return "Invalid Http2FrameType";
86 }
87}
88
89// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
90inline std::ostream& operator<<(std::ostream& out, Http2FrameType v) {
91 return out << Http2FrameTypeToString(v);
92}
93
94// Flag bits in the flag field of the common header of HTTP/2 frames
95// (see https://httpwg.github.io/specs/rfc7540.html#FrameHeader for details on
96// the fixed 9-octet header structure shared by all frames).
97// Flag bits are only valid for specified frame types.
98// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
99enum Http2HeaderFlag {
100 NO_FLAGS = 0,
101
102 END_STREAM_FLAG = 0x1,
103 ACK_FLAG = 0x1,
104 END_HEADERS_FLAG = 0x4,
105 PADDED_FLAG = 0x8,
106 PRIORITY_FLAG = 0x20,
107};
108
109// Returns name of frame type.
110// TODO(jamessynge): Switch to using http2/http2_constants.h when ready.
111const char* Http2FrameTypeToString(Http2FrameType v);
112
113void SpdyDeframerVisitorInterface::OnPingAck(
114 std::unique_ptr<SpdyPingIR> frame) {
115 OnPing(std::move(frame));
116}
117
118void SpdyDeframerVisitorInterface::OnSettingsAck(
119 std::unique_ptr<SpdySettingsIR> frame) {
120 OnSettings(std::move(frame), nullptr);
121}
122
123class SpdyTestDeframerImpl : public SpdyTestDeframer,
124 public SpdyHeadersHandlerInterface {
125 public:
126 explicit SpdyTestDeframerImpl(
127 std::unique_ptr<SpdyDeframerVisitorInterface> listener)
128 : listener_(std::move(listener)) {
129 CHECK(listener_ != nullptr);
130 }
131 SpdyTestDeframerImpl(const SpdyTestDeframerImpl&) = delete;
132 SpdyTestDeframerImpl& operator=(const SpdyTestDeframerImpl&) = delete;
133 ~SpdyTestDeframerImpl() override = default;
134
135 bool AtFrameEnd() override;
136
137 // Callbacks defined in SpdyFramerVisitorInterface. These are in the
138 // alphabetical order for ease of navigation, and are not in same order
139 // as in SpdyFramerVisitorInterface.
140 void OnAltSvc(SpdyStreamId stream_id,
bnc7f82d042020-01-03 12:18:53 -0800141 quiche::QuicheStringPiece origin,
QUICHE team82dee2f2019-01-18 12:35:12 -0500142 const SpdyAltSvcWireFormat::AlternativeServiceVector&
143 altsvc_vector) override;
144 void OnContinuation(SpdyStreamId stream_id, bool end) override;
145 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
146 SpdyStreamId stream_id) override;
147 void OnHeaderFrameEnd(SpdyStreamId stream_id) override;
148 void OnDataFrameHeader(SpdyStreamId stream_id,
149 size_t length,
150 bool fin) override;
151 void OnError(http2::Http2DecoderAdapter::SpdyFramerError error) override;
152 void OnGoAway(SpdyStreamId last_accepted_stream_id,
153 SpdyErrorCode error_code) override;
154 bool OnGoAwayFrameData(const char* goaway_data, size_t len) override;
155 void OnHeaders(SpdyStreamId stream_id,
156 bool has_priority,
157 int weight,
158 SpdyStreamId parent_stream_id,
159 bool exclusive,
160 bool fin,
161 bool end) override;
162 void OnPing(SpdyPingId unique_id, bool is_ack) override;
163 void OnPriority(SpdyStreamId stream_id,
164 SpdyStreamId parent_stream_id,
165 int weight,
166 bool exclusive) override;
167 void OnPushPromise(SpdyStreamId stream_id,
168 SpdyStreamId promised_stream_id,
169 bool end) override;
170 void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override;
171 void OnSetting(SpdySettingsId id, uint32_t value) override;
172 void OnSettings() override;
173 void OnSettingsAck() override;
174 void OnSettingsEnd() override;
175 void OnStreamFrameData(SpdyStreamId stream_id,
176 const char* data,
177 size_t len) override;
178 void OnStreamEnd(SpdyStreamId stream_id) override;
179 void OnStreamPadLength(SpdyStreamId stream_id, size_t value) override;
180 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override;
181 bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override;
182 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override;
183
184 // Callbacks defined in SpdyHeadersHandlerInterface.
185
186 void OnHeaderBlockStart() override;
bnc7f82d042020-01-03 12:18:53 -0800187 void OnHeader(quiche::QuicheStringPiece key,
188 quiche::QuicheStringPiece value) override;
QUICHE team82dee2f2019-01-18 12:35:12 -0500189 void OnHeaderBlockEnd(size_t header_bytes_parsed,
190 size_t compressed_header_bytes_parsed) override;
191
192 protected:
193 void AtDataEnd();
194 void AtGoAwayEnd();
195 void AtHeadersEnd();
196 void AtPushPromiseEnd();
197
198 // Per-physical frame state.
199 // Frame type of the frame currently being processed.
200 Http2FrameType frame_type_ = UNSET;
201 // Stream id of the frame currently being processed.
202 SpdyStreamId stream_id_;
203 // Did the most recent frame header include the END_HEADERS flag?
204 bool end_ = false;
205 // Did the most recent frame header include the ack flag?
206 bool ack_ = false;
207
208 // Per-HPACK block state. Only valid while processing a HEADERS or
209 // PUSH_PROMISE frame, and its CONTINUATION frames.
210 // Did the most recent HEADERS or PUSH_PROMISE include the END_STREAM flag?
211 // Note that this does not necessarily indicate that the current frame is
212 // the last frame for the stream (may be followed by CONTINUATION frames,
213 // may only half close).
214 bool fin_ = false;
215 bool got_hpack_end_ = false;
216
bnc44712912019-08-15 18:58:14 -0700217 std::unique_ptr<std::string> data_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500218
219 // Total length of the data frame.
220 size_t data_len_ = 0;
221
222 // Amount of skipped padding (i.e. total length of padding, including Pad
223 // Length field).
224 size_t padding_len_ = 0;
225
bnc44712912019-08-15 18:58:14 -0700226 std::unique_ptr<std::string> goaway_description_;
QUICHE team82dee2f2019-01-18 12:35:12 -0500227 std::unique_ptr<StringPairVector> headers_;
228 std::unique_ptr<SettingVector> settings_;
229 std::unique_ptr<TestHeadersHandler> headers_handler_;
230
231 std::unique_ptr<SpdyGoAwayIR> goaway_ir_;
232 std::unique_ptr<SpdyHeadersIR> headers_ir_;
233 std::unique_ptr<SpdyPushPromiseIR> push_promise_ir_;
234 std::unique_ptr<SpdySettingsIR> settings_ir_;
235
236 private:
237 std::unique_ptr<SpdyDeframerVisitorInterface> listener_;
238};
239
240// static
241std::unique_ptr<SpdyTestDeframer> SpdyTestDeframer::CreateConverter(
242 std::unique_ptr<SpdyDeframerVisitorInterface> listener) {
bnc463f2352019-10-10 04:49:34 -0700243 return std::make_unique<SpdyTestDeframerImpl>(std::move(listener));
QUICHE team82dee2f2019-01-18 12:35:12 -0500244}
245
246void SpdyTestDeframerImpl::AtDataEnd() {
QUICHE teamded03512019-03-07 14:45:11 -0800247 SPDY_DVLOG(1) << "AtDataEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500248 CHECK_EQ(data_len_, padding_len_ + data_->size());
bnc463f2352019-10-10 04:49:34 -0700249 auto ptr = std::make_unique<SpdyDataIR>(stream_id_, std::move(*data_));
QUICHE team82dee2f2019-01-18 12:35:12 -0500250 CHECK_EQ(0u, data_->size());
251 data_.reset();
252
253 CHECK_LE(0u, padding_len_);
254 CHECK_LE(padding_len_, 256u);
255 if (padding_len_ > 0) {
256 ptr->set_padding_len(padding_len_);
257 }
258 padding_len_ = 0;
259
260 ptr->set_fin(fin_);
261 listener_->OnData(std::move(ptr));
262 frame_type_ = UNSET;
263 fin_ = false;
264 data_len_ = 0;
265}
266
267void SpdyTestDeframerImpl::AtGoAwayEnd() {
QUICHE teamded03512019-03-07 14:45:11 -0800268 SPDY_DVLOG(1) << "AtDataEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500269 CHECK_EQ(frame_type_, GOAWAY);
270 if (HTTP2_DIE_IF_NULL(goaway_description_)->empty()) {
271 listener_->OnGoAway(std::move(goaway_ir_));
272 } else {
bnc463f2352019-10-10 04:49:34 -0700273 listener_->OnGoAway(std::make_unique<SpdyGoAwayIR>(
QUICHE team82dee2f2019-01-18 12:35:12 -0500274 goaway_ir_->last_good_stream_id(), goaway_ir_->error_code(),
275 std::move(*goaway_description_)));
276 CHECK_EQ(0u, goaway_description_->size());
277 }
278 goaway_description_.reset();
279 goaway_ir_.reset();
280 frame_type_ = UNSET;
281}
282
283void SpdyTestDeframerImpl::AtHeadersEnd() {
QUICHE teamded03512019-03-07 14:45:11 -0800284 SPDY_DVLOG(1) << "AtDataEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500285 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION)
286 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
287 CHECK(end_) << " frame_type_=" << Http2FrameTypeToString(frame_type_);
288 CHECK(got_hpack_end_);
289
290 CHECK(headers_ir_ != nullptr);
291 CHECK(headers_ != nullptr);
292 CHECK(headers_handler_ != nullptr);
293
294 CHECK_LE(0u, padding_len_);
295 CHECK_LE(padding_len_, 256u);
296 if (padding_len_ > 0) {
297 headers_ir_->set_padding_len(padding_len_);
298 }
299 padding_len_ = 0;
300
301 headers_ir_->set_header_block(headers_handler_->decoded_block().Clone());
302 headers_handler_.reset();
303 listener_->OnHeaders(std::move(headers_ir_), std::move(headers_));
304
305 frame_type_ = UNSET;
306 fin_ = false;
307 end_ = false;
308 got_hpack_end_ = false;
309}
310
311void SpdyTestDeframerImpl::AtPushPromiseEnd() {
QUICHE teamded03512019-03-07 14:45:11 -0800312 SPDY_DVLOG(1) << "AtDataEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500313 CHECK(frame_type_ == PUSH_PROMISE || frame_type_ == CONTINUATION)
314 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
315 CHECK(end_) << " frame_type_=" << Http2FrameTypeToString(frame_type_);
316
317 CHECK(push_promise_ir_ != nullptr);
318 CHECK(headers_ != nullptr);
319 CHECK(headers_handler_ != nullptr);
320
321 CHECK_EQ(headers_ir_.get(), nullptr);
322
323 CHECK_LE(0u, padding_len_);
324 CHECK_LE(padding_len_, 256u);
325 if (padding_len_ > 0) {
326 push_promise_ir_->set_padding_len(padding_len_);
327 }
328 padding_len_ = 0;
329
330 push_promise_ir_->set_header_block(headers_handler_->decoded_block().Clone());
331 headers_handler_.reset();
332 listener_->OnPushPromise(std::move(push_promise_ir_), std::move(headers_));
333
334 frame_type_ = UNSET;
335 end_ = false;
336}
337
338bool SpdyTestDeframerImpl::AtFrameEnd() {
339 bool incomplete_logical_header = false;
340 // The caller says that the SpdyFrame has reached the end of the frame,
341 // so if we have any accumulated data, flush it.
342 switch (frame_type_) {
343 case DATA:
344 AtDataEnd();
345 break;
346
347 case GOAWAY:
348 AtGoAwayEnd();
349 break;
350
351 case HEADERS:
352 if (end_) {
353 AtHeadersEnd();
354 } else {
355 incomplete_logical_header = true;
356 }
357 break;
358
359 case PUSH_PROMISE:
360 if (end_) {
361 AtPushPromiseEnd();
362 } else {
363 incomplete_logical_header = true;
364 }
365 break;
366
367 case CONTINUATION:
368 if (end_) {
369 if (headers_ir_) {
370 AtHeadersEnd();
371 } else if (push_promise_ir_) {
372 AtPushPromiseEnd();
373 } else {
QUICHE teamded03512019-03-07 14:45:11 -0800374 SPDY_LOG(FATAL) << "Where is the SpdyFrameIR for the headers!";
QUICHE team82dee2f2019-01-18 12:35:12 -0500375 }
376 } else {
377 incomplete_logical_header = true;
378 }
379 break;
380
381 case UNSET:
382 // Except for the frame types above, the others don't leave any record
383 // in the state of this object. Make sure nothing got left by accident.
384 CHECK_EQ(data_.get(), nullptr);
385 CHECK_EQ(goaway_description_.get(), nullptr);
386 CHECK_EQ(goaway_ir_.get(), nullptr);
387 CHECK_EQ(headers_.get(), nullptr);
388 CHECK_EQ(headers_handler_.get(), nullptr);
389 CHECK_EQ(headers_ir_.get(), nullptr);
390 CHECK_EQ(push_promise_ir_.get(), nullptr);
391 CHECK_EQ(settings_.get(), nullptr);
392 CHECK_EQ(settings_ir_.get(), nullptr);
393 break;
394
395 default:
396 SPDY_BUG << "Expected UNSET, instead frame_type_==" << frame_type_;
397 return false;
398 }
399 frame_type_ = UNSET;
400 stream_id_ = 0;
401 end_ = false;
402 ack_ = false;
403 if (!incomplete_logical_header) {
404 fin_ = false;
405 }
406 return true;
407}
408
409// Overridden methods from SpdyFramerVisitorInterface in alpha order...
410
411void SpdyTestDeframerImpl::OnAltSvc(
412 SpdyStreamId stream_id,
bnc7f82d042020-01-03 12:18:53 -0800413 quiche::QuicheStringPiece origin,
QUICHE team82dee2f2019-01-18 12:35:12 -0500414 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) {
QUICHE teamded03512019-03-07 14:45:11 -0800415 SPDY_DVLOG(1) << "OnAltSvc stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500416 CHECK_EQ(frame_type_, UNSET)
417 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
418 CHECK_GT(stream_id, 0u);
bnc463f2352019-10-10 04:49:34 -0700419 auto ptr = std::make_unique<SpdyAltSvcIR>(stream_id);
bnc44712912019-08-15 18:58:14 -0700420 ptr->set_origin(std::string(origin));
QUICHE team82dee2f2019-01-18 12:35:12 -0500421 for (auto& altsvc : altsvc_vector) {
422 ptr->add_altsvc(altsvc);
423 }
424 listener_->OnAltSvc(std::move(ptr));
425}
426
427// A CONTINUATION frame contains a Header Block Fragment, and immediately
428// follows another frame that contains a Header Block Fragment (HEADERS,
429// PUSH_PROMISE or CONTINUATION). The last such frame has the END flag set.
430// SpdyFramer ensures that the behavior is correct before calling the visitor.
431void SpdyTestDeframerImpl::OnContinuation(SpdyStreamId stream_id, bool end) {
QUICHE teamded03512019-03-07 14:45:11 -0800432 SPDY_DVLOG(1) << "OnContinuation stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500433 CHECK_EQ(frame_type_, UNSET)
434 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
435 CHECK_GT(stream_id, 0u);
436 CHECK_NE(nullptr, headers_.get());
437 frame_type_ = CONTINUATION;
438
439 stream_id_ = stream_id;
440 end_ = end;
441}
442
443// Note that length includes the padding length (0 to 256, when the optional
444// padding length field is counted). Padding comes after the payload, both
445// for DATA frames and for control frames.
446void SpdyTestDeframerImpl::OnDataFrameHeader(SpdyStreamId stream_id,
447 size_t length,
448 bool fin) {
QUICHE teamded03512019-03-07 14:45:11 -0800449 SPDY_DVLOG(1) << "OnDataFrameHeader stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500450 CHECK_EQ(frame_type_, UNSET)
451 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
452 CHECK_GT(stream_id, 0u);
453 CHECK_EQ(data_.get(), nullptr);
454 frame_type_ = DATA;
455
456 stream_id_ = stream_id;
457 fin_ = fin;
458 data_len_ = length;
bnc463f2352019-10-10 04:49:34 -0700459 data_ = std::make_unique<std::string>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500460}
461
462// The SpdyFramer will not process any more data at this point.
463void SpdyTestDeframerImpl::OnError(
464 http2::Http2DecoderAdapter::SpdyFramerError error) {
QUICHE teamded03512019-03-07 14:45:11 -0800465 SPDY_DVLOG(1) << "SpdyFramer detected an error in the stream: "
466 << http2::Http2DecoderAdapter::SpdyFramerErrorToString(error)
467 << " frame_type_: " << Http2FrameTypeToString(frame_type_);
QUICHE team82dee2f2019-01-18 12:35:12 -0500468 listener_->OnError(error, this);
469}
470
471// Received a GOAWAY frame from the peer. The last stream id it accepted from us
472// is |last_accepted_stream_id|. |status| is a protocol defined error code.
473// The frame may also contain data. After this OnGoAwayFrameData will be called
474// for any non-zero amount of data, and after that it will be called with len==0
475// to indicate the end of the GOAWAY frame.
476void SpdyTestDeframerImpl::OnGoAway(SpdyStreamId last_good_stream_id,
477 SpdyErrorCode error_code) {
QUICHE teamded03512019-03-07 14:45:11 -0800478 SPDY_DVLOG(1) << "OnGoAway last_good_stream_id: " << last_good_stream_id
479 << " error code: " << error_code;
QUICHE team82dee2f2019-01-18 12:35:12 -0500480 CHECK_EQ(frame_type_, UNSET)
481 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
482 frame_type_ = GOAWAY;
483 goaway_ir_ =
bnc463f2352019-10-10 04:49:34 -0700484 std::make_unique<SpdyGoAwayIR>(last_good_stream_id, error_code, "");
485 goaway_description_ = std::make_unique<std::string>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500486}
487
488// If len==0 then we've reached the end of the GOAWAY frame.
489bool SpdyTestDeframerImpl::OnGoAwayFrameData(const char* goaway_data,
490 size_t len) {
QUICHE teamded03512019-03-07 14:45:11 -0800491 SPDY_DVLOG(1) << "OnGoAwayFrameData";
QUICHE team82dee2f2019-01-18 12:35:12 -0500492 CHECK_EQ(frame_type_, GOAWAY)
493 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
494 CHECK(goaway_description_ != nullptr);
495 goaway_description_->append(goaway_data, len);
496 return true;
497}
498
499SpdyHeadersHandlerInterface* SpdyTestDeframerImpl::OnHeaderFrameStart(
danzh8f3a5762019-06-25 13:43:51 -0700500 SpdyStreamId /*stream_id*/) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500501 return this;
502}
503
504void SpdyTestDeframerImpl::OnHeaderFrameEnd(SpdyStreamId stream_id) {
QUICHE teamded03512019-03-07 14:45:11 -0800505 SPDY_DVLOG(1) << "OnHeaderFrameEnd stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500506}
507
508// Received the fixed portion of a HEADERS frame. Called before the variable
509// length (including zero length) Header Block Fragment is processed. If fin
510// is true then there will be no DATA or trailing HEADERS after this HEADERS
511// frame.
512// If end is true, then there will be no CONTINUATION frame(s) following this
513// frame; else if true then there will be CONTINATION frames(s) immediately
514// following this frame, terminated by a CONTINUATION frame with end==true.
515void SpdyTestDeframerImpl::OnHeaders(SpdyStreamId stream_id,
516 bool has_priority,
517 int weight,
518 SpdyStreamId parent_stream_id,
519 bool exclusive,
520 bool fin,
521 bool end) {
QUICHE teamded03512019-03-07 14:45:11 -0800522 SPDY_DVLOG(1) << "OnHeaders stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500523 CHECK_EQ(frame_type_, UNSET)
524 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
525 CHECK_GT(stream_id, 0u);
526 frame_type_ = HEADERS;
527
528 stream_id_ = stream_id;
529 fin_ = fin;
530 end_ = end;
531
bnc463f2352019-10-10 04:49:34 -0700532 headers_ = std::make_unique<StringPairVector>();
533 headers_handler_ = std::make_unique<TestHeadersHandler>();
534 headers_ir_ = std::make_unique<SpdyHeadersIR>(stream_id);
QUICHE team82dee2f2019-01-18 12:35:12 -0500535 headers_ir_->set_fin(fin);
536 if (has_priority) {
537 headers_ir_->set_has_priority(true);
538 headers_ir_->set_weight(weight);
539 headers_ir_->set_parent_stream_id(parent_stream_id);
540 headers_ir_->set_exclusive(exclusive);
541 }
542}
543
544// The HTTP/2 protocol refers to the payload, |unique_id| here, as 8 octets of
545// opaque data that is to be echoed back to the sender, with the ACK bit added.
546// It isn't defined as a counter,
547// or frame id, as the SpdyPingId naming might imply.
548// Responding to a PING is supposed to be at the highest priority.
549void SpdyTestDeframerImpl::OnPing(uint64_t unique_id, bool is_ack) {
QUICHE teamded03512019-03-07 14:45:11 -0800550 SPDY_DVLOG(1) << "OnPing unique_id: " << unique_id
551 << " is_ack: " << (is_ack ? "true" : "false");
QUICHE team82dee2f2019-01-18 12:35:12 -0500552 CHECK_EQ(frame_type_, UNSET)
553 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
bnc463f2352019-10-10 04:49:34 -0700554 auto ptr = std::make_unique<SpdyPingIR>(unique_id);
QUICHE team82dee2f2019-01-18 12:35:12 -0500555 if (is_ack) {
556 ptr->set_is_ack(is_ack);
557 listener_->OnPingAck(std::move(ptr));
558 } else {
559 listener_->OnPing(std::move(ptr));
560 }
561}
562
563void SpdyTestDeframerImpl::OnPriority(SpdyStreamId stream_id,
564 SpdyStreamId parent_stream_id,
565 int weight,
566 bool exclusive) {
QUICHE teamded03512019-03-07 14:45:11 -0800567 SPDY_DVLOG(1) << "OnPriority stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500568 CHECK_EQ(frame_type_, UNSET)
569 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
570 CHECK_GT(stream_id, 0u);
571
bnc463f2352019-10-10 04:49:34 -0700572 listener_->OnPriority(std::make_unique<SpdyPriorityIR>(
QUICHE team82dee2f2019-01-18 12:35:12 -0500573 stream_id, parent_stream_id, weight, exclusive));
574}
575
576void SpdyTestDeframerImpl::OnPushPromise(SpdyStreamId stream_id,
577 SpdyStreamId promised_stream_id,
578 bool end) {
QUICHE teamded03512019-03-07 14:45:11 -0800579 SPDY_DVLOG(1) << "OnPushPromise stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500580 CHECK_EQ(frame_type_, UNSET)
581 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
582 CHECK_GT(stream_id, 0u);
583
584 frame_type_ = PUSH_PROMISE;
585 stream_id_ = stream_id;
586 end_ = end;
587
bnc463f2352019-10-10 04:49:34 -0700588 headers_ = std::make_unique<StringPairVector>();
589 headers_handler_ = std::make_unique<TestHeadersHandler>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500590 push_promise_ir_ =
bnc463f2352019-10-10 04:49:34 -0700591 std::make_unique<SpdyPushPromiseIR>(stream_id, promised_stream_id);
QUICHE team82dee2f2019-01-18 12:35:12 -0500592}
593
594// Closes the specified stream. After this the sender may still send PRIORITY
595// frames for this stream, which we can ignore.
596void SpdyTestDeframerImpl::OnRstStream(SpdyStreamId stream_id,
597 SpdyErrorCode error_code) {
QUICHE teamded03512019-03-07 14:45:11 -0800598 SPDY_DVLOG(1) << "OnRstStream stream_id: " << stream_id
599 << " error code: " << error_code;
QUICHE team82dee2f2019-01-18 12:35:12 -0500600 CHECK_EQ(frame_type_, UNSET)
601 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
602 CHECK_GT(stream_id, 0u);
603
604 listener_->OnRstStream(
bnc463f2352019-10-10 04:49:34 -0700605 std::make_unique<SpdyRstStreamIR>(stream_id, error_code));
QUICHE team82dee2f2019-01-18 12:35:12 -0500606}
607
608// Called for an individual setting. There is no negotiation; the sender is
609// stating the value that the sender is using.
610void SpdyTestDeframerImpl::OnSetting(SpdySettingsId id, uint32_t value) {
QUICHE teamded03512019-03-07 14:45:11 -0800611 SPDY_DVLOG(1) << "OnSetting id: " << id << std::hex << " value: " << value;
QUICHE team82dee2f2019-01-18 12:35:12 -0500612 CHECK_EQ(frame_type_, SETTINGS)
613 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
614 CHECK(settings_ != nullptr);
615 SpdyKnownSettingsId known_id;
616 if (ParseSettingsId(id, &known_id)) {
617 settings_->push_back(std::make_pair(known_id, value));
618 settings_ir_->AddSetting(known_id, value);
619 }
620}
621
622// Called at the start of a SETTINGS frame with setting entries, but not the
623// (required) ACK of a SETTINGS frame. There is no stream_id because
624// the settings apply to the entire connection, not to an individual stream.
625void SpdyTestDeframerImpl::OnSettings() {
QUICHE teamded03512019-03-07 14:45:11 -0800626 SPDY_DVLOG(1) << "OnSettings";
QUICHE team82dee2f2019-01-18 12:35:12 -0500627 CHECK_EQ(frame_type_, UNSET)
628 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
629 CHECK_EQ(nullptr, settings_ir_.get());
630 CHECK_EQ(nullptr, settings_.get());
631 frame_type_ = SETTINGS;
632 ack_ = false;
633
bnc463f2352019-10-10 04:49:34 -0700634 settings_ = std::make_unique<SettingVector>();
635 settings_ir_ = std::make_unique<SpdySettingsIR>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500636}
637
638void SpdyTestDeframerImpl::OnSettingsAck() {
QUICHE teamded03512019-03-07 14:45:11 -0800639 SPDY_DVLOG(1) << "OnSettingsAck";
QUICHE team82dee2f2019-01-18 12:35:12 -0500640 CHECK_EQ(frame_type_, UNSET)
641 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
bnc463f2352019-10-10 04:49:34 -0700642 auto ptr = std::make_unique<SpdySettingsIR>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500643 ptr->set_is_ack(true);
644 listener_->OnSettingsAck(std::move(ptr));
645}
646
647void SpdyTestDeframerImpl::OnSettingsEnd() {
QUICHE teamded03512019-03-07 14:45:11 -0800648 SPDY_DVLOG(1) << "OnSettingsEnd";
QUICHE team82dee2f2019-01-18 12:35:12 -0500649 CHECK_EQ(frame_type_, SETTINGS)
650 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
651 CHECK(!ack_);
652 CHECK_NE(nullptr, settings_ir_.get());
653 CHECK_NE(nullptr, settings_.get());
654 listener_->OnSettings(std::move(settings_ir_), std::move(settings_));
655 frame_type_ = UNSET;
656}
657
658// Called for a zero length DATA frame with the END_STREAM flag set, or at the
659// end a complete HPACK block (and its padding) that started with a HEADERS
660// frame with the END_STREAM flag set. Doesn't apply to PUSH_PROMISE frames
661// because they don't have END_STREAM flags.
662void SpdyTestDeframerImpl::OnStreamEnd(SpdyStreamId stream_id) {
QUICHE teamded03512019-03-07 14:45:11 -0800663 SPDY_DVLOG(1) << "OnStreamEnd stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500664 CHECK_EQ(stream_id_, stream_id);
665 CHECK(frame_type_ == DATA || frame_type_ == HEADERS ||
666 frame_type_ == CONTINUATION)
667 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
668 CHECK(fin_);
669}
670
671// The data arg points into the non-padding payload of a DATA frame.
672// This must be a DATA frame (i.e. this method will not be
673// called for HEADERS or CONTINUATION frames).
674// This method may be called multiple times for a single DATA frame, depending
675// upon buffer boundaries.
676void SpdyTestDeframerImpl::OnStreamFrameData(SpdyStreamId stream_id,
677 const char* data,
678 size_t len) {
QUICHE teamded03512019-03-07 14:45:11 -0800679 SPDY_DVLOG(1) << "OnStreamFrameData stream_id: " << stream_id
680 << " len: " << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500681 CHECK_EQ(stream_id_, stream_id);
682 CHECK_EQ(frame_type_, DATA);
683 data_->append(data, len);
684}
685
686// Called when receiving the padding length field at the start of the DATA frame
687// payload. value will be in the range 0 to 255.
688void SpdyTestDeframerImpl::OnStreamPadLength(SpdyStreamId stream_id,
689 size_t value) {
QUICHE teamded03512019-03-07 14:45:11 -0800690 SPDY_DVLOG(1) << "OnStreamPadding stream_id: " << stream_id
691 << " value: " << value;
QUICHE team82dee2f2019-01-18 12:35:12 -0500692 CHECK(frame_type_ == DATA || frame_type_ == HEADERS ||
693 frame_type_ == PUSH_PROMISE)
694 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
695 CHECK_EQ(stream_id_, stream_id);
696 CHECK_GE(255u, value);
697 // Count the padding length byte against total padding.
698 padding_len_ += 1;
699 CHECK_EQ(1u, padding_len_);
700}
701
702// Called when padding is skipped over at the end of the DATA frame. len will
703// be in the range 1 to 255.
704void SpdyTestDeframerImpl::OnStreamPadding(SpdyStreamId stream_id, size_t len) {
QUICHE teamded03512019-03-07 14:45:11 -0800705 SPDY_DVLOG(1) << "OnStreamPadding stream_id: " << stream_id
706 << " len: " << len;
QUICHE team82dee2f2019-01-18 12:35:12 -0500707 CHECK(frame_type_ == DATA || frame_type_ == HEADERS ||
708 frame_type_ == PUSH_PROMISE)
709 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
710 CHECK_EQ(stream_id_, stream_id);
711 CHECK_LE(1u, len);
712 CHECK_GE(255u, len);
713 padding_len_ += len;
714 CHECK_LE(padding_len_, 256u) << "len=" << len;
715}
716
717// WINDOW_UPDATE is supposed to be hop-by-hop, according to the spec.
718// stream_id is 0 if the update applies to the connection, else stream_id
719// will be the id of a stream previously seen, which maybe half or fully
720// closed.
721void SpdyTestDeframerImpl::OnWindowUpdate(SpdyStreamId stream_id,
722 int delta_window_size) {
QUICHE teamded03512019-03-07 14:45:11 -0800723 SPDY_DVLOG(1) << "OnWindowUpdate stream_id: " << stream_id
724 << " delta_window_size: " << delta_window_size;
QUICHE team82dee2f2019-01-18 12:35:12 -0500725 CHECK_EQ(frame_type_, UNSET)
726 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
727 CHECK_NE(0, delta_window_size);
728
729 listener_->OnWindowUpdate(
bnc463f2352019-10-10 04:49:34 -0700730 std::make_unique<SpdyWindowUpdateIR>(stream_id, delta_window_size));
QUICHE team82dee2f2019-01-18 12:35:12 -0500731}
732
733// Return true to indicate that the stream_id is valid; if not valid then
734// SpdyFramer considers the connection corrupted. Requires keeping track
735// of the set of currently open streams. For now we'll assume that unknown
736// frame types are unsupported.
737bool SpdyTestDeframerImpl::OnUnknownFrame(SpdyStreamId stream_id,
danzh8f3a5762019-06-25 13:43:51 -0700738 uint8_t /*frame_type*/) {
QUICHE teamded03512019-03-07 14:45:11 -0800739 SPDY_DVLOG(1) << "OnAltSvc stream_id: " << stream_id;
QUICHE team82dee2f2019-01-18 12:35:12 -0500740 CHECK_EQ(frame_type_, UNSET)
741 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
742 frame_type_ = UNKNOWN;
743
744 stream_id_ = stream_id;
745 return false;
746}
747
748// Callbacks defined in SpdyHeadersHandlerInterface.
749
750void SpdyTestDeframerImpl::OnHeaderBlockStart() {
751 CHECK(frame_type_ == HEADERS || frame_type_ == PUSH_PROMISE)
752 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
753 CHECK(headers_ != nullptr);
754 CHECK_EQ(0u, headers_->size());
755 got_hpack_end_ = false;
756}
757
bnc7f82d042020-01-03 12:18:53 -0800758void SpdyTestDeframerImpl::OnHeader(quiche::QuicheStringPiece key,
759 quiche::QuicheStringPiece value) {
QUICHE team82dee2f2019-01-18 12:35:12 -0500760 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION ||
761 frame_type_ == PUSH_PROMISE)
762 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
763 CHECK(!got_hpack_end_);
bnc44712912019-08-15 18:58:14 -0700764 HTTP2_DIE_IF_NULL(headers_)->emplace_back(std::string(key),
765 std::string(value));
QUICHE team82dee2f2019-01-18 12:35:12 -0500766 HTTP2_DIE_IF_NULL(headers_handler_)->OnHeader(key, value);
767}
768
769void SpdyTestDeframerImpl::OnHeaderBlockEnd(
770 size_t /* header_bytes_parsed */,
771 size_t /* compressed_header_bytes_parsed */) {
772 CHECK(headers_ != nullptr);
773 CHECK(frame_type_ == HEADERS || frame_type_ == CONTINUATION ||
774 frame_type_ == PUSH_PROMISE)
775 << " frame_type_=" << Http2FrameTypeToString(frame_type_);
776 CHECK(end_);
777 CHECK(!got_hpack_end_);
778 got_hpack_end_ = true;
779}
780
781class LoggingSpdyDeframerDelegate : public SpdyDeframerVisitorInterface {
782 public:
783 explicit LoggingSpdyDeframerDelegate(
784 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped)
785 : wrapped_(std::move(wrapped)) {
786 if (!wrapped_) {
bnc463f2352019-10-10 04:49:34 -0700787 wrapped_ = std::make_unique<SpdyDeframerVisitorInterface>();
QUICHE team82dee2f2019-01-18 12:35:12 -0500788 }
789 }
790 ~LoggingSpdyDeframerDelegate() override = default;
791
792 void OnAltSvc(std::unique_ptr<SpdyAltSvcIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800793 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnAltSvc";
QUICHE team82dee2f2019-01-18 12:35:12 -0500794 wrapped_->OnAltSvc(std::move(frame));
795 }
796 void OnData(std::unique_ptr<SpdyDataIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800797 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnData";
QUICHE team82dee2f2019-01-18 12:35:12 -0500798 wrapped_->OnData(std::move(frame));
799 }
800 void OnGoAway(std::unique_ptr<SpdyGoAwayIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800801 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnGoAway";
QUICHE team82dee2f2019-01-18 12:35:12 -0500802 wrapped_->OnGoAway(std::move(frame));
803 }
804
805 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
806 // significantly modifies the headers, so the actual header entries (name
807 // and value strings) are provided in a vector.
808 void OnHeaders(std::unique_ptr<SpdyHeadersIR> frame,
809 std::unique_ptr<StringPairVector> headers) override {
QUICHE teamded03512019-03-07 14:45:11 -0800810 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnHeaders";
QUICHE team82dee2f2019-01-18 12:35:12 -0500811 wrapped_->OnHeaders(std::move(frame), std::move(headers));
812 }
813
814 void OnPing(std::unique_ptr<SpdyPingIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800815 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPing";
QUICHE team82dee2f2019-01-18 12:35:12 -0500816 wrapped_->OnPing(std::move(frame));
817 }
818 void OnPingAck(std::unique_ptr<SpdyPingIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800819 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPingAck";
QUICHE team82dee2f2019-01-18 12:35:12 -0500820 wrapped_->OnPingAck(std::move(frame));
821 }
822
823 void OnPriority(std::unique_ptr<SpdyPriorityIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800824 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPriority";
QUICHE team82dee2f2019-01-18 12:35:12 -0500825 wrapped_->OnPriority(std::move(frame));
826 }
827
828 // SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
829 // significantly modifies the headers, so the actual header entries (name
830 // and value strings) are provided in a vector.
831 void OnPushPromise(std::unique_ptr<SpdyPushPromiseIR> frame,
832 std::unique_ptr<StringPairVector> headers) override {
QUICHE teamded03512019-03-07 14:45:11 -0800833 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnPushPromise";
QUICHE team82dee2f2019-01-18 12:35:12 -0500834 wrapped_->OnPushPromise(std::move(frame), std::move(headers));
835 }
836
837 void OnRstStream(std::unique_ptr<SpdyRstStreamIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800838 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnRstStream";
QUICHE team82dee2f2019-01-18 12:35:12 -0500839 wrapped_->OnRstStream(std::move(frame));
840 }
841
842 // SpdySettingsIR has a map for settings, so loses info about the order of
843 // settings, and whether the same setting appeared more than once, so the
844 // the actual settings (parameter and value) are provided in a vector.
845 void OnSettings(std::unique_ptr<SpdySettingsIR> frame,
846 std::unique_ptr<SettingVector> settings) override {
QUICHE teamded03512019-03-07 14:45:11 -0800847 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnSettings";
QUICHE team82dee2f2019-01-18 12:35:12 -0500848 wrapped_->OnSettings(std::move(frame), std::move(settings));
849 }
850
851 // A settings frame with an ACK has no content, but for uniformity passing
852 // a frame with the ACK flag set.
853 void OnSettingsAck(std::unique_ptr<SpdySettingsIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800854 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnSettingsAck";
QUICHE team82dee2f2019-01-18 12:35:12 -0500855 wrapped_->OnSettingsAck(std::move(frame));
856 }
857
858 void OnWindowUpdate(std::unique_ptr<SpdyWindowUpdateIR> frame) override {
QUICHE teamded03512019-03-07 14:45:11 -0800859 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnWindowUpdate";
QUICHE team82dee2f2019-01-18 12:35:12 -0500860 wrapped_->OnWindowUpdate(std::move(frame));
861 }
862
863 // The SpdyFramer will not process any more data at this point.
864 void OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
865 SpdyTestDeframer* deframer) override {
QUICHE teamded03512019-03-07 14:45:11 -0800866 SPDY_DVLOG(1) << "LoggingSpdyDeframerDelegate::OnError";
QUICHE team82dee2f2019-01-18 12:35:12 -0500867 wrapped_->OnError(error, deframer);
868 }
869
870 private:
871 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_;
872};
873
874// static
875std::unique_ptr<SpdyDeframerVisitorInterface>
876SpdyDeframerVisitorInterface::LogBeforeVisiting(
877 std::unique_ptr<SpdyDeframerVisitorInterface> wrapped_listener) {
bnc463f2352019-10-10 04:49:34 -0700878 return std::make_unique<LoggingSpdyDeframerDelegate>(
QUICHE team82dee2f2019-01-18 12:35:12 -0500879 std::move(wrapped_listener));
880}
881
882CollectedFrame::CollectedFrame() = default;
883
884CollectedFrame::CollectedFrame(CollectedFrame&& other)
885 : frame_ir(std::move(other.frame_ir)),
886 headers(std::move(other.headers)),
887 settings(std::move(other.settings)),
888 error_reported(other.error_reported) {}
889
890CollectedFrame::~CollectedFrame() = default;
891
892CollectedFrame& CollectedFrame::operator=(CollectedFrame&& other) {
893 frame_ir = std::move(other.frame_ir);
894 headers = std::move(other.headers);
895 settings = std::move(other.settings);
896 error_reported = other.error_reported;
897 return *this;
898}
899
900AssertionResult CollectedFrame::VerifyHasHeaders(
901 const StringPairVector& expected_headers) const {
902 VERIFY_NE(headers.get(), nullptr);
903 VERIFY_THAT(*headers, ::testing::ContainerEq(expected_headers));
904 return AssertionSuccess();
905}
906
907AssertionResult CollectedFrame::VerifyHasSettings(
908 const SettingVector& expected_settings) const {
909 VERIFY_NE(settings.get(), nullptr);
910 VERIFY_THAT(*settings, testing::ContainerEq(expected_settings));
911 return AssertionSuccess();
912}
913
914DeframerCallbackCollector::DeframerCallbackCollector(
915 std::vector<CollectedFrame>* collected_frames)
916 : collected_frames_(HTTP2_DIE_IF_NULL(collected_frames)) {}
917
918void DeframerCallbackCollector::OnAltSvc(
919 std::unique_ptr<SpdyAltSvcIR> frame_ir) {
920 CollectedFrame cf;
921 cf.frame_ir = std::move(frame_ir);
922 collected_frames_->push_back(std::move(cf));
923}
924void DeframerCallbackCollector::OnData(std::unique_ptr<SpdyDataIR> frame_ir) {
925 CollectedFrame cf;
926 cf.frame_ir = std::move(frame_ir);
927 collected_frames_->push_back(std::move(cf));
928}
929void DeframerCallbackCollector::OnGoAway(
930 std::unique_ptr<SpdyGoAwayIR> frame_ir) {
931 CollectedFrame cf;
932 cf.frame_ir = std::move(frame_ir);
933 collected_frames_->push_back(std::move(cf));
934}
935
936// SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
937// significantly modifies the headers, so the actual header entries (name
938// and value strings) are provided in a vector.
939void DeframerCallbackCollector::OnHeaders(
940 std::unique_ptr<SpdyHeadersIR> frame_ir,
941 std::unique_ptr<StringPairVector> headers) {
942 CollectedFrame cf;
943 cf.frame_ir = std::move(frame_ir);
944 cf.headers = std::move(headers);
945 collected_frames_->push_back(std::move(cf));
946}
947
948void DeframerCallbackCollector::OnPing(std::unique_ptr<SpdyPingIR> frame_ir) {
949 EXPECT_TRUE(frame_ir && !frame_ir->is_ack());
950 CollectedFrame cf;
951 cf.frame_ir = std::move(frame_ir);
952 collected_frames_->push_back(std::move(cf));
953}
954
955void DeframerCallbackCollector::OnPingAck(
956 std::unique_ptr<SpdyPingIR> frame_ir) {
957 EXPECT_TRUE(frame_ir && frame_ir->is_ack());
958 CollectedFrame cf;
959 cf.frame_ir = std::move(frame_ir);
960 collected_frames_->push_back(std::move(cf));
961}
962
963void DeframerCallbackCollector::OnPriority(
964 std::unique_ptr<SpdyPriorityIR> frame_ir) {
965 CollectedFrame cf;
966 cf.frame_ir = std::move(frame_ir);
967 collected_frames_->push_back(std::move(cf));
968}
969
970// SpdyHeadersIR and SpdyPushPromiseIR each has a SpdyHeaderBlock which
971// significantly modifies the headers, so the actual header entries (name
972// and value strings) are provided in a vector.
973void DeframerCallbackCollector::OnPushPromise(
974 std::unique_ptr<SpdyPushPromiseIR> frame_ir,
975 std::unique_ptr<StringPairVector> headers) {
976 CollectedFrame cf;
977 cf.frame_ir = std::move(frame_ir);
978 cf.headers = std::move(headers);
979 collected_frames_->push_back(std::move(cf));
980}
981
982void DeframerCallbackCollector::OnRstStream(
983 std::unique_ptr<SpdyRstStreamIR> frame_ir) {
984 CollectedFrame cf;
985 cf.frame_ir = std::move(frame_ir);
986 collected_frames_->push_back(std::move(cf));
987}
988
989// SpdySettingsIR has a map for settings, so loses info about the order of
990// settings, and whether the same setting appeared more than once, so the
991// the actual settings (parameter and value) are provided in a vector.
992void DeframerCallbackCollector::OnSettings(
993 std::unique_ptr<SpdySettingsIR> frame_ir,
994 std::unique_ptr<SettingVector> settings) {
995 EXPECT_TRUE(frame_ir && !frame_ir->is_ack());
996 CollectedFrame cf;
997 cf.frame_ir = std::move(frame_ir);
998 cf.settings = std::move(settings);
999 collected_frames_->push_back(std::move(cf));
1000}
1001
1002// A settings frame_ir with an ACK has no content, but for uniformity passing
1003// a frame_ir with the ACK flag set.
1004void DeframerCallbackCollector::OnSettingsAck(
1005 std::unique_ptr<SpdySettingsIR> frame_ir) {
1006 EXPECT_TRUE(frame_ir && frame_ir->is_ack());
1007 CollectedFrame cf;
1008 cf.frame_ir = std::move(frame_ir);
1009 collected_frames_->push_back(std::move(cf));
1010}
1011
1012void DeframerCallbackCollector::OnWindowUpdate(
1013 std::unique_ptr<SpdyWindowUpdateIR> frame_ir) {
1014 CollectedFrame cf;
1015 cf.frame_ir = std::move(frame_ir);
1016 collected_frames_->push_back(std::move(cf));
1017}
1018
1019// The SpdyFramer will not process any more data at this point.
1020void DeframerCallbackCollector::OnError(
danzh8f3a5762019-06-25 13:43:51 -07001021 http2::Http2DecoderAdapter::SpdyFramerError /*error*/,
1022 SpdyTestDeframer* /*deframer*/) {
QUICHE team82dee2f2019-01-18 12:35:12 -05001023 CollectedFrame cf;
1024 cf.error_reported = true;
1025 collected_frames_->push_back(std::move(cf));
1026}
1027
1028} // namespace test
1029} // namespace spdy