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