1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/spdy/core/spdy_framer.h"
6
7 #include <stdlib.h>
8
9 #include <algorithm>
10 #include <cstdint>
11 #include <cstring>
12 #include <ios>
13 #include <limits>
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18
19 #include "absl/base/macros.h"
20 #include "absl/strings/string_view.h"
21 #include "quiche/common/platform/api/quiche_logging.h"
22 #include "quiche/common/platform/api/quiche_test.h"
23 #include "quiche/common/quiche_text_utils.h"
24 #include "quiche/spdy/core/array_output_buffer.h"
25 #include "quiche/spdy/core/hpack/hpack_encoder.h"
26 #include "quiche/spdy/core/http2_frame_decoder_adapter.h"
27 #include "quiche/spdy/core/http2_header_block.h"
28 #include "quiche/spdy/core/recording_headers_handler.h"
29 #include "quiche/spdy/core/spdy_alt_svc_wire_format.h"
30 #include "quiche/spdy/core/spdy_bitmasks.h"
31 #include "quiche/spdy/core/spdy_frame_builder.h"
32 #include "quiche/spdy/core/spdy_headers_handler_interface.h"
33 #include "quiche/spdy/core/spdy_protocol.h"
34 #include "quiche/spdy/test_tools/mock_spdy_framer_visitor.h"
35 #include "quiche/spdy/test_tools/spdy_test_utils.h"
36
37 using ::http2::Http2DecoderAdapter;
38 using ::testing::_;
39
40 namespace spdy {
41
42 namespace test {
43
44 namespace {
45
46 const int64_t kSize = 1024 * 1024;
47 char output_buffer[kSize] = "";
48
49 // frame_list_char is used to hold frames to be compared with output_buffer.
50 const int64_t buffer_size = 64 * 1024;
51 char frame_list_char[buffer_size] = "";
52 } // namespace
53
54 class MockDebugVisitor : public SpdyFramerDebugVisitorInterface {
55 public:
56 MOCK_METHOD(void, OnSendCompressedFrame,
57 (SpdyStreamId stream_id, SpdyFrameType type, size_t payload_len,
58 size_t frame_len),
59 (override));
60
61 MOCK_METHOD(void, OnReceiveCompressedFrame,
62 (SpdyStreamId stream_id, SpdyFrameType type, size_t frame_len),
63 (override));
64 };
65
66 MATCHER_P(IsFrameUnionOf, frame_list, "") {
67 size_t size_verified = 0;
68 for (const auto& frame : *frame_list) {
69 if (arg.size() < size_verified + frame.size()) {
70 QUICHE_LOG(FATAL)
71 << "Incremental header serialization should not lead to a "
72 << "higher total frame length than non-incremental method.";
73 return false;
74 }
75 if (memcmp(arg.data() + size_verified, frame.data(), frame.size())) {
76 CompareCharArraysWithHexError(
77 "Header serialization methods should be equivalent: ",
78 reinterpret_cast<unsigned char*>(arg.data() + size_verified),
79 frame.size(), reinterpret_cast<unsigned char*>(frame.data()),
80 frame.size());
81 return false;
82 }
83 size_verified += frame.size();
84 }
85 return size_verified == arg.size();
86 }
87
88 class SpdyFramerPeer {
89 public:
90 // TODO(dahollings): Remove these methods when deprecating non-incremental
91 // header serialization path.
CloneSpdyHeadersIR(const SpdyHeadersIR & headers)92 static std::unique_ptr<SpdyHeadersIR> CloneSpdyHeadersIR(
93 const SpdyHeadersIR& headers) {
94 auto new_headers = std::make_unique<SpdyHeadersIR>(
95 headers.stream_id(), headers.header_block().Clone());
96 new_headers->set_fin(headers.fin());
97 new_headers->set_has_priority(headers.has_priority());
98 new_headers->set_weight(headers.weight());
99 new_headers->set_parent_stream_id(headers.parent_stream_id());
100 new_headers->set_exclusive(headers.exclusive());
101 if (headers.padded()) {
102 new_headers->set_padding_len(headers.padding_payload_len() + 1);
103 }
104 return new_headers;
105 }
106
SerializeHeaders(SpdyFramer * framer,const SpdyHeadersIR & headers)107 static SpdySerializedFrame SerializeHeaders(SpdyFramer* framer,
108 const SpdyHeadersIR& headers) {
109 SpdySerializedFrame serialized_headers_old_version(
110 framer->SerializeHeaders(headers));
111 framer->hpack_encoder_.reset(nullptr);
112 auto* saved_debug_visitor = framer->debug_visitor_;
113 framer->debug_visitor_ = nullptr;
114
115 std::vector<SpdySerializedFrame> frame_list;
116 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
117 SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
118 while (it.HasNextFrame()) {
119 size_t size_before = frame_list_buffer.Size();
120 EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
121 frame_list.emplace_back(
122 MakeSerializedFrame(frame_list_buffer.Begin() + size_before,
123 frame_list_buffer.Size() - size_before));
124 }
125 framer->debug_visitor_ = saved_debug_visitor;
126
127 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
128 return serialized_headers_old_version;
129 }
130
SerializeHeaders(SpdyFramer * framer,const SpdyHeadersIR & headers,ArrayOutputBuffer * output)131 static SpdySerializedFrame SerializeHeaders(SpdyFramer* framer,
132 const SpdyHeadersIR& headers,
133 ArrayOutputBuffer* output) {
134 if (output == nullptr) {
135 return SerializeHeaders(framer, headers);
136 }
137 output->Reset();
138 EXPECT_TRUE(framer->SerializeHeaders(headers, output));
139 SpdySerializedFrame serialized_headers_old_version =
140 MakeSerializedFrame(output->Begin(), output->Size());
141 framer->hpack_encoder_.reset(nullptr);
142 auto* saved_debug_visitor = framer->debug_visitor_;
143 framer->debug_visitor_ = nullptr;
144
145 std::vector<SpdySerializedFrame> frame_list;
146 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
147 SpdyFramer::SpdyHeaderFrameIterator it(framer, CloneSpdyHeadersIR(headers));
148 while (it.HasNextFrame()) {
149 size_t size_before = frame_list_buffer.Size();
150 EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
151 frame_list.emplace_back(
152 MakeSerializedFrame(frame_list_buffer.Begin() + size_before,
153 frame_list_buffer.Size() - size_before));
154 }
155 framer->debug_visitor_ = saved_debug_visitor;
156
157 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
158 return serialized_headers_old_version;
159 }
160
CloneSpdyPushPromiseIR(const SpdyPushPromiseIR & push_promise)161 static std::unique_ptr<SpdyPushPromiseIR> CloneSpdyPushPromiseIR(
162 const SpdyPushPromiseIR& push_promise) {
163 auto new_push_promise = std::make_unique<SpdyPushPromiseIR>(
164 push_promise.stream_id(), push_promise.promised_stream_id(),
165 push_promise.header_block().Clone());
166 new_push_promise->set_fin(push_promise.fin());
167 if (push_promise.padded()) {
168 new_push_promise->set_padding_len(push_promise.padding_payload_len() + 1);
169 }
170 return new_push_promise;
171 }
172
SerializePushPromise(SpdyFramer * framer,const SpdyPushPromiseIR & push_promise)173 static SpdySerializedFrame SerializePushPromise(
174 SpdyFramer* framer, const SpdyPushPromiseIR& push_promise) {
175 SpdySerializedFrame serialized_headers_old_version =
176 framer->SerializePushPromise(push_promise);
177 framer->hpack_encoder_.reset(nullptr);
178 auto* saved_debug_visitor = framer->debug_visitor_;
179 framer->debug_visitor_ = nullptr;
180
181 std::vector<SpdySerializedFrame> frame_list;
182 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
183 frame_list_buffer.Reset();
184 SpdyFramer::SpdyPushPromiseFrameIterator it(
185 framer, CloneSpdyPushPromiseIR(push_promise));
186 while (it.HasNextFrame()) {
187 size_t size_before = frame_list_buffer.Size();
188 EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
189 frame_list.emplace_back(
190 MakeSerializedFrame(frame_list_buffer.Begin() + size_before,
191 frame_list_buffer.Size() - size_before));
192 }
193 framer->debug_visitor_ = saved_debug_visitor;
194
195 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
196 return serialized_headers_old_version;
197 }
198
SerializePushPromise(SpdyFramer * framer,const SpdyPushPromiseIR & push_promise,ArrayOutputBuffer * output)199 static SpdySerializedFrame SerializePushPromise(
200 SpdyFramer* framer, const SpdyPushPromiseIR& push_promise,
201 ArrayOutputBuffer* output) {
202 if (output == nullptr) {
203 return SerializePushPromise(framer, push_promise);
204 }
205 output->Reset();
206 EXPECT_TRUE(framer->SerializePushPromise(push_promise, output));
207 SpdySerializedFrame serialized_headers_old_version =
208 MakeSerializedFrame(output->Begin(), output->Size());
209 framer->hpack_encoder_.reset(nullptr);
210 auto* saved_debug_visitor = framer->debug_visitor_;
211 framer->debug_visitor_ = nullptr;
212
213 std::vector<SpdySerializedFrame> frame_list;
214 ArrayOutputBuffer frame_list_buffer(frame_list_char, buffer_size);
215 frame_list_buffer.Reset();
216 SpdyFramer::SpdyPushPromiseFrameIterator it(
217 framer, CloneSpdyPushPromiseIR(push_promise));
218 while (it.HasNextFrame()) {
219 size_t size_before = frame_list_buffer.Size();
220 EXPECT_GT(it.NextFrame(&frame_list_buffer), 0u);
221 frame_list.emplace_back(
222 MakeSerializedFrame(frame_list_buffer.Begin() + size_before,
223 frame_list_buffer.Size() - size_before));
224 }
225 framer->debug_visitor_ = saved_debug_visitor;
226
227 EXPECT_THAT(serialized_headers_old_version, IsFrameUnionOf(&frame_list));
228 return serialized_headers_old_version;
229 }
230 };
231
232 class TestSpdyVisitor : public SpdyFramerVisitorInterface,
233 public SpdyFramerDebugVisitorInterface {
234 public:
235 // This is larger than our max frame size because header blocks that
236 // are too long can spill over into CONTINUATION frames.
237 static constexpr size_t kDefaultHeaderBufferSize = 16 * 1024 * 1024;
238
TestSpdyVisitor(SpdyFramer::CompressionOption option)239 explicit TestSpdyVisitor(SpdyFramer::CompressionOption option)
240 : framer_(option),
241 error_count_(0),
242 headers_frame_count_(0),
243 push_promise_frame_count_(0),
244 goaway_count_(0),
245 setting_count_(0),
246 settings_ack_sent_(0),
247 settings_ack_received_(0),
248 continuation_count_(0),
249 altsvc_count_(0),
250 priority_count_(0),
251 unknown_frame_count_(0),
252 on_unknown_frame_result_(false),
253 last_window_update_stream_(0),
254 last_window_update_delta_(0),
255 last_push_promise_stream_(0),
256 last_push_promise_promised_stream_(0),
257 data_bytes_(0),
258 fin_frame_count_(0),
259 fin_flag_count_(0),
260 end_of_stream_count_(0),
261 control_frame_header_data_count_(0),
262 zero_length_control_frame_header_data_count_(0),
263 data_frame_count_(0),
264 last_payload_len_(0),
265 last_frame_len_(0),
266 unknown_payload_len_(0),
267 header_buffer_(new char[kDefaultHeaderBufferSize]),
268 header_buffer_length_(0),
269 header_buffer_size_(kDefaultHeaderBufferSize),
270 header_stream_id_(static_cast<SpdyStreamId>(-1)),
271 header_control_type_(SpdyFrameType::DATA),
272 header_buffer_valid_(false) {}
273
OnError(Http2DecoderAdapter::SpdyFramerError error,std::string)274 void OnError(Http2DecoderAdapter::SpdyFramerError error,
275 std::string /*detailed_error*/) override {
276 QUICHE_VLOG(1) << "SpdyFramer Error: "
277 << Http2DecoderAdapter::SpdyFramerErrorToString(error);
278 ++error_count_;
279 }
280
OnDataFrameHeader(SpdyStreamId stream_id,size_t length,bool fin)281 void OnDataFrameHeader(SpdyStreamId stream_id, size_t length,
282 bool fin) override {
283 QUICHE_VLOG(1) << "OnDataFrameHeader(" << stream_id << ", " << length
284 << ", " << fin << ")";
285 ++data_frame_count_;
286 header_stream_id_ = stream_id;
287 }
288
OnStreamFrameData(SpdyStreamId stream_id,const char * data,size_t len)289 void OnStreamFrameData(SpdyStreamId stream_id, const char* data,
290 size_t len) override {
291 QUICHE_VLOG(1) << "OnStreamFrameData(" << stream_id << ", data, " << len
292 << ", "
293 << ") data:\n"
294 << quiche::QuicheTextUtils::HexDump(
295 absl::string_view(data, len));
296 EXPECT_EQ(header_stream_id_, stream_id);
297
298 data_bytes_ += len;
299 }
300
OnStreamEnd(SpdyStreamId stream_id)301 void OnStreamEnd(SpdyStreamId stream_id) override {
302 QUICHE_VLOG(1) << "OnStreamEnd(" << stream_id << ")";
303 EXPECT_EQ(header_stream_id_, stream_id);
304 ++end_of_stream_count_;
305 }
306
OnStreamPadLength(SpdyStreamId stream_id,size_t value)307 void OnStreamPadLength(SpdyStreamId stream_id, size_t value) override {
308 QUICHE_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << value << ")\n";
309 EXPECT_EQ(header_stream_id_, stream_id);
310 // Count the padding length field byte against total data bytes.
311 data_bytes_ += 1;
312 }
313
OnStreamPadding(SpdyStreamId stream_id,size_t len)314 void OnStreamPadding(SpdyStreamId stream_id, size_t len) override {
315 QUICHE_VLOG(1) << "OnStreamPadding(" << stream_id << ", " << len << ")\n";
316 EXPECT_EQ(header_stream_id_, stream_id);
317 data_bytes_ += len;
318 }
319
OnHeaderFrameStart(SpdyStreamId)320 SpdyHeadersHandlerInterface* OnHeaderFrameStart(
321 SpdyStreamId /*stream_id*/) override {
322 if (headers_handler_ == nullptr) {
323 headers_handler_ = std::make_unique<RecordingHeadersHandler>();
324 }
325 return headers_handler_.get();
326 }
327
OnHeaderFrameEnd(SpdyStreamId)328 void OnHeaderFrameEnd(SpdyStreamId /*stream_id*/) override {
329 QUICHE_CHECK(headers_handler_ != nullptr);
330 headers_ = headers_handler_->decoded_block().Clone();
331 header_bytes_received_ = headers_handler_->uncompressed_header_bytes();
332 headers_handler_.reset();
333 }
334
OnRstStream(SpdyStreamId stream_id,SpdyErrorCode error_code)335 void OnRstStream(SpdyStreamId stream_id, SpdyErrorCode error_code) override {
336 QUICHE_VLOG(1) << "OnRstStream(" << stream_id << ", " << error_code << ")";
337 ++fin_frame_count_;
338 }
339
OnSetting(SpdySettingsId id,uint32_t value)340 void OnSetting(SpdySettingsId id, uint32_t value) override {
341 QUICHE_VLOG(1) << "OnSetting(" << id << ", " << std::hex << value << ")";
342 ++setting_count_;
343 }
344
OnSettingsAck()345 void OnSettingsAck() override {
346 QUICHE_VLOG(1) << "OnSettingsAck";
347 ++settings_ack_received_;
348 }
349
OnSettingsEnd()350 void OnSettingsEnd() override {
351 QUICHE_VLOG(1) << "OnSettingsEnd";
352 ++settings_ack_sent_;
353 }
354
OnPing(SpdyPingId unique_id,bool is_ack)355 void OnPing(SpdyPingId unique_id, bool is_ack) override {
356 QUICHE_LOG(DFATAL) << "OnPing(" << unique_id << ", " << (is_ack ? 1 : 0)
357 << ")";
358 }
359
OnGoAway(SpdyStreamId last_accepted_stream_id,SpdyErrorCode error_code)360 void OnGoAway(SpdyStreamId last_accepted_stream_id,
361 SpdyErrorCode error_code) override {
362 QUICHE_VLOG(1) << "OnGoAway(" << last_accepted_stream_id << ", "
363 << error_code << ")";
364 ++goaway_count_;
365 }
366
OnHeaders(SpdyStreamId stream_id,size_t payload_length,bool has_priority,int weight,SpdyStreamId parent_stream_id,bool exclusive,bool fin,bool end)367 void OnHeaders(SpdyStreamId stream_id, size_t payload_length,
368 bool has_priority, int weight, SpdyStreamId parent_stream_id,
369 bool exclusive, bool fin, bool end) override {
370 QUICHE_VLOG(1) << "OnHeaders(" << stream_id << ", " << payload_length
371 << ", " << has_priority << ", " << weight << ", "
372 << parent_stream_id << ", " << exclusive << ", " << fin
373 << ", " << end << ")";
374 ++headers_frame_count_;
375 InitHeaderStreaming(SpdyFrameType::HEADERS, stream_id);
376 if (fin) {
377 ++fin_flag_count_;
378 }
379 header_has_priority_ = has_priority;
380 header_parent_stream_id_ = parent_stream_id;
381 header_exclusive_ = exclusive;
382 }
383
OnWindowUpdate(SpdyStreamId stream_id,int delta_window_size)384 void OnWindowUpdate(SpdyStreamId stream_id, int delta_window_size) override {
385 QUICHE_VLOG(1) << "OnWindowUpdate(" << stream_id << ", "
386 << delta_window_size << ")";
387 last_window_update_stream_ = stream_id;
388 last_window_update_delta_ = delta_window_size;
389 }
390
OnPushPromise(SpdyStreamId stream_id,SpdyStreamId promised_stream_id,bool end)391 void OnPushPromise(SpdyStreamId stream_id, SpdyStreamId promised_stream_id,
392 bool end) override {
393 QUICHE_VLOG(1) << "OnPushPromise(" << stream_id << ", "
394 << promised_stream_id << ", " << end << ")";
395 ++push_promise_frame_count_;
396 InitHeaderStreaming(SpdyFrameType::PUSH_PROMISE, stream_id);
397 last_push_promise_stream_ = stream_id;
398 last_push_promise_promised_stream_ = promised_stream_id;
399 }
400
OnContinuation(SpdyStreamId stream_id,size_t payload_size,bool end)401 void OnContinuation(SpdyStreamId stream_id, size_t payload_size,
402 bool end) override {
403 QUICHE_VLOG(1) << "OnContinuation(" << stream_id << ", " << payload_size
404 << ", " << end << ")";
405 ++continuation_count_;
406 }
407
OnAltSvc(SpdyStreamId stream_id,absl::string_view origin,const SpdyAltSvcWireFormat::AlternativeServiceVector & altsvc_vector)408 void OnAltSvc(SpdyStreamId stream_id, absl::string_view origin,
409 const SpdyAltSvcWireFormat::AlternativeServiceVector&
410 altsvc_vector) override {
411 QUICHE_VLOG(1) << "OnAltSvc(" << stream_id << ", \"" << origin
412 << "\", altsvc_vector)";
413 test_altsvc_ir_ = std::make_unique<SpdyAltSvcIR>(stream_id);
414 if (origin.length() > 0) {
415 test_altsvc_ir_->set_origin(std::string(origin));
416 }
417 for (const auto& altsvc : altsvc_vector) {
418 test_altsvc_ir_->add_altsvc(altsvc);
419 }
420 ++altsvc_count_;
421 }
422
OnPriority(SpdyStreamId stream_id,SpdyStreamId parent_stream_id,int weight,bool exclusive)423 void OnPriority(SpdyStreamId stream_id, SpdyStreamId parent_stream_id,
424 int weight, bool exclusive) override {
425 QUICHE_VLOG(1) << "OnPriority(" << stream_id << ", " << parent_stream_id
426 << ", " << weight << ", " << (exclusive ? 1 : 0) << ")";
427 ++priority_count_;
428 }
429
OnPriorityUpdate(SpdyStreamId prioritized_stream_id,absl::string_view priority_field_value)430 void OnPriorityUpdate(SpdyStreamId prioritized_stream_id,
431 absl::string_view priority_field_value) override {
432 QUICHE_VLOG(1) << "OnPriorityUpdate(" << prioritized_stream_id << ", "
433 << priority_field_value << ")";
434 }
435
OnUnknownFrame(SpdyStreamId stream_id,uint8_t frame_type)436 bool OnUnknownFrame(SpdyStreamId stream_id, uint8_t frame_type) override {
437 QUICHE_VLOG(1) << "OnUnknownFrame(" << stream_id << ", " << frame_type
438 << ")";
439 return on_unknown_frame_result_;
440 }
441
OnUnknownFrameStart(SpdyStreamId stream_id,size_t length,uint8_t type,uint8_t flags)442 void OnUnknownFrameStart(SpdyStreamId stream_id, size_t length, uint8_t type,
443 uint8_t flags) override {
444 QUICHE_VLOG(1) << "OnUnknownFrameStart(" << stream_id << ", " << length
445 << ", " << static_cast<int>(type) << ", "
446 << static_cast<int>(flags) << ")";
447 ++unknown_frame_count_;
448 }
449
OnUnknownFramePayload(SpdyStreamId stream_id,absl::string_view payload)450 void OnUnknownFramePayload(SpdyStreamId stream_id,
451 absl::string_view payload) override {
452 QUICHE_VLOG(1) << "OnUnknownFramePayload(" << stream_id << ", " << payload
453 << ")";
454 unknown_payload_len_ += payload.length();
455 }
456
OnSendCompressedFrame(SpdyStreamId stream_id,SpdyFrameType type,size_t payload_len,size_t frame_len)457 void OnSendCompressedFrame(SpdyStreamId stream_id, SpdyFrameType type,
458 size_t payload_len, size_t frame_len) override {
459 QUICHE_VLOG(1) << "OnSendCompressedFrame(" << stream_id << ", " << type
460 << ", " << payload_len << ", " << frame_len << ")";
461 last_payload_len_ = payload_len;
462 last_frame_len_ = frame_len;
463 }
464
OnReceiveCompressedFrame(SpdyStreamId stream_id,SpdyFrameType type,size_t frame_len)465 void OnReceiveCompressedFrame(SpdyStreamId stream_id, SpdyFrameType type,
466 size_t frame_len) override {
467 QUICHE_VLOG(1) << "OnReceiveCompressedFrame(" << stream_id << ", " << type
468 << ", " << frame_len << ")";
469 last_frame_len_ = frame_len;
470 }
471
472 // Convenience function which runs a framer simulation with particular input.
SimulateInFramer(const unsigned char * input,size_t size)473 void SimulateInFramer(const unsigned char* input, size_t size) {
474 deframer_.set_visitor(this);
475 size_t input_remaining = size;
476 const char* input_ptr = reinterpret_cast<const char*>(input);
477 while (input_remaining > 0 && deframer_.spdy_framer_error() ==
478 Http2DecoderAdapter::SPDY_NO_ERROR) {
479 // To make the tests more interesting, we feed random (and small) chunks
480 // into the framer. This simulates getting strange-sized reads from
481 // the socket.
482 const size_t kMaxReadSize = 32;
483 size_t bytes_read =
484 (rand() % std::min(input_remaining, kMaxReadSize)) + 1; // NOLINT
485 size_t bytes_processed = deframer_.ProcessInput(input_ptr, bytes_read);
486 input_remaining -= bytes_processed;
487 input_ptr += bytes_processed;
488 }
489 }
490
InitHeaderStreaming(SpdyFrameType header_control_type,SpdyStreamId stream_id)491 void InitHeaderStreaming(SpdyFrameType header_control_type,
492 SpdyStreamId stream_id) {
493 if (!IsDefinedFrameType(SerializeFrameType(header_control_type))) {
494 QUICHE_DLOG(FATAL) << "Attempted to init header streaming with "
495 << "invalid control frame type: "
496 << header_control_type;
497 }
498 memset(header_buffer_.get(), 0, header_buffer_size_);
499 header_buffer_length_ = 0;
500 header_stream_id_ = stream_id;
501 header_control_type_ = header_control_type;
502 header_buffer_valid_ = true;
503 }
504
set_extension_visitor(ExtensionVisitorInterface * extension)505 void set_extension_visitor(ExtensionVisitorInterface* extension) {
506 deframer_.set_extension_visitor(extension);
507 }
508
509 // Override the default buffer size (16K). Call before using the framer!
set_header_buffer_size(size_t header_buffer_size)510 void set_header_buffer_size(size_t header_buffer_size) {
511 header_buffer_size_ = header_buffer_size;
512 header_buffer_.reset(new char[header_buffer_size]);
513 }
514
515 SpdyFramer framer_;
516 Http2DecoderAdapter deframer_;
517
518 // Counters from the visitor callbacks.
519 int error_count_;
520 int headers_frame_count_;
521 int push_promise_frame_count_;
522 int goaway_count_;
523 int setting_count_;
524 int settings_ack_sent_;
525 int settings_ack_received_;
526 int continuation_count_;
527 int altsvc_count_;
528 int priority_count_;
529 std::unique_ptr<SpdyAltSvcIR> test_altsvc_ir_;
530 int unknown_frame_count_;
531 bool on_unknown_frame_result_;
532 SpdyStreamId last_window_update_stream_;
533 int last_window_update_delta_;
534 SpdyStreamId last_push_promise_stream_;
535 SpdyStreamId last_push_promise_promised_stream_;
536 int data_bytes_;
537 int fin_frame_count_; // The count of RST_STREAM type frames received.
538 int fin_flag_count_; // The count of frames with the FIN flag set.
539 int end_of_stream_count_; // The count of zero-length data frames.
540 int control_frame_header_data_count_; // The count of chunks received.
541 // The count of zero-length control frame header data chunks received.
542 int zero_length_control_frame_header_data_count_;
543 int data_frame_count_;
544 size_t last_payload_len_;
545 size_t last_frame_len_;
546 size_t unknown_payload_len_;
547
548 // Header block streaming state:
549 std::unique_ptr<char[]> header_buffer_;
550 size_t header_buffer_length_;
551 size_t header_buffer_size_;
552 size_t header_bytes_received_;
553 SpdyStreamId header_stream_id_;
554 SpdyFrameType header_control_type_;
555 bool header_buffer_valid_;
556 std::unique_ptr<RecordingHeadersHandler> headers_handler_;
557 Http2HeaderBlock headers_;
558 bool header_has_priority_;
559 SpdyStreamId header_parent_stream_id_;
560 bool header_exclusive_;
561 };
562
563 class TestExtension : public ExtensionVisitorInterface {
564 public:
OnSetting(SpdySettingsId id,uint32_t value)565 void OnSetting(SpdySettingsId id, uint32_t value) override {
566 settings_received_.push_back({id, value});
567 }
568
569 // Called when non-standard frames are received.
OnFrameHeader(SpdyStreamId stream_id,size_t length,uint8_t type,uint8_t flags)570 bool OnFrameHeader(SpdyStreamId stream_id, size_t length, uint8_t type,
571 uint8_t flags) override {
572 stream_id_ = stream_id;
573 length_ = length;
574 type_ = type;
575 flags_ = flags;
576 return true;
577 }
578
579 // The payload for a single frame may be delivered as multiple calls to
580 // OnFramePayload.
OnFramePayload(const char * data,size_t len)581 void OnFramePayload(const char* data, size_t len) override {
582 payload_.append(data, len);
583 }
584
585 std::vector<std::pair<SpdySettingsId, uint32_t>> settings_received_;
586 SpdyStreamId stream_id_ = 0;
587 size_t length_ = 0;
588 uint8_t type_ = 0;
589 uint8_t flags_ = 0;
590 std::string payload_;
591 };
592
593 // Exposes SpdyUnknownIR::set_length() for testing purposes.
594 class TestSpdyUnknownIR : public SpdyUnknownIR {
595 public:
596 using SpdyUnknownIR::set_length;
597 using SpdyUnknownIR::SpdyUnknownIR;
598 };
599
600 enum Output { USE, NOT_USE };
601
602 class SpdyFramerTest : public quiche::test::QuicheTestWithParam<Output> {
603 public:
SpdyFramerTest()604 SpdyFramerTest()
605 : output_(output_buffer, kSize),
606 framer_(SpdyFramer::ENABLE_COMPRESSION),
607 deframer_(std::make_unique<Http2DecoderAdapter>()) {}
608
609 protected:
SetUp()610 void SetUp() override {
611 switch (GetParam()) {
612 case USE:
613 use_output_ = true;
614 break;
615 case NOT_USE:
616 // TODO(yasong): remove this case after
617 // gfe2_reloadable_flag_write_queue_zero_copy_buffer deprecates.
618 use_output_ = false;
619 break;
620 }
621 }
622
CompareFrame(const std::string & description,const SpdySerializedFrame & actual_frame,const unsigned char * expected,const int expected_len)623 void CompareFrame(const std::string& description,
624 const SpdySerializedFrame& actual_frame,
625 const unsigned char* expected, const int expected_len) {
626 const unsigned char* actual =
627 reinterpret_cast<const unsigned char*>(actual_frame.data());
628 CompareCharArraysWithHexError(description, actual, actual_frame.size(),
629 expected, expected_len);
630 }
631
632 bool use_output_ = false;
633 ArrayOutputBuffer output_;
634 SpdyFramer framer_;
635 std::unique_ptr<Http2DecoderAdapter> deframer_;
636 };
637
638 INSTANTIATE_TEST_SUITE_P(SpdyFramerTests, SpdyFramerTest,
639 ::testing::Values(USE, NOT_USE));
640
641 // Test that we can encode and decode a Http2HeaderBlock in serialized form.
TEST_P(SpdyFramerTest,HeaderBlockInBuffer)642 TEST_P(SpdyFramerTest, HeaderBlockInBuffer) {
643 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
644
645 // Encode the header block into a Headers frame.
646 SpdyHeadersIR headers(/* stream_id = */ 1);
647 headers.SetHeader("alpha", "beta");
648 headers.SetHeader("gamma", "charlie");
649 headers.SetHeader("cookie", "key1=value1; key2=value2");
650 SpdySerializedFrame frame(
651 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
652
653 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
654 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
655 frame.size());
656
657 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
658 EXPECT_EQ(headers.header_block(), visitor.headers_);
659 }
660
661 // Test that if there's not a full frame, we fail to parse it.
TEST_P(SpdyFramerTest,UndersizedHeaderBlockInBuffer)662 TEST_P(SpdyFramerTest, UndersizedHeaderBlockInBuffer) {
663 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
664
665 // Encode the header block into a Headers frame.
666 SpdyHeadersIR headers(/* stream_id = */ 1);
667 headers.SetHeader("alpha", "beta");
668 headers.SetHeader("gamma", "charlie");
669 SpdySerializedFrame frame(
670 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
671
672 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
673 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
674 frame.size() - 2);
675
676 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
677 EXPECT_THAT(visitor.headers_, testing::IsEmpty());
678 }
679
680 // Test that we can encode and decode stream dependency values in a header
681 // frame.
TEST_P(SpdyFramerTest,HeaderStreamDependencyValues)682 TEST_P(SpdyFramerTest, HeaderStreamDependencyValues) {
683 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
684
685 const SpdyStreamId parent_stream_id_test_array[] = {0, 3};
686 for (SpdyStreamId parent_stream_id : parent_stream_id_test_array) {
687 const bool exclusive_test_array[] = {true, false};
688 for (bool exclusive : exclusive_test_array) {
689 SpdyHeadersIR headers(1);
690 headers.set_has_priority(true);
691 headers.set_parent_stream_id(parent_stream_id);
692 headers.set_exclusive(exclusive);
693 SpdySerializedFrame frame(
694 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
695
696 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
697 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
698 frame.size());
699
700 EXPECT_TRUE(visitor.header_has_priority_);
701 EXPECT_EQ(parent_stream_id, visitor.header_parent_stream_id_);
702 EXPECT_EQ(exclusive, visitor.header_exclusive_);
703 }
704 }
705 }
706
707 // Test that if we receive a frame with a payload length field at the default
708 // max size, we do not set an error in ProcessInput.
TEST_P(SpdyFramerTest,AcceptMaxFrameSizeSetting)709 TEST_P(SpdyFramerTest, AcceptMaxFrameSizeSetting) {
710 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
711 deframer_->set_visitor(&visitor);
712
713 // DATA frame with maximum allowed payload length.
714 unsigned char kH2FrameData[] = {
715 0x00, 0x40, 0x00, // Length: 2^14
716 0x00, // Type: DATA
717 0x00, // Flags: None
718 0x00, 0x00, 0x00, 0x01, // Stream: 1
719 0x00, 0x00, 0x00, 0x00, // Junk payload
720 };
721
722 SpdySerializedFrame frame = MakeSerializedFrame(
723 reinterpret_cast<char*>(kH2FrameData), sizeof(kH2FrameData));
724
725 EXPECT_CALL(visitor, OnCommonHeader(1, 16384, 0x0, 0x0));
726 EXPECT_CALL(visitor, OnDataFrameHeader(1, 1 << 14, false));
727 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 4));
728 deframer_->ProcessInput(frame.data(), frame.size());
729 EXPECT_FALSE(deframer_->HasError());
730 }
731
732 // Test that if we receive a frame with a payload length larger than the default
733 // max size, we set an error of SPDY_INVALID_CONTROL_FRAME_SIZE.
TEST_P(SpdyFramerTest,ExceedMaxFrameSizeSetting)734 TEST_P(SpdyFramerTest, ExceedMaxFrameSizeSetting) {
735 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
736 deframer_->set_visitor(&visitor);
737
738 // DATA frame with too large payload length.
739 unsigned char kH2FrameData[] = {
740 0x00, 0x40, 0x01, // Length: 2^14 + 1
741 0x00, // Type: DATA
742 0x00, // Flags: None
743 0x00, 0x00, 0x00, 0x01, // Stream: 1
744 0x00, 0x00, 0x00, 0x00, // Junk payload
745 };
746
747 SpdySerializedFrame frame = MakeSerializedFrame(
748 reinterpret_cast<char*>(kH2FrameData), sizeof(kH2FrameData));
749
750 EXPECT_CALL(visitor, OnCommonHeader(1, 16385, 0x0, 0x0));
751 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD, _));
752 deframer_->ProcessInput(frame.data(), frame.size());
753 EXPECT_TRUE(deframer_->HasError());
754 EXPECT_EQ(Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD,
755 deframer_->spdy_framer_error())
756 << Http2DecoderAdapter::SpdyFramerErrorToString(
757 deframer_->spdy_framer_error());
758 }
759
760 // Test that if we set a larger max frame size and then receive a frame with a
761 // payload length at that larger size, we do not set an error in ProcessInput.
TEST_P(SpdyFramerTest,AcceptLargerMaxFrameSizeSetting)762 TEST_P(SpdyFramerTest, AcceptLargerMaxFrameSizeSetting) {
763 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
764 deframer_->set_visitor(&visitor);
765
766 const size_t big_frame_size = (1 << 14) + 1;
767 deframer_->SetMaxFrameSize(big_frame_size);
768
769 // DATA frame with larger-than-default but acceptable payload length.
770 unsigned char kH2FrameData[] = {
771 0x00, 0x40, 0x01, // Length: 2^14 + 1
772 0x00, // Type: DATA
773 0x00, // Flags: None
774 0x00, 0x00, 0x00, 0x01, // Stream: 1
775 0x00, 0x00, 0x00, 0x00, // Junk payload
776 };
777
778 SpdySerializedFrame frame = MakeSerializedFrame(
779 reinterpret_cast<char*>(kH2FrameData), sizeof(kH2FrameData));
780
781 EXPECT_CALL(visitor, OnCommonHeader(1, big_frame_size, 0x0, 0x0));
782 EXPECT_CALL(visitor, OnDataFrameHeader(1, big_frame_size, false));
783 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 4));
784 deframer_->ProcessInput(frame.data(), frame.size());
785 EXPECT_FALSE(deframer_->HasError());
786 }
787
788 // Test that if we receive a DATA frame with padding length larger than the
789 // payload length, we set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest,OversizedDataPaddingError)790 TEST_P(SpdyFramerTest, OversizedDataPaddingError) {
791 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
792 deframer_->set_visitor(&visitor);
793
794 // DATA frame with invalid padding length.
795 // |kH2FrameData| has to be |unsigned char|, because Chromium on Windows uses
796 // MSVC, where |char| is signed by default, which would not compile because of
797 // the element exceeding 127.
798 unsigned char kH2FrameData[] = {
799 0x00, 0x00, 0x05, // Length: 5
800 0x00, // Type: DATA
801 0x09, // Flags: END_STREAM|PADDED
802 0x00, 0x00, 0x00, 0x01, // Stream: 1
803 0xff, // PadLen: 255 trailing bytes (Too Long)
804 0x00, 0x00, 0x00, 0x00, // Padding
805 };
806
807 SpdySerializedFrame frame = MakeSerializedFrame(
808 reinterpret_cast<char*>(kH2FrameData), sizeof(kH2FrameData));
809
810 {
811 testing::InSequence seq;
812 EXPECT_CALL(visitor, OnCommonHeader(1, 5, 0x0, 0x9));
813 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, 1));
814 EXPECT_CALL(visitor, OnStreamPadding(1, 1));
815 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_PADDING, _));
816 }
817 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
818 EXPECT_TRUE(deframer_->HasError());
819 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_PADDING,
820 deframer_->spdy_framer_error())
821 << Http2DecoderAdapter::SpdyFramerErrorToString(
822 deframer_->spdy_framer_error());
823 }
824
825 // Test that if we receive a DATA frame with padding length not larger than the
826 // payload length, we do not set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest,CorrectlySizedDataPaddingNoError)827 TEST_P(SpdyFramerTest, CorrectlySizedDataPaddingNoError) {
828 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
829
830 deframer_->set_visitor(&visitor);
831
832 // DATA frame with valid Padding length
833 char kH2FrameData[] = {
834 0x00, 0x00, 0x05, // Length: 5
835 0x00, // Type: DATA
836 0x08, // Flags: PADDED
837 0x00, 0x00, 0x00, 0x01, // Stream: 1
838 0x04, // PadLen: 4 trailing bytes
839 0x00, 0x00, 0x00, 0x00, // Padding
840 };
841
842 SpdySerializedFrame frame =
843 MakeSerializedFrame(kH2FrameData, sizeof(kH2FrameData));
844
845 {
846 testing::InSequence seq;
847 EXPECT_CALL(visitor, OnCommonHeader(1, 5, 0x0, 0x8));
848 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, false));
849 EXPECT_CALL(visitor, OnStreamPadLength(1, 4));
850 EXPECT_CALL(visitor, OnError(_, _)).Times(0);
851 // Note that OnStreamFrameData(1, _, 1)) is never called
852 // since there is no data, only padding
853 EXPECT_CALL(visitor, OnStreamPadding(1, 4));
854 }
855
856 EXPECT_EQ(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
857 EXPECT_FALSE(deframer_->HasError());
858 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
859 << Http2DecoderAdapter::SpdyFramerErrorToString(
860 deframer_->spdy_framer_error());
861 }
862
863 // Test that if we receive a HEADERS frame with padding length larger than the
864 // payload length, we set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest,OversizedHeadersPaddingError)865 TEST_P(SpdyFramerTest, OversizedHeadersPaddingError) {
866 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
867
868 deframer_->set_visitor(&visitor);
869
870 // HEADERS frame with invalid padding length.
871 // |kH2FrameData| has to be |unsigned char|, because Chromium on Windows uses
872 // MSVC, where |char| is signed by default, which would not compile because of
873 // the element exceeding 127.
874 unsigned char kH2FrameData[] = {
875 0x00, 0x00, 0x05, // Length: 5
876 0x01, // Type: HEADERS
877 0x08, // Flags: PADDED
878 0x00, 0x00, 0x00, 0x01, // Stream: 1
879 0xff, // PadLen: 255 trailing bytes (Too Long)
880 0x00, 0x00, 0x00, 0x00, // Padding
881 };
882
883 SpdySerializedFrame frame = MakeSerializedFrame(
884 reinterpret_cast<char*>(kH2FrameData), sizeof(kH2FrameData));
885
886 EXPECT_CALL(visitor, OnCommonHeader(1, 5, 0x1, 0x8));
887 EXPECT_CALL(visitor, OnHeaders(1, 5, false, 0, 0, false, false, false));
888 EXPECT_CALL(visitor, OnHeaderFrameStart(1)).Times(1);
889 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_PADDING, _));
890 EXPECT_EQ(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
891 EXPECT_TRUE(deframer_->HasError());
892 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_PADDING,
893 deframer_->spdy_framer_error())
894 << Http2DecoderAdapter::SpdyFramerErrorToString(
895 deframer_->spdy_framer_error());
896 }
897
898 // Test that if we receive a HEADERS frame with padding length not larger
899 // than the payload length, we do not set an error of SPDY_INVALID_PADDING
TEST_P(SpdyFramerTest,CorrectlySizedHeadersPaddingNoError)900 TEST_P(SpdyFramerTest, CorrectlySizedHeadersPaddingNoError) {
901 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
902
903 deframer_->set_visitor(&visitor);
904
905 // HEADERS frame with invalid Padding length
906 char kH2FrameData[] = {
907 0x00, 0x00, 0x05, // Length: 5
908 0x01, // Type: HEADERS
909 0x08, // Flags: PADDED
910 0x00, 0x00, 0x00, 0x01, // Stream: 1
911 0x04, // PadLen: 4 trailing bytes
912 0x00, 0x00, 0x00, 0x00, // Padding
913 };
914
915 SpdySerializedFrame frame =
916 MakeSerializedFrame(kH2FrameData, sizeof(kH2FrameData));
917
918 EXPECT_CALL(visitor, OnCommonHeader(1, 5, 0x1, 0x8));
919 EXPECT_CALL(visitor, OnHeaders(1, 5, false, 0, 0, false, false, false));
920 EXPECT_CALL(visitor, OnHeaderFrameStart(1)).Times(1);
921
922 EXPECT_EQ(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
923 EXPECT_FALSE(deframer_->HasError());
924 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
925 << Http2DecoderAdapter::SpdyFramerErrorToString(
926 deframer_->spdy_framer_error());
927 }
928
929 // Test that if we receive a DATA with stream ID zero, we signal an error
930 // (but don't crash).
TEST_P(SpdyFramerTest,DataWithStreamIdZero)931 TEST_P(SpdyFramerTest, DataWithStreamIdZero) {
932 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
933
934 deframer_->set_visitor(&visitor);
935
936 const char bytes[] = "hello";
937 SpdyDataIR data_ir(/* stream_id = */ 0, bytes);
938 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
939
940 // We shouldn't have to read the whole frame before we signal an error.
941 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x0, _));
942 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
943 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
944 EXPECT_TRUE(deframer_->HasError());
945 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
946 deframer_->spdy_framer_error())
947 << Http2DecoderAdapter::SpdyFramerErrorToString(
948 deframer_->spdy_framer_error());
949 }
950
951 // Test that if we receive a HEADERS with stream ID zero, we signal an error
952 // (but don't crash).
TEST_P(SpdyFramerTest,HeadersWithStreamIdZero)953 TEST_P(SpdyFramerTest, HeadersWithStreamIdZero) {
954 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
955
956 deframer_->set_visitor(&visitor);
957
958 SpdyHeadersIR headers(/* stream_id = */ 0);
959 headers.SetHeader("alpha", "beta");
960 SpdySerializedFrame frame(
961 SpdyFramerPeer::SerializeHeaders(&framer_, headers, &output_));
962
963 // We shouldn't have to read the whole frame before we signal an error.
964 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x1, _));
965 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
966 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
967 EXPECT_TRUE(deframer_->HasError());
968 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
969 deframer_->spdy_framer_error())
970 << Http2DecoderAdapter::SpdyFramerErrorToString(
971 deframer_->spdy_framer_error());
972 }
973
974 // Test that if we receive a PRIORITY with stream ID zero, we signal an error
975 // (but don't crash).
TEST_P(SpdyFramerTest,PriorityWithStreamIdZero)976 TEST_P(SpdyFramerTest, PriorityWithStreamIdZero) {
977 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
978
979 deframer_->set_visitor(&visitor);
980
981 SpdyPriorityIR priority_ir(/* stream_id = */ 0,
982 /* parent_stream_id = */ 1,
983 /* weight = */ 16,
984 /* exclusive = */ true);
985 SpdySerializedFrame frame(framer_.SerializeFrame(priority_ir));
986 if (use_output_) {
987 EXPECT_EQ(framer_.SerializeFrame(priority_ir, &output_), frame.size());
988 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
989 }
990
991 // We shouldn't have to read the whole frame before we signal an error.
992 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x2, _));
993 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
994 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
995 EXPECT_TRUE(deframer_->HasError());
996 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
997 deframer_->spdy_framer_error())
998 << Http2DecoderAdapter::SpdyFramerErrorToString(
999 deframer_->spdy_framer_error());
1000 }
1001
1002 // Test that if we receive a RST_STREAM with stream ID zero, we signal an error
1003 // (but don't crash).
TEST_P(SpdyFramerTest,RstStreamWithStreamIdZero)1004 TEST_P(SpdyFramerTest, RstStreamWithStreamIdZero) {
1005 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1006
1007 deframer_->set_visitor(&visitor);
1008
1009 SpdyRstStreamIR rst_stream_ir(/* stream_id = */ 0, ERROR_CODE_PROTOCOL_ERROR);
1010 SpdySerializedFrame frame(framer_.SerializeRstStream(rst_stream_ir));
1011 if (use_output_) {
1012 EXPECT_TRUE(framer_.SerializeRstStream(rst_stream_ir, &output_));
1013 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1014 }
1015
1016 // We shouldn't have to read the whole frame before we signal an error.
1017 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x3, _));
1018 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
1019 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
1020 EXPECT_TRUE(deframer_->HasError());
1021 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
1022 deframer_->spdy_framer_error())
1023 << Http2DecoderAdapter::SpdyFramerErrorToString(
1024 deframer_->spdy_framer_error());
1025 }
1026
1027 // Test that if we receive a SETTINGS with stream ID other than zero,
1028 // we signal an error (but don't crash).
TEST_P(SpdyFramerTest,SettingsWithStreamIdNotZero)1029 TEST_P(SpdyFramerTest, SettingsWithStreamIdNotZero) {
1030 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1031
1032 deframer_->set_visitor(&visitor);
1033
1034 // Settings frame with invalid StreamID of 0x01
1035 char kH2FrameData[] = {
1036 0x00, 0x00, 0x06, // Length: 6
1037 0x04, // Type: SETTINGS
1038 0x00, // Flags: none
1039 0x00, 0x00, 0x00, 0x01, // Stream: 1
1040 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1041 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141
1042 };
1043
1044 SpdySerializedFrame frame =
1045 MakeSerializedFrame(kH2FrameData, sizeof(kH2FrameData));
1046
1047 // We shouldn't have to read the whole frame before we signal an error.
1048 EXPECT_CALL(visitor, OnCommonHeader(1, 6, 0x4, 0x0));
1049 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
1050 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
1051 EXPECT_TRUE(deframer_->HasError());
1052 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
1053 deframer_->spdy_framer_error())
1054 << Http2DecoderAdapter::SpdyFramerErrorToString(
1055 deframer_->spdy_framer_error());
1056 }
1057
1058 // Test that if we receive a GOAWAY with stream ID other than zero,
1059 // we signal an error (but don't crash).
TEST_P(SpdyFramerTest,GoawayWithStreamIdNotZero)1060 TEST_P(SpdyFramerTest, GoawayWithStreamIdNotZero) {
1061 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1062
1063 deframer_->set_visitor(&visitor);
1064
1065 // GOAWAY frame with invalid StreamID of 0x01
1066 char kH2FrameData[] = {
1067 0x00, 0x00, 0x0a, // Length: 10
1068 0x07, // Type: GOAWAY
1069 0x00, // Flags: none
1070 0x00, 0x00, 0x00, 0x01, // Stream: 1
1071 0x00, 0x00, 0x00, 0x00, // Last: 0
1072 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
1073 0x47, 0x41, // Description
1074 };
1075
1076 SpdySerializedFrame frame =
1077 MakeSerializedFrame(kH2FrameData, sizeof(kH2FrameData));
1078
1079 // We shouldn't have to read the whole frame before we signal an error.
1080 EXPECT_CALL(visitor, OnCommonHeader(1, 10, 0x7, 0x0));
1081 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
1082 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
1083 EXPECT_TRUE(deframer_->HasError());
1084 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
1085 deframer_->spdy_framer_error())
1086 << Http2DecoderAdapter::SpdyFramerErrorToString(
1087 deframer_->spdy_framer_error());
1088 }
1089
1090 // Test that if we receive a CONTINUATION with stream ID zero, we signal
1091 // SPDY_INVALID_STREAM_ID.
TEST_P(SpdyFramerTest,ContinuationWithStreamIdZero)1092 TEST_P(SpdyFramerTest, ContinuationWithStreamIdZero) {
1093 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1094
1095 deframer_->set_visitor(&visitor);
1096
1097 SpdyContinuationIR continuation(/* stream_id = */ 0);
1098 std::string some_nonsense_encoding = "some nonsense encoding";
1099 continuation.take_encoding(std::move(some_nonsense_encoding));
1100 continuation.set_end_headers(true);
1101 SpdySerializedFrame frame(framer_.SerializeContinuation(continuation));
1102 if (use_output_) {
1103 ASSERT_TRUE(framer_.SerializeContinuation(continuation, &output_));
1104 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1105 }
1106
1107 // We shouldn't have to read the whole frame before we signal an error.
1108 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x9, _));
1109 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
1110 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
1111 EXPECT_TRUE(deframer_->HasError());
1112 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
1113 deframer_->spdy_framer_error())
1114 << Http2DecoderAdapter::SpdyFramerErrorToString(
1115 deframer_->spdy_framer_error());
1116 }
1117
1118 // Test that if we receive a PUSH_PROMISE with stream ID zero, we signal
1119 // SPDY_INVALID_STREAM_ID.
TEST_P(SpdyFramerTest,PushPromiseWithStreamIdZero)1120 TEST_P(SpdyFramerTest, PushPromiseWithStreamIdZero) {
1121 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1122
1123 deframer_->set_visitor(&visitor);
1124
1125 SpdyPushPromiseIR push_promise(/* stream_id = */ 0,
1126 /* promised_stream_id = */ 4);
1127 push_promise.SetHeader("alpha", "beta");
1128 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
1129 &framer_, push_promise, use_output_ ? &output_ : nullptr));
1130
1131 // We shouldn't have to read the whole frame before we signal an error.
1132 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x5, _));
1133 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
1134 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
1135 EXPECT_TRUE(deframer_->HasError());
1136 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID,
1137 deframer_->spdy_framer_error())
1138 << Http2DecoderAdapter::SpdyFramerErrorToString(
1139 deframer_->spdy_framer_error());
1140 }
1141
1142 // Test that if we receive a PUSH_PROMISE with promised stream ID zero, we
1143 // signal SPDY_INVALID_CONTROL_FRAME.
TEST_P(SpdyFramerTest,PushPromiseWithPromisedStreamIdZero)1144 TEST_P(SpdyFramerTest, PushPromiseWithPromisedStreamIdZero) {
1145 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1146
1147 deframer_->set_visitor(&visitor);
1148
1149 SpdyPushPromiseIR push_promise(/* stream_id = */ 3,
1150 /* promised_stream_id = */ 0);
1151 push_promise.SetHeader("alpha", "beta");
1152 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
1153 &framer_, push_promise, use_output_ ? &output_ : nullptr));
1154
1155 EXPECT_CALL(visitor, OnCommonHeader(3, _, 0x5, _));
1156 EXPECT_CALL(visitor,
1157 OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME, _));
1158 deframer_->ProcessInput(frame.data(), frame.size());
1159 EXPECT_TRUE(deframer_->HasError());
1160 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
1161 deframer_->spdy_framer_error())
1162 << Http2DecoderAdapter::SpdyFramerErrorToString(
1163 deframer_->spdy_framer_error());
1164 }
1165
TEST_P(SpdyFramerTest,MultiValueHeader)1166 TEST_P(SpdyFramerTest, MultiValueHeader) {
1167 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
1168 std::string value("value1\0value2", 13);
1169 // TODO(jgraettinger): If this pattern appears again, move to test class.
1170 Http2HeaderBlock header_set;
1171 header_set["name"] = value;
1172 HpackEncoder encoder;
1173 encoder.DisableCompression();
1174 std::string buffer = encoder.EncodeHeaderBlock(header_set);
1175 // Frame builder with plentiful buffer size.
1176 SpdyFrameBuilder frame(1024);
1177 frame.BeginNewFrame(SpdyFrameType::HEADERS,
1178 HEADERS_FLAG_PRIORITY | HEADERS_FLAG_END_HEADERS, 3,
1179 buffer.size() + 5 /* priority */);
1180 frame.WriteUInt32(0); // Priority exclusivity and dependent stream.
1181 frame.WriteUInt8(255); // Priority weight.
1182 frame.WriteBytes(&buffer[0], buffer.size());
1183
1184 SpdySerializedFrame control_frame(frame.take());
1185
1186 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1187 visitor.SimulateInFramer(
1188 reinterpret_cast<unsigned char*>(control_frame.data()),
1189 control_frame.size());
1190
1191 EXPECT_THAT(visitor.headers_, testing::ElementsAre(testing::Pair(
1192 "name", absl::string_view(value))));
1193 }
1194
TEST_P(SpdyFramerTest,CompressEmptyHeaders)1195 TEST_P(SpdyFramerTest, CompressEmptyHeaders) {
1196 // See https://crbug.com/172383/
1197 SpdyHeadersIR headers(1);
1198 headers.SetHeader("server", "SpdyServer 1.0");
1199 headers.SetHeader("date", "Mon 12 Jan 2009 12:12:12 PST");
1200 headers.SetHeader("status", "200");
1201 headers.SetHeader("version", "HTTP/1.1");
1202 headers.SetHeader("content-type", "text/html");
1203 headers.SetHeader("content-length", "12");
1204 headers.SetHeader("x-empty-header", "");
1205
1206 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
1207 SpdySerializedFrame frame1(
1208 SpdyFramerPeer::SerializeHeaders(&framer, headers, &output_));
1209 }
1210
TEST_P(SpdyFramerTest,Basic)1211 TEST_P(SpdyFramerTest, Basic) {
1212 // Send HEADERS frames with PRIORITY and END_HEADERS set.
1213 // frame-format off
1214 const unsigned char kH2Input[] = {
1215 0x00, 0x00, 0x05, // Length: 5
1216 0x01, // Type: HEADERS
1217 0x24, // Flags: END_HEADERS|PRIORITY
1218 0x00, 0x00, 0x00, 0x01, // Stream: 1
1219 0x00, 0x00, 0x00, 0x00, // Parent: 0
1220 0x82, // Weight: 131
1221
1222 0x00, 0x00, 0x01, // Length: 1
1223 0x01, // Type: HEADERS
1224 0x04, // Flags: END_HEADERS
1225 0x00, 0x00, 0x00, 0x01, // Stream: 1
1226 0x8c, // :status: 200
1227
1228 0x00, 0x00, 0x0c, // Length: 12
1229 0x00, // Type: DATA
1230 0x00, // Flags: none
1231 0x00, 0x00, 0x00, 0x01, // Stream: 1
1232 0xde, 0xad, 0xbe, 0xef, // Payload
1233 0xde, 0xad, 0xbe, 0xef, //
1234 0xde, 0xad, 0xbe, 0xef, //
1235
1236 0x00, 0x00, 0x05, // Length: 5
1237 0x01, // Type: HEADERS
1238 0x24, // Flags: END_HEADERS|PRIORITY
1239 0x00, 0x00, 0x00, 0x03, // Stream: 3
1240 0x00, 0x00, 0x00, 0x00, // Parent: 0
1241 0x82, // Weight: 131
1242
1243 0x00, 0x00, 0x08, // Length: 8
1244 0x00, // Type: DATA
1245 0x00, // Flags: none
1246 0x00, 0x00, 0x00, 0x03, // Stream: 3
1247 0xde, 0xad, 0xbe, 0xef, // Payload
1248 0xde, 0xad, 0xbe, 0xef, //
1249
1250 0x00, 0x00, 0x04, // Length: 4
1251 0x00, // Type: DATA
1252 0x00, // Flags: none
1253 0x00, 0x00, 0x00, 0x01, // Stream: 1
1254 0xde, 0xad, 0xbe, 0xef, // Payload
1255
1256 0x00, 0x00, 0x04, // Length: 4
1257 0x03, // Type: RST_STREAM
1258 0x00, // Flags: none
1259 0x00, 0x00, 0x00, 0x01, // Stream: 1
1260 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1261
1262 0x00, 0x00, 0x00, // Length: 0
1263 0x00, // Type: DATA
1264 0x00, // Flags: none
1265 0x00, 0x00, 0x00, 0x03, // Stream: 3
1266
1267 0x00, 0x00, 0x04, // Length: 4
1268 0x03, // Type: RST_STREAM
1269 0x00, // Flags: none
1270 0x00, 0x00, 0x00, 0x03, // Stream: 3
1271 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1272 };
1273 // frame-format on
1274
1275 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1276 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1277
1278 EXPECT_EQ(24, visitor.data_bytes_);
1279 EXPECT_EQ(0, visitor.error_count_);
1280 EXPECT_EQ(2, visitor.fin_frame_count_);
1281
1282 EXPECT_EQ(3, visitor.headers_frame_count_);
1283
1284 EXPECT_EQ(0, visitor.fin_flag_count_);
1285 EXPECT_EQ(0, visitor.end_of_stream_count_);
1286 EXPECT_EQ(4, visitor.data_frame_count_);
1287 }
1288
1289 // Verifies that the decoder stops delivering events after a user error.
TEST_P(SpdyFramerTest,BasicWithError)1290 TEST_P(SpdyFramerTest, BasicWithError) {
1291 // Send HEADERS frames with PRIORITY and END_HEADERS set.
1292 // frame-format off
1293 const unsigned char kH2Input[] = {
1294 0x00, 0x00, 0x01, // Length: 1
1295 0x01, // Type: HEADERS
1296 0x04, // Flags: END_HEADERS
1297 0x00, 0x00, 0x00, 0x01, // Stream: 1
1298 0x8c, // :status: 200
1299
1300 0x00, 0x00, 0x0c, // Length: 12
1301 0x00, // Type: DATA
1302 0x00, // Flags: none
1303 0x00, 0x00, 0x00, 0x01, // Stream: 1
1304 0xde, 0xad, 0xbe, 0xef, // Payload
1305 0xde, 0xad, 0xbe, 0xef, //
1306 0xde, 0xad, 0xbe, 0xef, //
1307
1308 0x00, 0x00, 0x06, // Length: 6
1309 0x01, // Type: HEADERS
1310 0x24, // Flags: END_HEADERS|PRIORITY
1311 0x00, 0x00, 0x00, 0x03, // Stream: 3
1312 0x00, 0x00, 0x00, 0x00, // Parent: 0
1313 0x82, // Weight: 131
1314 0x8c, // :status: 200
1315
1316 0x00, 0x00, 0x08, // Length: 8
1317 0x00, // Type: DATA
1318 0x00, // Flags: none
1319 0x00, 0x00, 0x00, 0x03, // Stream: 3
1320 0xde, 0xad, 0xbe, 0xef, // Payload
1321 0xde, 0xad, 0xbe, 0xef, //
1322
1323 0x00, 0x00, 0x04, // Length: 4
1324 0x00, // Type: DATA
1325 0x00, // Flags: none
1326 0x00, 0x00, 0x00, 0x01, // Stream: 1
1327 0xde, 0xad, 0xbe, 0xef, // Payload
1328
1329 0x00, 0x00, 0x04, // Length: 4
1330 0x03, // Type: RST_STREAM
1331 0x00, // Flags: none
1332 0x00, 0x00, 0x00, 0x01, // Stream: 1
1333 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1334
1335 0x00, 0x00, 0x00, // Length: 0
1336 0x00, // Type: DATA
1337 0x00, // Flags: none
1338 0x00, 0x00, 0x00, 0x03, // Stream: 3
1339
1340 0x00, 0x00, 0x04, // Length: 4
1341 0x03, // Type: RST_STREAM
1342 0x00, // Flags: none
1343 0x00, 0x00, 0x00, 0x03, // Stream: 3
1344 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
1345 };
1346 // frame-format on
1347
1348 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
1349
1350 deframer_->set_visitor(&visitor);
1351
1352 testing::InSequence s;
1353 EXPECT_CALL(visitor, OnCommonHeader(1, 1, 0x1, 0x4));
1354 EXPECT_CALL(visitor, OnHeaders(1, 1, false, 0, 0, false, false, true));
1355 EXPECT_CALL(visitor, OnHeaderFrameStart(1));
1356 EXPECT_CALL(visitor, OnHeaderFrameEnd(1));
1357 EXPECT_CALL(visitor, OnCommonHeader(1, 12, 0x0, 0x0));
1358 EXPECT_CALL(visitor, OnDataFrameHeader(1, 12, false));
1359 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 12));
1360 EXPECT_CALL(visitor, OnCommonHeader(3, 6, 0x1, 0x24));
1361 EXPECT_CALL(visitor, OnHeaders(3, 6, true, 131, 0, false, false, true));
1362 EXPECT_CALL(visitor, OnHeaderFrameStart(3));
1363 EXPECT_CALL(visitor, OnHeaderFrameEnd(3));
1364 EXPECT_CALL(visitor, OnCommonHeader(3, 8, 0x0, 0x0));
1365 EXPECT_CALL(visitor, OnDataFrameHeader(3, 8, false))
1366 .WillOnce(testing::InvokeWithoutArgs(
1367 [this]() { deframer_->StopProcessing(); }));
1368 // Remaining frames are not processed due to the error.
1369 EXPECT_CALL(
1370 visitor,
1371 OnError(http2::Http2DecoderAdapter::SpdyFramerError::SPDY_STOP_PROCESSING,
1372 "Ignoring further events on this connection."));
1373
1374 size_t processed = deframer_->ProcessInput(
1375 reinterpret_cast<const char*>(kH2Input), sizeof(kH2Input));
1376 EXPECT_LT(processed, sizeof(kH2Input));
1377 }
1378
1379 // Test that the FIN flag on a data frame signifies EOF.
TEST_P(SpdyFramerTest,FinOnDataFrame)1380 TEST_P(SpdyFramerTest, FinOnDataFrame) {
1381 // Send HEADERS frames with END_HEADERS set.
1382 // frame-format off
1383 const unsigned char kH2Input[] = {
1384 0x00, 0x00, 0x05, // Length: 5
1385 0x01, // Type: HEADERS
1386 0x24, // Flags: END_HEADERS|PRIORITY
1387 0x00, 0x00, 0x00, 0x01, // Stream: 1
1388 0x00, 0x00, 0x00, 0x00, // Parent: 0
1389 0x82, // Weight: 131
1390
1391 0x00, 0x00, 0x01, // Length: 1
1392 0x01, // Type: HEADERS
1393 0x04, // Flags: END_HEADERS
1394 0x00, 0x00, 0x00, 0x01, // Stream: 1
1395 0x8c, // :status: 200
1396
1397 0x00, 0x00, 0x0c, // Length: 12
1398 0x00, // Type: DATA
1399 0x00, // Flags: none
1400 0x00, 0x00, 0x00, 0x01, // Stream: 1
1401 0xde, 0xad, 0xbe, 0xef, // Payload
1402 0xde, 0xad, 0xbe, 0xef, //
1403 0xde, 0xad, 0xbe, 0xef, //
1404
1405 0x00, 0x00, 0x04, // Length: 4
1406 0x00, // Type: DATA
1407 0x01, // Flags: END_STREAM
1408 0x00, 0x00, 0x00, 0x01, // Stream: 1
1409 0xde, 0xad, 0xbe, 0xef, // Payload
1410 };
1411 // frame-format on
1412
1413 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1414 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1415
1416 EXPECT_EQ(0, visitor.error_count_);
1417 EXPECT_EQ(2, visitor.headers_frame_count_);
1418 EXPECT_EQ(16, visitor.data_bytes_);
1419 EXPECT_EQ(0, visitor.fin_frame_count_);
1420 EXPECT_EQ(0, visitor.fin_flag_count_);
1421 EXPECT_EQ(1, visitor.end_of_stream_count_);
1422 EXPECT_EQ(2, visitor.data_frame_count_);
1423 }
1424
TEST_P(SpdyFramerTest,FinOnHeadersFrame)1425 TEST_P(SpdyFramerTest, FinOnHeadersFrame) {
1426 // Send HEADERS frames with END_HEADERS set.
1427 // frame-format off
1428 const unsigned char kH2Input[] = {
1429 0x00, 0x00, 0x05, // Length: 5
1430 0x01, // Type: HEADERS
1431 0x24, // Flags: END_HEADERS|PRIORITY
1432 0x00, 0x00, 0x00, 0x01, // Stream: 1
1433 0x00, 0x00, 0x00, 0x00, // Parent: 0
1434 0x82, // Weight: 131
1435
1436 0x00, 0x00, 0x01, // Length: 1
1437 0x01, // Type: HEADERS
1438 0x05, // Flags: END_STREAM|END_HEADERS
1439 0x00, 0x00, 0x00, 0x01, // Stream: 1
1440 0x8c, // :status: 200
1441 };
1442 // frame-format on
1443
1444 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
1445 visitor.SimulateInFramer(kH2Input, sizeof(kH2Input));
1446
1447 EXPECT_EQ(0, visitor.error_count_);
1448 EXPECT_EQ(2, visitor.headers_frame_count_);
1449 EXPECT_EQ(0, visitor.data_bytes_);
1450 EXPECT_EQ(0, visitor.fin_frame_count_);
1451 EXPECT_EQ(1, visitor.fin_flag_count_);
1452 EXPECT_EQ(1, visitor.end_of_stream_count_);
1453 EXPECT_EQ(0, visitor.data_frame_count_);
1454 }
1455
1456 // Verify we can decompress the stream even if handed over to the
1457 // framer 1 byte at a time.
TEST_P(SpdyFramerTest,UnclosedStreamDataCompressorsOneByteAtATime)1458 TEST_P(SpdyFramerTest, UnclosedStreamDataCompressorsOneByteAtATime) {
1459 const char kHeader1[] = "header1";
1460 const char kHeader2[] = "header2";
1461 const char kValue1[] = "value1";
1462 const char kValue2[] = "value2";
1463
1464 SpdyHeadersIR headers(/* stream_id = */ 1);
1465 headers.SetHeader(kHeader1, kValue1);
1466 headers.SetHeader(kHeader2, kValue2);
1467 SpdySerializedFrame headers_frame(SpdyFramerPeer::SerializeHeaders(
1468 &framer_, headers, use_output_ ? &output_ : nullptr));
1469
1470 const char bytes[] = "this is a test test test test test!";
1471 SpdyDataIR data_ir(/* stream_id = */ 1,
1472 absl::string_view(bytes, ABSL_ARRAYSIZE(bytes)));
1473 data_ir.set_fin(true);
1474 SpdySerializedFrame send_frame(framer_.SerializeData(data_ir));
1475
1476 // Run the inputs through the framer.
1477 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
1478 const unsigned char* data;
1479 data = reinterpret_cast<const unsigned char*>(headers_frame.data());
1480 for (size_t idx = 0; idx < headers_frame.size(); ++idx) {
1481 visitor.SimulateInFramer(data + idx, 1);
1482 ASSERT_EQ(0, visitor.error_count_);
1483 }
1484 data = reinterpret_cast<const unsigned char*>(send_frame.data());
1485 for (size_t idx = 0; idx < send_frame.size(); ++idx) {
1486 visitor.SimulateInFramer(data + idx, 1);
1487 ASSERT_EQ(0, visitor.error_count_);
1488 }
1489
1490 EXPECT_EQ(0, visitor.error_count_);
1491 EXPECT_EQ(1, visitor.headers_frame_count_);
1492 EXPECT_EQ(ABSL_ARRAYSIZE(bytes), static_cast<unsigned>(visitor.data_bytes_));
1493 EXPECT_EQ(0, visitor.fin_frame_count_);
1494 EXPECT_EQ(0, visitor.fin_flag_count_);
1495 EXPECT_EQ(1, visitor.end_of_stream_count_);
1496 EXPECT_EQ(1, visitor.data_frame_count_);
1497 }
1498
TEST_P(SpdyFramerTest,WindowUpdateFrame)1499 TEST_P(SpdyFramerTest, WindowUpdateFrame) {
1500 SpdyWindowUpdateIR window_update(/* stream_id = */ 1,
1501 /* delta = */ 0x12345678);
1502 SpdySerializedFrame frame(framer_.SerializeWindowUpdate(window_update));
1503 if (use_output_) {
1504 ASSERT_TRUE(framer_.SerializeWindowUpdate(window_update, &output_));
1505 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1506 }
1507
1508 const char kDescription[] = "WINDOW_UPDATE frame, stream 1, delta 0x12345678";
1509 const unsigned char kH2FrameData[] = {
1510 0x00, 0x00, 0x04, // Length: 4
1511 0x08, // Type: WINDOW_UPDATE
1512 0x00, // Flags: none
1513 0x00, 0x00, 0x00, 0x01, // Stream: 1
1514 0x12, 0x34, 0x56, 0x78, // Increment: 305419896
1515 };
1516
1517 CompareFrame(kDescription, frame, kH2FrameData, ABSL_ARRAYSIZE(kH2FrameData));
1518 }
1519
TEST_P(SpdyFramerTest,CreateDataFrame)1520 TEST_P(SpdyFramerTest, CreateDataFrame) {
1521 {
1522 const char kDescription[] = "'hello' data frame, no FIN";
1523 // frame-format off
1524 const unsigned char kH2FrameData[] = {
1525 0x00, 0x00, 0x05, // Length: 5
1526 0x00, // Type: DATA
1527 0x00, // Flags: none
1528 0x00, 0x00, 0x00, 0x01, // Stream: 1
1529 'h', 'e', 'l', 'l', // Payload
1530 'o', //
1531 };
1532 // frame-format on
1533 const char bytes[] = "hello";
1534
1535 SpdyDataIR data_ir(/* stream_id = */ 1, bytes);
1536 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1537 CompareFrame(kDescription, frame, kH2FrameData,
1538 ABSL_ARRAYSIZE(kH2FrameData));
1539
1540 SpdyDataIR data_header_ir(/* stream_id = */ 1);
1541 data_header_ir.SetDataShallow(bytes);
1542 frame =
1543 framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_header_ir);
1544 CompareCharArraysWithHexError(
1545 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1546 kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
1547 }
1548
1549 {
1550 const char kDescription[] = "'hello' data frame with more padding, no FIN";
1551 // clang-format off
1552 // frame-format off
1553 const unsigned char kH2FrameData[] = {
1554 0x00, 0x00, 0xfd, // Length: 253
1555 0x00, // Type: DATA
1556 0x08, // Flags: PADDED
1557 0x00, 0x00, 0x00, 0x01, // Stream: 1
1558 0xf7, // PadLen: 247 trailing bytes
1559 'h', 'e', 'l', 'l', // Payload
1560 'o', //
1561 // Padding of 247 0x00(s).
1562 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1563 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1564 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1565 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1566 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1567 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1568 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1569 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1570 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1571 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1572 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1574 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1575 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1576 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1578 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1579 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1580 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1581 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1582 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1583 };
1584 // frame-format on
1585 // clang-format on
1586 const char bytes[] = "hello";
1587
1588 SpdyDataIR data_ir(/* stream_id = */ 1, bytes);
1589 // 247 zeros and the pad length field make the overall padding to be 248
1590 // bytes.
1591 data_ir.set_padding_len(248);
1592 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1593 CompareFrame(kDescription, frame, kH2FrameData,
1594 ABSL_ARRAYSIZE(kH2FrameData));
1595
1596 frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1597 CompareCharArraysWithHexError(
1598 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1599 kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
1600 }
1601
1602 {
1603 const char kDescription[] = "'hello' data frame with few padding, no FIN";
1604 // frame-format off
1605 const unsigned char kH2FrameData[] = {
1606 0x00, 0x00, 0x0d, // Length: 13
1607 0x00, // Type: DATA
1608 0x08, // Flags: PADDED
1609 0x00, 0x00, 0x00, 0x01, // Stream: 1
1610 0x07, // PadLen: 7 trailing bytes
1611 'h', 'e', 'l', 'l', // Payload
1612 'o', //
1613 0x00, 0x00, 0x00, 0x00, // Padding
1614 0x00, 0x00, 0x00, // Padding
1615 };
1616 // frame-format on
1617 const char bytes[] = "hello";
1618
1619 SpdyDataIR data_ir(/* stream_id = */ 1, bytes);
1620 // 7 zeros and the pad length field make the overall padding to be 8 bytes.
1621 data_ir.set_padding_len(8);
1622 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1623 CompareFrame(kDescription, frame, kH2FrameData,
1624 ABSL_ARRAYSIZE(kH2FrameData));
1625
1626 frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1627 CompareCharArraysWithHexError(
1628 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1629 kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
1630 }
1631
1632 {
1633 const char kDescription[] =
1634 "'hello' data frame with 1 byte padding, no FIN";
1635 // frame-format off
1636 const unsigned char kH2FrameData[] = {
1637 0x00, 0x00, 0x06, // Length: 6
1638 0x00, // Type: DATA
1639 0x08, // Flags: PADDED
1640 0x00, 0x00, 0x00, 0x01, // Stream: 1
1641 0x00, // PadLen: 0 trailing bytes
1642 'h', 'e', 'l', 'l', // Payload
1643 'o', //
1644 };
1645 // frame-format on
1646 const char bytes[] = "hello";
1647
1648 SpdyDataIR data_ir(/* stream_id = */ 1, bytes);
1649 // The pad length field itself is used for the 1-byte padding and no padding
1650 // payload is needed.
1651 data_ir.set_padding_len(1);
1652 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1653 CompareFrame(kDescription, frame, kH2FrameData,
1654 ABSL_ARRAYSIZE(kH2FrameData));
1655
1656 frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1657 CompareCharArraysWithHexError(
1658 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1659 kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
1660 }
1661
1662 {
1663 const char kDescription[] = "Data frame with negative data byte, no FIN";
1664 const unsigned char kH2FrameData[] = {
1665 0x00, 0x00, 0x01, // Length: 1
1666 0x00, // Type: DATA
1667 0x00, // Flags: none
1668 0x00, 0x00, 0x00, 0x01, // Stream: 1
1669 0xff, // Payload
1670 };
1671 SpdyDataIR data_ir(/* stream_id = */ 1, "\xff");
1672 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1673 CompareFrame(kDescription, frame, kH2FrameData,
1674 ABSL_ARRAYSIZE(kH2FrameData));
1675 }
1676
1677 {
1678 const char kDescription[] = "'hello' data frame, with FIN";
1679 const unsigned char kH2FrameData[] = {
1680 0x00, 0x00, 0x05, // Length: 5
1681 0x00, // Type: DATA
1682 0x01, // Flags: END_STREAM
1683 0x00, 0x00, 0x00, 0x01, // Stream: 1
1684 0x68, 0x65, 0x6c, 0x6c, // Payload
1685 0x6f, //
1686 };
1687 SpdyDataIR data_ir(/* stream_id = */ 1, "hello");
1688 data_ir.set_fin(true);
1689 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1690 CompareFrame(kDescription, frame, kH2FrameData,
1691 ABSL_ARRAYSIZE(kH2FrameData));
1692 }
1693
1694 {
1695 const char kDescription[] = "Empty data frame";
1696 const unsigned char kH2FrameData[] = {
1697 0x00, 0x00, 0x00, // Length: 0
1698 0x00, // Type: DATA
1699 0x00, // Flags: none
1700 0x00, 0x00, 0x00, 0x01, // Stream: 1
1701 };
1702 SpdyDataIR data_ir(/* stream_id = */ 1, "");
1703 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1704 CompareFrame(kDescription, frame, kH2FrameData,
1705 ABSL_ARRAYSIZE(kH2FrameData));
1706
1707 frame = framer_.SerializeDataFrameHeaderWithPaddingLengthField(data_ir);
1708 CompareCharArraysWithHexError(
1709 kDescription, reinterpret_cast<const unsigned char*>(frame.data()),
1710 kDataFrameMinimumSize, kH2FrameData, kDataFrameMinimumSize);
1711 }
1712
1713 {
1714 const char kDescription[] = "Data frame with max stream ID";
1715 const unsigned char kH2FrameData[] = {
1716 0x00, 0x00, 0x05, // Length: 5
1717 0x00, // Type: DATA
1718 0x01, // Flags: END_STREAM
1719 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1720 0x68, 0x65, 0x6c, 0x6c, // Payload
1721 0x6f, //
1722 };
1723 SpdyDataIR data_ir(/* stream_id = */ 0x7fffffff, "hello");
1724 data_ir.set_fin(true);
1725 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
1726 CompareFrame(kDescription, frame, kH2FrameData,
1727 ABSL_ARRAYSIZE(kH2FrameData));
1728 }
1729 }
1730
TEST_P(SpdyFramerTest,CreateRstStream)1731 TEST_P(SpdyFramerTest, CreateRstStream) {
1732 {
1733 const char kDescription[] = "RST_STREAM frame";
1734 const unsigned char kH2FrameData[] = {
1735 0x00, 0x00, 0x04, // Length: 4
1736 0x03, // Type: RST_STREAM
1737 0x00, // Flags: none
1738 0x00, 0x00, 0x00, 0x01, // Stream: 1
1739 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
1740 };
1741 SpdyRstStreamIR rst_stream(/* stream_id = */ 1, ERROR_CODE_PROTOCOL_ERROR);
1742 SpdySerializedFrame frame(framer_.SerializeRstStream(rst_stream));
1743 if (use_output_) {
1744 ASSERT_TRUE(framer_.SerializeRstStream(rst_stream, &output_));
1745 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1746 }
1747 CompareFrame(kDescription, frame, kH2FrameData,
1748 ABSL_ARRAYSIZE(kH2FrameData));
1749 }
1750
1751 {
1752 const char kDescription[] = "RST_STREAM frame with max stream ID";
1753 const unsigned char kH2FrameData[] = {
1754 0x00, 0x00, 0x04, // Length: 4
1755 0x03, // Type: RST_STREAM
1756 0x00, // Flags: none
1757 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1758 0x00, 0x00, 0x00, 0x01, // Error: PROTOCOL_ERROR
1759 };
1760 SpdyRstStreamIR rst_stream(/* stream_id = */ 0x7FFFFFFF,
1761 ERROR_CODE_PROTOCOL_ERROR);
1762 SpdySerializedFrame frame(framer_.SerializeRstStream(rst_stream));
1763 if (use_output_) {
1764 output_.Reset();
1765 ASSERT_TRUE(framer_.SerializeRstStream(rst_stream, &output_));
1766 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1767 }
1768 CompareFrame(kDescription, frame, kH2FrameData,
1769 ABSL_ARRAYSIZE(kH2FrameData));
1770 }
1771
1772 {
1773 const char kDescription[] = "RST_STREAM frame with max status code";
1774 const unsigned char kH2FrameData[] = {
1775 0x00, 0x00, 0x04, // Length: 4
1776 0x03, // Type: RST_STREAM
1777 0x00, // Flags: none
1778 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
1779 0x00, 0x00, 0x00, 0x02, // Error: INTERNAL_ERROR
1780 };
1781 SpdyRstStreamIR rst_stream(/* stream_id = */ 0x7FFFFFFF,
1782 ERROR_CODE_INTERNAL_ERROR);
1783 SpdySerializedFrame frame(framer_.SerializeRstStream(rst_stream));
1784 if (use_output_) {
1785 output_.Reset();
1786 ASSERT_TRUE(framer_.SerializeRstStream(rst_stream, &output_));
1787 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1788 }
1789 CompareFrame(kDescription, frame, kH2FrameData,
1790 ABSL_ARRAYSIZE(kH2FrameData));
1791 }
1792 }
1793
TEST_P(SpdyFramerTest,CreateSettings)1794 TEST_P(SpdyFramerTest, CreateSettings) {
1795 {
1796 const char kDescription[] = "Network byte order SETTINGS frame";
1797 const unsigned char kH2FrameData[] = {
1798 0x00, 0x00, 0x06, // Length: 6
1799 0x04, // Type: SETTINGS
1800 0x00, // Flags: none
1801 0x00, 0x00, 0x00, 0x00, // Stream: 0
1802 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1803 0x0a, 0x0b, 0x0c, 0x0d, // Value: 168496141
1804 };
1805
1806 uint32_t kValue = 0x0a0b0c0d;
1807 SpdySettingsIR settings_ir;
1808
1809 SpdyKnownSettingsId kId = SETTINGS_INITIAL_WINDOW_SIZE;
1810 settings_ir.AddSetting(kId, kValue);
1811
1812 SpdySerializedFrame frame(framer_.SerializeSettings(settings_ir));
1813 if (use_output_) {
1814 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
1815 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1816 }
1817 CompareFrame(kDescription, frame, kH2FrameData,
1818 ABSL_ARRAYSIZE(kH2FrameData));
1819 }
1820
1821 {
1822 const char kDescription[] = "Basic SETTINGS frame";
1823 // These end up seemingly out of order because of the way that our internal
1824 // ordering for settings_ir works. HTTP2 has no requirement on ordering on
1825 // the wire.
1826 const unsigned char kH2FrameData[] = {
1827 0x00, 0x00, 0x18, // Length: 24
1828 0x04, // Type: SETTINGS
1829 0x00, // Flags: none
1830 0x00, 0x00, 0x00, 0x00, // Stream: 0
1831 0x00, 0x01, // Param: HEADER_TABLE_SIZE
1832 0x00, 0x00, 0x00, 0x05, // Value: 5
1833 0x00, 0x02, // Param: ENABLE_PUSH
1834 0x00, 0x00, 0x00, 0x06, // Value: 6
1835 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
1836 0x00, 0x00, 0x00, 0x07, // Value: 7
1837 0x00, 0x04, // Param: INITIAL_WINDOW_SIZE
1838 0x00, 0x00, 0x00, 0x08, // Value: 8
1839 };
1840
1841 SpdySettingsIR settings_ir;
1842 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
1843 settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
1844 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
1845 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 8);
1846 SpdySerializedFrame frame(framer_.SerializeSettings(settings_ir));
1847 if (use_output_) {
1848 output_.Reset();
1849 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
1850 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1851 }
1852
1853 CompareFrame(kDescription, frame, kH2FrameData,
1854 ABSL_ARRAYSIZE(kH2FrameData));
1855 }
1856
1857 {
1858 const char kDescription[] = "Empty SETTINGS frame";
1859 const unsigned char kH2FrameData[] = {
1860 0x00, 0x00, 0x00, // Length: 0
1861 0x04, // Type: SETTINGS
1862 0x00, // Flags: none
1863 0x00, 0x00, 0x00, 0x00, // Stream: 0
1864 };
1865 SpdySettingsIR settings_ir;
1866 SpdySerializedFrame frame(framer_.SerializeSettings(settings_ir));
1867 if (use_output_) {
1868 output_.Reset();
1869 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
1870 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1871 }
1872
1873 CompareFrame(kDescription, frame, kH2FrameData,
1874 ABSL_ARRAYSIZE(kH2FrameData));
1875 }
1876 }
1877
TEST_P(SpdyFramerTest,CreatePingFrame)1878 TEST_P(SpdyFramerTest, CreatePingFrame) {
1879 {
1880 const char kDescription[] = "PING frame";
1881 const unsigned char kH2FrameData[] = {
1882 0x00, 0x00, 0x08, // Length: 8
1883 0x06, // Type: PING
1884 0x00, // Flags: none
1885 0x00, 0x00, 0x00, 0x00, // Stream: 0
1886 0x12, 0x34, 0x56, 0x78, // Opaque
1887 0x9a, 0xbc, 0xde, 0xff, // Data
1888 };
1889 const unsigned char kH2FrameDataWithAck[] = {
1890 0x00, 0x00, 0x08, // Length: 8
1891 0x06, // Type: PING
1892 0x01, // Flags: ACK
1893 0x00, 0x00, 0x00, 0x00, // Stream: 0
1894 0x12, 0x34, 0x56, 0x78, // Opaque
1895 0x9a, 0xbc, 0xde, 0xff, // Data
1896 };
1897 const SpdyPingId kPingId = 0x123456789abcdeffULL;
1898 SpdyPingIR ping_ir(kPingId);
1899 // Tests SpdyPingIR when the ping is not an ack.
1900 ASSERT_FALSE(ping_ir.is_ack());
1901 SpdySerializedFrame frame(framer_.SerializePing(ping_ir));
1902 if (use_output_) {
1903 ASSERT_TRUE(framer_.SerializePing(ping_ir, &output_));
1904 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1905 }
1906 CompareFrame(kDescription, frame, kH2FrameData,
1907 ABSL_ARRAYSIZE(kH2FrameData));
1908
1909 // Tests SpdyPingIR when the ping is an ack.
1910 ping_ir.set_is_ack(true);
1911 frame = framer_.SerializePing(ping_ir);
1912 if (use_output_) {
1913 output_.Reset();
1914 ASSERT_TRUE(framer_.SerializePing(ping_ir, &output_));
1915 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1916 }
1917 CompareFrame(kDescription, frame, kH2FrameDataWithAck,
1918 ABSL_ARRAYSIZE(kH2FrameDataWithAck));
1919 }
1920 }
1921
TEST_P(SpdyFramerTest,CreateGoAway)1922 TEST_P(SpdyFramerTest, CreateGoAway) {
1923 {
1924 const char kDescription[] = "GOAWAY frame";
1925 const unsigned char kH2FrameData[] = {
1926 0x00, 0x00, 0x0a, // Length: 10
1927 0x07, // Type: GOAWAY
1928 0x00, // Flags: none
1929 0x00, 0x00, 0x00, 0x00, // Stream: 0
1930 0x00, 0x00, 0x00, 0x00, // Last: 0
1931 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
1932 0x47, 0x41, // Description
1933 };
1934 SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0, ERROR_CODE_NO_ERROR,
1935 "GA");
1936 SpdySerializedFrame frame(framer_.SerializeGoAway(goaway_ir));
1937 if (use_output_) {
1938 ASSERT_TRUE(framer_.SerializeGoAway(goaway_ir, &output_));
1939 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1940 }
1941 CompareFrame(kDescription, frame, kH2FrameData,
1942 ABSL_ARRAYSIZE(kH2FrameData));
1943 }
1944
1945 {
1946 const char kDescription[] = "GOAWAY frame with max stream ID, status";
1947 const unsigned char kH2FrameData[] = {
1948 0x00, 0x00, 0x0a, // Length: 10
1949 0x07, // Type: GOAWAY
1950 0x00, // Flags: none
1951 0x00, 0x00, 0x00, 0x00, // Stream: 0
1952 0x7f, 0xff, 0xff, 0xff, // Last: 0x7fffffff
1953 0x00, 0x00, 0x00, 0x02, // Error: INTERNAL_ERROR
1954 0x47, 0x41, // Description
1955 };
1956 SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 0x7FFFFFFF,
1957 ERROR_CODE_INTERNAL_ERROR, "GA");
1958 SpdySerializedFrame frame(framer_.SerializeGoAway(goaway_ir));
1959 if (use_output_) {
1960 output_.Reset();
1961 ASSERT_TRUE(framer_.SerializeGoAway(goaway_ir, &output_));
1962 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
1963 }
1964 CompareFrame(kDescription, frame, kH2FrameData,
1965 ABSL_ARRAYSIZE(kH2FrameData));
1966 }
1967 }
1968
TEST_P(SpdyFramerTest,CreateHeadersUncompressed)1969 TEST_P(SpdyFramerTest, CreateHeadersUncompressed) {
1970 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
1971
1972 {
1973 const char kDescription[] = "HEADERS frame, no FIN";
1974 // frame-format off
1975 const unsigned char kH2FrameData[] = {
1976 0x00, 0x00, 0x12, // Length: 18
1977 0x01, // Type: HEADERS
1978 0x04, // Flags: END_HEADERS
1979 0x00, 0x00, 0x00, 0x01, // Stream: 1
1980
1981 0x00, // Unindexed Entry
1982 0x03, // Name Len: 3
1983 0x62, 0x61, 0x72, // bar
1984 0x03, // Value Len: 3
1985 0x66, 0x6f, 0x6f, // foo
1986
1987 0x00, // Unindexed Entry
1988 0x03, // Name Len: 3
1989 0x66, 0x6f, 0x6f, // foo
1990 0x03, // Value Len: 3
1991 0x62, 0x61, 0x72, // bar
1992 };
1993 // frame-format on
1994 SpdyHeadersIR headers(/* stream_id = */ 1);
1995 headers.SetHeader("bar", "foo");
1996 headers.SetHeader("foo", "bar");
1997 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
1998 &framer, headers, use_output_ ? &output_ : nullptr));
1999 CompareFrame(kDescription, frame, kH2FrameData,
2000 ABSL_ARRAYSIZE(kH2FrameData));
2001 }
2002
2003 {
2004 const char kDescription[] =
2005 "HEADERS frame with a 0-length header name, FIN, max stream ID";
2006 // frame-format off
2007 const unsigned char kH2FrameData[] = {
2008 0x00, 0x00, 0x0f, // Length: 15
2009 0x01, // Type: HEADERS
2010 0x05, // Flags: END_STREAM|END_HEADERS
2011 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2012
2013 0x00, // Unindexed Entry
2014 0x00, // Name Len: 0
2015 0x03, // Value Len: 3
2016 0x66, 0x6f, 0x6f, // foo
2017
2018 0x00, // Unindexed Entry
2019 0x03, // Name Len: 3
2020 0x66, 0x6f, 0x6f, // foo
2021 0x03, // Value Len: 3
2022 0x62, 0x61, 0x72, // bar
2023 };
2024 // frame-format on
2025 SpdyHeadersIR headers(/* stream_id = */ 0x7fffffff);
2026 headers.set_fin(true);
2027 headers.SetHeader("", "foo");
2028 headers.SetHeader("foo", "bar");
2029 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2030 &framer, headers, use_output_ ? &output_ : nullptr));
2031 CompareFrame(kDescription, frame, kH2FrameData,
2032 ABSL_ARRAYSIZE(kH2FrameData));
2033 }
2034
2035 {
2036 const char kDescription[] =
2037 "HEADERS frame with a 0-length header val, FIN, max stream ID";
2038 // frame-format off
2039 const unsigned char kH2FrameData[] = {
2040 0x00, 0x00, 0x0f, // Length: 15
2041 0x01, // Type: HEADERS
2042 0x05, // Flags: END_STREAM|END_HEADERS
2043 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2044
2045 0x00, // Unindexed Entry
2046 0x03, // Name Len: 3
2047 0x62, 0x61, 0x72, // bar
2048 0x03, // Value Len: 3
2049 0x66, 0x6f, 0x6f, // foo
2050
2051 0x00, // Unindexed Entry
2052 0x03, // Name Len: 3
2053 0x66, 0x6f, 0x6f, // foo
2054 0x00, // Value Len: 0
2055 };
2056 // frame-format on
2057 SpdyHeadersIR headers_ir(/* stream_id = */ 0x7fffffff);
2058 headers_ir.set_fin(true);
2059 headers_ir.SetHeader("bar", "foo");
2060 headers_ir.SetHeader("foo", "");
2061 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2062 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2063 CompareFrame(kDescription, frame, kH2FrameData,
2064 ABSL_ARRAYSIZE(kH2FrameData));
2065 }
2066
2067 {
2068 const char kDescription[] =
2069 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri";
2070
2071 // frame-format off
2072 const unsigned char kH2FrameData[] = {
2073 0x00, 0x00, 0x14, // Length: 20
2074 0x01, // Type: HEADERS
2075 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2076 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2077 0x00, 0x00, 0x00, 0x00, // Parent: 0
2078 0xdb, // Weight: 220
2079
2080 0x00, // Unindexed Entry
2081 0x03, // Name Len: 3
2082 0x62, 0x61, 0x72, // bar
2083 0x03, // Value Len: 3
2084 0x66, 0x6f, 0x6f, // foo
2085
2086 0x00, // Unindexed Entry
2087 0x03, // Name Len: 3
2088 0x66, 0x6f, 0x6f, // foo
2089 0x00, // Value Len: 0
2090 };
2091 // frame-format on
2092 SpdyHeadersIR headers_ir(/* stream_id = */ 0x7fffffff);
2093 headers_ir.set_fin(true);
2094 headers_ir.set_has_priority(true);
2095 headers_ir.set_weight(220);
2096 headers_ir.SetHeader("bar", "foo");
2097 headers_ir.SetHeader("foo", "");
2098 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2099 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2100 CompareFrame(kDescription, frame, kH2FrameData,
2101 ABSL_ARRAYSIZE(kH2FrameData));
2102 }
2103
2104 {
2105 const char kDescription[] =
2106 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2107 "exclusive=true, parent_stream=0";
2108
2109 // frame-format off
2110 const unsigned char kV4FrameData[] = {
2111 0x00, 0x00, 0x14, // Length: 20
2112 0x01, // Type: HEADERS
2113 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2114 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2115 0x80, 0x00, 0x00, 0x00, // Parent: 0 (Exclusive)
2116 0xdb, // Weight: 220
2117
2118 0x00, // Unindexed Entry
2119 0x03, // Name Len: 3
2120 0x62, 0x61, 0x72, // bar
2121 0x03, // Value Len: 3
2122 0x66, 0x6f, 0x6f, // foo
2123
2124 0x00, // Unindexed Entry
2125 0x03, // Name Len: 3
2126 0x66, 0x6f, 0x6f, // foo
2127 0x00, // Value Len: 0
2128 };
2129 // frame-format on
2130 SpdyHeadersIR headers_ir(/* stream_id = */ 0x7fffffff);
2131 headers_ir.set_fin(true);
2132 headers_ir.set_has_priority(true);
2133 headers_ir.set_weight(220);
2134 headers_ir.set_exclusive(true);
2135 headers_ir.set_parent_stream_id(0);
2136 headers_ir.SetHeader("bar", "foo");
2137 headers_ir.SetHeader("foo", "");
2138 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2139 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2140 CompareFrame(kDescription, frame, kV4FrameData,
2141 ABSL_ARRAYSIZE(kV4FrameData));
2142 }
2143
2144 {
2145 const char kDescription[] =
2146 "HEADERS frame with a 0-length header val, FIN, max stream ID, pri, "
2147 "exclusive=false, parent_stream=max stream ID";
2148
2149 // frame-format off
2150 const unsigned char kV4FrameData[] = {
2151 0x00, 0x00, 0x14, // Length: 20
2152 0x01, // Type: HEADERS
2153 0x25, // Flags: END_STREAM|END_HEADERS|PRIORITY
2154 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2155 0x7f, 0xff, 0xff, 0xff, // Parent: 2147483647
2156 0xdb, // Weight: 220
2157
2158 0x00, // Unindexed Entry
2159 0x03, // Name Len: 3
2160 0x62, 0x61, 0x72, // bar
2161 0x03, // Value Len: 3
2162 0x66, 0x6f, 0x6f, // foo
2163
2164 0x00, // Unindexed Entry
2165 0x03, // Name Len: 3
2166 0x66, 0x6f, 0x6f, // foo
2167 0x00, // Value Len: 0
2168 };
2169 // frame-format on
2170 SpdyHeadersIR headers_ir(/* stream_id = */ 0x7fffffff);
2171 headers_ir.set_fin(true);
2172 headers_ir.set_has_priority(true);
2173 headers_ir.set_weight(220);
2174 headers_ir.set_exclusive(false);
2175 headers_ir.set_parent_stream_id(0x7fffffff);
2176 headers_ir.SetHeader("bar", "foo");
2177 headers_ir.SetHeader("foo", "");
2178 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2179 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2180 CompareFrame(kDescription, frame, kV4FrameData,
2181 ABSL_ARRAYSIZE(kV4FrameData));
2182 }
2183
2184 {
2185 const char kDescription[] =
2186 "HEADERS frame with a 0-length header name, FIN, max stream ID, padded";
2187
2188 // frame-format off
2189 const unsigned char kH2FrameData[] = {
2190 0x00, 0x00, 0x15, // Length: 21
2191 0x01, // Type: HEADERS
2192 0x0d, // Flags: END_STREAM|END_HEADERS|PADDED
2193 0x7f, 0xff, 0xff, 0xff, // Stream: 2147483647
2194 0x05, // PadLen: 5 trailing bytes
2195
2196 0x00, // Unindexed Entry
2197 0x00, // Name Len: 0
2198 0x03, // Value Len: 3
2199 0x66, 0x6f, 0x6f, // foo
2200
2201 0x00, // Unindexed Entry
2202 0x03, // Name Len: 3
2203 0x66, 0x6f, 0x6f, // foo
2204 0x03, // Value Len: 3
2205 0x62, 0x61, 0x72, // bar
2206
2207 0x00, 0x00, 0x00, 0x00, // Padding
2208 0x00, // Padding
2209 };
2210 // frame-format on
2211 SpdyHeadersIR headers_ir(/* stream_id = */ 0x7fffffff);
2212 headers_ir.set_fin(true);
2213 headers_ir.SetHeader("", "foo");
2214 headers_ir.SetHeader("foo", "bar");
2215 headers_ir.set_padding_len(6);
2216 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
2217 &framer, headers_ir, use_output_ ? &output_ : nullptr));
2218 CompareFrame(kDescription, frame, kH2FrameData,
2219 ABSL_ARRAYSIZE(kH2FrameData));
2220 }
2221 }
2222
TEST_P(SpdyFramerTest,CreateWindowUpdate)2223 TEST_P(SpdyFramerTest, CreateWindowUpdate) {
2224 {
2225 const char kDescription[] = "WINDOW_UPDATE frame";
2226 const unsigned char kH2FrameData[] = {
2227 0x00, 0x00, 0x04, // Length: 4
2228 0x08, // Type: WINDOW_UPDATE
2229 0x00, // Flags: none
2230 0x00, 0x00, 0x00, 0x01, // Stream: 1
2231 0x00, 0x00, 0x00, 0x01, // Increment: 1
2232 };
2233 SpdySerializedFrame frame(framer_.SerializeWindowUpdate(
2234 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1)));
2235 if (use_output_) {
2236 output_.Reset();
2237 ASSERT_TRUE(framer_.SerializeWindowUpdate(
2238 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 1), &output_));
2239 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2240 }
2241 CompareFrame(kDescription, frame, kH2FrameData,
2242 ABSL_ARRAYSIZE(kH2FrameData));
2243 }
2244
2245 {
2246 const char kDescription[] = "WINDOW_UPDATE frame with max stream ID";
2247 const unsigned char kH2FrameData[] = {
2248 0x00, 0x00, 0x04, // Length: 4
2249 0x08, // Type: WINDOW_UPDATE
2250 0x00, // Flags: none
2251 0x7f, 0xff, 0xff, 0xff, // Stream: 0x7fffffff
2252 0x00, 0x00, 0x00, 0x01, // Increment: 1
2253 };
2254 SpdySerializedFrame frame(framer_.SerializeWindowUpdate(
2255 SpdyWindowUpdateIR(/* stream_id = */ 0x7FFFFFFF, /* delta = */ 1)));
2256 if (use_output_) {
2257 output_.Reset();
2258 ASSERT_TRUE(framer_.SerializeWindowUpdate(
2259 SpdyWindowUpdateIR(/* stream_id = */ 0x7FFFFFFF, /* delta = */ 1),
2260 &output_));
2261 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2262 }
2263 CompareFrame(kDescription, frame, kH2FrameData,
2264 ABSL_ARRAYSIZE(kH2FrameData));
2265 }
2266
2267 {
2268 const char kDescription[] = "WINDOW_UPDATE frame with max window delta";
2269 const unsigned char kH2FrameData[] = {
2270 0x00, 0x00, 0x04, // Length: 4
2271 0x08, // Type: WINDOW_UPDATE
2272 0x00, // Flags: none
2273 0x00, 0x00, 0x00, 0x01, // Stream: 1
2274 0x7f, 0xff, 0xff, 0xff, // Increment: 0x7fffffff
2275 };
2276 SpdySerializedFrame frame(framer_.SerializeWindowUpdate(
2277 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 0x7FFFFFFF)));
2278 if (use_output_) {
2279 output_.Reset();
2280 ASSERT_TRUE(framer_.SerializeWindowUpdate(
2281 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 0x7FFFFFFF),
2282 &output_));
2283 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2284 }
2285 CompareFrame(kDescription, frame, kH2FrameData,
2286 ABSL_ARRAYSIZE(kH2FrameData));
2287 }
2288 }
2289
TEST_P(SpdyFramerTest,CreatePushPromiseUncompressed)2290 TEST_P(SpdyFramerTest, CreatePushPromiseUncompressed) {
2291 {
2292 // Test framing PUSH_PROMISE without padding.
2293 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2294 const char kDescription[] = "PUSH_PROMISE frame without padding";
2295
2296 // frame-format off
2297 const unsigned char kFrameData[] = {
2298 0x00, 0x00, 0x16, // Length: 22
2299 0x05, // Type: PUSH_PROMISE
2300 0x04, // Flags: END_HEADERS
2301 0x00, 0x00, 0x00, 0x29, // Stream: 41
2302 0x00, 0x00, 0x00, 0x3a, // Promise: 58
2303
2304 0x00, // Unindexed Entry
2305 0x03, // Name Len: 3
2306 0x62, 0x61, 0x72, // bar
2307 0x03, // Value Len: 3
2308 0x66, 0x6f, 0x6f, // foo
2309
2310 0x00, // Unindexed Entry
2311 0x03, // Name Len: 3
2312 0x66, 0x6f, 0x6f, // foo
2313 0x03, // Value Len: 3
2314 0x62, 0x61, 0x72, // bar
2315 };
2316 // frame-format on
2317
2318 SpdyPushPromiseIR push_promise(/* stream_id = */ 41,
2319 /* promised_stream_id = */ 58);
2320 push_promise.SetHeader("bar", "foo");
2321 push_promise.SetHeader("foo", "bar");
2322 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2323 &framer, push_promise, use_output_ ? &output_ : nullptr));
2324 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2325 }
2326
2327 {
2328 // Test framing PUSH_PROMISE with one byte of padding.
2329 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2330 const char kDescription[] = "PUSH_PROMISE frame with one byte of padding";
2331
2332 // frame-format off
2333 const unsigned char kFrameData[] = {
2334 0x00, 0x00, 0x17, // Length: 23
2335 0x05, // Type: PUSH_PROMISE
2336 0x0c, // Flags: END_HEADERS|PADDED
2337 0x00, 0x00, 0x00, 0x29, // Stream: 41
2338 0x00, // PadLen: 0 trailing bytes
2339 0x00, 0x00, 0x00, 0x3a, // Promise: 58
2340
2341 0x00, // Unindexed Entry
2342 0x03, // Name Len: 3
2343 0x62, 0x61, 0x72, // bar
2344 0x03, // Value Len: 3
2345 0x66, 0x6f, 0x6f, // foo
2346
2347 0x00, // Unindexed Entry
2348 0x03, // Name Len: 3
2349 0x66, 0x6f, 0x6f, // foo
2350 0x03, // Value Len: 3
2351 0x62, 0x61, 0x72, // bar
2352 };
2353 // frame-format on
2354
2355 SpdyPushPromiseIR push_promise(/* stream_id = */ 41,
2356 /* promised_stream_id = */ 58);
2357 push_promise.set_padding_len(1);
2358 push_promise.SetHeader("bar", "foo");
2359 push_promise.SetHeader("foo", "bar");
2360 output_.Reset();
2361 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2362 &framer, push_promise, use_output_ ? &output_ : nullptr));
2363
2364 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2365 }
2366
2367 {
2368 // Test framing PUSH_PROMISE with 177 bytes of padding.
2369 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2370 const char kDescription[] = "PUSH_PROMISE frame with 177 bytes of padding";
2371
2372 // frame-format off
2373 // clang-format off
2374 const unsigned char kFrameData[] = {
2375 0x00, 0x00, 0xc7, // Length: 199
2376 0x05, // Type: PUSH_PROMISE
2377 0x0c, // Flags: END_HEADERS|PADDED
2378 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2379 0xb0, // PadLen: 176 trailing bytes
2380 0x00, 0x00, 0x00, 0x39, // Promise: 57
2381
2382 0x00, // Unindexed Entry
2383 0x03, // Name Len: 3
2384 0x62, 0x61, 0x72, // bar
2385 0x03, // Value Len: 3
2386 0x66, 0x6f, 0x6f, // foo
2387
2388 0x00, // Unindexed Entry
2389 0x03, // Name Len: 3
2390 0x66, 0x6f, 0x6f, // foo
2391 0x03, // Value Len: 3
2392 0x62, 0x61, 0x72, // bar
2393
2394 // Padding of 176 0x00(s).
2395 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2397 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2401 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2404 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2405 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2406 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2407 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2408 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2410 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2411 };
2412 // clang-format on
2413 // frame-format on
2414
2415 SpdyPushPromiseIR push_promise(/* stream_id = */ 42,
2416 /* promised_stream_id = */ 57);
2417 push_promise.set_padding_len(177);
2418 push_promise.SetHeader("bar", "foo");
2419 push_promise.SetHeader("foo", "bar");
2420 output_.Reset();
2421 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2422 &framer, push_promise, use_output_ ? &output_ : nullptr));
2423
2424 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2425 }
2426 }
2427
2428 // Regression test for https://crbug.com/464748.
TEST_P(SpdyFramerTest,GetNumberRequiredContinuationFrames)2429 TEST_P(SpdyFramerTest, GetNumberRequiredContinuationFrames) {
2430 EXPECT_EQ(1u, GetNumberRequiredContinuationFrames(16383 + 16374));
2431 EXPECT_EQ(2u, GetNumberRequiredContinuationFrames(16383 + 16374 + 1));
2432 EXPECT_EQ(2u, GetNumberRequiredContinuationFrames(16383 + 2 * 16374));
2433 EXPECT_EQ(3u, GetNumberRequiredContinuationFrames(16383 + 2 * 16374 + 1));
2434 }
2435
TEST_P(SpdyFramerTest,CreateContinuationUncompressed)2436 TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
2437 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2438 const char kDescription[] = "CONTINUATION frame";
2439
2440 // frame-format off
2441 const unsigned char kFrameData[] = {
2442 0x00, 0x00, 0x12, // Length: 18
2443 0x09, // Type: CONTINUATION
2444 0x04, // Flags: END_HEADERS
2445 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2446
2447 0x00, // Unindexed Entry
2448 0x03, // Name Len: 3
2449 0x62, 0x61, 0x72, // bar
2450 0x03, // Value Len: 3
2451 0x66, 0x6f, 0x6f, // foo
2452
2453 0x00, // Unindexed Entry
2454 0x03, // Name Len: 3
2455 0x66, 0x6f, 0x6f, // foo
2456 0x03, // Value Len: 3
2457 0x62, 0x61, 0x72, // bar
2458 };
2459 // frame-format on
2460
2461 Http2HeaderBlock header_block;
2462 header_block["bar"] = "foo";
2463 header_block["foo"] = "bar";
2464 HpackEncoder encoder;
2465 encoder.DisableCompression();
2466 std::string buffer = encoder.EncodeHeaderBlock(header_block);
2467
2468 SpdyContinuationIR continuation(/* stream_id = */ 42);
2469 continuation.take_encoding(std::move(buffer));
2470 continuation.set_end_headers(true);
2471
2472 SpdySerializedFrame frame(framer.SerializeContinuation(continuation));
2473 if (use_output_) {
2474 ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
2475 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2476 }
2477 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2478 }
2479
2480 // Test that if we send an unexpected CONTINUATION
2481 // we signal an error (but don't crash).
TEST_P(SpdyFramerTest,SendUnexpectedContinuation)2482 TEST_P(SpdyFramerTest, SendUnexpectedContinuation) {
2483 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
2484
2485 deframer_->set_visitor(&visitor);
2486
2487 // frame-format off
2488 char kH2FrameData[] = {
2489 0x00, 0x00, 0x12, // Length: 18
2490 0x09, // Type: CONTINUATION
2491 0x04, // Flags: END_HEADERS
2492 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2493
2494 0x00, // Unindexed Entry
2495 0x03, // Name Len: 3
2496 0x62, 0x61, 0x72, // bar
2497 0x03, // Value Len: 3
2498 0x66, 0x6f, 0x6f, // foo
2499
2500 0x00, // Unindexed Entry
2501 0x03, // Name Len: 3
2502 0x66, 0x6f, 0x6f, // foo
2503 0x03, // Value Len: 3
2504 0x62, 0x61, 0x72, // bar
2505 };
2506 // frame-format on
2507
2508 SpdySerializedFrame frame =
2509 MakeSerializedFrame(kH2FrameData, sizeof(kH2FrameData));
2510
2511 // We shouldn't have to read the whole frame before we signal an error.
2512 EXPECT_CALL(visitor, OnCommonHeader(42, 18, 0x9, 0x4));
2513 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME, _));
2514 EXPECT_GT(frame.size(), deframer_->ProcessInput(frame.data(), frame.size()));
2515 EXPECT_TRUE(deframer_->HasError());
2516 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
2517 deframer_->spdy_framer_error())
2518 << Http2DecoderAdapter::SpdyFramerErrorToString(
2519 deframer_->spdy_framer_error());
2520 }
2521
TEST_P(SpdyFramerTest,CreatePushPromiseThenContinuationUncompressed)2522 TEST_P(SpdyFramerTest, CreatePushPromiseThenContinuationUncompressed) {
2523 {
2524 // Test framing in a case such that a PUSH_PROMISE frame, with one byte of
2525 // padding, cannot hold all the data payload, which is overflowed to the
2526 // consecutive CONTINUATION frame.
2527 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2528 const char kDescription[] =
2529 "PUSH_PROMISE and CONTINUATION frames with one byte of padding";
2530
2531 // frame-format off
2532 const unsigned char kPartialPushPromiseFrameData[] = {
2533 0x00, 0x3f, 0xf6, // Length: 16374
2534 0x05, // Type: PUSH_PROMISE
2535 0x08, // Flags: PADDED
2536 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2537 0x00, // PadLen: 0 trailing bytes
2538 0x00, 0x00, 0x00, 0x39, // Promise: 57
2539
2540 0x00, // Unindexed Entry
2541 0x03, // Name Len: 3
2542 0x78, 0x78, 0x78, // xxx
2543 0x7f, 0x80, 0x7f, // Value Len: 16361
2544 0x78, 0x78, 0x78, 0x78, // xxxx
2545 0x78, 0x78, 0x78, 0x78, // xxxx
2546 0x78, 0x78, 0x78, 0x78, // xxxx
2547 0x78, 0x78, 0x78, 0x78, // xxxx
2548 0x78, 0x78, 0x78, 0x78, // xxxx
2549 0x78, 0x78, 0x78, 0x78, // xxxx
2550 0x78, 0x78, 0x78, 0x78, // xxxx
2551 0x78, 0x78, 0x78, 0x78, // xxxx
2552 0x78, 0x78, 0x78, 0x78, // xxxx
2553 0x78, 0x78, 0x78, 0x78, // xxxx
2554 0x78, 0x78, 0x78, 0x78, // xxxx
2555 0x78, 0x78, 0x78, 0x78, // xxxx
2556 0x78, 0x78, 0x78, 0x78, // xxxx
2557 0x78, 0x78, 0x78, 0x78, // xxxx
2558 0x78, 0x78, 0x78, 0x78, // xxxx
2559 0x78, 0x78, 0x78, 0x78, // xxxx
2560 0x78, 0x78, 0x78, 0x78, // xxxx
2561 0x78, 0x78, 0x78, 0x78, // xxxx
2562 0x78, 0x78, 0x78, 0x78, // xxxx
2563 0x78, 0x78, 0x78, 0x78, // xxxx
2564 0x78, 0x78, 0x78, 0x78, // xxxx
2565 };
2566 const unsigned char kContinuationFrameData[] = {
2567 0x00, 0x00, 0x16, // Length: 22
2568 0x09, // Type: CONTINUATION
2569 0x04, // Flags: END_HEADERS
2570 0x00, 0x00, 0x00, 0x2a, // Stream: 42
2571 0x78, 0x78, 0x78, 0x78, // xxxx
2572 0x78, 0x78, 0x78, 0x78, // xxxx
2573 0x78, 0x78, 0x78, 0x78, // xxxx
2574 0x78, 0x78, 0x78, 0x78, // xxxx
2575 0x78, 0x78, 0x78, 0x78, // xxxx
2576 0x78, // x
2577 };
2578 // frame-format on
2579
2580 SpdyPushPromiseIR push_promise(/* stream_id = */ 42,
2581 /* promised_stream_id = */ 57);
2582 push_promise.set_padding_len(1);
2583 std::string big_value(kHttp2MaxControlFrameSendSize, 'x');
2584 push_promise.SetHeader("xxx", big_value);
2585 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
2586 &framer, push_promise, use_output_ ? &output_ : nullptr));
2587
2588 // The entire frame should look like below:
2589 // Name Length in Byte
2590 // ------------------------------------------- Begin of PUSH_PROMISE frame
2591 // PUSH_PROMISE header 9
2592 // Pad length field 1
2593 // Promised stream 4
2594 // Length field of key 2
2595 // Content of key 3
2596 // Length field of value 3
2597 // Part of big_value 16361
2598 // ------------------------------------------- Begin of CONTINUATION frame
2599 // CONTINUATION header 9
2600 // Remaining of big_value 22
2601 // ------------------------------------------- End
2602
2603 // Length of everything listed above except big_value.
2604 int len_non_data_payload = 31;
2605 EXPECT_EQ(kHttp2MaxControlFrameSendSize + len_non_data_payload,
2606 frame.size());
2607
2608 // Partially compare the PUSH_PROMISE frame against the template.
2609 const unsigned char* frame_data =
2610 reinterpret_cast<const unsigned char*>(frame.data());
2611 CompareCharArraysWithHexError(kDescription, frame_data,
2612 ABSL_ARRAYSIZE(kPartialPushPromiseFrameData),
2613 kPartialPushPromiseFrameData,
2614 ABSL_ARRAYSIZE(kPartialPushPromiseFrameData));
2615
2616 // Compare the CONTINUATION frame against the template.
2617 frame_data += kHttp2MaxControlFrameSendSize;
2618 CompareCharArraysWithHexError(
2619 kDescription, frame_data, ABSL_ARRAYSIZE(kContinuationFrameData),
2620 kContinuationFrameData, ABSL_ARRAYSIZE(kContinuationFrameData));
2621 }
2622 }
2623
TEST_P(SpdyFramerTest,CreateAltSvc)2624 TEST_P(SpdyFramerTest, CreateAltSvc) {
2625 const char kDescription[] = "ALTSVC frame";
2626 const unsigned char kType = SerializeFrameType(SpdyFrameType::ALTSVC);
2627 const unsigned char kFrameData[] = {
2628 0x00, 0x00, 0x49, kType, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 'o',
2629 'r', 'i', 'g', 'i', 'n', 'p', 'i', 'd', '1', '=', '"', 'h',
2630 'o', 's', 't', ':', '4', '4', '3', '"', ';', ' ', 'm', 'a',
2631 '=', '5', ',', 'p', '%', '2', '2', '%', '3', 'D', 'i', '%',
2632 '3', 'A', 'd', '=', '"', 'h', '_', '\\', '\\', 'o', '\\', '"',
2633 's', 't', ':', '1', '2', '3', '"', ';', ' ', 'm', 'a', '=',
2634 '4', '2', ';', ' ', 'v', '=', '"', '2', '4', '"'};
2635 SpdyAltSvcIR altsvc_ir(/* stream_id = */ 3);
2636 altsvc_ir.set_origin("origin");
2637 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
2638 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector()));
2639 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
2640 "p\"=i:d", "h_\\o\"st", 123, 42,
2641 SpdyAltSvcWireFormat::VersionVector{24}));
2642 SpdySerializedFrame frame(framer_.SerializeFrame(altsvc_ir));
2643 if (use_output_) {
2644 EXPECT_EQ(framer_.SerializeFrame(altsvc_ir, &output_), frame.size());
2645 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2646 }
2647 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2648 }
2649
TEST_P(SpdyFramerTest,CreatePriority)2650 TEST_P(SpdyFramerTest, CreatePriority) {
2651 const char kDescription[] = "PRIORITY frame";
2652 const unsigned char kFrameData[] = {
2653 0x00, 0x00, 0x05, // Length: 5
2654 0x02, // Type: PRIORITY
2655 0x00, // Flags: none
2656 0x00, 0x00, 0x00, 0x02, // Stream: 2
2657 0x80, 0x00, 0x00, 0x01, // Parent: 1 (Exclusive)
2658 0x10, // Weight: 17
2659 };
2660 SpdyPriorityIR priority_ir(/* stream_id = */ 2,
2661 /* parent_stream_id = */ 1,
2662 /* weight = */ 17,
2663 /* exclusive = */ true);
2664 SpdySerializedFrame frame(framer_.SerializeFrame(priority_ir));
2665 if (use_output_) {
2666 EXPECT_EQ(framer_.SerializeFrame(priority_ir, &output_), frame.size());
2667 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2668 }
2669 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2670 }
2671
TEST_P(SpdyFramerTest,CreatePriorityUpdate)2672 TEST_P(SpdyFramerTest, CreatePriorityUpdate) {
2673 const char kDescription[] = "PRIORITY_UPDATE frame";
2674 const unsigned char kType =
2675 SerializeFrameType(SpdyFrameType::PRIORITY_UPDATE);
2676 const unsigned char kFrameData[] = {
2677 0x00, 0x00, 0x07, // frame length
2678 kType, // frame type
2679 0x00, // flags
2680 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0 for PRIORITY_UPDATE
2681 0x00, 0x00, 0x00, 0x03, // prioritized stream ID
2682 'u', '=', '0'}; // priority field value
2683 SpdyPriorityUpdateIR priority_update_ir(/* stream_id = */ 0,
2684 /* prioritized_stream_id = */ 3,
2685 /* priority_field_value = */ "u=0");
2686 SpdySerializedFrame frame(framer_.SerializeFrame(priority_update_ir));
2687 if (use_output_) {
2688 EXPECT_EQ(framer_.SerializeFrame(priority_update_ir, &output_),
2689 frame.size());
2690 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2691 }
2692 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2693 }
2694
TEST_P(SpdyFramerTest,CreateAcceptCh)2695 TEST_P(SpdyFramerTest, CreateAcceptCh) {
2696 const char kDescription[] = "ACCEPT_CH frame";
2697 const unsigned char kType = SerializeFrameType(SpdyFrameType::ACCEPT_CH);
2698 const unsigned char kFrameData[] = {
2699 0x00, 0x00, 0x2d, // frame length
2700 kType, // frame type
2701 0x00, // flags
2702 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0 for ACCEPT_CH
2703 0x00, 0x0f, // origin length
2704 'w', 'w', 'w', '.', 'e', 'x', // origin
2705 'a', 'm', 'p', 'l', 'e', '.', //
2706 'c', 'o', 'm', //
2707 0x00, 0x03, // value length
2708 'f', 'o', 'o', // value
2709 0x00, 0x10, // origin length
2710 'm', 'a', 'i', 'l', '.', 'e', //
2711 'x', 'a', 'm', 'p', 'l', 'e', //
2712 '.', 'c', 'o', 'm', //
2713 0x00, 0x03, // value length
2714 'b', 'a', 'r'}; // value
2715 SpdyAcceptChIR accept_ch_ir(
2716 {{"www.example.com", "foo"}, {"mail.example.com", "bar"}});
2717 SpdySerializedFrame frame(framer_.SerializeFrame(accept_ch_ir));
2718 if (use_output_) {
2719 EXPECT_EQ(framer_.SerializeFrame(accept_ch_ir, &output_), frame.size());
2720 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2721 }
2722 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2723 }
2724
TEST_P(SpdyFramerTest,CreateUnknown)2725 TEST_P(SpdyFramerTest, CreateUnknown) {
2726 const char kDescription[] = "Unknown frame";
2727 const uint8_t kType = 0xaf;
2728 const uint8_t kFlags = 0x11;
2729 const uint8_t kLength = strlen(kDescription);
2730 const unsigned char kFrameData[] = {
2731 0x00, 0x00, kLength, // Length: 13
2732 kType, // Type: undefined
2733 kFlags, // Flags: arbitrary, undefined
2734 0x00, 0x00, 0x00, 0x02, // Stream: 2
2735 0x55, 0x6e, 0x6b, 0x6e, // "Unkn"
2736 0x6f, 0x77, 0x6e, 0x20, // "own "
2737 0x66, 0x72, 0x61, 0x6d, // "fram"
2738 0x65, // "e"
2739 };
2740 SpdyUnknownIR unknown_ir(/* stream_id = */ 2,
2741 /* type = */ kType,
2742 /* flags = */ kFlags,
2743 /* payload = */ kDescription);
2744 SpdySerializedFrame frame(framer_.SerializeFrame(unknown_ir));
2745 if (use_output_) {
2746 EXPECT_EQ(framer_.SerializeFrame(unknown_ir, &output_), frame.size());
2747 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2748 }
2749 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2750 }
2751
2752 // Test serialization of a SpdyUnknownIR with a defined type, a length field
2753 // that does not match the payload size and in fact exceeds framer limits, and a
2754 // stream ID that effectively flips the reserved bit.
TEST_P(SpdyFramerTest,CreateUnknownUnchecked)2755 TEST_P(SpdyFramerTest, CreateUnknownUnchecked) {
2756 const char kDescription[] = "Unknown frame";
2757 const uint8_t kType = 0x00;
2758 const uint8_t kFlags = 0x11;
2759 const uint8_t kLength = std::numeric_limits<uint8_t>::max();
2760 const unsigned int kStreamId = kStreamIdMask + 42;
2761 const unsigned char kFrameData[] = {
2762 0x00, 0x00, kLength, // Length: 16426
2763 kType, // Type: DATA, defined
2764 kFlags, // Flags: arbitrary, undefined
2765 0x80, 0x00, 0x00, 0x29, // Stream: 2147483689
2766 0x55, 0x6e, 0x6b, 0x6e, // "Unkn"
2767 0x6f, 0x77, 0x6e, 0x20, // "own "
2768 0x66, 0x72, 0x61, 0x6d, // "fram"
2769 0x65, // "e"
2770 };
2771 TestSpdyUnknownIR unknown_ir(/* stream_id = */ kStreamId,
2772 /* type = */ kType,
2773 /* flags = */ kFlags,
2774 /* payload = */ kDescription);
2775 unknown_ir.set_length(kLength);
2776 SpdySerializedFrame frame(framer_.SerializeFrame(unknown_ir));
2777 if (use_output_) {
2778 EXPECT_EQ(framer_.SerializeFrame(unknown_ir, &output_), frame.size());
2779 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
2780 }
2781 CompareFrame(kDescription, frame, kFrameData, ABSL_ARRAYSIZE(kFrameData));
2782 }
2783
TEST_P(SpdyFramerTest,ReadCompressedHeadersHeaderBlock)2784 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlock) {
2785 SpdyHeadersIR headers_ir(/* stream_id = */ 1);
2786 headers_ir.SetHeader("alpha", "beta");
2787 headers_ir.SetHeader("gamma", "delta");
2788 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2789 &framer_, headers_ir, use_output_ ? &output_ : nullptr));
2790 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
2791 visitor.SimulateInFramer(
2792 reinterpret_cast<unsigned char*>(control_frame.data()),
2793 control_frame.size());
2794 EXPECT_EQ(1, visitor.headers_frame_count_);
2795 EXPECT_EQ(0, visitor.control_frame_header_data_count_);
2796 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2797 EXPECT_EQ(0, visitor.end_of_stream_count_);
2798 EXPECT_EQ(headers_ir.header_block(), visitor.headers_);
2799 }
2800
TEST_P(SpdyFramerTest,ReadCompressedHeadersHeaderBlockWithHalfClose)2801 TEST_P(SpdyFramerTest, ReadCompressedHeadersHeaderBlockWithHalfClose) {
2802 SpdyHeadersIR headers_ir(/* stream_id = */ 1);
2803 headers_ir.set_fin(true);
2804 headers_ir.SetHeader("alpha", "beta");
2805 headers_ir.SetHeader("gamma", "delta");
2806 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2807 &framer_, headers_ir, use_output_ ? &output_ : nullptr));
2808 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
2809 visitor.SimulateInFramer(
2810 reinterpret_cast<unsigned char*>(control_frame.data()),
2811 control_frame.size());
2812 EXPECT_EQ(1, visitor.headers_frame_count_);
2813 EXPECT_EQ(0, visitor.control_frame_header_data_count_);
2814 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2815 EXPECT_EQ(1, visitor.end_of_stream_count_);
2816 EXPECT_EQ(headers_ir.header_block(), visitor.headers_);
2817 }
2818
TEST_P(SpdyFramerTest,TooLargeHeadersFrameUsesContinuation)2819 TEST_P(SpdyFramerTest, TooLargeHeadersFrameUsesContinuation) {
2820 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2821 SpdyHeadersIR headers(/* stream_id = */ 1);
2822 headers.set_padding_len(256);
2823
2824 // Exact payload length will change with HPACK, but this should be long
2825 // enough to cause an overflow.
2826 const size_t kBigValueSize = kHttp2MaxControlFrameSendSize;
2827 std::string big_value(kBigValueSize, 'x');
2828 headers.SetHeader("aa", big_value);
2829 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
2830 &framer, headers, use_output_ ? &output_ : nullptr));
2831 EXPECT_GT(control_frame.size(), kHttp2MaxControlFrameSendSize);
2832
2833 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2834 visitor.SimulateInFramer(
2835 reinterpret_cast<unsigned char*>(control_frame.data()),
2836 control_frame.size());
2837 EXPECT_TRUE(visitor.header_buffer_valid_);
2838 EXPECT_EQ(0, visitor.error_count_);
2839 EXPECT_EQ(1, visitor.headers_frame_count_);
2840 EXPECT_EQ(1, visitor.continuation_count_);
2841 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2842 }
2843
TEST_P(SpdyFramerTest,MultipleContinuationFramesWithIterator)2844 TEST_P(SpdyFramerTest, MultipleContinuationFramesWithIterator) {
2845 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2846 auto headers = std::make_unique<SpdyHeadersIR>(/* stream_id = */ 1);
2847 headers->set_padding_len(256);
2848
2849 // Exact payload length will change with HPACK, but this should be long
2850 // enough to cause an overflow.
2851 const size_t kBigValueSize = kHttp2MaxControlFrameSendSize;
2852 std::string big_valuex(kBigValueSize, 'x');
2853 headers->SetHeader("aa", big_valuex);
2854 std::string big_valuez(kBigValueSize, 'z');
2855 headers->SetHeader("bb", big_valuez);
2856
2857 SpdyFramer::SpdyHeaderFrameIterator frame_it(&framer, std::move(headers));
2858
2859 EXPECT_TRUE(frame_it.HasNextFrame());
2860 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2861 SpdySerializedFrame headers_frame =
2862 MakeSerializedFrame(output_.Begin(), output_.Size());
2863 EXPECT_EQ(headers_frame.size(), kHttp2MaxControlFrameSendSize);
2864
2865 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2866 visitor.SimulateInFramer(
2867 reinterpret_cast<unsigned char*>(headers_frame.data()),
2868 headers_frame.size());
2869 EXPECT_TRUE(visitor.header_buffer_valid_);
2870 EXPECT_EQ(0, visitor.error_count_);
2871 EXPECT_EQ(1, visitor.headers_frame_count_);
2872 EXPECT_EQ(0, visitor.continuation_count_);
2873 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2874
2875 output_.Reset();
2876 EXPECT_TRUE(frame_it.HasNextFrame());
2877 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2878 SpdySerializedFrame first_cont_frame =
2879 MakeSerializedFrame(output_.Begin(), output_.Size());
2880 EXPECT_EQ(first_cont_frame.size(), kHttp2MaxControlFrameSendSize);
2881
2882 visitor.SimulateInFramer(
2883 reinterpret_cast<unsigned char*>(first_cont_frame.data()),
2884 first_cont_frame.size());
2885 EXPECT_TRUE(visitor.header_buffer_valid_);
2886 EXPECT_EQ(0, visitor.error_count_);
2887 EXPECT_EQ(1, visitor.headers_frame_count_);
2888 EXPECT_EQ(1, visitor.continuation_count_);
2889 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2890
2891 output_.Reset();
2892 EXPECT_TRUE(frame_it.HasNextFrame());
2893 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2894 SpdySerializedFrame second_cont_frame =
2895 MakeSerializedFrame(output_.Begin(), output_.Size());
2896 EXPECT_LT(second_cont_frame.size(), kHttp2MaxControlFrameSendSize);
2897
2898 visitor.SimulateInFramer(
2899 reinterpret_cast<unsigned char*>(second_cont_frame.data()),
2900 second_cont_frame.size());
2901 EXPECT_TRUE(visitor.header_buffer_valid_);
2902 EXPECT_EQ(0, visitor.error_count_);
2903 EXPECT_EQ(1, visitor.headers_frame_count_);
2904 EXPECT_EQ(2, visitor.continuation_count_);
2905 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2906
2907 EXPECT_FALSE(frame_it.HasNextFrame());
2908 }
2909
TEST_P(SpdyFramerTest,PushPromiseFramesWithIterator)2910 TEST_P(SpdyFramerTest, PushPromiseFramesWithIterator) {
2911 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2912 auto push_promise =
2913 std::make_unique<SpdyPushPromiseIR>(/* stream_id = */ 1,
2914 /* promised_stream_id = */ 2);
2915 push_promise->set_padding_len(256);
2916
2917 // Exact payload length will change with HPACK, but this should be long
2918 // enough to cause an overflow.
2919 const size_t kBigValueSize = kHttp2MaxControlFrameSendSize;
2920 std::string big_valuex(kBigValueSize, 'x');
2921 push_promise->SetHeader("aa", big_valuex);
2922 std::string big_valuez(kBigValueSize, 'z');
2923 push_promise->SetHeader("bb", big_valuez);
2924
2925 SpdyFramer::SpdyPushPromiseFrameIterator frame_it(&framer,
2926 std::move(push_promise));
2927
2928 EXPECT_TRUE(frame_it.HasNextFrame());
2929 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2930 SpdySerializedFrame push_promise_frame =
2931 MakeSerializedFrame(output_.Begin(), output_.Size());
2932 EXPECT_EQ(push_promise_frame.size(), kHttp2MaxControlFrameSendSize);
2933
2934 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
2935 visitor.SimulateInFramer(
2936 reinterpret_cast<unsigned char*>(push_promise_frame.data()),
2937 push_promise_frame.size());
2938 EXPECT_TRUE(visitor.header_buffer_valid_);
2939 EXPECT_EQ(0, visitor.error_count_);
2940 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2941 EXPECT_EQ(0, visitor.continuation_count_);
2942 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2943
2944 EXPECT_TRUE(frame_it.HasNextFrame());
2945 output_.Reset();
2946 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2947 SpdySerializedFrame first_cont_frame =
2948 MakeSerializedFrame(output_.Begin(), output_.Size());
2949
2950 EXPECT_EQ(first_cont_frame.size(), kHttp2MaxControlFrameSendSize);
2951 visitor.SimulateInFramer(
2952 reinterpret_cast<unsigned char*>(first_cont_frame.data()),
2953 first_cont_frame.size());
2954 EXPECT_TRUE(visitor.header_buffer_valid_);
2955 EXPECT_EQ(0, visitor.error_count_);
2956 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2957 EXPECT_EQ(1, visitor.continuation_count_);
2958 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2959
2960 EXPECT_TRUE(frame_it.HasNextFrame());
2961 output_.Reset();
2962 EXPECT_GT(frame_it.NextFrame(&output_), 0u);
2963 SpdySerializedFrame second_cont_frame =
2964 MakeSerializedFrame(output_.Begin(), output_.Size());
2965 EXPECT_LT(second_cont_frame.size(), kHttp2MaxControlFrameSendSize);
2966
2967 visitor.SimulateInFramer(
2968 reinterpret_cast<unsigned char*>(second_cont_frame.data()),
2969 second_cont_frame.size());
2970 EXPECT_TRUE(visitor.header_buffer_valid_);
2971 EXPECT_EQ(0, visitor.error_count_);
2972 EXPECT_EQ(1, visitor.push_promise_frame_count_);
2973 EXPECT_EQ(2, visitor.continuation_count_);
2974 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
2975
2976 EXPECT_FALSE(frame_it.HasNextFrame());
2977 }
2978
2979 class SpdyControlFrameIteratorTest : public quiche::test::QuicheTest {
2980 public:
SpdyControlFrameIteratorTest()2981 SpdyControlFrameIteratorTest() : output_(output_buffer, kSize) {}
2982
RunTest(std::unique_ptr<SpdyFrameIR> ir)2983 void RunTest(std::unique_ptr<SpdyFrameIR> ir) {
2984 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
2985 SpdySerializedFrame frame(framer.SerializeFrame(*ir));
2986 std::unique_ptr<SpdyFrameSequence> it =
2987 SpdyFramer::CreateIterator(&framer, std::move(ir));
2988 EXPECT_TRUE(it->HasNextFrame());
2989 EXPECT_EQ(it->NextFrame(&output_), frame.size());
2990 EXPECT_FALSE(it->HasNextFrame());
2991 }
2992
2993 private:
2994 ArrayOutputBuffer output_;
2995 };
2996
TEST_F(SpdyControlFrameIteratorTest,RstStreamFrameWithIterator)2997 TEST_F(SpdyControlFrameIteratorTest, RstStreamFrameWithIterator) {
2998 auto ir = std::make_unique<SpdyRstStreamIR>(0, ERROR_CODE_PROTOCOL_ERROR);
2999 RunTest(std::move(ir));
3000 }
3001
TEST_F(SpdyControlFrameIteratorTest,SettingsFrameWithIterator)3002 TEST_F(SpdyControlFrameIteratorTest, SettingsFrameWithIterator) {
3003 auto ir = std::make_unique<SpdySettingsIR>();
3004 uint32_t kValue = 0x0a0b0c0d;
3005 SpdyKnownSettingsId kId = SETTINGS_INITIAL_WINDOW_SIZE;
3006 ir->AddSetting(kId, kValue);
3007 RunTest(std::move(ir));
3008 }
3009
TEST_F(SpdyControlFrameIteratorTest,PingFrameWithIterator)3010 TEST_F(SpdyControlFrameIteratorTest, PingFrameWithIterator) {
3011 const SpdyPingId kPingId = 0x123456789abcdeffULL;
3012 auto ir = std::make_unique<SpdyPingIR>(kPingId);
3013 RunTest(std::move(ir));
3014 }
3015
TEST_F(SpdyControlFrameIteratorTest,GoAwayFrameWithIterator)3016 TEST_F(SpdyControlFrameIteratorTest, GoAwayFrameWithIterator) {
3017 auto ir = std::make_unique<SpdyGoAwayIR>(0, ERROR_CODE_NO_ERROR, "GA");
3018 RunTest(std::move(ir));
3019 }
3020
TEST_F(SpdyControlFrameIteratorTest,WindowUpdateFrameWithIterator)3021 TEST_F(SpdyControlFrameIteratorTest, WindowUpdateFrameWithIterator) {
3022 auto ir = std::make_unique<SpdyWindowUpdateIR>(1, 1);
3023 RunTest(std::move(ir));
3024 }
3025
TEST_F(SpdyControlFrameIteratorTest,AtlSvcFrameWithIterator)3026 TEST_F(SpdyControlFrameIteratorTest, AtlSvcFrameWithIterator) {
3027 auto ir = std::make_unique<SpdyAltSvcIR>(3);
3028 ir->set_origin("origin");
3029 ir->add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
3030 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector()));
3031 ir->add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
3032 "p\"=i:d", "h_\\o\"st", 123, 42,
3033 SpdyAltSvcWireFormat::VersionVector{24}));
3034 RunTest(std::move(ir));
3035 }
3036
TEST_F(SpdyControlFrameIteratorTest,PriorityFrameWithIterator)3037 TEST_F(SpdyControlFrameIteratorTest, PriorityFrameWithIterator) {
3038 auto ir = std::make_unique<SpdyPriorityIR>(2, 1, 17, true);
3039 RunTest(std::move(ir));
3040 }
3041
TEST_P(SpdyFramerTest,TooLargePushPromiseFrameUsesContinuation)3042 TEST_P(SpdyFramerTest, TooLargePushPromiseFrameUsesContinuation) {
3043 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
3044 SpdyPushPromiseIR push_promise(/* stream_id = */ 1,
3045 /* promised_stream_id = */ 2);
3046 push_promise.set_padding_len(256);
3047
3048 // Exact payload length will change with HPACK, but this should be long
3049 // enough to cause an overflow.
3050 const size_t kBigValueSize = kHttp2MaxControlFrameSendSize;
3051 std::string big_value(kBigValueSize, 'x');
3052 push_promise.SetHeader("aa", big_value);
3053 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializePushPromise(
3054 &framer, push_promise, use_output_ ? &output_ : nullptr));
3055 EXPECT_GT(control_frame.size(), kHttp2MaxControlFrameSendSize);
3056
3057 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3058 visitor.SimulateInFramer(
3059 reinterpret_cast<unsigned char*>(control_frame.data()),
3060 control_frame.size());
3061 EXPECT_TRUE(visitor.header_buffer_valid_);
3062 EXPECT_EQ(0, visitor.error_count_);
3063 EXPECT_EQ(1, visitor.push_promise_frame_count_);
3064 EXPECT_EQ(1, visitor.continuation_count_);
3065 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3066 }
3067
3068 // Check that the framer stops delivering header data chunks once the visitor
3069 // declares it doesn't want any more. This is important to guard against
3070 // "zip bomb" types of attacks.
TEST_P(SpdyFramerTest,ControlFrameMuchTooLarge)3071 TEST_P(SpdyFramerTest, ControlFrameMuchTooLarge) {
3072 const size_t kHeaderBufferChunks = 4;
3073 const size_t kHeaderBufferSize =
3074 kHttp2DefaultFramePayloadLimit / kHeaderBufferChunks;
3075 const size_t kBigValueSize = kHeaderBufferSize * 2;
3076 std::string big_value(kBigValueSize, 'x');
3077 SpdyHeadersIR headers(/* stream_id = */ 1);
3078 headers.set_fin(true);
3079 headers.SetHeader("aa", big_value);
3080 SpdySerializedFrame control_frame(SpdyFramerPeer::SerializeHeaders(
3081 &framer_, headers, use_output_ ? &output_ : nullptr));
3082 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
3083 visitor.set_header_buffer_size(kHeaderBufferSize);
3084 visitor.SimulateInFramer(
3085 reinterpret_cast<unsigned char*>(control_frame.data()),
3086 control_frame.size());
3087 // It's up to the visitor to ignore extraneous header data; the framer
3088 // won't throw an error.
3089 EXPECT_GT(visitor.header_bytes_received_, visitor.header_buffer_size_);
3090 EXPECT_EQ(1, visitor.end_of_stream_count_);
3091 }
3092
TEST_P(SpdyFramerTest,ControlFrameSizesAreValidated)3093 TEST_P(SpdyFramerTest, ControlFrameSizesAreValidated) {
3094 // Create a GoAway frame that has a few extra bytes at the end.
3095 const size_t length = 20;
3096
3097 // HTTP/2 GOAWAY frames are only bound by a minimal length, since they may
3098 // carry opaque data. Verify that minimal length is tested.
3099 ASSERT_GT(kGoawayFrameMinimumSize, kFrameHeaderSize);
3100 const size_t less_than_min_length =
3101 kGoawayFrameMinimumSize - kFrameHeaderSize - 1;
3102 ASSERT_LE(less_than_min_length, std::numeric_limits<unsigned char>::max());
3103 const unsigned char kH2Len = static_cast<unsigned char>(less_than_min_length);
3104 const unsigned char kH2FrameData[] = {
3105 0x00, 0x00, kH2Len, // Length: min length - 1
3106 0x07, // Type: GOAWAY
3107 0x00, // Flags: none
3108 0x00, 0x00, 0x00, 0x00, // Stream: 0
3109 0x00, 0x00, 0x00, 0x00, // Last: 0
3110 0x00, 0x00, 0x00, // Truncated Status Field
3111 };
3112 const size_t pad_length = length + kFrameHeaderSize - sizeof(kH2FrameData);
3113 std::string pad(pad_length, 'A');
3114 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3115
3116 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3117 visitor.SimulateInFramer(reinterpret_cast<const unsigned char*>(pad.c_str()),
3118 pad.length());
3119
3120 EXPECT_EQ(1, visitor.error_count_); // This generated an error.
3121 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
3122 visitor.deframer_.spdy_framer_error())
3123 << Http2DecoderAdapter::SpdyFramerErrorToString(
3124 visitor.deframer_.spdy_framer_error());
3125 EXPECT_EQ(0, visitor.goaway_count_); // Frame not parsed.
3126 }
3127
TEST_P(SpdyFramerTest,ReadZeroLenSettingsFrame)3128 TEST_P(SpdyFramerTest, ReadZeroLenSettingsFrame) {
3129 SpdySettingsIR settings_ir;
3130 SpdySerializedFrame control_frame(framer_.SerializeSettings(settings_ir));
3131 if (use_output_) {
3132 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
3133 control_frame = MakeSerializedFrame(output_.Begin(), output_.Size());
3134 }
3135 SetFrameLength(&control_frame, 0);
3136 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3137 visitor.SimulateInFramer(
3138 reinterpret_cast<unsigned char*>(control_frame.data()), kFrameHeaderSize);
3139 // Zero-len settings frames are permitted as of HTTP/2.
3140 EXPECT_EQ(0, visitor.error_count_);
3141 }
3142
3143 // Tests handling of SETTINGS frames with invalid length.
TEST_P(SpdyFramerTest,ReadBogusLenSettingsFrame)3144 TEST_P(SpdyFramerTest, ReadBogusLenSettingsFrame) {
3145 SpdySettingsIR settings_ir;
3146
3147 // Add settings to more than fill the frame so that we don't get a buffer
3148 // overflow when calling SimulateInFramer() below. These settings must be
3149 // distinct parameters because SpdySettingsIR has a map for settings, and
3150 // will collapse multiple copies of the same parameter.
3151 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 0x00000002);
3152 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 0x00000002);
3153 SpdySerializedFrame control_frame(framer_.SerializeSettings(settings_ir));
3154 if (use_output_) {
3155 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
3156 control_frame = MakeSerializedFrame(output_.Begin(), output_.Size());
3157 }
3158 const size_t kNewLength = 8;
3159 SetFrameLength(&control_frame, kNewLength);
3160 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3161 visitor.SimulateInFramer(
3162 reinterpret_cast<unsigned char*>(control_frame.data()),
3163 kFrameHeaderSize + kNewLength);
3164 // Should generate an error, since its not possible to have a
3165 // settings frame of length kNewLength.
3166 EXPECT_EQ(1, visitor.error_count_);
3167 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
3168 visitor.deframer_.spdy_framer_error())
3169 << Http2DecoderAdapter::SpdyFramerErrorToString(
3170 visitor.deframer_.spdy_framer_error());
3171 }
3172
3173 // Tests handling of larger SETTINGS frames.
TEST_P(SpdyFramerTest,ReadLargeSettingsFrame)3174 TEST_P(SpdyFramerTest, ReadLargeSettingsFrame) {
3175 SpdySettingsIR settings_ir;
3176 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
3177 settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
3178 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
3179
3180 SpdySerializedFrame control_frame(framer_.SerializeSettings(settings_ir));
3181 if (use_output_) {
3182 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
3183 control_frame = MakeSerializedFrame(output_.Begin(), output_.Size());
3184 }
3185
3186 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3187
3188 // Read all at once.
3189 visitor.SimulateInFramer(
3190 reinterpret_cast<unsigned char*>(control_frame.data()),
3191 control_frame.size());
3192 EXPECT_EQ(0, visitor.error_count_);
3193 EXPECT_EQ(3, visitor.setting_count_);
3194 EXPECT_EQ(1, visitor.settings_ack_sent_);
3195
3196 // Read data in small chunks.
3197 size_t framed_data = 0;
3198 size_t unframed_data = control_frame.size();
3199 size_t kReadChunkSize = 5; // Read five bytes at a time.
3200 while (unframed_data > 0) {
3201 size_t to_read = std::min(kReadChunkSize, unframed_data);
3202 visitor.SimulateInFramer(
3203 reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
3204 to_read);
3205 unframed_data -= to_read;
3206 framed_data += to_read;
3207 }
3208 EXPECT_EQ(0, visitor.error_count_);
3209 EXPECT_EQ(3 * 2, visitor.setting_count_);
3210 EXPECT_EQ(2, visitor.settings_ack_sent_);
3211 }
3212
3213 // Tests handling of SETTINGS frame with duplicate entries.
TEST_P(SpdyFramerTest,ReadDuplicateSettings)3214 TEST_P(SpdyFramerTest, ReadDuplicateSettings) {
3215 const unsigned char kH2FrameData[] = {
3216 0x00, 0x00, 0x12, // Length: 18
3217 0x04, // Type: SETTINGS
3218 0x00, // Flags: none
3219 0x00, 0x00, 0x00, 0x00, // Stream: 0
3220 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3221 0x00, 0x00, 0x00, 0x02, // Value: 2
3222 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3223 0x00, 0x00, 0x00, 0x03, // Value: 3
3224 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
3225 0x00, 0x00, 0x00, 0x03, // Value: 3
3226 };
3227
3228 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3229 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3230
3231 // In HTTP/2, duplicate settings are allowed;
3232 // each setting replaces the previous value for that setting.
3233 EXPECT_EQ(3, visitor.setting_count_);
3234 EXPECT_EQ(0, visitor.error_count_);
3235 EXPECT_EQ(1, visitor.settings_ack_sent_);
3236 }
3237
3238 // Tests handling of SETTINGS frame with a setting we don't recognize.
TEST_P(SpdyFramerTest,ReadUnknownSettingsId)3239 TEST_P(SpdyFramerTest, ReadUnknownSettingsId) {
3240 const unsigned char kH2FrameData[] = {
3241 0x00, 0x00, 0x06, // Length: 6
3242 0x04, // Type: SETTINGS
3243 0x00, // Flags: none
3244 0x00, 0x00, 0x00, 0x00, // Stream: 0
3245 0x00, 0x10, // Param: 16
3246 0x00, 0x00, 0x00, 0x02, // Value: 2
3247 };
3248
3249 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3250 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3251
3252 // In HTTP/2, we ignore unknown settings because of extensions. However, we
3253 // pass the SETTINGS to the visitor, which can decide how to handle them.
3254 EXPECT_EQ(1, visitor.setting_count_);
3255 EXPECT_EQ(0, visitor.error_count_);
3256 }
3257
TEST_P(SpdyFramerTest,ReadKnownAndUnknownSettingsWithExtension)3258 TEST_P(SpdyFramerTest, ReadKnownAndUnknownSettingsWithExtension) {
3259 const unsigned char kH2FrameData[] = {
3260 0x00, 0x00, 0x18, // Length: 24
3261 0x04, // Type: SETTINGS
3262 0x00, // Flags: none
3263 0x00, 0x00, 0x00, 0x00, // Stream: 0
3264 0x00, 0x10, // Param: 16
3265 0x00, 0x00, 0x00, 0x02, // Value: 2
3266 0x00, 0x5f, // Param: 95
3267 0x00, 0x01, 0x00, 0x02, // Value: 65538
3268 0x00, 0x02, // Param: ENABLE_PUSH
3269 0x00, 0x00, 0x00, 0x01, // Value: 1
3270 0x00, 0x08, // Param: ENABLE_CONNECT_PROTOCOL
3271 0x00, 0x00, 0x00, 0x01, // Value: 1
3272 };
3273
3274 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3275 TestExtension extension;
3276 visitor.set_extension_visitor(&extension);
3277 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3278
3279 // In HTTP/2, we ignore unknown settings because of extensions. However, we
3280 // pass the SETTINGS to the visitor, which can decide how to handle them.
3281 EXPECT_EQ(4, visitor.setting_count_);
3282 EXPECT_EQ(0, visitor.error_count_);
3283
3284 // The extension receives only the non-standard SETTINGS.
3285 EXPECT_THAT(
3286 extension.settings_received_,
3287 testing::ElementsAre(testing::Pair(16, 2), testing::Pair(95, 65538)));
3288 }
3289
3290 // Tests handling of SETTINGS frame with entries out of order.
TEST_P(SpdyFramerTest,ReadOutOfOrderSettings)3291 TEST_P(SpdyFramerTest, ReadOutOfOrderSettings) {
3292 const unsigned char kH2FrameData[] = {
3293 0x00, 0x00, 0x12, // Length: 18
3294 0x04, // Type: SETTINGS
3295 0x00, // Flags: none
3296 0x00, 0x00, 0x00, 0x00, // Stream: 0
3297 0x00, 0x02, // Param: ENABLE_PUSH
3298 0x00, 0x00, 0x00, 0x02, // Value: 2
3299 0x00, 0x01, // Param: HEADER_TABLE_SIZE
3300 0x00, 0x00, 0x00, 0x03, // Value: 3
3301 0x00, 0x03, // Param: MAX_CONCURRENT_STREAMS
3302 0x00, 0x00, 0x00, 0x03, // Value: 3
3303 };
3304
3305 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3306 visitor.SimulateInFramer(kH2FrameData, sizeof(kH2FrameData));
3307
3308 // In HTTP/2, settings are allowed in any order.
3309 EXPECT_EQ(3, visitor.setting_count_);
3310 EXPECT_EQ(0, visitor.error_count_);
3311 }
3312
TEST_P(SpdyFramerTest,ProcessSettingsAckFrame)3313 TEST_P(SpdyFramerTest, ProcessSettingsAckFrame) {
3314 const unsigned char kFrameData[] = {
3315 0x00, 0x00, 0x00, // Length: 0
3316 0x04, // Type: SETTINGS
3317 0x01, // Flags: ACK
3318 0x00, 0x00, 0x00, 0x00, // Stream: 0
3319 };
3320
3321 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3322 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
3323
3324 EXPECT_EQ(0, visitor.error_count_);
3325 EXPECT_EQ(0, visitor.setting_count_);
3326 EXPECT_EQ(1, visitor.settings_ack_received_);
3327 }
3328
TEST_P(SpdyFramerTest,ProcessDataFrameWithPadding)3329 TEST_P(SpdyFramerTest, ProcessDataFrameWithPadding) {
3330 const int kPaddingLen = 119;
3331 const char data_payload[] = "hello";
3332
3333 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
3334 deframer_->set_visitor(&visitor);
3335
3336 SpdyDataIR data_ir(/* stream_id = */ 1, data_payload);
3337 data_ir.set_padding_len(kPaddingLen);
3338 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
3339
3340 int bytes_consumed = 0;
3341
3342 // Send the frame header.
3343 EXPECT_CALL(visitor,
3344 OnCommonHeader(1, kPaddingLen + strlen(data_payload), 0x0, 0x8));
3345 EXPECT_CALL(visitor,
3346 OnDataFrameHeader(1, kPaddingLen + strlen(data_payload), false));
3347 QUICHE_CHECK_EQ(kDataFrameMinimumSize,
3348 deframer_->ProcessInput(frame.data(), kDataFrameMinimumSize));
3349 QUICHE_CHECK_EQ(deframer_->state(),
3350 Http2DecoderAdapter::SPDY_READ_DATA_FRAME_PADDING_LENGTH);
3351 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3352 Http2DecoderAdapter::SPDY_NO_ERROR);
3353 bytes_consumed += kDataFrameMinimumSize;
3354
3355 // Send the padding length field.
3356 EXPECT_CALL(visitor, OnStreamPadLength(1, kPaddingLen - 1));
3357 QUICHE_CHECK_EQ(1u,
3358 deframer_->ProcessInput(frame.data() + bytes_consumed, 1));
3359 QUICHE_CHECK_EQ(deframer_->state(),
3360 Http2DecoderAdapter::SPDY_FORWARD_STREAM_FRAME);
3361 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3362 Http2DecoderAdapter::SPDY_NO_ERROR);
3363 bytes_consumed += 1;
3364
3365 // Send the first two bytes of the data payload, i.e., "he".
3366 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 2));
3367 QUICHE_CHECK_EQ(2u,
3368 deframer_->ProcessInput(frame.data() + bytes_consumed, 2));
3369 QUICHE_CHECK_EQ(deframer_->state(),
3370 Http2DecoderAdapter::SPDY_FORWARD_STREAM_FRAME);
3371 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3372 Http2DecoderAdapter::SPDY_NO_ERROR);
3373 bytes_consumed += 2;
3374
3375 // Send the rest three bytes of the data payload, i.e., "llo".
3376 EXPECT_CALL(visitor, OnStreamFrameData(1, _, 3));
3377 QUICHE_CHECK_EQ(3u,
3378 deframer_->ProcessInput(frame.data() + bytes_consumed, 3));
3379 QUICHE_CHECK_EQ(deframer_->state(),
3380 Http2DecoderAdapter::SPDY_CONSUME_PADDING);
3381 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3382 Http2DecoderAdapter::SPDY_NO_ERROR);
3383 bytes_consumed += 3;
3384
3385 // Send the first 100 bytes of the padding payload.
3386 EXPECT_CALL(visitor, OnStreamPadding(1, 100));
3387 QUICHE_CHECK_EQ(100u,
3388 deframer_->ProcessInput(frame.data() + bytes_consumed, 100));
3389 QUICHE_CHECK_EQ(deframer_->state(),
3390 Http2DecoderAdapter::SPDY_CONSUME_PADDING);
3391 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3392 Http2DecoderAdapter::SPDY_NO_ERROR);
3393 bytes_consumed += 100;
3394
3395 // Send rest of the padding payload.
3396 EXPECT_CALL(visitor, OnStreamPadding(1, 18));
3397 QUICHE_CHECK_EQ(18u,
3398 deframer_->ProcessInput(frame.data() + bytes_consumed, 18));
3399 QUICHE_CHECK_EQ(deframer_->state(),
3400 Http2DecoderAdapter::SPDY_READY_FOR_FRAME);
3401 QUICHE_CHECK_EQ(deframer_->spdy_framer_error(),
3402 Http2DecoderAdapter::SPDY_NO_ERROR);
3403 }
3404
TEST_P(SpdyFramerTest,ReadWindowUpdate)3405 TEST_P(SpdyFramerTest, ReadWindowUpdate) {
3406 SpdySerializedFrame control_frame(framer_.SerializeWindowUpdate(
3407 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 2)));
3408 if (use_output_) {
3409 ASSERT_TRUE(framer_.SerializeWindowUpdate(
3410 SpdyWindowUpdateIR(/* stream_id = */ 1, /* delta = */ 2), &output_));
3411 control_frame = MakeSerializedFrame(output_.Begin(), output_.Size());
3412 }
3413 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3414 visitor.SimulateInFramer(
3415 reinterpret_cast<unsigned char*>(control_frame.data()),
3416 control_frame.size());
3417 EXPECT_EQ(1u, visitor.last_window_update_stream_);
3418 EXPECT_EQ(2, visitor.last_window_update_delta_);
3419 }
3420
TEST_P(SpdyFramerTest,ReadCompressedPushPromise)3421 TEST_P(SpdyFramerTest, ReadCompressedPushPromise) {
3422 SpdyPushPromiseIR push_promise(/* stream_id = */ 42,
3423 /* promised_stream_id = */ 57);
3424 push_promise.SetHeader("foo", "bar");
3425 push_promise.SetHeader("bar", "foofoo");
3426 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
3427 &framer_, push_promise, use_output_ ? &output_ : nullptr));
3428 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
3429 visitor.SimulateInFramer(reinterpret_cast<unsigned char*>(frame.data()),
3430 frame.size());
3431 EXPECT_EQ(42u, visitor.last_push_promise_stream_);
3432 EXPECT_EQ(57u, visitor.last_push_promise_promised_stream_);
3433 EXPECT_EQ(push_promise.header_block(), visitor.headers_);
3434 }
3435
TEST_P(SpdyFramerTest,ReadHeadersWithContinuation)3436 TEST_P(SpdyFramerTest, ReadHeadersWithContinuation) {
3437 // frame-format off
3438 const unsigned char kInput[] = {
3439 0x00, 0x00, 0x14, // Length: 20
3440 0x01, // Type: HEADERS
3441 0x08, // Flags: PADDED
3442 0x00, 0x00, 0x00, 0x01, // Stream: 1
3443 0x03, // PadLen: 3 trailing bytes
3444 0x00, // Unindexed Entry
3445 0x06, // Name Len: 6
3446 'c', 'o', 'o', 'k', 'i', 'e', // Name
3447 0x07, // Value Len: 7
3448 'f', 'o', 'o', '=', 'b', 'a', 'r', // Value
3449 0x00, 0x00, 0x00, // Padding
3450
3451 0x00, 0x00, 0x14, // Length: 20
3452 0x09, // Type: CONTINUATION
3453 0x00, // Flags: none
3454 0x00, 0x00, 0x00, 0x01, // Stream: 1
3455 0x00, // Unindexed Entry
3456 0x06, // Name Len: 6
3457 'c', 'o', 'o', 'k', 'i', 'e', // Name
3458 0x08, // Value Len: 7
3459 'b', 'a', 'z', '=', 'b', 'i', 'n', 'g', // Value
3460 0x00, // Unindexed Entry
3461 0x06, // Name Len: 6
3462 'c', // Name (split)
3463
3464 0x00, 0x00, 0x12, // Length: 18
3465 0x09, // Type: CONTINUATION
3466 0x04, // Flags: END_HEADERS
3467 0x00, 0x00, 0x00, 0x01, // Stream: 1
3468 'o', 'o', 'k', 'i', 'e', // Name (continued)
3469 0x00, // Value Len: 0
3470 0x00, // Unindexed Entry
3471 0x04, // Name Len: 4
3472 'n', 'a', 'm', 'e', // Name
3473 0x05, // Value Len: 5
3474 'v', 'a', 'l', 'u', 'e', // Value
3475 };
3476 // frame-format on
3477
3478 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3479 visitor.SimulateInFramer(kInput, sizeof(kInput));
3480
3481 EXPECT_EQ(0, visitor.error_count_);
3482 EXPECT_EQ(1, visitor.headers_frame_count_);
3483 EXPECT_EQ(2, visitor.continuation_count_);
3484 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3485 EXPECT_EQ(0, visitor.end_of_stream_count_);
3486
3487 EXPECT_THAT(
3488 visitor.headers_,
3489 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3490 testing::Pair("name", "value")));
3491 }
3492
TEST_P(SpdyFramerTest,ReadHeadersWithContinuationAndFin)3493 TEST_P(SpdyFramerTest, ReadHeadersWithContinuationAndFin) {
3494 // frame-format off
3495 const unsigned char kInput[] = {
3496 0x00, 0x00, 0x10, // Length: 20
3497 0x01, // Type: HEADERS
3498 0x01, // Flags: END_STREAM
3499 0x00, 0x00, 0x00, 0x01, // Stream: 1
3500 0x00, // Unindexed Entry
3501 0x06, // Name Len: 6
3502 'c', 'o', 'o', 'k', 'i', 'e', // Name
3503 0x07, // Value Len: 7
3504 'f', 'o', 'o', '=', 'b', 'a', 'r', // Value
3505
3506 0x00, 0x00, 0x14, // Length: 20
3507 0x09, // Type: CONTINUATION
3508 0x00, // Flags: none
3509 0x00, 0x00, 0x00, 0x01, // Stream: 1
3510 0x00, // Unindexed Entry
3511 0x06, // Name Len: 6
3512 'c', 'o', 'o', 'k', 'i', 'e', // Name
3513 0x08, // Value Len: 7
3514 'b', 'a', 'z', '=', 'b', 'i', 'n', 'g', // Value
3515 0x00, // Unindexed Entry
3516 0x06, // Name Len: 6
3517 'c', // Name (split)
3518
3519 0x00, 0x00, 0x12, // Length: 18
3520 0x09, // Type: CONTINUATION
3521 0x04, // Flags: END_HEADERS
3522 0x00, 0x00, 0x00, 0x01, // Stream: 1
3523 'o', 'o', 'k', 'i', 'e', // Name (continued)
3524 0x00, // Value Len: 0
3525 0x00, // Unindexed Entry
3526 0x04, // Name Len: 4
3527 'n', 'a', 'm', 'e', // Name
3528 0x05, // Value Len: 5
3529 'v', 'a', 'l', 'u', 'e', // Value
3530 };
3531 // frame-format on
3532
3533 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3534 visitor.SimulateInFramer(kInput, sizeof(kInput));
3535
3536 EXPECT_EQ(0, visitor.error_count_);
3537 EXPECT_EQ(1, visitor.headers_frame_count_);
3538 EXPECT_EQ(2, visitor.continuation_count_);
3539 EXPECT_EQ(1, visitor.fin_flag_count_);
3540 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3541 EXPECT_EQ(1, visitor.end_of_stream_count_);
3542
3543 EXPECT_THAT(
3544 visitor.headers_,
3545 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3546 testing::Pair("name", "value")));
3547 }
3548
TEST_P(SpdyFramerTest,ReadPushPromiseWithContinuation)3549 TEST_P(SpdyFramerTest, ReadPushPromiseWithContinuation) {
3550 // frame-format off
3551 const unsigned char kInput[] = {
3552 0x00, 0x00, 0x17, // Length: 23
3553 0x05, // Type: PUSH_PROMISE
3554 0x08, // Flags: PADDED
3555 0x00, 0x00, 0x00, 0x01, // Stream: 1
3556 0x02, // PadLen: 2 trailing bytes
3557 0x00, 0x00, 0x00, 0x2a, // Promise: 42
3558 0x00, // Unindexed Entry
3559 0x06, // Name Len: 6
3560 'c', 'o', 'o', 'k', 'i', 'e', // Name
3561 0x07, // Value Len: 7
3562 'f', 'o', 'o', '=', 'b', 'a', 'r', // Value
3563 0x00, 0x00, // Padding
3564
3565 0x00, 0x00, 0x14, // Length: 20
3566 0x09, // Type: CONTINUATION
3567 0x00, // Flags: none
3568 0x00, 0x00, 0x00, 0x01, // Stream: 1
3569 0x00, // Unindexed Entry
3570 0x06, // Name Len: 6
3571 'c', 'o', 'o', 'k', 'i', 'e', // Name
3572 0x08, // Value Len: 7
3573 'b', 'a', 'z', '=', 'b', 'i', 'n', 'g', // Value
3574 0x00, // Unindexed Entry
3575 0x06, // Name Len: 6
3576 'c', // Name (split)
3577
3578 0x00, 0x00, 0x12, // Length: 18
3579 0x09, // Type: CONTINUATION
3580 0x04, // Flags: END_HEADERS
3581 0x00, 0x00, 0x00, 0x01, // Stream: 1
3582 'o', 'o', 'k', 'i', 'e', // Name (continued)
3583 0x00, // Value Len: 0
3584 0x00, // Unindexed Entry
3585 0x04, // Name Len: 4
3586 'n', 'a', 'm', 'e', // Name
3587 0x05, // Value Len: 5
3588 'v', 'a', 'l', 'u', 'e', // Value
3589 };
3590 // frame-format on
3591
3592 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3593 visitor.SimulateInFramer(kInput, sizeof(kInput));
3594
3595 EXPECT_EQ(0, visitor.error_count_);
3596 EXPECT_EQ(1u, visitor.last_push_promise_stream_);
3597 EXPECT_EQ(42u, visitor.last_push_promise_promised_stream_);
3598 EXPECT_EQ(2, visitor.continuation_count_);
3599 EXPECT_EQ(0, visitor.zero_length_control_frame_header_data_count_);
3600 EXPECT_EQ(0, visitor.end_of_stream_count_);
3601
3602 EXPECT_THAT(
3603 visitor.headers_,
3604 testing::ElementsAre(testing::Pair("cookie", "foo=bar; baz=bing; "),
3605 testing::Pair("name", "value")));
3606 }
3607
3608 // Receiving an unknown frame when a continuation is expected should
3609 // result in a SPDY_UNEXPECTED_FRAME error
TEST_P(SpdyFramerTest,ReceiveUnknownMidContinuation)3610 TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuation) {
3611 const unsigned char kInput[] = {
3612 0x00, 0x00, 0x10, // Length: 16
3613 0x01, // Type: HEADERS
3614 0x00, // Flags: none
3615 0x00, 0x00, 0x00, 0x01, // Stream: 1
3616 0x00, 0x06, 0x63, 0x6f, // HPACK
3617 0x6f, 0x6b, 0x69, 0x65, //
3618 0x07, 0x66, 0x6f, 0x6f, //
3619 0x3d, 0x62, 0x61, 0x72, //
3620
3621 0x00, 0x00, 0x14, // Length: 20
3622 0xa9, // Type: UnknownFrameType(169)
3623 0x00, // Flags: none
3624 0x00, 0x00, 0x00, 0x01, // Stream: 1
3625 0x00, 0x06, 0x63, 0x6f, // Payload
3626 0x6f, 0x6b, 0x69, 0x65, //
3627 0x08, 0x62, 0x61, 0x7a, //
3628 0x3d, 0x62, 0x69, 0x6e, //
3629 0x67, 0x00, 0x06, 0x63, //
3630 };
3631
3632 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3633 // Assume the unknown frame is allowed
3634 visitor.on_unknown_frame_result_ = true;
3635 deframer_->set_visitor(&visitor);
3636 visitor.SimulateInFramer(kInput, sizeof(kInput));
3637
3638 EXPECT_EQ(1, visitor.error_count_);
3639 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3640 visitor.deframer_.spdy_framer_error())
3641 << Http2DecoderAdapter::SpdyFramerErrorToString(
3642 visitor.deframer_.spdy_framer_error());
3643 EXPECT_EQ(1, visitor.headers_frame_count_);
3644 EXPECT_EQ(0, visitor.continuation_count_);
3645 EXPECT_EQ(0u, visitor.header_buffer_length_);
3646 }
3647
3648 // Receiving an unknown frame when a continuation is expected should
3649 // result in a SPDY_UNEXPECTED_FRAME error
TEST_P(SpdyFramerTest,ReceiveUnknownMidContinuationWithExtension)3650 TEST_P(SpdyFramerTest, ReceiveUnknownMidContinuationWithExtension) {
3651 const unsigned char kInput[] = {
3652 0x00, 0x00, 0x10, // Length: 16
3653 0x01, // Type: HEADERS
3654 0x00, // Flags: none
3655 0x00, 0x00, 0x00, 0x01, // Stream: 1
3656 0x00, 0x06, 0x63, 0x6f, // HPACK
3657 0x6f, 0x6b, 0x69, 0x65, //
3658 0x07, 0x66, 0x6f, 0x6f, //
3659 0x3d, 0x62, 0x61, 0x72, //
3660
3661 0x00, 0x00, 0x14, // Length: 20
3662 0xa9, // Type: UnknownFrameType(169)
3663 0x00, // Flags: none
3664 0x00, 0x00, 0x00, 0x01, // Stream: 1
3665 0x00, 0x06, 0x63, 0x6f, // Payload
3666 0x6f, 0x6b, 0x69, 0x65, //
3667 0x08, 0x62, 0x61, 0x7a, //
3668 0x3d, 0x62, 0x69, 0x6e, //
3669 0x67, 0x00, 0x06, 0x63, //
3670 };
3671
3672 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3673 TestExtension extension;
3674 visitor.set_extension_visitor(&extension);
3675 deframer_->set_visitor(&visitor);
3676 visitor.SimulateInFramer(kInput, sizeof(kInput));
3677
3678 EXPECT_EQ(1, visitor.error_count_);
3679 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3680 visitor.deframer_.spdy_framer_error())
3681 << Http2DecoderAdapter::SpdyFramerErrorToString(
3682 visitor.deframer_.spdy_framer_error());
3683 EXPECT_EQ(1, visitor.headers_frame_count_);
3684 EXPECT_EQ(0, visitor.continuation_count_);
3685 EXPECT_EQ(0u, visitor.header_buffer_length_);
3686 }
3687
TEST_P(SpdyFramerTest,ReceiveContinuationOnWrongStream)3688 TEST_P(SpdyFramerTest, ReceiveContinuationOnWrongStream) {
3689 const unsigned char kInput[] = {
3690 0x00, 0x00, 0x10, // Length: 16
3691 0x01, // Type: HEADERS
3692 0x00, // Flags: none
3693 0x00, 0x00, 0x00, 0x01, // Stream: 1
3694 0x00, 0x06, 0x63, 0x6f, // HPACK
3695 0x6f, 0x6b, 0x69, 0x65, //
3696 0x07, 0x66, 0x6f, 0x6f, //
3697 0x3d, 0x62, 0x61, 0x72, //
3698
3699 0x00, 0x00, 0x14, // Length: 20
3700 0x09, // Type: CONTINUATION
3701 0x00, // Flags: none
3702 0x00, 0x00, 0x00, 0x02, // Stream: 2
3703 0x00, 0x06, 0x63, 0x6f, // HPACK
3704 0x6f, 0x6b, 0x69, 0x65, //
3705 0x08, 0x62, 0x61, 0x7a, //
3706 0x3d, 0x62, 0x69, 0x6e, //
3707 0x67, 0x00, 0x06, 0x63, //
3708 };
3709
3710 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3711 deframer_->set_visitor(&visitor);
3712 visitor.SimulateInFramer(kInput, sizeof(kInput));
3713
3714 EXPECT_EQ(1, visitor.error_count_);
3715 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3716 visitor.deframer_.spdy_framer_error())
3717 << Http2DecoderAdapter::SpdyFramerErrorToString(
3718 visitor.deframer_.spdy_framer_error());
3719 EXPECT_EQ(1, visitor.headers_frame_count_);
3720 EXPECT_EQ(0, visitor.continuation_count_);
3721 EXPECT_EQ(0u, visitor.header_buffer_length_);
3722 }
3723
TEST_P(SpdyFramerTest,ReadContinuationOutOfOrder)3724 TEST_P(SpdyFramerTest, ReadContinuationOutOfOrder) {
3725 const unsigned char kInput[] = {
3726 0x00, 0x00, 0x18, // Length: 24
3727 0x09, // Type: CONTINUATION
3728 0x00, // Flags: none
3729 0x00, 0x00, 0x00, 0x01, // Stream: 1
3730 0x00, 0x06, 0x63, 0x6f, // HPACK
3731 0x6f, 0x6b, 0x69, 0x65, //
3732 0x07, 0x66, 0x6f, 0x6f, //
3733 0x3d, 0x62, 0x61, 0x72, //
3734 };
3735
3736 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3737 deframer_->set_visitor(&visitor);
3738 visitor.SimulateInFramer(kInput, sizeof(kInput));
3739
3740 EXPECT_EQ(1, visitor.error_count_);
3741 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3742 visitor.deframer_.spdy_framer_error())
3743 << Http2DecoderAdapter::SpdyFramerErrorToString(
3744 visitor.deframer_.spdy_framer_error());
3745 EXPECT_EQ(0, visitor.continuation_count_);
3746 EXPECT_EQ(0u, visitor.header_buffer_length_);
3747 }
3748
TEST_P(SpdyFramerTest,ExpectContinuationReceiveData)3749 TEST_P(SpdyFramerTest, ExpectContinuationReceiveData) {
3750 const unsigned char kInput[] = {
3751 0x00, 0x00, 0x10, // Length: 16
3752 0x01, // Type: HEADERS
3753 0x00, // Flags: none
3754 0x00, 0x00, 0x00, 0x01, // Stream: 1
3755 0x00, 0x06, 0x63, 0x6f, // HPACK
3756 0x6f, 0x6b, 0x69, 0x65, //
3757 0x07, 0x66, 0x6f, 0x6f, //
3758 0x3d, 0x62, 0x61, 0x72, //
3759
3760 0x00, 0x00, 0x00, // Length: 0
3761 0x00, // Type: DATA
3762 0x01, // Flags: END_STREAM
3763 0x00, 0x00, 0x00, 0x04, // Stream: 4
3764
3765 0xde, 0xad, 0xbe, 0xef, // Truncated Frame Header
3766 };
3767
3768 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3769 deframer_->set_visitor(&visitor);
3770 visitor.SimulateInFramer(kInput, sizeof(kInput));
3771
3772 EXPECT_EQ(1, visitor.error_count_);
3773 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3774 visitor.deframer_.spdy_framer_error())
3775 << Http2DecoderAdapter::SpdyFramerErrorToString(
3776 visitor.deframer_.spdy_framer_error());
3777 EXPECT_EQ(1, visitor.headers_frame_count_);
3778 EXPECT_EQ(0, visitor.continuation_count_);
3779 EXPECT_EQ(0u, visitor.header_buffer_length_);
3780 EXPECT_EQ(0, visitor.data_frame_count_);
3781 }
3782
TEST_P(SpdyFramerTest,ExpectContinuationReceiveControlFrame)3783 TEST_P(SpdyFramerTest, ExpectContinuationReceiveControlFrame) {
3784 const unsigned char kInput[] = {
3785 0x00, 0x00, 0x10, // Length: 16
3786 0x01, // Type: HEADERS
3787 0x00, // Flags: none
3788 0x00, 0x00, 0x00, 0x01, // Stream: 1
3789 0x00, 0x06, 0x63, 0x6f, // HPACK
3790 0x6f, 0x6b, 0x69, 0x65, //
3791 0x07, 0x66, 0x6f, 0x6f, //
3792 0x3d, 0x62, 0x61, 0x72, //
3793
3794 0x00, 0x00, 0x10, // Length: 16
3795 0x01, // Type: HEADERS
3796 0x00, // Flags: none
3797 0x00, 0x00, 0x00, 0x01, // Stream: 1
3798 0x00, 0x06, 0x63, 0x6f, // HPACK
3799 0x6f, 0x6b, 0x69, 0x65, //
3800 0x07, 0x66, 0x6f, 0x6f, //
3801 0x3d, 0x62, 0x61, 0x72, //
3802 };
3803
3804 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3805 deframer_->set_visitor(&visitor);
3806 visitor.SimulateInFramer(kInput, sizeof(kInput));
3807
3808 EXPECT_EQ(1, visitor.error_count_);
3809 EXPECT_EQ(Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME,
3810 visitor.deframer_.spdy_framer_error())
3811 << Http2DecoderAdapter::SpdyFramerErrorToString(
3812 visitor.deframer_.spdy_framer_error());
3813 EXPECT_EQ(1, visitor.headers_frame_count_);
3814 EXPECT_EQ(0, visitor.continuation_count_);
3815 EXPECT_EQ(0u, visitor.header_buffer_length_);
3816 EXPECT_EQ(0, visitor.data_frame_count_);
3817 }
3818
TEST_P(SpdyFramerTest,ReadGarbage)3819 TEST_P(SpdyFramerTest, ReadGarbage) {
3820 unsigned char garbage_frame[256];
3821 memset(garbage_frame, ~0, sizeof(garbage_frame));
3822 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3823 visitor.SimulateInFramer(garbage_frame, sizeof(garbage_frame));
3824 EXPECT_EQ(1, visitor.error_count_);
3825 }
3826
TEST_P(SpdyFramerTest,ReadUnknownExtensionFrame)3827 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrame) {
3828 // The unrecognized frame type should still have a valid length.
3829 const unsigned char unknown_frame[] = {
3830 0x00, 0x00, 0x08, // Length: 8
3831 0xff, // Type: UnknownFrameType(255)
3832 0xff, // Flags: 0xff
3833 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3834 0xff, 0xff, 0xff, 0xff, // Payload
3835 0xff, 0xff, 0xff, 0xff, //
3836 };
3837 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3838
3839 // Simulate the case where the stream id validation checks out.
3840 visitor.on_unknown_frame_result_ = true;
3841 visitor.SimulateInFramer(unknown_frame, ABSL_ARRAYSIZE(unknown_frame));
3842 EXPECT_EQ(0, visitor.error_count_);
3843 EXPECT_EQ(1, visitor.unknown_frame_count_);
3844 EXPECT_EQ(8, visitor.unknown_payload_len_);
3845
3846 // Follow it up with a valid control frame to make sure we handle
3847 // subsequent frames correctly.
3848 SpdySettingsIR settings_ir;
3849 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 10);
3850 SpdySerializedFrame control_frame(framer_.SerializeSettings(settings_ir));
3851 if (use_output_) {
3852 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
3853 control_frame = MakeSerializedFrame(output_.Begin(), output_.Size());
3854 }
3855 visitor.SimulateInFramer(
3856 reinterpret_cast<unsigned char*>(control_frame.data()),
3857 control_frame.size());
3858 EXPECT_EQ(0, visitor.error_count_);
3859 EXPECT_EQ(1, visitor.setting_count_);
3860 EXPECT_EQ(1, visitor.settings_ack_sent_);
3861 }
3862
TEST_P(SpdyFramerTest,ReadUnknownExtensionFrameWithExtension)3863 TEST_P(SpdyFramerTest, ReadUnknownExtensionFrameWithExtension) {
3864 // The unrecognized frame type should still have a valid length.
3865 const unsigned char unknown_frame[] = {
3866 0x00, 0x00, 0x14, // Length: 20
3867 0xff, // Type: UnknownFrameType(255)
3868 0xff, // Flags: 0xff
3869 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3870 0xff, 0xff, 0xff, 0xff, // Payload
3871 0xff, 0xff, 0xff, 0xff, //
3872 0xff, 0xff, 0xff, 0xff, //
3873 0xff, 0xff, 0xff, 0xff, //
3874 0xff, 0xff, 0xff, 0xff, //
3875 };
3876 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3877 TestExtension extension;
3878 visitor.set_extension_visitor(&extension);
3879 visitor.SimulateInFramer(unknown_frame, ABSL_ARRAYSIZE(unknown_frame));
3880 EXPECT_EQ(0, visitor.error_count_);
3881 EXPECT_EQ(0x7fffffffu, extension.stream_id_);
3882 EXPECT_EQ(20u, extension.length_);
3883 EXPECT_EQ(255, extension.type_);
3884 EXPECT_EQ(0xff, extension.flags_);
3885 EXPECT_EQ(std::string(20, '\xff'), extension.payload_);
3886
3887 // Follow it up with a valid control frame to make sure we handle
3888 // subsequent frames correctly.
3889 SpdySettingsIR settings_ir;
3890 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 10);
3891 SpdySerializedFrame control_frame(framer_.SerializeSettings(settings_ir));
3892 visitor.SimulateInFramer(
3893 reinterpret_cast<unsigned char*>(control_frame.data()),
3894 control_frame.size());
3895 EXPECT_EQ(0, visitor.error_count_);
3896 EXPECT_EQ(1, visitor.setting_count_);
3897 EXPECT_EQ(1, visitor.settings_ack_sent_);
3898 }
3899
TEST_P(SpdyFramerTest,ReadGarbageWithValidLength)3900 TEST_P(SpdyFramerTest, ReadGarbageWithValidLength) {
3901 const unsigned char kFrameData[] = {
3902 0x00, 0x00, 0x08, // Length: 8
3903 0xff, // Type: UnknownFrameType(255)
3904 0xff, // Flags: 0xff
3905 0xff, 0xff, 0xff, 0xff, // Stream: 0x7fffffff (R-bit set)
3906 0xff, 0xff, 0xff, 0xff, // Payload
3907 0xff, 0xff, 0xff, 0xff, //
3908 };
3909 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3910 visitor.SimulateInFramer(kFrameData, ABSL_ARRAYSIZE(kFrameData));
3911 EXPECT_EQ(1, visitor.error_count_);
3912 }
3913
TEST_P(SpdyFramerTest,ReadGarbageHPACKEncoding)3914 TEST_P(SpdyFramerTest, ReadGarbageHPACKEncoding) {
3915 const unsigned char kInput[] = {
3916 0x00, 0x12, 0x01, // Length: 4609
3917 0x04, // Type: SETTINGS
3918 0x00, // Flags: none
3919 0x00, 0x00, 0x01, 0xef, // Stream: 495
3920 0xef, 0xff, // Param: 61439
3921 0xff, 0xff, 0xff, 0xff, // Value: 4294967295
3922 0xff, 0xff, // Param: 0xffff
3923 0xff, 0xff, 0xff, 0xff, // Value: 4294967295
3924 0xff, 0xff, 0xff, 0xff, // Settings (Truncated)
3925 0xff, //
3926 };
3927
3928 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
3929 visitor.SimulateInFramer(kInput, ABSL_ARRAYSIZE(kInput));
3930 EXPECT_EQ(1, visitor.error_count_);
3931 }
3932
TEST_P(SpdyFramerTest,SizesTest)3933 TEST_P(SpdyFramerTest, SizesTest) {
3934 EXPECT_EQ(9u, kFrameHeaderSize);
3935 EXPECT_EQ(9u, kDataFrameMinimumSize);
3936 EXPECT_EQ(9u, kHeadersFrameMinimumSize);
3937 EXPECT_EQ(14u, kPriorityFrameSize);
3938 EXPECT_EQ(13u, kRstStreamFrameSize);
3939 EXPECT_EQ(9u, kSettingsFrameMinimumSize);
3940 EXPECT_EQ(13u, kPushPromiseFrameMinimumSize);
3941 EXPECT_EQ(17u, kPingFrameSize);
3942 EXPECT_EQ(17u, kGoawayFrameMinimumSize);
3943 EXPECT_EQ(13u, kWindowUpdateFrameSize);
3944 EXPECT_EQ(9u, kContinuationFrameMinimumSize);
3945 EXPECT_EQ(11u, kGetAltSvcFrameMinimumSize);
3946 EXPECT_EQ(9u, kFrameMinimumSize);
3947
3948 EXPECT_EQ(16384u, kHttp2DefaultFramePayloadLimit);
3949 EXPECT_EQ(16393u, kHttp2DefaultFrameSizeLimit);
3950 }
3951
TEST_P(SpdyFramerTest,StateToStringTest)3952 TEST_P(SpdyFramerTest, StateToStringTest) {
3953 EXPECT_STREQ("ERROR", Http2DecoderAdapter::StateToString(
3954 Http2DecoderAdapter::SPDY_ERROR));
3955 EXPECT_STREQ("FRAME_COMPLETE", Http2DecoderAdapter::StateToString(
3956 Http2DecoderAdapter::SPDY_FRAME_COMPLETE));
3957 EXPECT_STREQ("READY_FOR_FRAME",
3958 Http2DecoderAdapter::StateToString(
3959 Http2DecoderAdapter::SPDY_READY_FOR_FRAME));
3960 EXPECT_STREQ("READING_COMMON_HEADER",
3961 Http2DecoderAdapter::StateToString(
3962 Http2DecoderAdapter::SPDY_READING_COMMON_HEADER));
3963 EXPECT_STREQ("CONTROL_FRAME_PAYLOAD",
3964 Http2DecoderAdapter::StateToString(
3965 Http2DecoderAdapter::SPDY_CONTROL_FRAME_PAYLOAD));
3966 EXPECT_STREQ("IGNORE_REMAINING_PAYLOAD",
3967 Http2DecoderAdapter::StateToString(
3968 Http2DecoderAdapter::SPDY_IGNORE_REMAINING_PAYLOAD));
3969 EXPECT_STREQ("FORWARD_STREAM_FRAME",
3970 Http2DecoderAdapter::StateToString(
3971 Http2DecoderAdapter::SPDY_FORWARD_STREAM_FRAME));
3972 EXPECT_STREQ(
3973 "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK",
3974 Http2DecoderAdapter::StateToString(
3975 Http2DecoderAdapter::SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK));
3976 EXPECT_STREQ("SPDY_CONTROL_FRAME_HEADER_BLOCK",
3977 Http2DecoderAdapter::StateToString(
3978 Http2DecoderAdapter::SPDY_CONTROL_FRAME_HEADER_BLOCK));
3979 EXPECT_STREQ("SPDY_SETTINGS_FRAME_PAYLOAD",
3980 Http2DecoderAdapter::StateToString(
3981 Http2DecoderAdapter::SPDY_SETTINGS_FRAME_PAYLOAD));
3982 EXPECT_STREQ("SPDY_ALTSVC_FRAME_PAYLOAD",
3983 Http2DecoderAdapter::StateToString(
3984 Http2DecoderAdapter::SPDY_ALTSVC_FRAME_PAYLOAD));
3985 EXPECT_STREQ("UNKNOWN_STATE",
3986 Http2DecoderAdapter::StateToString(
3987 Http2DecoderAdapter::SPDY_ALTSVC_FRAME_PAYLOAD + 1));
3988 }
3989
TEST_P(SpdyFramerTest,SpdyFramerErrorToStringTest)3990 TEST_P(SpdyFramerTest, SpdyFramerErrorToStringTest) {
3991 EXPECT_STREQ("NO_ERROR", Http2DecoderAdapter::SpdyFramerErrorToString(
3992 Http2DecoderAdapter::SPDY_NO_ERROR));
3993 EXPECT_STREQ("INVALID_STREAM_ID",
3994 Http2DecoderAdapter::SpdyFramerErrorToString(
3995 Http2DecoderAdapter::SPDY_INVALID_STREAM_ID));
3996 EXPECT_STREQ("INVALID_CONTROL_FRAME",
3997 Http2DecoderAdapter::SpdyFramerErrorToString(
3998 Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME));
3999 EXPECT_STREQ("CONTROL_PAYLOAD_TOO_LARGE",
4000 Http2DecoderAdapter::SpdyFramerErrorToString(
4001 Http2DecoderAdapter::SPDY_CONTROL_PAYLOAD_TOO_LARGE));
4002 EXPECT_STREQ("DECOMPRESS_FAILURE",
4003 Http2DecoderAdapter::SpdyFramerErrorToString(
4004 Http2DecoderAdapter::SPDY_DECOMPRESS_FAILURE));
4005 EXPECT_STREQ("INVALID_PADDING",
4006 Http2DecoderAdapter::SpdyFramerErrorToString(
4007 Http2DecoderAdapter::SPDY_INVALID_PADDING));
4008 EXPECT_STREQ("INVALID_DATA_FRAME_FLAGS",
4009 Http2DecoderAdapter::SpdyFramerErrorToString(
4010 Http2DecoderAdapter::SPDY_INVALID_DATA_FRAME_FLAGS));
4011 EXPECT_STREQ("UNEXPECTED_FRAME",
4012 Http2DecoderAdapter::SpdyFramerErrorToString(
4013 Http2DecoderAdapter::SPDY_UNEXPECTED_FRAME));
4014 EXPECT_STREQ("INTERNAL_FRAMER_ERROR",
4015 Http2DecoderAdapter::SpdyFramerErrorToString(
4016 Http2DecoderAdapter::SPDY_INTERNAL_FRAMER_ERROR));
4017 EXPECT_STREQ("INVALID_CONTROL_FRAME_SIZE",
4018 Http2DecoderAdapter::SpdyFramerErrorToString(
4019 Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE));
4020 EXPECT_STREQ("OVERSIZED_PAYLOAD",
4021 Http2DecoderAdapter::SpdyFramerErrorToString(
4022 Http2DecoderAdapter::SPDY_OVERSIZED_PAYLOAD));
4023 EXPECT_STREQ("UNKNOWN_ERROR", Http2DecoderAdapter::SpdyFramerErrorToString(
4024 Http2DecoderAdapter::LAST_ERROR));
4025 EXPECT_STREQ("UNKNOWN_ERROR",
4026 Http2DecoderAdapter::SpdyFramerErrorToString(
4027 static_cast<Http2DecoderAdapter::SpdyFramerError>(
4028 Http2DecoderAdapter::LAST_ERROR + 1)));
4029 }
4030
TEST_P(SpdyFramerTest,DataFrameFlagsV4)4031 TEST_P(SpdyFramerTest, DataFrameFlagsV4) {
4032 uint8_t valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
4033
4034 uint8_t flags = 0;
4035 do {
4036 SCOPED_TRACE(testing::Message()
4037 << "Flags " << std::hex << static_cast<int>(flags));
4038
4039 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4040
4041 deframer_->set_visitor(&visitor);
4042
4043 SpdyDataIR data_ir(/* stream_id = */ 1, "hello");
4044 SpdySerializedFrame frame(framer_.SerializeData(data_ir));
4045 SetFrameFlags(&frame, flags);
4046
4047 EXPECT_CALL(visitor, OnCommonHeader(1, 5, 0x0, flags));
4048 if (flags & ~valid_data_flags) {
4049 EXPECT_CALL(visitor, OnError(_, _));
4050 } else {
4051 EXPECT_CALL(visitor, OnDataFrameHeader(1, 5, flags & DATA_FLAG_FIN));
4052 if (flags & DATA_FLAG_PADDED) {
4053 // The first byte of payload is parsed as padding length, but 'h'
4054 // (0x68) is too large a padding length for a 5 byte payload.
4055 EXPECT_CALL(visitor, OnStreamPadding(_, 1));
4056 // Expect Error since the frame ends prematurely.
4057 EXPECT_CALL(visitor, OnError(_, _));
4058 } else {
4059 EXPECT_CALL(visitor, OnStreamFrameData(_, _, 5));
4060 if (flags & DATA_FLAG_FIN) {
4061 EXPECT_CALL(visitor, OnStreamEnd(_));
4062 }
4063 }
4064 }
4065
4066 deframer_->ProcessInput(frame.data(), frame.size());
4067 if (flags & ~valid_data_flags) {
4068 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, deframer_->state());
4069 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_DATA_FRAME_FLAGS,
4070 deframer_->spdy_framer_error())
4071 << Http2DecoderAdapter::SpdyFramerErrorToString(
4072 deframer_->spdy_framer_error());
4073 } else if (flags & DATA_FLAG_PADDED) {
4074 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, deframer_->state());
4075 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_PADDING,
4076 deframer_->spdy_framer_error())
4077 << Http2DecoderAdapter::SpdyFramerErrorToString(
4078 deframer_->spdy_framer_error());
4079 } else {
4080 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4081 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4082 deframer_->spdy_framer_error())
4083 << Http2DecoderAdapter::SpdyFramerErrorToString(
4084 deframer_->spdy_framer_error());
4085 }
4086 deframer_ = std::make_unique<Http2DecoderAdapter>();
4087 } while (++flags != 0);
4088 }
4089
TEST_P(SpdyFramerTest,RstStreamFrameFlags)4090 TEST_P(SpdyFramerTest, RstStreamFrameFlags) {
4091 uint8_t flags = 0;
4092 do {
4093 SCOPED_TRACE(testing::Message()
4094 << "Flags " << std::hex << static_cast<int>(flags));
4095
4096 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4097 deframer_->set_visitor(&visitor);
4098
4099 SpdyRstStreamIR rst_stream(/* stream_id = */ 13, ERROR_CODE_CANCEL);
4100 SpdySerializedFrame frame(framer_.SerializeRstStream(rst_stream));
4101 if (use_output_) {
4102 output_.Reset();
4103 ASSERT_TRUE(framer_.SerializeRstStream(rst_stream, &output_));
4104 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4105 }
4106 SetFrameFlags(&frame, flags);
4107
4108 EXPECT_CALL(visitor, OnCommonHeader(13, 4, 0x3, flags));
4109 EXPECT_CALL(visitor, OnRstStream(13, ERROR_CODE_CANCEL));
4110
4111 deframer_->ProcessInput(frame.data(), frame.size());
4112 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4113 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4114 deframer_->spdy_framer_error())
4115 << Http2DecoderAdapter::SpdyFramerErrorToString(
4116 deframer_->spdy_framer_error());
4117 deframer_ = std::make_unique<Http2DecoderAdapter>();
4118 } while (++flags != 0);
4119 }
4120
TEST_P(SpdyFramerTest,SettingsFrameFlags)4121 TEST_P(SpdyFramerTest, SettingsFrameFlags) {
4122 uint8_t flags = 0;
4123 do {
4124 SCOPED_TRACE(testing::Message()
4125 << "Flags " << std::hex << static_cast<int>(flags));
4126
4127 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4128 deframer_->set_visitor(&visitor);
4129
4130 SpdySettingsIR settings_ir;
4131 settings_ir.AddSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16);
4132 SpdySerializedFrame frame(framer_.SerializeSettings(settings_ir));
4133 if (use_output_) {
4134 output_.Reset();
4135 ASSERT_TRUE(framer_.SerializeSettings(settings_ir, &output_));
4136 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4137 }
4138 SetFrameFlags(&frame, flags);
4139
4140 EXPECT_CALL(visitor, OnCommonHeader(0, 6, 0x4, flags));
4141 if (flags & SETTINGS_FLAG_ACK) {
4142 EXPECT_CALL(visitor, OnError(_, _));
4143 } else {
4144 EXPECT_CALL(visitor, OnSettings());
4145 EXPECT_CALL(visitor, OnSetting(SETTINGS_INITIAL_WINDOW_SIZE, 16));
4146 EXPECT_CALL(visitor, OnSettingsEnd());
4147 }
4148
4149 deframer_->ProcessInput(frame.data(), frame.size());
4150 if (flags & SETTINGS_FLAG_ACK) {
4151 // The frame is invalid because ACK frames should have no payload.
4152 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, deframer_->state());
4153 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4154 deframer_->spdy_framer_error())
4155 << Http2DecoderAdapter::SpdyFramerErrorToString(
4156 deframer_->spdy_framer_error());
4157 } else {
4158 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4159 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4160 deframer_->spdy_framer_error())
4161 << Http2DecoderAdapter::SpdyFramerErrorToString(
4162 deframer_->spdy_framer_error());
4163 }
4164 deframer_ = std::make_unique<Http2DecoderAdapter>();
4165 } while (++flags != 0);
4166 }
4167
TEST_P(SpdyFramerTest,GoawayFrameFlags)4168 TEST_P(SpdyFramerTest, GoawayFrameFlags) {
4169 uint8_t flags = 0;
4170 do {
4171 SCOPED_TRACE(testing::Message()
4172 << "Flags " << std::hex << static_cast<int>(flags));
4173
4174 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4175
4176 deframer_->set_visitor(&visitor);
4177
4178 SpdyGoAwayIR goaway_ir(/* last_good_stream_id = */ 97, ERROR_CODE_NO_ERROR,
4179 "test");
4180 SpdySerializedFrame frame(framer_.SerializeGoAway(goaway_ir));
4181 if (use_output_) {
4182 output_.Reset();
4183 ASSERT_TRUE(framer_.SerializeGoAway(goaway_ir, &output_));
4184 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4185 }
4186 SetFrameFlags(&frame, flags);
4187
4188 EXPECT_CALL(visitor, OnCommonHeader(0, _, 0x7, flags));
4189 EXPECT_CALL(visitor, OnGoAway(97, ERROR_CODE_NO_ERROR));
4190 EXPECT_CALL(visitor, OnGoAwayFrameData)
4191 .WillRepeatedly(testing::Return(true));
4192
4193 deframer_->ProcessInput(frame.data(), frame.size());
4194 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4195 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4196 deframer_->spdy_framer_error())
4197 << Http2DecoderAdapter::SpdyFramerErrorToString(
4198 deframer_->spdy_framer_error());
4199 deframer_ = std::make_unique<Http2DecoderAdapter>();
4200 } while (++flags != 0);
4201 }
4202
TEST_P(SpdyFramerTest,HeadersFrameFlags)4203 TEST_P(SpdyFramerTest, HeadersFrameFlags) {
4204 uint8_t flags = 0;
4205 do {
4206 SCOPED_TRACE(testing::Message()
4207 << "Flags " << std::hex << static_cast<int>(flags));
4208
4209 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4210 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4211 Http2DecoderAdapter deframer;
4212 deframer.set_visitor(&visitor);
4213
4214 SpdyHeadersIR headers_ir(/* stream_id = */ 57);
4215 if (flags & HEADERS_FLAG_PRIORITY) {
4216 headers_ir.set_weight(3);
4217 headers_ir.set_has_priority(true);
4218 headers_ir.set_parent_stream_id(5);
4219 headers_ir.set_exclusive(true);
4220 }
4221 headers_ir.SetHeader("foo", "bar");
4222 SpdySerializedFrame frame(SpdyFramerPeer::SerializeHeaders(
4223 &framer, headers_ir, use_output_ ? &output_ : nullptr));
4224 uint8_t set_flags = flags & ~HEADERS_FLAG_PADDED;
4225 SetFrameFlags(&frame, set_flags);
4226
4227 // Expected callback values
4228 SpdyStreamId stream_id = 57;
4229 bool has_priority = false;
4230 int weight = 0;
4231 SpdyStreamId parent_stream_id = 0;
4232 bool exclusive = false;
4233 bool fin = flags & CONTROL_FLAG_FIN;
4234 bool end = flags & HEADERS_FLAG_END_HEADERS;
4235 if (flags & HEADERS_FLAG_PRIORITY) {
4236 has_priority = true;
4237 weight = 3;
4238 parent_stream_id = 5;
4239 exclusive = true;
4240 }
4241 EXPECT_CALL(visitor, OnCommonHeader(stream_id, _, 0x1, set_flags));
4242 EXPECT_CALL(visitor, OnHeaders(stream_id, _, has_priority, weight,
4243 parent_stream_id, exclusive, fin, end));
4244 EXPECT_CALL(visitor, OnHeaderFrameStart(57)).Times(1);
4245 if (end) {
4246 EXPECT_CALL(visitor, OnHeaderFrameEnd(57)).Times(1);
4247 }
4248 if (flags & DATA_FLAG_FIN && end) {
4249 EXPECT_CALL(visitor, OnStreamEnd(_));
4250 } else {
4251 // Do not close the stream if we are expecting a CONTINUATION frame.
4252 EXPECT_CALL(visitor, OnStreamEnd(_)).Times(0);
4253 }
4254
4255 deframer.ProcessInput(frame.data(), frame.size());
4256 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer.state());
4257 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer.spdy_framer_error())
4258 << Http2DecoderAdapter::SpdyFramerErrorToString(
4259 deframer.spdy_framer_error());
4260 } while (++flags != 0);
4261 }
4262
TEST_P(SpdyFramerTest,PingFrameFlags)4263 TEST_P(SpdyFramerTest, PingFrameFlags) {
4264 uint8_t flags = 0;
4265 do {
4266 SCOPED_TRACE(testing::Message()
4267 << "Flags " << std::hex << static_cast<int>(flags));
4268
4269 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4270 deframer_->set_visitor(&visitor);
4271
4272 SpdySerializedFrame frame(framer_.SerializePing(SpdyPingIR(42)));
4273 SetFrameFlags(&frame, flags);
4274
4275 EXPECT_CALL(visitor, OnCommonHeader(0, 8, 0x6, flags));
4276 EXPECT_CALL(visitor, OnPing(42, flags & PING_FLAG_ACK));
4277
4278 deframer_->ProcessInput(frame.data(), frame.size());
4279 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4280 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4281 deframer_->spdy_framer_error())
4282 << Http2DecoderAdapter::SpdyFramerErrorToString(
4283 deframer_->spdy_framer_error());
4284 deframer_ = std::make_unique<Http2DecoderAdapter>();
4285 } while (++flags != 0);
4286 }
4287
TEST_P(SpdyFramerTest,WindowUpdateFrameFlags)4288 TEST_P(SpdyFramerTest, WindowUpdateFrameFlags) {
4289 uint8_t flags = 0;
4290 do {
4291 SCOPED_TRACE(testing::Message()
4292 << "Flags " << std::hex << static_cast<int>(flags));
4293
4294 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4295
4296 deframer_->set_visitor(&visitor);
4297
4298 SpdySerializedFrame frame(framer_.SerializeWindowUpdate(
4299 SpdyWindowUpdateIR(/* stream_id = */ 4, /* delta = */ 1024)));
4300 SetFrameFlags(&frame, flags);
4301
4302 EXPECT_CALL(visitor, OnCommonHeader(4, 4, 0x8, flags));
4303 EXPECT_CALL(visitor, OnWindowUpdate(4, 1024));
4304
4305 deframer_->ProcessInput(frame.data(), frame.size());
4306 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4307 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4308 deframer_->spdy_framer_error())
4309 << Http2DecoderAdapter::SpdyFramerErrorToString(
4310 deframer_->spdy_framer_error());
4311 deframer_ = std::make_unique<Http2DecoderAdapter>();
4312 } while (++flags != 0);
4313 }
4314
TEST_P(SpdyFramerTest,PushPromiseFrameFlags)4315 TEST_P(SpdyFramerTest, PushPromiseFrameFlags) {
4316 const SpdyStreamId client_id = 123; // Must be odd.
4317 const SpdyStreamId promised_id = 22; // Must be even.
4318 uint8_t flags = 0;
4319 do {
4320 SCOPED_TRACE(testing::Message()
4321 << "Flags " << std::hex << static_cast<int>(flags));
4322
4323 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4324 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4325 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4326 Http2DecoderAdapter deframer;
4327 deframer.set_visitor(&visitor);
4328 deframer.set_debug_visitor(&debug_visitor);
4329 framer.set_debug_visitor(&debug_visitor);
4330
4331 EXPECT_CALL(
4332 debug_visitor,
4333 OnSendCompressedFrame(client_id, SpdyFrameType::PUSH_PROMISE, _, _));
4334
4335 SpdyPushPromiseIR push_promise(client_id, promised_id);
4336 push_promise.SetHeader("foo", "bar");
4337 SpdySerializedFrame frame(SpdyFramerPeer::SerializePushPromise(
4338 &framer, push_promise, use_output_ ? &output_ : nullptr));
4339 // TODO(jgraettinger): Add padding to SpdyPushPromiseIR,
4340 // and implement framing.
4341 SetFrameFlags(&frame, flags & ~HEADERS_FLAG_PADDED);
4342
4343 bool end = flags & PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
4344 EXPECT_CALL(debug_visitor, OnReceiveCompressedFrame(
4345 client_id, SpdyFrameType::PUSH_PROMISE, _));
4346 EXPECT_CALL(visitor, OnCommonHeader(client_id, _, 0x5,
4347 flags & ~HEADERS_FLAG_PADDED));
4348 EXPECT_CALL(visitor, OnPushPromise(client_id, promised_id, end));
4349 EXPECT_CALL(visitor, OnHeaderFrameStart(client_id)).Times(1);
4350 if (end) {
4351 EXPECT_CALL(visitor, OnHeaderFrameEnd(client_id)).Times(1);
4352 }
4353
4354 deframer.ProcessInput(frame.data(), frame.size());
4355 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer.state());
4356 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer.spdy_framer_error())
4357 << Http2DecoderAdapter::SpdyFramerErrorToString(
4358 deframer.spdy_framer_error());
4359 } while (++flags != 0);
4360 }
4361
TEST_P(SpdyFramerTest,ContinuationFrameFlags)4362 TEST_P(SpdyFramerTest, ContinuationFrameFlags) {
4363 uint8_t flags = 0;
4364 do {
4365 if (use_output_) {
4366 output_.Reset();
4367 }
4368 SCOPED_TRACE(testing::Message()
4369 << "Flags " << std::hex << static_cast<int>(flags));
4370
4371 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4372 testing::StrictMock<test::MockDebugVisitor> debug_visitor;
4373 SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
4374 Http2DecoderAdapter deframer;
4375 deframer.set_visitor(&visitor);
4376 deframer.set_debug_visitor(&debug_visitor);
4377 framer.set_debug_visitor(&debug_visitor);
4378
4379 EXPECT_CALL(debug_visitor,
4380 OnSendCompressedFrame(42, SpdyFrameType::HEADERS, _, _));
4381 EXPECT_CALL(debug_visitor,
4382 OnReceiveCompressedFrame(42, SpdyFrameType::HEADERS, _));
4383 EXPECT_CALL(visitor, OnCommonHeader(42, _, 0x1, 0));
4384 EXPECT_CALL(visitor, OnHeaders(42, _, false, 0, 0, false, false, false));
4385 EXPECT_CALL(visitor, OnHeaderFrameStart(42)).Times(1);
4386
4387 SpdyHeadersIR headers_ir(/* stream_id = */ 42);
4388 headers_ir.SetHeader("foo", "bar");
4389 SpdySerializedFrame frame0;
4390 if (use_output_) {
4391 EXPECT_TRUE(framer.SerializeHeaders(headers_ir, &output_));
4392 frame0 = MakeSerializedFrame(output_.Begin(), output_.Size());
4393 } else {
4394 frame0 = framer.SerializeHeaders(headers_ir);
4395 }
4396 SetFrameFlags(&frame0, 0);
4397
4398 SpdyContinuationIR continuation(/* stream_id = */ 42);
4399 SpdySerializedFrame frame1;
4400 if (use_output_) {
4401 char* begin = output_.Begin() + output_.Size();
4402 ASSERT_TRUE(framer.SerializeContinuation(continuation, &output_));
4403 frame1 = MakeSerializedFrame(begin, output_.Size() - frame0.size());
4404 } else {
4405 frame1 = framer.SerializeContinuation(continuation);
4406 }
4407 SetFrameFlags(&frame1, flags);
4408
4409 EXPECT_CALL(debug_visitor,
4410 OnReceiveCompressedFrame(42, SpdyFrameType::CONTINUATION, _));
4411 EXPECT_CALL(visitor, OnCommonHeader(42, _, 0x9, flags));
4412 EXPECT_CALL(visitor,
4413 OnContinuation(42, _, flags & HEADERS_FLAG_END_HEADERS));
4414 bool end = flags & HEADERS_FLAG_END_HEADERS;
4415 if (end) {
4416 EXPECT_CALL(visitor, OnHeaderFrameEnd(42)).Times(1);
4417 }
4418
4419 deframer.ProcessInput(frame0.data(), frame0.size());
4420 deframer.ProcessInput(frame1.data(), frame1.size());
4421 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer.state());
4422 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer.spdy_framer_error())
4423 << Http2DecoderAdapter::SpdyFramerErrorToString(
4424 deframer.spdy_framer_error());
4425 } while (++flags != 0);
4426 }
4427
4428 // TODO(mlavan): Add TEST_P(SpdyFramerTest, AltSvcFrameFlags)
4429
4430 // Test handling of a RST_STREAM with out-of-bounds status codes.
TEST_P(SpdyFramerTest,RstStreamStatusBounds)4431 TEST_P(SpdyFramerTest, RstStreamStatusBounds) {
4432 const unsigned char kH2RstStreamInvalid[] = {
4433 0x00, 0x00, 0x04, // Length: 4
4434 0x03, // Type: RST_STREAM
4435 0x00, // Flags: none
4436 0x00, 0x00, 0x00, 0x01, // Stream: 1
4437 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4438 };
4439 const unsigned char kH2RstStreamNumStatusCodes[] = {
4440 0x00, 0x00, 0x04, // Length: 4
4441 0x03, // Type: RST_STREAM
4442 0x00, // Flags: none
4443 0x00, 0x00, 0x00, 0x01, // Stream: 1
4444 0x00, 0x00, 0x00, 0xff, // Error: 255
4445 };
4446
4447 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4448 deframer_->set_visitor(&visitor);
4449
4450 EXPECT_CALL(visitor, OnCommonHeader(1, 4, 0x3, 0x0));
4451 EXPECT_CALL(visitor, OnRstStream(1, ERROR_CODE_NO_ERROR));
4452 deframer_->ProcessInput(reinterpret_cast<const char*>(kH2RstStreamInvalid),
4453 ABSL_ARRAYSIZE(kH2RstStreamInvalid));
4454 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4455 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4456 << Http2DecoderAdapter::SpdyFramerErrorToString(
4457 deframer_->spdy_framer_error());
4458 deframer_ = std::make_unique<Http2DecoderAdapter>();
4459 deframer_->set_visitor(&visitor);
4460
4461 EXPECT_CALL(visitor, OnCommonHeader(1, 4, 0x3, 0x0));
4462 EXPECT_CALL(visitor, OnRstStream(1, ERROR_CODE_INTERNAL_ERROR));
4463 deframer_->ProcessInput(
4464 reinterpret_cast<const char*>(kH2RstStreamNumStatusCodes),
4465 ABSL_ARRAYSIZE(kH2RstStreamNumStatusCodes));
4466 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4467 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4468 << Http2DecoderAdapter::SpdyFramerErrorToString(
4469 deframer_->spdy_framer_error());
4470 }
4471
4472 // Test handling of GOAWAY frames with out-of-bounds status code.
TEST_P(SpdyFramerTest,GoAwayStatusBounds)4473 TEST_P(SpdyFramerTest, GoAwayStatusBounds) {
4474 const unsigned char kH2FrameData[] = {
4475 0x00, 0x00, 0x0a, // Length: 10
4476 0x07, // Type: GOAWAY
4477 0x00, // Flags: none
4478 0x00, 0x00, 0x00, 0x00, // Stream: 0
4479 0x00, 0x00, 0x00, 0x01, // Last: 1
4480 0xff, 0xff, 0xff, 0xff, // Error: 0xffffffff
4481 0x47, 0x41, // Description
4482 };
4483 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4484 deframer_->set_visitor(&visitor);
4485
4486 EXPECT_CALL(visitor, OnCommonHeader(0, 10, 0x7, 0x0));
4487 EXPECT_CALL(visitor, OnGoAway(1, ERROR_CODE_INTERNAL_ERROR));
4488 EXPECT_CALL(visitor, OnGoAwayFrameData).WillRepeatedly(testing::Return(true));
4489 deframer_->ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
4490 ABSL_ARRAYSIZE(kH2FrameData));
4491 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4492 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4493 << Http2DecoderAdapter::SpdyFramerErrorToString(
4494 deframer_->spdy_framer_error());
4495 }
4496
4497 // Tests handling of a GOAWAY frame with out-of-bounds stream ID.
TEST_P(SpdyFramerTest,GoAwayStreamIdBounds)4498 TEST_P(SpdyFramerTest, GoAwayStreamIdBounds) {
4499 const unsigned char kH2FrameData[] = {
4500 0x00, 0x00, 0x08, // Length: 8
4501 0x07, // Type: GOAWAY
4502 0x00, // Flags: none
4503 0x00, 0x00, 0x00, 0x00, // Stream: 0
4504 0xff, 0xff, 0xff, 0xff, // Last: 0x7fffffff (R-bit set)
4505 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4506 };
4507
4508 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4509
4510 deframer_->set_visitor(&visitor);
4511
4512 EXPECT_CALL(visitor, OnCommonHeader(0, 8, 0x7, 0x0));
4513 EXPECT_CALL(visitor, OnGoAway(0x7fffffff, ERROR_CODE_NO_ERROR));
4514 EXPECT_CALL(visitor, OnGoAwayFrameData).WillRepeatedly(testing::Return(true));
4515 deframer_->ProcessInput(reinterpret_cast<const char*>(kH2FrameData),
4516 ABSL_ARRAYSIZE(kH2FrameData));
4517 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4518 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4519 << Http2DecoderAdapter::SpdyFramerErrorToString(
4520 deframer_->spdy_framer_error());
4521 }
4522
TEST_P(SpdyFramerTest,OnAltSvcWithOrigin)4523 TEST_P(SpdyFramerTest, OnAltSvcWithOrigin) {
4524 const SpdyStreamId kStreamId = 0; // Stream id must be zero if origin given.
4525
4526 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4527
4528 deframer_->set_visitor(&visitor);
4529
4530 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4531 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4532 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4533 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4534 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
4535 altsvc_vector.push_back(altsvc1);
4536 altsvc_vector.push_back(altsvc2);
4537 EXPECT_CALL(visitor, OnCommonHeader(kStreamId, _, 0x0A, 0x0));
4538 EXPECT_CALL(visitor,
4539 OnAltSvc(kStreamId, absl::string_view("o_r|g!n"), altsvc_vector));
4540
4541 SpdyAltSvcIR altsvc_ir(kStreamId);
4542 altsvc_ir.set_origin("o_r|g!n");
4543 altsvc_ir.add_altsvc(altsvc1);
4544 altsvc_ir.add_altsvc(altsvc2);
4545 SpdySerializedFrame frame(framer_.SerializeFrame(altsvc_ir));
4546 if (use_output_) {
4547 output_.Reset();
4548 EXPECT_EQ(framer_.SerializeFrame(altsvc_ir, &output_), frame.size());
4549 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4550 }
4551 deframer_->ProcessInput(frame.data(), frame.size());
4552
4553 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4554 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4555 << Http2DecoderAdapter::SpdyFramerErrorToString(
4556 deframer_->spdy_framer_error());
4557 }
4558
TEST_P(SpdyFramerTest,OnAltSvcNoOrigin)4559 TEST_P(SpdyFramerTest, OnAltSvcNoOrigin) {
4560 const SpdyStreamId kStreamId = 1;
4561
4562 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4563
4564 deframer_->set_visitor(&visitor);
4565
4566 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4567 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4568 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4569 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4570 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
4571 altsvc_vector.push_back(altsvc1);
4572 altsvc_vector.push_back(altsvc2);
4573 EXPECT_CALL(visitor, OnCommonHeader(kStreamId, _, 0x0A, 0x0));
4574 EXPECT_CALL(visitor,
4575 OnAltSvc(kStreamId, absl::string_view(""), altsvc_vector));
4576
4577 SpdyAltSvcIR altsvc_ir(kStreamId);
4578 altsvc_ir.add_altsvc(altsvc1);
4579 altsvc_ir.add_altsvc(altsvc2);
4580 SpdySerializedFrame frame(framer_.SerializeFrame(altsvc_ir));
4581 deframer_->ProcessInput(frame.data(), frame.size());
4582
4583 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4584 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4585 << Http2DecoderAdapter::SpdyFramerErrorToString(
4586 deframer_->spdy_framer_error());
4587 }
4588
TEST_P(SpdyFramerTest,OnAltSvcEmptyProtocolId)4589 TEST_P(SpdyFramerTest, OnAltSvcEmptyProtocolId) {
4590 const SpdyStreamId kStreamId = 0; // Stream id must be zero if origin given.
4591
4592 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4593
4594 deframer_->set_visitor(&visitor);
4595
4596 EXPECT_CALL(visitor, OnCommonHeader(kStreamId, _, 0x0A, 0x0));
4597 EXPECT_CALL(visitor,
4598 OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME, _));
4599
4600 SpdyAltSvcIR altsvc_ir(kStreamId);
4601 altsvc_ir.set_origin("o1");
4602 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
4603 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector()));
4604 altsvc_ir.add_altsvc(SpdyAltSvcWireFormat::AlternativeService(
4605 "", "h1", 443, 10, SpdyAltSvcWireFormat::VersionVector()));
4606 SpdySerializedFrame frame(framer_.SerializeFrame(altsvc_ir));
4607 if (use_output_) {
4608 output_.Reset();
4609 EXPECT_EQ(framer_.SerializeFrame(altsvc_ir, &output_), frame.size());
4610 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4611 }
4612 deframer_->ProcessInput(frame.data(), frame.size());
4613
4614 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, deframer_->state());
4615 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
4616 deframer_->spdy_framer_error())
4617 << Http2DecoderAdapter::SpdyFramerErrorToString(
4618 deframer_->spdy_framer_error());
4619 }
4620
TEST_P(SpdyFramerTest,OnAltSvcBadLengths)4621 TEST_P(SpdyFramerTest, OnAltSvcBadLengths) {
4622 const unsigned char kType = SerializeFrameType(SpdyFrameType::ALTSVC);
4623 const unsigned char kFrameDataOriginLenLargerThanFrame[] = {
4624 0x00, 0x00, 0x05, kType, 0x00, 0x00, 0x00,
4625 0x00, 0x03, 0x42, 0x42, 'f', 'o', 'o',
4626 };
4627
4628 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4629
4630 deframer_->set_visitor(&visitor);
4631 visitor.SimulateInFramer(kFrameDataOriginLenLargerThanFrame,
4632 sizeof(kFrameDataOriginLenLargerThanFrame));
4633
4634 EXPECT_EQ(1, visitor.error_count_);
4635 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
4636 visitor.deframer_.spdy_framer_error());
4637 }
4638
4639 // Tests handling of ALTSVC frames delivered in small chunks.
TEST_P(SpdyFramerTest,ReadChunkedAltSvcFrame)4640 TEST_P(SpdyFramerTest, ReadChunkedAltSvcFrame) {
4641 SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
4642 SpdyAltSvcWireFormat::AlternativeService altsvc1(
4643 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4644 SpdyAltSvcWireFormat::AlternativeService altsvc2(
4645 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
4646 altsvc_ir.add_altsvc(altsvc1);
4647 altsvc_ir.add_altsvc(altsvc2);
4648
4649 SpdySerializedFrame control_frame(framer_.SerializeAltSvc(altsvc_ir));
4650 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4651
4652 // Read data in small chunks.
4653 size_t framed_data = 0;
4654 size_t unframed_data = control_frame.size();
4655 size_t kReadChunkSize = 5; // Read five bytes at a time.
4656 while (unframed_data > 0) {
4657 size_t to_read = std::min(kReadChunkSize, unframed_data);
4658 visitor.SimulateInFramer(
4659 reinterpret_cast<unsigned char*>(control_frame.data() + framed_data),
4660 to_read);
4661 unframed_data -= to_read;
4662 framed_data += to_read;
4663 }
4664 EXPECT_EQ(0, visitor.error_count_);
4665 EXPECT_EQ(1, visitor.altsvc_count_);
4666 ASSERT_NE(nullptr, visitor.test_altsvc_ir_);
4667 ASSERT_EQ(2u, visitor.test_altsvc_ir_->altsvc_vector().size());
4668 EXPECT_TRUE(visitor.test_altsvc_ir_->altsvc_vector()[0] == altsvc1);
4669 EXPECT_TRUE(visitor.test_altsvc_ir_->altsvc_vector()[1] == altsvc2);
4670 }
4671
4672 // While RFC7838 Section 4 says that an ALTSVC frame on stream 0 with empty
4673 // origin MUST be ignored, it is not implemented at the framer level: instead,
4674 // such frames are passed on to the consumer.
TEST_P(SpdyFramerTest,ReadAltSvcFrame)4675 TEST_P(SpdyFramerTest, ReadAltSvcFrame) {
4676 constexpr struct {
4677 uint32_t stream_id;
4678 const char* origin;
4679 } test_cases[] = {{0, ""},
4680 {1, ""},
4681 {0, "https://www.example.com"},
4682 {1, "https://www.example.com"}};
4683 for (const auto& test_case : test_cases) {
4684 SpdyAltSvcIR altsvc_ir(test_case.stream_id);
4685 SpdyAltSvcWireFormat::AlternativeService altsvc(
4686 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
4687 altsvc_ir.add_altsvc(altsvc);
4688 altsvc_ir.set_origin(test_case.origin);
4689 SpdySerializedFrame frame(framer_.SerializeAltSvc(altsvc_ir));
4690
4691 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
4692 deframer_->set_visitor(&visitor);
4693 deframer_->ProcessInput(frame.data(), frame.size());
4694
4695 EXPECT_EQ(0, visitor.error_count_);
4696 EXPECT_EQ(1, visitor.altsvc_count_);
4697 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4698 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR,
4699 deframer_->spdy_framer_error())
4700 << Http2DecoderAdapter::SpdyFramerErrorToString(
4701 deframer_->spdy_framer_error());
4702 }
4703 }
4704
4705 // An ALTSVC frame with invalid Alt-Svc-Field-Value results in an error.
TEST_P(SpdyFramerTest,ErrorOnAltSvcFrameWithInvalidValue)4706 TEST_P(SpdyFramerTest, ErrorOnAltSvcFrameWithInvalidValue) {
4707 // Alt-Svc-Field-Value must be "clear" or must contain an "=" character
4708 // per RFC7838 Section 3.
4709 const char kFrameData[] = {
4710 0x00, 0x00, 0x16, // Length: 22
4711 0x0a, // Type: ALTSVC
4712 0x00, // Flags: none
4713 0x00, 0x00, 0x00, 0x01, // Stream: 1
4714 0x00, 0x00, // Origin-Len: 0
4715 0x74, 0x68, 0x69, 0x73, // thisisnotavalidvalue
4716 0x69, 0x73, 0x6e, 0x6f, 0x74, 0x61, 0x76, 0x61,
4717 0x6c, 0x69, 0x64, 0x76, 0x61, 0x6c, 0x75, 0x65,
4718 };
4719
4720 TestSpdyVisitor visitor(SpdyFramer::ENABLE_COMPRESSION);
4721 deframer_->set_visitor(&visitor);
4722 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4723
4724 EXPECT_EQ(1, visitor.error_count_);
4725 EXPECT_EQ(0, visitor.altsvc_count_);
4726 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, deframer_->state());
4727 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME,
4728 deframer_->spdy_framer_error())
4729 << Http2DecoderAdapter::SpdyFramerErrorToString(
4730 deframer_->spdy_framer_error());
4731 }
4732
TEST_P(SpdyFramerTest,ReadPriorityUpdateFrame)4733 TEST_P(SpdyFramerTest, ReadPriorityUpdateFrame) {
4734 const char kFrameData[] = {
4735 0x00, 0x00, 0x07, // payload length
4736 0x10, // frame type PRIORITY_UPDATE
4737 0x00, // flags
4738 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0
4739 0x00, 0x00, 0x00, 0x03, // prioritized stream ID, must not be zero
4740 'f', 'o', 'o' // priority field value
4741 };
4742
4743 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4744 deframer_->set_visitor(&visitor);
4745
4746 EXPECT_CALL(visitor, OnCommonHeader(0, 7, 0x10, 0x0));
4747 EXPECT_CALL(visitor, OnPriorityUpdate(3, "foo"));
4748 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4749 EXPECT_FALSE(deframer_->HasError());
4750 }
4751
TEST_P(SpdyFramerTest,ReadPriorityUpdateFrameWithEmptyPriorityFieldValue)4752 TEST_P(SpdyFramerTest, ReadPriorityUpdateFrameWithEmptyPriorityFieldValue) {
4753 const char kFrameData[] = {
4754 0x00, 0x00, 0x04, // payload length
4755 0x10, // frame type PRIORITY_UPDATE
4756 0x00, // flags
4757 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0
4758 0x00, 0x00, 0x00, 0x03 // prioritized stream ID, must not be zero
4759 };
4760
4761 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4762 deframer_->set_visitor(&visitor);
4763
4764 EXPECT_CALL(visitor, OnCommonHeader(0, 4, 0x10, 0x0));
4765 EXPECT_CALL(visitor, OnPriorityUpdate(3, ""));
4766 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4767 EXPECT_FALSE(deframer_->HasError());
4768 }
4769
TEST_P(SpdyFramerTest,PriorityUpdateFrameWithEmptyPayload)4770 TEST_P(SpdyFramerTest, PriorityUpdateFrameWithEmptyPayload) {
4771 const char kFrameData[] = {
4772 0x00, 0x00, 0x00, // payload length
4773 0x10, // frame type PRIORITY_UPDATE
4774 0x00, // flags
4775 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0
4776 };
4777
4778 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4779 deframer_->set_visitor(&visitor);
4780
4781 EXPECT_CALL(visitor, OnCommonHeader(0, 0, 0x10, 0x0));
4782 EXPECT_CALL(visitor,
4783 OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
4784 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4785 EXPECT_TRUE(deframer_->HasError());
4786 }
4787
TEST_P(SpdyFramerTest,PriorityUpdateFrameWithShortPayload)4788 TEST_P(SpdyFramerTest, PriorityUpdateFrameWithShortPayload) {
4789 const char kFrameData[] = {
4790 0x00, 0x00, 0x02, // payload length
4791 0x10, // frame type PRIORITY_UPDATE
4792 0x00, // flags
4793 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0
4794 0x00, 0x01 // payload not long enough to hold 32 bits of prioritized
4795 // stream ID
4796 };
4797
4798 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4799 deframer_->set_visitor(&visitor);
4800
4801 EXPECT_CALL(visitor, OnCommonHeader(0, 2, 0x10, 0x0));
4802 EXPECT_CALL(visitor,
4803 OnError(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE, _));
4804 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4805 EXPECT_TRUE(deframer_->HasError());
4806 }
4807
TEST_P(SpdyFramerTest,PriorityUpdateFrameOnIncorrectStream)4808 TEST_P(SpdyFramerTest, PriorityUpdateFrameOnIncorrectStream) {
4809 const char kFrameData[] = {
4810 0x00, 0x00, 0x04, // payload length
4811 0x10, // frame type PRIORITY_UPDATE
4812 0x00, // flags
4813 0x00, 0x00, 0x00, 0x01, // invalid stream ID, must be 0
4814 0x00, 0x00, 0x00, 0x01, // prioritized stream ID, must not be zero
4815 };
4816
4817 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4818 deframer_->set_visitor(&visitor);
4819
4820 EXPECT_CALL(visitor, OnCommonHeader(1, 4, 0x10, 0x0));
4821 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
4822 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4823 EXPECT_TRUE(deframer_->HasError());
4824 }
4825
TEST_P(SpdyFramerTest,PriorityUpdateFramePrioritizingIncorrectStream)4826 TEST_P(SpdyFramerTest, PriorityUpdateFramePrioritizingIncorrectStream) {
4827 const char kFrameData[] = {
4828 0x00, 0x00, 0x04, // payload length
4829 0x10, // frame type PRIORITY_UPDATE
4830 0x00, // flags
4831 0x00, 0x00, 0x00, 0x00, // stream ID, must be 0
4832 0x00, 0x00, 0x00, 0x00, // prioritized stream ID, must not be zero
4833 };
4834
4835 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4836 deframer_->set_visitor(&visitor);
4837
4838 EXPECT_CALL(visitor, OnCommonHeader(0, 4, 0x10, 0x0));
4839 EXPECT_CALL(visitor, OnError(Http2DecoderAdapter::SPDY_INVALID_STREAM_ID, _));
4840 deframer_->ProcessInput(kFrameData, sizeof(kFrameData));
4841 EXPECT_TRUE(deframer_->HasError());
4842 }
4843
4844 // Tests handling of PRIORITY frames.
TEST_P(SpdyFramerTest,ReadPriority)4845 TEST_P(SpdyFramerTest, ReadPriority) {
4846 SpdyPriorityIR priority(/* stream_id = */ 3,
4847 /* parent_stream_id = */ 1,
4848 /* weight = */ 256,
4849 /* exclusive = */ false);
4850 SpdySerializedFrame frame(framer_.SerializePriority(priority));
4851 if (use_output_) {
4852 output_.Reset();
4853 ASSERT_TRUE(framer_.SerializePriority(priority, &output_));
4854 frame = MakeSerializedFrame(output_.Begin(), output_.Size());
4855 }
4856 testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
4857 deframer_->set_visitor(&visitor);
4858 EXPECT_CALL(visitor, OnCommonHeader(3, 5, 0x2, 0x0));
4859 EXPECT_CALL(visitor, OnPriority(3, 1, 256, false));
4860 deframer_->ProcessInput(frame.data(), frame.size());
4861
4862 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
4863 EXPECT_EQ(Http2DecoderAdapter::SPDY_NO_ERROR, deframer_->spdy_framer_error())
4864 << Http2DecoderAdapter::SpdyFramerErrorToString(
4865 deframer_->spdy_framer_error());
4866 }
4867
4868 // Tests handling of PRIORITY frame with incorrect size.
TEST_P(SpdyFramerTest,ReadIncorrectlySizedPriority)4869 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPriority) {
4870 // PRIORITY frame of size 4, which isn't correct.
4871 const unsigned char kFrameData[] = {
4872 0x00, 0x00, 0x04, // Length: 4
4873 0x02, // Type: PRIORITY
4874 0x00, // Flags: none
4875 0x00, 0x00, 0x00, 0x03, // Stream: 3
4876 0x00, 0x00, 0x00, 0x01, // Priority (Truncated)
4877 };
4878
4879 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4880 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4881
4882 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, visitor.deframer_.state());
4883 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4884 visitor.deframer_.spdy_framer_error())
4885 << Http2DecoderAdapter::SpdyFramerErrorToString(
4886 visitor.deframer_.spdy_framer_error());
4887 }
4888
4889 // Tests handling of PING frame with incorrect size.
TEST_P(SpdyFramerTest,ReadIncorrectlySizedPing)4890 TEST_P(SpdyFramerTest, ReadIncorrectlySizedPing) {
4891 // PING frame of size 4, which isn't correct.
4892 const unsigned char kFrameData[] = {
4893 0x00, 0x00, 0x04, // Length: 4
4894 0x06, // Type: PING
4895 0x00, // Flags: none
4896 0x00, 0x00, 0x00, 0x00, // Stream: 0
4897 0x00, 0x00, 0x00, 0x01, // Ping (Truncated)
4898 };
4899
4900 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4901 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4902
4903 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, visitor.deframer_.state());
4904 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4905 visitor.deframer_.spdy_framer_error())
4906 << Http2DecoderAdapter::SpdyFramerErrorToString(
4907 visitor.deframer_.spdy_framer_error());
4908 }
4909
4910 // Tests handling of WINDOW_UPDATE frame with incorrect size.
TEST_P(SpdyFramerTest,ReadIncorrectlySizedWindowUpdate)4911 TEST_P(SpdyFramerTest, ReadIncorrectlySizedWindowUpdate) {
4912 // WINDOW_UPDATE frame of size 3, which isn't correct.
4913 const unsigned char kFrameData[] = {
4914 0x00, 0x00, 0x03, // Length: 3
4915 0x08, // Type: WINDOW_UPDATE
4916 0x00, // Flags: none
4917 0x00, 0x00, 0x00, 0x03, // Stream: 3
4918 0x00, 0x00, 0x01, // WindowUpdate (Truncated)
4919 };
4920
4921 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4922 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4923
4924 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, visitor.deframer_.state());
4925 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4926 visitor.deframer_.spdy_framer_error())
4927 << Http2DecoderAdapter::SpdyFramerErrorToString(
4928 visitor.deframer_.spdy_framer_error());
4929 }
4930
4931 // Tests handling of RST_STREAM frame with incorrect size.
TEST_P(SpdyFramerTest,ReadIncorrectlySizedRstStream)4932 TEST_P(SpdyFramerTest, ReadIncorrectlySizedRstStream) {
4933 // RST_STREAM frame of size 3, which isn't correct.
4934 const unsigned char kFrameData[] = {
4935 0x00, 0x00, 0x03, // Length: 3
4936 0x03, // Type: RST_STREAM
4937 0x00, // Flags: none
4938 0x00, 0x00, 0x00, 0x03, // Stream: 3
4939 0x00, 0x00, 0x01, // RstStream (Truncated)
4940 };
4941
4942 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4943 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4944
4945 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, visitor.deframer_.state());
4946 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4947 visitor.deframer_.spdy_framer_error())
4948 << Http2DecoderAdapter::SpdyFramerErrorToString(
4949 visitor.deframer_.spdy_framer_error());
4950 }
4951
4952 // Regression test for https://crbug.com/548674:
4953 // RST_STREAM with payload must not be accepted.
TEST_P(SpdyFramerTest,ReadInvalidRstStreamWithPayload)4954 TEST_P(SpdyFramerTest, ReadInvalidRstStreamWithPayload) {
4955 const unsigned char kFrameData[] = {
4956 0x00, 0x00, 0x07, // Length: 7
4957 0x03, // Type: RST_STREAM
4958 0x00, // Flags: none
4959 0x00, 0x00, 0x00, 0x01, // Stream: 1
4960 0x00, 0x00, 0x00, 0x00, // Error: NO_ERROR
4961 'f', 'o', 'o' // Payload: "foo"
4962 };
4963
4964 TestSpdyVisitor visitor(SpdyFramer::DISABLE_COMPRESSION);
4965 visitor.SimulateInFramer(kFrameData, sizeof(kFrameData));
4966
4967 EXPECT_EQ(Http2DecoderAdapter::SPDY_ERROR, visitor.deframer_.state());
4968 EXPECT_EQ(Http2DecoderAdapter::SPDY_INVALID_CONTROL_FRAME_SIZE,
4969 visitor.deframer_.spdy_framer_error())
4970 << Http2DecoderAdapter::SpdyFramerErrorToString(
4971 visitor.deframer_.spdy_framer_error());
4972 }
4973
4974 // Test that SpdyFramer processes all passed input in one call to ProcessInput.
TEST_P(SpdyFramerTest,ProcessAllInput)4975 TEST_P(SpdyFramerTest, ProcessAllInput) {
4976 auto visitor =
4977 std::make_unique<TestSpdyVisitor>(SpdyFramer::DISABLE_COMPRESSION);
4978 deframer_->set_visitor(visitor.get());
4979
4980 // Create two input frames.
4981 SpdyHeadersIR headers(/* stream_id = */ 1);
4982 headers.SetHeader("alpha", "beta");
4983 headers.SetHeader("gamma", "charlie");
4984 headers.SetHeader("cookie", "key1=value1; key2=value2");
4985 SpdySerializedFrame headers_frame(SpdyFramerPeer::SerializeHeaders(
4986 &framer_, headers, use_output_ ? &output_ : nullptr));
4987
4988 const char four_score[] = "Four score and seven years ago";
4989 SpdyDataIR four_score_ir(/* stream_id = */ 1, four_score);
4990 SpdySerializedFrame four_score_frame(framer_.SerializeData(four_score_ir));
4991
4992 // Put them in a single buffer (new variables here to make it easy to
4993 // change the order and type of frames).
4994 SpdySerializedFrame frame1 = std::move(headers_frame);
4995 SpdySerializedFrame frame2 = std::move(four_score_frame);
4996
4997 const size_t frame1_size = frame1.size();
4998 const size_t frame2_size = frame2.size();
4999
5000 QUICHE_VLOG(1) << "frame1_size = " << frame1_size;
5001 QUICHE_VLOG(1) << "frame2_size = " << frame2_size;
5002
5003 std::string input_buffer;
5004 input_buffer.append(frame1.data(), frame1_size);
5005 input_buffer.append(frame2.data(), frame2_size);
5006
5007 const char* buf = input_buffer.data();
5008 const size_t buf_size = input_buffer.size();
5009
5010 QUICHE_VLOG(1) << "buf_size = " << buf_size;
5011
5012 size_t processed = deframer_->ProcessInput(buf, buf_size);
5013 EXPECT_EQ(buf_size, processed);
5014 EXPECT_EQ(Http2DecoderAdapter::SPDY_READY_FOR_FRAME, deframer_->state());
5015 EXPECT_EQ(1, visitor->headers_frame_count_);
5016 EXPECT_EQ(1, visitor->data_frame_count_);
5017 EXPECT_EQ(strlen(four_score), static_cast<unsigned>(visitor->data_bytes_));
5018 }
5019
5020 namespace {
CheckFrameAndIRSize(SpdyFrameIR * ir,SpdyFramer * framer,ArrayOutputBuffer * array_output_buffer)5021 void CheckFrameAndIRSize(SpdyFrameIR* ir, SpdyFramer* framer,
5022 ArrayOutputBuffer* array_output_buffer) {
5023 array_output_buffer->Reset();
5024 SpdyFrameType type = ir->frame_type();
5025 size_t ir_size = ir->size();
5026 framer->SerializeFrame(*ir, array_output_buffer);
5027 if (type == SpdyFrameType::HEADERS || type == SpdyFrameType::PUSH_PROMISE) {
5028 // For HEADERS and PUSH_PROMISE, the size is an estimate.
5029 EXPECT_GE(ir_size, array_output_buffer->Size() * 9 / 10);
5030 EXPECT_LT(ir_size, array_output_buffer->Size() * 11 / 10);
5031 } else {
5032 EXPECT_EQ(ir_size, array_output_buffer->Size());
5033 }
5034 }
5035 } // namespace
5036
TEST_P(SpdyFramerTest,SpdyFrameIRSize)5037 TEST_P(SpdyFramerTest, SpdyFrameIRSize) {
5038 SpdyFramer framer(SpdyFramer::DISABLE_COMPRESSION);
5039
5040 const char bytes[] = "this is a very short data frame";
5041 SpdyDataIR data_ir(1, absl::string_view(bytes, ABSL_ARRAYSIZE(bytes)));
5042 CheckFrameAndIRSize(&data_ir, &framer, &output_);
5043
5044 SpdyRstStreamIR rst_ir(/* stream_id = */ 1, ERROR_CODE_PROTOCOL_ERROR);
5045 CheckFrameAndIRSize(&rst_ir, &framer, &output_);
5046
5047 SpdySettingsIR settings_ir;
5048 settings_ir.AddSetting(SETTINGS_HEADER_TABLE_SIZE, 5);
5049 settings_ir.AddSetting(SETTINGS_ENABLE_PUSH, 6);
5050 settings_ir.AddSetting(SETTINGS_MAX_CONCURRENT_STREAMS, 7);
5051 CheckFrameAndIRSize(&settings_ir, &framer, &output_);
5052
5053 SpdyPingIR ping_ir(42);
5054 CheckFrameAndIRSize(&ping_ir, &framer, &output_);
5055
5056 SpdyGoAwayIR goaway_ir(97, ERROR_CODE_NO_ERROR, "Goaway description");
5057 CheckFrameAndIRSize(&goaway_ir, &framer, &output_);
5058
5059 SpdyHeadersIR headers_ir(1);
5060 headers_ir.SetHeader("alpha", "beta");
5061 headers_ir.SetHeader("gamma", "charlie");
5062 headers_ir.SetHeader("cookie", "key1=value1; key2=value2");
5063 CheckFrameAndIRSize(&headers_ir, &framer, &output_);
5064
5065 SpdyHeadersIR headers_ir_with_continuation(1);
5066 headers_ir_with_continuation.SetHeader("alpha", std::string(100000, 'x'));
5067 headers_ir_with_continuation.SetHeader("beta", std::string(100000, 'x'));
5068 headers_ir_with_continuation.SetHeader("cookie", "key1=value1; key2=value2");
5069 CheckFrameAndIRSize(&headers_ir_with_continuation, &framer, &output_);
5070
5071 SpdyWindowUpdateIR window_update_ir(4, 1024);
5072 CheckFrameAndIRSize(&window_update_ir, &framer, &output_);
5073
5074 SpdyPushPromiseIR push_promise_ir(3, 8);
5075 push_promise_ir.SetHeader("alpha", std::string(100000, 'x'));
5076 push_promise_ir.SetHeader("beta", std::string(100000, 'x'));
5077 push_promise_ir.SetHeader("cookie", "key1=value1; key2=value2");
5078 CheckFrameAndIRSize(&push_promise_ir, &framer, &output_);
5079
5080 SpdyAltSvcWireFormat::AlternativeService altsvc1(
5081 "pid1", "host", 443, 5, SpdyAltSvcWireFormat::VersionVector());
5082 SpdyAltSvcWireFormat::AlternativeService altsvc2(
5083 "p\"=i:d", "h_\\o\"st", 123, 42, SpdyAltSvcWireFormat::VersionVector{24});
5084 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
5085 altsvc_vector.push_back(altsvc1);
5086 altsvc_vector.push_back(altsvc2);
5087 SpdyAltSvcIR altsvc_ir(0);
5088 altsvc_ir.set_origin("o_r|g!n");
5089 altsvc_ir.add_altsvc(altsvc1);
5090 altsvc_ir.add_altsvc(altsvc2);
5091 CheckFrameAndIRSize(&altsvc_ir, &framer, &output_);
5092
5093 SpdyPriorityIR priority_ir(3, 1, 256, false);
5094 CheckFrameAndIRSize(&priority_ir, &framer, &output_);
5095
5096 const char kDescription[] = "Unknown frame";
5097 const uint8_t kType = 0xaf;
5098 const uint8_t kFlags = 0x11;
5099 SpdyUnknownIR unknown_ir(2, kType, kFlags, kDescription);
5100 CheckFrameAndIRSize(&unknown_ir, &framer, &output_);
5101 }
5102
5103 } // namespace test
5104
5105 } // namespace spdy
5106