Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(759)

Side by Side Diff: net/spdy/spdy_framer.cc

Issue 2832973003: Split net/spdy into core and chromium subdirectories. (Closed)
Patch Set: Fix some more build rules. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_decoder_adapter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/spdy/spdy_framer.h"
6
7 #include <string.h>
8
9 #include <algorithm>
10 #include <cctype>
11 #include <ios>
12 #include <iterator>
13 #include <list>
14 #include <memory>
15 #include <new>
16 #include <vector>
17
18 #include "base/lazy_instance.h"
19 #include "base/logging.h"
20 #include "base/memory/ptr_util.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/strings/string_util.h"
23 #include "net/quic/platform/api/quic_flags.h"
24 #include "net/spdy/hpack/hpack_constants.h"
25 #include "net/spdy/hpack/hpack_decoder.h"
26 #include "net/spdy/hpack/hpack_decoder3.h"
27 #include "net/spdy/http2_frame_decoder_adapter.h"
28 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h"
29 #include "net/spdy/platform/api/spdy_string_utils.h"
30 #include "net/spdy/spdy_bitmasks.h"
31 #include "net/spdy/spdy_bug_tracker.h"
32 #include "net/spdy/spdy_flags.h"
33 #include "net/spdy/spdy_frame_builder.h"
34 #include "net/spdy/spdy_frame_reader.h"
35 #include "net/spdy/spdy_framer_decoder_adapter.h"
36
37 using std::vector;
38
39 namespace net {
40
41 namespace {
42
43 // Pack parent stream ID and exclusive flag into the format used by HTTP/2
44 // headers and priority frames.
45 uint32_t PackStreamDependencyValues(bool exclusive,
46 SpdyStreamId parent_stream_id) {
47 // Make sure the highest-order bit in the parent stream id is zeroed out.
48 uint32_t parent = parent_stream_id & 0x7fffffff;
49 // Set the one-bit exclusivity flag.
50 uint32_t e_bit = exclusive ? 0x80000000 : 0;
51 return parent | e_bit;
52 }
53
54 // Unpack parent stream ID and exclusive flag from the format used by HTTP/2
55 // headers and priority frames.
56 void UnpackStreamDependencyValues(uint32_t packed,
57 bool* exclusive,
58 SpdyStreamId* parent_stream_id) {
59 *exclusive = (packed >> 31) != 0;
60 // Zero out the highest-order bit to get the parent stream id.
61 *parent_stream_id = packed & 0x7fffffff;
62 }
63
64 // Creates a SpdyFramerDecoderAdapter if flags indicate that one should be
65 // used. This code is isolated to hopefully make merging into Chromium easier.
66 std::unique_ptr<SpdyFramerDecoderAdapter> DecoderAdapterFactory(
67 SpdyFramer* outer) {
68 if (FLAGS_use_nested_spdy_framer_decoder) {
69 // Since chromium_reloadable_flag_spdy_use_http2_frame_decoder_adapter can
70 // be flipped on in any test when all the feature flags are on,
71 // it can unintentionally override use_nested_spdy_framer_decoder which is
72 // used to validate that the adapter technique is working. Therefore, we
73 // give precedence to use_nested_spdy_framer_decoder.
74 if (FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter) {
75 VLOG(1) << "Both NestedSpdyFramerDecoder and Http2FrameDecoderAdapter "
76 << "are enabled. NestedSpdyFramerDecoder selected.";
77 }
78 DVLOG(1) << "Creating NestedSpdyFramerDecoder.";
79 return CreateNestedSpdyFramerDecoder(outer);
80 }
81
82 if (FLAGS_chromium_http2_flag_spdy_use_http2_frame_decoder_adapter) {
83 DVLOG(1) << "Creating Http2FrameDecoderAdapter.";
84 return CreateHttp2FrameDecoderAdapter(outer);
85 }
86
87 return nullptr;
88 }
89
90 // Used to indicate no flags in a HTTP2 flags field.
91 const uint8_t kNoFlags = 0;
92
93 // Wire sizes of priority payloads.
94 const size_t kPriorityDependencyPayloadSize = 4;
95 const size_t kPriorityWeightPayloadSize = 1;
96
97 // Wire size of pad length field.
98 const size_t kPadLengthFieldSize = 1;
99
100 } // namespace
101
102 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1);
103 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
104 // Even though the length field is 24 bits, we keep this 16 kB
105 // limit on control frame size for legacy reasons and to
106 // mitigate DOS attacks.
107 const size_t SpdyFramer::kMaxControlFrameSize = (1 << 14) - 1;
108 const size_t SpdyFramer::kMaxDataPayloadSendSize = 1 << 14;
109 // The size of the control frame buffer. Must be >= the minimum size of the
110 // largest control frame.
111 const size_t SpdyFramer::kControlFrameBufferSize = 19;
112 const size_t SpdyFramer::kOneSettingParameterSize = 6;
113
114 #ifdef DEBUG_SPDY_STATE_CHANGES
115 #define CHANGE_STATE(newstate) \
116 do { \
117 DVLOG(1) << "Changing state from: " \
118 << StateToString(state_) \
119 << " to " << StateToString(newstate) << "\n"; \
120 DCHECK(state_ != SPDY_ERROR); \
121 DCHECK_EQ(previous_state_, state_); \
122 previous_state_ = state_; \
123 state_ = newstate; \
124 } while (false)
125 #else
126 #define CHANGE_STATE(newstate) \
127 do { \
128 DCHECK(state_ != SPDY_ERROR); \
129 DCHECK_EQ(previous_state_, state_); \
130 previous_state_ = state_; \
131 state_ = newstate; \
132 } while (false)
133 #endif
134
135 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
136 size_t len) {
137 return true;
138 }
139
140 SpdyFramer::SpdyFramer(SpdyFramer::DecoderAdapterFactoryFn adapter_factory,
141 CompressionOption option)
142 : current_frame_buffer_(kControlFrameBufferSize),
143 expect_continuation_(0),
144 visitor_(nullptr),
145 extension_(nullptr),
146 debug_visitor_(nullptr),
147 header_handler_(nullptr),
148 compression_option_(option),
149 probable_http_response_(false),
150 end_stream_when_done_(false) {
151 static_assert(
152 kMaxControlFrameSize <= kSpdyInitialFrameSizeLimit + kFrameHeaderSize,
153 "Our send limit should be at most our receive limit");
154 Reset();
155
156 if (adapter_factory != nullptr) {
157 decoder_adapter_ = adapter_factory(this);
158 }
159 skip_rewritelength_ = FLAGS_chromium_http2_flag_remove_rewritelength;
160 }
161
162 SpdyFramer::SpdyFramer(CompressionOption option)
163 : SpdyFramer(&DecoderAdapterFactory, option) {}
164
165 SpdyFramer::~SpdyFramer() {}
166
167 void SpdyFramer::Reset() {
168 if (decoder_adapter_ != nullptr) {
169 decoder_adapter_->Reset();
170 }
171 state_ = SPDY_READY_FOR_FRAME;
172 previous_state_ = SPDY_READY_FOR_FRAME;
173 spdy_framer_error_ = SPDY_NO_ERROR;
174 remaining_data_length_ = 0;
175 remaining_control_header_ = 0;
176 current_frame_buffer_.Rewind();
177 current_frame_type_ = SpdyFrameType::DATA;
178 current_frame_flags_ = 0;
179 current_frame_length_ = 0;
180 current_frame_stream_id_ = kInvalidStream;
181 settings_scratch_.Reset();
182 altsvc_scratch_.reset();
183 remaining_padding_payload_length_ = 0;
184 }
185
186 void SpdyFramer::set_visitor(SpdyFramerVisitorInterface* visitor) {
187 if (decoder_adapter_ != nullptr) {
188 decoder_adapter_->set_visitor(visitor);
189 }
190 visitor_ = visitor;
191 }
192
193 void SpdyFramer::set_extension_visitor(ExtensionVisitorInterface* extension) {
194 if (decoder_adapter_ != nullptr) {
195 decoder_adapter_->set_extension_visitor(extension);
196 }
197 extension_ = extension;
198 }
199
200 void SpdyFramer::set_debug_visitor(
201 SpdyFramerDebugVisitorInterface* debug_visitor) {
202 if (decoder_adapter_ != nullptr) {
203 decoder_adapter_->set_debug_visitor(debug_visitor);
204 }
205 debug_visitor_ = debug_visitor;
206 }
207
208 void SpdyFramer::set_process_single_input_frame(bool v) {
209 if (decoder_adapter_ != nullptr) {
210 decoder_adapter_->set_process_single_input_frame(v);
211 }
212 process_single_input_frame_ = v;
213 }
214
215 bool SpdyFramer::probable_http_response() const {
216 if (decoder_adapter_) {
217 return decoder_adapter_->probable_http_response();
218 }
219 return probable_http_response_;
220 }
221
222 SpdyFramer::SpdyFramerError SpdyFramer::spdy_framer_error() const {
223 if (decoder_adapter_ != nullptr) {
224 return decoder_adapter_->spdy_framer_error();
225 }
226 return spdy_framer_error_;
227 }
228
229 SpdyFramer::SpdyState SpdyFramer::state() const {
230 if (decoder_adapter_ != nullptr) {
231 return decoder_adapter_->state();
232 }
233 return state_;
234 }
235
236 size_t SpdyFramer::GetDataFrameMinimumSize() const {
237 return kDataFrameMinimumSize;
238 }
239
240 // Size, in bytes, of the control frame header.
241 size_t SpdyFramer::GetFrameHeaderSize() const {
242 return kFrameHeaderSize;
243 }
244
245 size_t SpdyFramer::GetRstStreamSize() const {
246 // Size, in bytes, of a RST_STREAM frame.
247 // Calculated as:
248 // frame prefix + 4 (status code)
249 return GetFrameHeaderSize() + 4;
250 }
251
252 size_t SpdyFramer::GetSettingsMinimumSize() const {
253 // Size, in bytes, of a SETTINGS frame not including the IDs and values
254 // from the variable-length value block.
255 return GetFrameHeaderSize();
256 }
257
258 size_t SpdyFramer::GetPingSize() const {
259 // Size, in bytes, of this PING frame.
260 // Calculated as:
261 // control frame header + 8 (id)
262 return GetFrameHeaderSize() + 8;
263 }
264
265 size_t SpdyFramer::GetGoAwayMinimumSize() const {
266 // Size, in bytes, of this GOAWAY frame. Calculated as:
267 // Control frame header + last stream id (4 bytes) + error code (4 bytes).
268 return GetFrameHeaderSize() + 8;
269 }
270
271 size_t SpdyFramer::GetHeadersMinimumSize() const {
272 // Size, in bytes, of a HEADERS frame not including the variable-length
273 // header block.
274 return GetFrameHeaderSize();
275 }
276
277 size_t SpdyFramer::GetWindowUpdateSize() const {
278 // Size, in bytes, of a WINDOW_UPDATE frame.
279 // Calculated as:
280 // frame prefix + 4 (delta)
281 return GetFrameHeaderSize() + 4;
282 }
283
284 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
285 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
286 // Calculated as frame prefix + 4 (promised stream id)
287 return GetFrameHeaderSize() + 4;
288 }
289
290 size_t SpdyFramer::GetContinuationMinimumSize() const {
291 // Size, in bytes, of a CONTINUATION frame not including the variable-length
292 // headers fragments.
293 return GetFrameHeaderSize();
294 }
295
296 size_t SpdyFramer::GetAltSvcMinimumSize() const {
297 // Size, in bytes, of an ALTSVC frame not including the Field-Value and
298 // (optional) Origin fields, both of which can vary in length. Note that this
299 // gives a lower bound on the frame size rather than a true minimum; the
300 // actual frame should always be larger than this.
301 // Calculated as frame prefix + 2 (origin_len).
302 return GetFrameHeaderSize() + 2;
303 }
304
305 size_t SpdyFramer::GetPrioritySize() const {
306 // Size, in bytes, of a PRIORITY frame.
307 return GetFrameHeaderSize() + kPriorityDependencyPayloadSize +
308 kPriorityWeightPayloadSize;
309 }
310
311 size_t SpdyFramer::GetFrameMinimumSize() const {
312 return GetFrameHeaderSize();
313 }
314
315 size_t SpdyFramer::GetFrameMaximumSize() const {
316 return send_frame_size_limit_ + kFrameHeaderSize;
317 }
318
319 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
320 return std::min(kMaxDataPayloadSendSize,
321 GetFrameMaximumSize() - GetDataFrameMinimumSize());
322 }
323
324 const char* SpdyFramer::StateToString(int state) {
325 switch (state) {
326 case SPDY_ERROR:
327 return "ERROR";
328 case SPDY_FRAME_COMPLETE:
329 return "FRAME_COMPLETE";
330 case SPDY_READY_FOR_FRAME:
331 return "READY_FOR_FRAME";
332 case SPDY_READING_COMMON_HEADER:
333 return "READING_COMMON_HEADER";
334 case SPDY_CONTROL_FRAME_PAYLOAD:
335 return "CONTROL_FRAME_PAYLOAD";
336 case SPDY_READ_DATA_FRAME_PADDING_LENGTH:
337 return "SPDY_READ_DATA_FRAME_PADDING_LENGTH";
338 case SPDY_CONSUME_PADDING:
339 return "SPDY_CONSUME_PADDING";
340 case SPDY_IGNORE_REMAINING_PAYLOAD:
341 return "IGNORE_REMAINING_PAYLOAD";
342 case SPDY_FORWARD_STREAM_FRAME:
343 return "FORWARD_STREAM_FRAME";
344 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
345 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
346 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
347 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
348 case SPDY_GOAWAY_FRAME_PAYLOAD:
349 return "SPDY_GOAWAY_FRAME_PAYLOAD";
350 case SPDY_SETTINGS_FRAME_HEADER:
351 return "SPDY_SETTINGS_FRAME_HEADER";
352 case SPDY_SETTINGS_FRAME_PAYLOAD:
353 return "SPDY_SETTINGS_FRAME_PAYLOAD";
354 case SPDY_ALTSVC_FRAME_PAYLOAD:
355 return "SPDY_ALTSVC_FRAME_PAYLOAD";
356 }
357 return "UNKNOWN_STATE";
358 }
359
360 void SpdyFramer::set_error(SpdyFramerError error) {
361 DCHECK(visitor_);
362 spdy_framer_error_ = error;
363 // These values will usually get reset once we come to the end
364 // of a header block, but if we run into an error that
365 // might not happen, so reset them here.
366 expect_continuation_ = 0;
367 end_stream_when_done_ = false;
368
369 CHANGE_STATE(SPDY_ERROR);
370 visitor_->OnError(this);
371 }
372
373 const char* SpdyFramer::SpdyFramerErrorToString(
374 SpdyFramerError spdy_framer_error) {
375 switch (spdy_framer_error) {
376 case SPDY_NO_ERROR:
377 return "NO_ERROR";
378 case SPDY_INVALID_STREAM_ID:
379 return "INVALID_STREAM_ID";
380 case SPDY_INVALID_CONTROL_FRAME:
381 return "INVALID_CONTROL_FRAME";
382 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
383 return "CONTROL_PAYLOAD_TOO_LARGE";
384 case SPDY_ZLIB_INIT_FAILURE:
385 return "ZLIB_INIT_FAILURE";
386 case SPDY_UNSUPPORTED_VERSION:
387 return "UNSUPPORTED_VERSION";
388 case SPDY_DECOMPRESS_FAILURE:
389 return "DECOMPRESS_FAILURE";
390 case SPDY_COMPRESS_FAILURE:
391 return "COMPRESS_FAILURE";
392 case SPDY_GOAWAY_FRAME_CORRUPT:
393 return "GOAWAY_FRAME_CORRUPT";
394 case SPDY_RST_STREAM_FRAME_CORRUPT:
395 return "RST_STREAM_FRAME_CORRUPT";
396 case SPDY_INVALID_PADDING:
397 return "INVALID_PADDING";
398 case SPDY_INVALID_DATA_FRAME_FLAGS:
399 return "INVALID_DATA_FRAME_FLAGS";
400 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
401 return "INVALID_CONTROL_FRAME_FLAGS";
402 case SPDY_UNEXPECTED_FRAME:
403 return "UNEXPECTED_FRAME";
404 case SPDY_INTERNAL_FRAMER_ERROR:
405 return "INTERNAL_FRAMER_ERROR";
406 case SPDY_INVALID_CONTROL_FRAME_SIZE:
407 return "INVALID_CONTROL_FRAME_SIZE";
408 case SPDY_OVERSIZED_PAYLOAD:
409 return "OVERSIZED_PAYLOAD";
410 case LAST_ERROR:
411 return "UNKNOWN_ERROR";
412 }
413 return "UNKNOWN_ERROR";
414 }
415
416 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
417 DCHECK(visitor_);
418 DCHECK(data);
419
420 if (decoder_adapter_ != nullptr) {
421 return decoder_adapter_->ProcessInput(data, len);
422 }
423 const size_t original_len = len;
424 do {
425 previous_state_ = state_;
426 switch (state_) {
427 case SPDY_ERROR:
428 goto bottom;
429
430 case SPDY_FRAME_COMPLETE:
431 // Should not enter in this state.
432 DCHECK_LT(len, original_len);
433 Reset();
434 if (len > 0 && !process_single_input_frame_) {
435 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
436 }
437 break;
438
439 case SPDY_READY_FOR_FRAME:
440 if (len > 0) {
441 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
442 }
443 break;
444
445 case SPDY_READING_COMMON_HEADER: {
446 size_t bytes_read = ProcessCommonHeader(data, len);
447 len -= bytes_read;
448 data += bytes_read;
449 break;
450 }
451
452 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
453 // Control frames that contain header blocks
454 // (HEADERS, PUSH_PROMISE, CONTINUATION)
455 // take a special path through the state machine - they
456 // will go:
457 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
458 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
459 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
460 len -= bytes_read;
461 data += bytes_read;
462 break;
463 }
464
465 case SPDY_SETTINGS_FRAME_HEADER: {
466 int bytes_read = ProcessSettingsFrameHeader(data, len);
467 len -= bytes_read;
468 data += bytes_read;
469 break;
470 }
471
472 case SPDY_SETTINGS_FRAME_PAYLOAD: {
473 int bytes_read = ProcessSettingsFramePayload(data, len);
474 len -= bytes_read;
475 data += bytes_read;
476 break;
477 }
478
479 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
480 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
481 len -= bytes_read;
482 data += bytes_read;
483 break;
484 }
485
486 case SPDY_GOAWAY_FRAME_PAYLOAD: {
487 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
488 len -= bytes_read;
489 data += bytes_read;
490 break;
491 }
492
493 case SPDY_ALTSVC_FRAME_PAYLOAD: {
494 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
495 len -= bytes_read;
496 data += bytes_read;
497 break;
498 }
499
500 case SPDY_CONTROL_FRAME_PAYLOAD: {
501 size_t bytes_read = ProcessControlFramePayload(data, len);
502 len -= bytes_read;
503 data += bytes_read;
504 break;
505 }
506
507 case SPDY_READ_DATA_FRAME_PADDING_LENGTH: {
508 size_t bytes_read = ProcessDataFramePaddingLength(data, len);
509 len -= bytes_read;
510 data += bytes_read;
511 break;
512 }
513
514 case SPDY_CONSUME_PADDING: {
515 size_t bytes_read = ProcessFramePadding(data, len);
516 len -= bytes_read;
517 data += bytes_read;
518 break;
519 }
520
521 case SPDY_IGNORE_REMAINING_PAYLOAD: {
522 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
523 len -= bytes_read;
524 data += bytes_read;
525 break;
526 }
527
528 case SPDY_FORWARD_STREAM_FRAME: {
529 size_t bytes_read = ProcessDataFramePayload(data, len);
530 len -= bytes_read;
531 data += bytes_read;
532 break;
533 }
534
535 case SPDY_EXTENSION_FRAME_PAYLOAD: {
536 size_t bytes_read = ProcessExtensionFramePayload(data, len);
537 len -= bytes_read;
538 data += bytes_read;
539 break;
540 }
541
542 default:
543 SPDY_BUG << "Invalid value for framer state: " << state_;
544 // This ensures that we don't infinite-loop if state_ gets an
545 // invalid value somehow, such as due to a SpdyFramer getting deleted
546 // from a callback it calls.
547 goto bottom;
548 }
549 } while (state_ != previous_state_);
550 bottom:
551 DCHECK(len == 0 || state_ == SPDY_ERROR || process_single_input_frame_)
552 << "len: " << len << " state: " << state_
553 << " process single input frame: " << process_single_input_frame_;
554 if (current_frame_buffer_.len() == 0 && remaining_data_length_ == 0 &&
555 remaining_control_header_ == 0) {
556 DCHECK(state_ == SPDY_READY_FOR_FRAME || state_ == SPDY_ERROR)
557 << "State: " << StateToString(state_);
558 }
559
560 return original_len - len;
561 }
562
563 SpdyFramer::CharBuffer::CharBuffer(size_t capacity)
564 : buffer_(new char[capacity]), capacity_(capacity), len_(0) {}
565 SpdyFramer::CharBuffer::~CharBuffer() {}
566
567 void SpdyFramer::CharBuffer::CopyFrom(const char* data, size_t size) {
568 DCHECK_GE(capacity_, len_ + size);
569 memcpy(buffer_.get() + len_, data, size);
570 len_ += size;
571 }
572
573 void SpdyFramer::CharBuffer::Rewind() {
574 len_ = 0;
575 }
576
577 size_t SpdyFramer::CharBuffer::EstimateMemoryUsage() const {
578 return capacity_;
579 }
580
581 SpdyFramer::SpdySettingsScratch::SpdySettingsScratch()
582 : buffer(8), last_setting_id(-1) {}
583
584 void SpdyFramer::SpdySettingsScratch::Reset() {
585 buffer.Rewind();
586 last_setting_id = -1;
587 }
588
589 size_t SpdyFramer::SpdySettingsScratch::EstimateMemoryUsage() const {
590 return SpdyEstimateMemoryUsage(buffer);
591 }
592
593 SpdyFrameType SpdyFramer::ValidateFrameHeader(bool is_control_frame,
594 uint8_t frame_type_field,
595 size_t payload_length_field) {
596 if (!IsDefinedFrameType(frame_type_field)) {
597 if (expect_continuation_) {
598 // Report an unexpected frame error and close the connection
599 // if we expect a continuation and receive an unknown frame.
600 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
601 << "frame, but instead received an unknown frame of type "
602 << SpdyStringPrintf("%x", frame_type_field);
603 set_error(SPDY_UNEXPECTED_FRAME);
604 return SpdyFrameType::DATA;
605 }
606 if (extension_ != nullptr) {
607 if (extension_->OnFrameHeader(current_frame_stream_id_,
608 payload_length_field, frame_type_field,
609 current_frame_flags_)) {
610 return SpdyFrameType::EXTENSION;
611 }
612 }
613 // We ignore unknown frame types for extensibility, as long as
614 // the rest of the control frame header is valid.
615 // We rely on the visitor to check validity of current_frame_stream_id_.
616 bool valid_stream =
617 visitor_->OnUnknownFrame(current_frame_stream_id_, frame_type_field);
618 if (!valid_stream) {
619 // Report an invalid frame error and close the stream if the
620 // stream_id is not valid.
621 DLOG(WARNING) << "Unknown control frame type "
622 << SpdyStringPrintf("%x", frame_type_field)
623 << " received on invalid stream "
624 << current_frame_stream_id_;
625 set_error(SPDY_INVALID_CONTROL_FRAME);
626 } else {
627 DVLOG(1) << "Ignoring unknown frame type.";
628 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
629 }
630 return SpdyFrameType::DATA;
631 }
632
633 SpdyFrameType frame_type = ParseFrameType(frame_type_field);
634
635 if (!IsValidHTTP2FrameStreamId(current_frame_stream_id_, frame_type)) {
636 DLOG(ERROR) << "The framer received an invalid streamID of "
637 << current_frame_stream_id_ << " for a frame of type "
638 << FrameTypeToString(frame_type);
639 set_error(SPDY_INVALID_STREAM_ID);
640 return frame_type;
641 }
642
643 // Ensure that we see a CONTINUATION frame iff we expect to.
644 if ((frame_type == SpdyFrameType::CONTINUATION) !=
645 (expect_continuation_ != 0)) {
646 if (expect_continuation_ != 0) {
647 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
648 << "frame, but instead received a frame of type "
649 << FrameTypeToString(frame_type);
650 } else {
651 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
652 }
653 set_error(SPDY_UNEXPECTED_FRAME);
654 return frame_type;
655 }
656
657 if (payload_length_field > recv_frame_size_limit_) {
658 set_error(SPDY_OVERSIZED_PAYLOAD);
659 }
660
661 return frame_type;
662 }
663
664 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
665 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
666 // state.
667 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
668
669 size_t original_len = len;
670
671 // Update current frame buffer as needed.
672 if (current_frame_buffer_.len() < GetFrameHeaderSize()) {
673 size_t bytes_desired = GetFrameHeaderSize() - current_frame_buffer_.len();
674 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
675 }
676
677 if (current_frame_buffer_.len() < GetFrameHeaderSize()) {
678 // Not enough information to do anything meaningful.
679 return original_len - len;
680 }
681
682 SpdyFrameReader reader(current_frame_buffer_.data(),
683 current_frame_buffer_.len());
684 bool is_control_frame = false;
685
686 uint32_t length_field = 0;
687 bool successful_read = reader.ReadUInt24(&length_field);
688 DCHECK(successful_read);
689
690 uint8_t control_frame_type_field = 0;
691 successful_read = reader.ReadUInt8(&control_frame_type_field);
692 DCHECK(successful_read);
693 // We check control_frame_type_field's validity in
694 // ValidateFrameHeader().
695 is_control_frame =
696 control_frame_type_field != SerializeFrameType(SpdyFrameType::DATA);
697
698 current_frame_length_ = length_field + GetFrameHeaderSize();
699
700 successful_read = reader.ReadUInt8(&current_frame_flags_);
701 DCHECK(successful_read);
702
703 successful_read = reader.ReadUInt31(&current_frame_stream_id_);
704 DCHECK(successful_read);
705
706 remaining_data_length_ = current_frame_length_ - reader.GetBytesConsumed();
707
708 DCHECK_EQ(GetFrameHeaderSize(), reader.GetBytesConsumed());
709 DCHECK_EQ(current_frame_length_,
710 remaining_data_length_ + reader.GetBytesConsumed());
711
712 // This is just a sanity check for help debugging early frame errors.
713 // The strncmp for 5 is safe because we only hit this point if we
714 // have kMinCommonHeader (8) bytes
715 if (remaining_data_length_ > 1000000u &&
716 strncmp(current_frame_buffer_.data(), "HTTP/", 5) == 0) {
717 LOG(WARNING) << "Unexpected HTTP response to HTTP2 request";
718 probable_http_response_ = true;
719 }
720
721 // If we're here, then we have the common header all received.
722 visitor_->OnCommonHeader(current_frame_stream_id_, remaining_data_length_,
723 control_frame_type_field, current_frame_flags_);
724
725 current_frame_type_ = ValidateFrameHeader(
726 is_control_frame, control_frame_type_field, remaining_data_length_);
727
728 if (state_ == SPDY_ERROR || state_ == SPDY_IGNORE_REMAINING_PAYLOAD) {
729 return original_len - len;
730 }
731
732 if (!is_control_frame) {
733 uint8_t valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_PADDED;
734
735 if (current_frame_flags_ & ~valid_data_flags) {
736 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
737 } else {
738 visitor_->OnDataFrameHeader(current_frame_stream_id_,
739 remaining_data_length_,
740 current_frame_flags_ & DATA_FLAG_FIN);
741 if (remaining_data_length_ > 0) {
742 CHANGE_STATE(SPDY_READ_DATA_FRAME_PADDING_LENGTH);
743 } else {
744 // Empty data frame.
745 if (current_frame_flags_ & DATA_FLAG_FIN) {
746 visitor_->OnStreamEnd(current_frame_stream_id_);
747 }
748 CHANGE_STATE(SPDY_FRAME_COMPLETE);
749 }
750 }
751 } else {
752 ProcessControlFrameHeader();
753 }
754
755 return original_len - len;
756 }
757
758 void SpdyFramer::ProcessControlFrameHeader() {
759 DCHECK_EQ(SPDY_NO_ERROR, spdy_framer_error_);
760 DCHECK_LE(GetFrameHeaderSize(), current_frame_buffer_.len());
761
762 // Do some sanity checking on the control frame sizes and flags.
763 switch (current_frame_type_) {
764 case SpdyFrameType::RST_STREAM:
765 if (current_frame_length_ != GetRstStreamSize()) {
766 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
767 } else if (current_frame_flags_ != 0) {
768 VLOG(1) << "Undefined frame flags for RST_STREAM frame: " << std::hex
769 << static_cast<int>(current_frame_flags_);
770 current_frame_flags_ = 0;
771 }
772 break;
773 case SpdyFrameType::SETTINGS: {
774 // Make sure that we have an integral number of 8-byte key/value pairs,
775 // Size of each key/value pair in bytes.
776 if (current_frame_length_ < GetSettingsMinimumSize() ||
777 (current_frame_length_ - GetFrameHeaderSize()) %
778 kOneSettingParameterSize !=
779 0) {
780 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
781 << current_frame_length_;
782 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
783 } else if (current_frame_flags_ & SETTINGS_FLAG_ACK &&
784 current_frame_length_ > GetSettingsMinimumSize()) {
785 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
786 } else if (current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
787 VLOG(1) << "Undefined frame flags for SETTINGS frame: " << std::hex
788 << static_cast<int>(current_frame_flags_);
789 current_frame_flags_ &= SETTINGS_FLAG_ACK;
790 }
791 break;
792 }
793 case SpdyFrameType::PING:
794 if (current_frame_length_ != GetPingSize()) {
795 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
796 } else {
797 if (current_frame_flags_ & ~PING_FLAG_ACK) {
798 VLOG(1) << "Undefined frame flags for PING frame: " << std::hex
799 << static_cast<int>(current_frame_flags_);
800 current_frame_flags_ &= PING_FLAG_ACK;
801 }
802 }
803 break;
804 case SpdyFrameType::GOAWAY: {
805 // For HTTP/2, optional opaque data may be appended to the
806 // GOAWAY frame, thus there is only a minimal length restriction.
807 if (current_frame_length_ < GetGoAwayMinimumSize()) {
808 set_error(SPDY_INVALID_CONTROL_FRAME);
809 } else if (current_frame_flags_ != 0) {
810 VLOG(1) << "Undefined frame flags for GOAWAY frame: " << std::hex
811 << static_cast<int>(current_frame_flags_);
812 current_frame_flags_ = 0;
813 }
814 break;
815 }
816 case SpdyFrameType::HEADERS: {
817 size_t min_size = GetHeadersMinimumSize();
818 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
819 min_size += 4;
820 }
821 if (current_frame_length_ < min_size) {
822 // TODO(mlavan): check here for HEADERS with no payload?
823 // (not allowed in HTTP2)
824 set_error(SPDY_INVALID_CONTROL_FRAME);
825 } else if (current_frame_flags_ &
826 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
827 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED)) {
828 VLOG(1) << "Undefined frame flags for HEADERS frame: " << std::hex
829 << static_cast<int>(current_frame_flags_);
830 current_frame_flags_ &=
831 (CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
832 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PADDED);
833 }
834 break;
835 }
836 case SpdyFrameType::WINDOW_UPDATE:
837 if (current_frame_length_ != GetWindowUpdateSize()) {
838 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
839 } else if (current_frame_flags_ != 0) {
840 VLOG(1) << "Undefined frame flags for WINDOW_UPDATE frame: " << std::hex
841 << static_cast<int>(current_frame_flags_);
842 current_frame_flags_ = 0;
843 }
844 break;
845 case SpdyFrameType::PUSH_PROMISE:
846 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
847 set_error(SPDY_INVALID_CONTROL_FRAME);
848 } else if (current_frame_flags_ &
849 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED)) {
850 VLOG(1) << "Undefined frame flags for PUSH_PROMISE frame: " << std::hex
851 << static_cast<int>(current_frame_flags_);
852 current_frame_flags_ &=
853 (PUSH_PROMISE_FLAG_END_PUSH_PROMISE | HEADERS_FLAG_PADDED);
854 }
855 break;
856 case SpdyFrameType::CONTINUATION:
857 if (current_frame_length_ < GetContinuationMinimumSize()) {
858 set_error(SPDY_INVALID_CONTROL_FRAME);
859 } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
860 VLOG(1) << "Undefined frame flags for CONTINUATION frame: " << std::hex
861 << static_cast<int>(current_frame_flags_);
862 current_frame_flags_ &= HEADERS_FLAG_END_HEADERS;
863 }
864 break;
865 case SpdyFrameType::ALTSVC:
866 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
867 set_error(SPDY_INVALID_CONTROL_FRAME);
868 } else if (current_frame_flags_ != 0) {
869 VLOG(1) << "Undefined frame flags for ALTSVC frame: " << std::hex
870 << static_cast<int>(current_frame_flags_);
871 current_frame_flags_ = 0;
872 }
873 break;
874 case SpdyFrameType::PRIORITY:
875 if (current_frame_length_ != GetPrioritySize()) {
876 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE);
877 } else if (current_frame_flags_ != 0) {
878 VLOG(1) << "Undefined frame flags for PRIORITY frame: " << std::hex
879 << static_cast<int>(current_frame_flags_);
880 current_frame_flags_ = 0;
881 }
882 break;
883 case SpdyFrameType::EXTENSION:
884 // No particular requirements on frames handled by the registered
885 // extension.
886 break;
887 default:
888 LOG(WARNING) << "Valid control frame with unhandled type: "
889 << SerializeFrameType(current_frame_type_);
890 // This branch should be unreachable because of the frame type bounds
891 // check above. However, we DLOG(FATAL) here in an effort to painfully
892 // club the head of the developer who failed to keep this file in sync
893 // with spdy_protocol.h.
894 set_error(SPDY_INVALID_CONTROL_FRAME);
895 DLOG(FATAL);
896 break;
897 }
898
899 if (state_ == SPDY_ERROR) {
900 return;
901 }
902
903 if (current_frame_type_ == SpdyFrameType::GOAWAY) {
904 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
905 return;
906 }
907
908 if (current_frame_type_ == SpdyFrameType::ALTSVC) {
909 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
910 return;
911 }
912 // Determine the frame size without variable-length data.
913 int32_t frame_size_without_variable_data;
914 switch (current_frame_type_) {
915 case SpdyFrameType::SETTINGS:
916 frame_size_without_variable_data = GetSettingsMinimumSize();
917 break;
918 case SpdyFrameType::HEADERS:
919 frame_size_without_variable_data = GetHeadersMinimumSize();
920 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
921 frame_size_without_variable_data += kPadLengthFieldSize;
922 }
923 if (current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
924 frame_size_without_variable_data +=
925 kPriorityDependencyPayloadSize + kPriorityWeightPayloadSize;
926 }
927 break;
928 case SpdyFrameType::PUSH_PROMISE:
929 frame_size_without_variable_data = GetPushPromiseMinimumSize();
930 if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
931 frame_size_without_variable_data += kPadLengthFieldSize;
932 }
933 break;
934 case SpdyFrameType::CONTINUATION:
935 frame_size_without_variable_data = GetContinuationMinimumSize();
936 break;
937 case SpdyFrameType::EXTENSION:
938 frame_size_without_variable_data = GetFrameHeaderSize();
939 break;
940 default:
941 frame_size_without_variable_data = -1;
942 break;
943 }
944
945 if ((frame_size_without_variable_data == -1) &&
946 (current_frame_length_ > kControlFrameBufferSize)) {
947 // We should already be in an error state. Double-check.
948 DCHECK_EQ(SPDY_ERROR, state_);
949 if (state_ != SPDY_ERROR) {
950 SPDY_BUG << "Control frame buffer too small for fixed-length frame.";
951 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
952 }
953 return;
954 }
955
956 if (frame_size_without_variable_data > 0) {
957 // We have a control frame with variable-size data. We need to parse the
958 // remainder of the control frame's header before we can parse the payload.
959 // The start of the payload varies with the control frame type.
960 DCHECK_GE(frame_size_without_variable_data,
961 static_cast<int32_t>(current_frame_buffer_.len()));
962 remaining_control_header_ =
963 frame_size_without_variable_data - current_frame_buffer_.len();
964
965 if (current_frame_type_ == SpdyFrameType::SETTINGS) {
966 CHANGE_STATE(SPDY_SETTINGS_FRAME_HEADER);
967 } else if (current_frame_type_ == SpdyFrameType::EXTENSION) {
968 CHANGE_STATE(SPDY_EXTENSION_FRAME_PAYLOAD);
969 } else {
970 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
971 }
972 return;
973 }
974
975 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
976 }
977
978 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
979 size_t max_bytes) {
980 size_t bytes_to_read = std::min(*len, max_bytes);
981 if (bytes_to_read > 0) {
982 current_frame_buffer_.CopyFrom(*data, bytes_to_read);
983 *data += bytes_to_read;
984 *len -= bytes_to_read;
985 }
986 return bytes_to_read;
987 }
988
989 size_t SpdyFramer::GetSerializedLength(
990 const SpdyHeaderBlock* headers) {
991 const size_t num_name_value_pairs_size = sizeof(uint32_t);
992 const size_t length_of_name_size = num_name_value_pairs_size;
993 const size_t length_of_value_size = num_name_value_pairs_size;
994
995 size_t total_length = num_name_value_pairs_size;
996 for (const auto& header : *headers) {
997 // We add space for the length of the name and the length of the value as
998 // well as the length of the name and the length of the value.
999 total_length += length_of_name_size + header.first.size() +
1000 length_of_value_size + header.second.size();
1001 }
1002 return total_length;
1003 }
1004
1005 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1006 size_t len) {
1007 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1008 const size_t original_len = len;
1009
1010 if (remaining_control_header_ > 0) {
1011 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1012 remaining_control_header_);
1013 remaining_control_header_ -= bytes_read;
1014 remaining_data_length_ -= bytes_read;
1015 }
1016
1017 if (remaining_control_header_ == 0) {
1018 SpdyFrameReader reader(current_frame_buffer_.data(),
1019 current_frame_buffer_.len());
1020 reader.Seek(GetFrameHeaderSize()); // Seek past frame header.
1021
1022 switch (current_frame_type_) {
1023 case SpdyFrameType::HEADERS: {
1024 bool successful_read = true;
1025 if (current_frame_stream_id_ == 0) {
1026 set_error(SPDY_INVALID_CONTROL_FRAME);
1027 return original_len - len;
1028 }
1029 if (!(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1030 current_frame_type_ == SpdyFrameType::HEADERS) {
1031 expect_continuation_ = current_frame_stream_id_;
1032 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1033 }
1034 if (current_frame_flags_ & HEADERS_FLAG_PADDED) {
1035 uint8_t pad_payload_len = 0;
1036 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1037 successful_read = reader.ReadUInt8(&pad_payload_len);
1038 DCHECK(successful_read);
1039 remaining_padding_payload_length_ = pad_payload_len;
1040 }
1041 const bool has_priority =
1042 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1043 int weight = 0;
1044 uint32_t parent_stream_id = 0;
1045 bool exclusive = false;
1046 if (has_priority) {
1047 uint32_t stream_dependency;
1048 successful_read = reader.ReadUInt32(&stream_dependency);
1049 DCHECK(successful_read);
1050 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1051 &parent_stream_id);
1052
1053 uint8_t serialized_weight = 0;
1054 successful_read = reader.ReadUInt8(&serialized_weight);
1055 if (successful_read) {
1056 // Per RFC 7540 section 6.3, serialized weight value is actual
1057 // value - 1.
1058 weight = serialized_weight + 1;
1059 }
1060 }
1061 DCHECK(reader.IsDoneReading());
1062 if (debug_visitor_) {
1063 debug_visitor_->OnReceiveCompressedFrame(current_frame_stream_id_,
1064 current_frame_type_,
1065 current_frame_length_);
1066 }
1067 visitor_->OnHeaders(current_frame_stream_id_,
1068 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0,
1069 weight, parent_stream_id, exclusive,
1070 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1071 expect_continuation_ == 0);
1072 }
1073 break;
1074 case SpdyFrameType::PUSH_PROMISE: {
1075 if (current_frame_stream_id_ == 0) {
1076 set_error(SPDY_INVALID_CONTROL_FRAME);
1077 return original_len - len;
1078 }
1079 bool successful_read = true;
1080 if (current_frame_flags_ & PUSH_PROMISE_FLAG_PADDED) {
1081 DCHECK_EQ(remaining_padding_payload_length_, 0u);
1082 uint8_t pad_payload_len = 0;
1083 successful_read = reader.ReadUInt8(&pad_payload_len);
1084 DCHECK(successful_read);
1085 remaining_padding_payload_length_ = pad_payload_len;
1086 }
1087 }
1088 {
1089 SpdyStreamId promised_stream_id = kInvalidStream;
1090 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1091 DCHECK(successful_read);
1092 DCHECK(reader.IsDoneReading());
1093 if (promised_stream_id == 0) {
1094 set_error(SPDY_INVALID_CONTROL_FRAME);
1095 return original_len - len;
1096 }
1097 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1098 expect_continuation_ = current_frame_stream_id_;
1099 }
1100 if (debug_visitor_) {
1101 debug_visitor_->OnReceiveCompressedFrame(
1102 current_frame_stream_id_,
1103 current_frame_type_,
1104 current_frame_length_);
1105 }
1106 visitor_->OnPushPromise(current_frame_stream_id_,
1107 promised_stream_id,
1108 (current_frame_flags_ &
1109 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1110 }
1111 break;
1112 case SpdyFrameType::CONTINUATION: {
1113 // Check to make sure the stream id of the current frame is
1114 // the same as that of the preceding frame.
1115 // If we're at this point we should already know that
1116 // expect_continuation_ != 0, so this doubles as a check
1117 // that current_frame_stream_id != 0.
1118 if (current_frame_stream_id_ != expect_continuation_) {
1119 set_error(SPDY_UNEXPECTED_FRAME);
1120 return original_len - len;
1121 }
1122 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1123 expect_continuation_ = 0;
1124 }
1125 if (debug_visitor_) {
1126 debug_visitor_->OnReceiveCompressedFrame(
1127 current_frame_stream_id_,
1128 current_frame_type_,
1129 current_frame_length_);
1130 }
1131 visitor_->OnContinuation(current_frame_stream_id_,
1132 (current_frame_flags_ &
1133 HEADERS_FLAG_END_HEADERS) != 0);
1134 }
1135 break;
1136 default:
1137 #ifndef NDEBUG
1138 LOG(FATAL) << "Invalid control frame type: " << current_frame_type_;
1139 #else
1140 set_error(SPDY_INVALID_CONTROL_FRAME);
1141 return original_len - len;
1142 #endif
1143 }
1144
1145 if (current_frame_type_ != SpdyFrameType::CONTINUATION) {
1146 header_handler_ = visitor_->OnHeaderFrameStart(current_frame_stream_id_);
1147 if (header_handler_ == nullptr) {
1148 SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr";
1149 set_error(SPDY_INTERNAL_FRAMER_ERROR);
1150 return original_len - len;
1151 }
1152 GetHpackDecoder()->HandleControlFrameHeadersStart(header_handler_);
1153 }
1154 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1155 }
1156 return original_len - len;
1157 }
1158
1159 // Does not buffer the control payload. Instead, either passes directly to the
1160 // visitor or decompresses and then passes directly to the visitor.
1161 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1162 size_t data_len) {
1163 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1164
1165 bool processed_successfully = true;
1166 if (current_frame_type_ != SpdyFrameType::HEADERS &&
1167 current_frame_type_ != SpdyFrameType::PUSH_PROMISE &&
1168 current_frame_type_ != SpdyFrameType::CONTINUATION) {
1169 SPDY_BUG << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1170 }
1171
1172 if (remaining_padding_payload_length_ > remaining_data_length_) {
1173 set_error(SPDY_INVALID_PADDING);
1174 return data_len;
1175 }
1176
1177 size_t process_bytes = std::min(
1178 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1179 if (!GetHpackDecoder()->HandleControlFrameHeadersData(data, process_bytes)) {
1180 // TODO(jgraettinger): Finer-grained HPACK error codes.
1181 set_error(SPDY_DECOMPRESS_FAILURE);
1182 processed_successfully = false;
1183 }
1184 remaining_data_length_ -= process_bytes;
1185
1186 // Handle the case that there is no futher data in this frame.
1187 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1188 processed_successfully) {
1189 if (expect_continuation_ == 0) {
1190 size_t compressed_len = 0;
1191 if (GetHpackDecoder()->HandleControlFrameHeadersComplete(
1192 &compressed_len)) {
1193 visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true);
1194 if (state_ == SPDY_ERROR) {
1195 return data_len;
1196 }
1197 } else {
1198 set_error(SPDY_DECOMPRESS_FAILURE);
1199 processed_successfully = false;
1200 }
1201 }
1202 if (processed_successfully) {
1203 CHANGE_STATE(SPDY_CONSUME_PADDING);
1204 }
1205 }
1206
1207 // Handle error.
1208 if (!processed_successfully) {
1209 return data_len;
1210 }
1211
1212 // Return amount processed.
1213 return process_bytes;
1214 }
1215
1216 size_t SpdyFramer::ProcessSettingsFrameHeader(const char* data, size_t len) {
1217 // TODO(birenroy): Remove this state when removing SPDY3. I think it only
1218 // exists to read the number of settings in the frame for SPDY3. This value
1219 // is never parsed or used.
1220 size_t bytes_read = 0;
1221 if (remaining_control_header_ > 0) {
1222 bytes_read =
1223 UpdateCurrentFrameBuffer(&data, &len, remaining_control_header_);
1224 remaining_control_header_ -= bytes_read;
1225 remaining_data_length_ -= bytes_read;
1226 }
1227 if (remaining_control_header_ == 0) {
1228 if (current_frame_flags_ & SETTINGS_FLAG_ACK) {
1229 visitor_->OnSettingsAck();
1230 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1231 } else {
1232 visitor_->OnSettings(current_frame_flags_ &
1233 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1234 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1235 }
1236 }
1237 return bytes_read;
1238 }
1239
1240 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1241 size_t data_len) {
1242 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1243 DCHECK_EQ(SpdyFrameType::SETTINGS, current_frame_type_);
1244 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1245 size_t processed_bytes = 0;
1246
1247 // Loop over our incoming data.
1248 while (unprocessed_bytes > 0) {
1249 // Process up to one setting at a time.
1250 size_t processing =
1251 std::min(unprocessed_bytes,
1252 kOneSettingParameterSize - settings_scratch_.buffer.len());
1253
1254 // Check if we have a complete setting in our input.
1255 if (processing == kOneSettingParameterSize) {
1256 // Parse the setting directly out of the input without buffering.
1257 if (!ProcessSetting(data + processed_bytes)) {
1258 set_error(SPDY_INVALID_CONTROL_FRAME);
1259 return processed_bytes;
1260 }
1261 } else {
1262 // Continue updating settings_scratch_.setting_buf.
1263 settings_scratch_.buffer.CopyFrom(data + processed_bytes, processing);
1264
1265 // Check if we have a complete setting buffered.
1266 if (settings_scratch_.buffer.len() == kOneSettingParameterSize) {
1267 if (!ProcessSetting(settings_scratch_.buffer.data())) {
1268 set_error(SPDY_INVALID_CONTROL_FRAME);
1269 return processed_bytes;
1270 }
1271 // Rewind settings buffer for our next setting.
1272 settings_scratch_.buffer.Rewind();
1273 }
1274 }
1275
1276 // Iterate.
1277 unprocessed_bytes -= processing;
1278 processed_bytes += processing;
1279 }
1280
1281 // Check if we're done handling this SETTINGS frame.
1282 remaining_data_length_ -= processed_bytes;
1283 if (remaining_data_length_ == 0) {
1284 visitor_->OnSettingsEnd();
1285 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1286 }
1287
1288 return processed_bytes;
1289 }
1290
1291 bool SpdyFramer::ProcessSetting(const char* data) {
1292 // Extract fields.
1293 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1294 uint16_t id_field =
1295 base::NetToHost16(*(reinterpret_cast<const uint16_t*>(data)));
1296 uint32_t value =
1297 base::NetToHost32(*(reinterpret_cast<const uint32_t*>(data + 2)));
1298
1299 // Validate id.
1300 SpdySettingsIds setting_id;
1301 if (!ParseSettingsId(id_field, &setting_id)) {
1302 if (extension_ == nullptr) {
1303 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1304 } else {
1305 extension_->OnSetting(id_field, value);
1306 }
1307 // Ignore unknown settings for extensibility.
1308 return true;
1309 }
1310
1311 // Validation succeeded. Pass on to visitor.
1312 visitor_->OnSetting(setting_id, value);
1313 return true;
1314 }
1315
1316 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1317 size_t original_len = len;
1318 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1319 remaining_data_length_);
1320 remaining_data_length_ -= bytes_read;
1321 if (remaining_data_length_ == 0) {
1322 SpdyFrameReader reader(current_frame_buffer_.data(),
1323 current_frame_buffer_.len());
1324 reader.Seek(GetFrameHeaderSize()); // Skip frame header.
1325
1326 // Use frame-specific handlers.
1327 switch (current_frame_type_) {
1328 case SpdyFrameType::RST_STREAM: {
1329 uint32_t error_code = ERROR_CODE_NO_ERROR;
1330 bool successful_read = reader.ReadUInt32(&error_code);
1331 DCHECK(successful_read);
1332 DCHECK(reader.IsDoneReading());
1333 visitor_->OnRstStream(current_frame_stream_id_,
1334 ParseErrorCode(error_code));
1335 } break;
1336 case SpdyFrameType::PING: {
1337 SpdyPingId id = 0;
1338 bool is_ack = current_frame_flags_ & PING_FLAG_ACK;
1339 bool successful_read = true;
1340 successful_read = reader.ReadUInt64(&id);
1341 DCHECK(successful_read);
1342 DCHECK(reader.IsDoneReading());
1343 visitor_->OnPing(id, is_ack);
1344 } break;
1345 case SpdyFrameType::WINDOW_UPDATE: {
1346 uint32_t delta_window_size = 0;
1347 bool successful_read = true;
1348 successful_read = reader.ReadUInt32(&delta_window_size);
1349 DCHECK(successful_read);
1350 DCHECK(reader.IsDoneReading());
1351 visitor_->OnWindowUpdate(current_frame_stream_id_, delta_window_size);
1352 } break;
1353 case SpdyFrameType::PRIORITY: {
1354 uint32_t stream_dependency;
1355 uint32_t parent_stream_id;
1356 bool exclusive;
1357 uint8_t serialized_weight;
1358 bool successful_read = reader.ReadUInt32(&stream_dependency);
1359 DCHECK(successful_read);
1360 UnpackStreamDependencyValues(stream_dependency, &exclusive,
1361 &parent_stream_id);
1362
1363 successful_read = reader.ReadUInt8(&serialized_weight);
1364 DCHECK(successful_read);
1365 DCHECK(reader.IsDoneReading());
1366 // Per RFC 7540 section 6.3, serialized weight value is
1367 // actual value - 1.
1368 int weight = serialized_weight + 1;
1369 visitor_->OnPriority(current_frame_stream_id_, parent_stream_id, weight,
1370 exclusive);
1371 } break;
1372 case SpdyFrameType::EXTENSION:
1373 if (extension_ == nullptr) {
1374 SPDY_BUG << "Reached EXTENSION frame processing with a null "
1375 << "extension!";
1376 break;
1377 }
1378 extension_->OnFramePayload(current_frame_buffer_.data(),
1379 current_frame_buffer_.len());
1380 break;
1381 default:
1382 // Unreachable.
1383 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1384 }
1385
1386 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1387 }
1388 return original_len - len;
1389 }
1390
1391 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1392 if (len == 0) {
1393 return 0;
1394 }
1395 // Clamp to the actual remaining payload.
1396 if (len > remaining_data_length_) {
1397 len = remaining_data_length_;
1398 }
1399 size_t original_len = len;
1400
1401 // Check if we had already read enough bytes to parse the GOAWAY header.
1402 const size_t header_size = GetGoAwayMinimumSize();
1403 size_t unread_header_bytes = header_size - current_frame_buffer_.len();
1404 bool already_parsed_header = (unread_header_bytes == 0);
1405 if (!already_parsed_header) {
1406 // Buffer the new GOAWAY header bytes we got.
1407 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1408
1409 // Do we have enough to parse the constant size GOAWAY header?
1410 if (current_frame_buffer_.len() == header_size) {
1411 // Parse out the last good stream id.
1412 SpdyFrameReader reader(current_frame_buffer_.data(),
1413 current_frame_buffer_.len());
1414 reader.Seek(GetFrameHeaderSize()); // Seek past frame header.
1415 bool successful_read = reader.ReadUInt31(&current_frame_stream_id_);
1416 DCHECK(successful_read);
1417
1418 // Parse status code.
1419 uint32_t error_code = ERROR_CODE_NO_ERROR;
1420 successful_read = reader.ReadUInt32(&error_code);
1421 DCHECK(successful_read);
1422 // Finished parsing the GOAWAY header, call frame handler.
1423 visitor_->OnGoAway(current_frame_stream_id_, ParseErrorCode(error_code));
1424 }
1425 }
1426
1427 // Handle remaining data as opaque.
1428 bool processed_successfully = true;
1429 if (len > 0) {
1430 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1431 }
1432 remaining_data_length_ -= original_len;
1433 if (!processed_successfully) {
1434 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1435 } else if (remaining_data_length_ == 0) {
1436 // Signal that there is not more opaque data.
1437 visitor_->OnGoAwayFrameData(nullptr, 0);
1438 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1439 }
1440 return original_len;
1441 }
1442
1443 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
1444 if (len == 0) {
1445 return 0;
1446 }
1447
1448 // Clamp to the actual remaining payload.
1449 len = std::min(len, remaining_data_length_);
1450
1451 if (altsvc_scratch_ == nullptr) {
1452 size_t capacity = current_frame_length_ - GetFrameHeaderSize();
1453 altsvc_scratch_.reset(new CharBuffer(capacity));
1454 }
1455 altsvc_scratch_->CopyFrom(data, len);
1456 remaining_data_length_ -= len;
1457 if (remaining_data_length_ > 0) {
1458 return len;
1459 }
1460
1461 SpdyFrameReader reader(altsvc_scratch_->data(), altsvc_scratch_->len());
1462 SpdyStringPiece origin;
1463 bool successful_read = reader.ReadStringPiece16(&origin);
1464 if (!successful_read) {
1465 set_error(SPDY_INVALID_CONTROL_FRAME);
1466 return 0;
1467 }
1468 SpdyStringPiece value(altsvc_scratch_->data() + reader.GetBytesConsumed(),
1469 altsvc_scratch_->len() - reader.GetBytesConsumed());
1470
1471 SpdyAltSvcWireFormat::AlternativeServiceVector altsvc_vector;
1472 bool success =
1473 SpdyAltSvcWireFormat::ParseHeaderFieldValue(value, &altsvc_vector);
1474 if (!success) {
1475 set_error(SPDY_INVALID_CONTROL_FRAME);
1476 return 0;
1477 }
1478
1479 visitor_->OnAltSvc(current_frame_stream_id_, origin, altsvc_vector);
1480 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1481 return len;
1482 }
1483
1484 size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
1485 DCHECK_EQ(SPDY_READ_DATA_FRAME_PADDING_LENGTH, state_);
1486 DCHECK_EQ(0u, remaining_padding_payload_length_);
1487 DCHECK_EQ(SpdyFrameType::DATA, current_frame_type_);
1488
1489 size_t original_len = len;
1490 if (current_frame_flags_ & DATA_FLAG_PADDED) {
1491 if (len != 0) {
1492 if (remaining_data_length_ < kPadLengthFieldSize) {
1493 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
1494 return 0;
1495 }
1496
1497 static_assert(kPadLengthFieldSize == 1,
1498 "Unexpected pad length field size.");
1499 remaining_padding_payload_length_ =
1500 *reinterpret_cast<const uint8_t*>(data);
1501 ++data;
1502 --len;
1503 --remaining_data_length_;
1504 visitor_->OnStreamPadding(current_frame_stream_id_, kPadLengthFieldSize);
1505 } else {
1506 // We don't have the data available for parsing the pad length field. Keep
1507 // waiting.
1508 return 0;
1509 }
1510 }
1511
1512 if (remaining_padding_payload_length_ > remaining_data_length_) {
1513 set_error(SPDY_INVALID_PADDING);
1514 return 0;
1515 }
1516 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
1517 return original_len - len;
1518 }
1519
1520 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
1521 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
1522
1523 size_t original_len = len;
1524 if (remaining_padding_payload_length_ > 0) {
1525 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1526 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
1527 if (current_frame_type_ == SpdyFrameType::DATA && amount_to_discard > 0) {
1528 visitor_->OnStreamPadding(current_frame_stream_id_, amount_to_discard);
1529 }
1530 data += amount_to_discard;
1531 len -= amount_to_discard;
1532 remaining_padding_payload_length_ -= amount_to_discard;
1533 remaining_data_length_ -= amount_to_discard;
1534 }
1535
1536 if (remaining_data_length_ == 0) {
1537 // If the FIN flag is set, or this ends a header block which set FIN,
1538 // inform the visitor of EOF via a 0-length data frame.
1539 if (expect_continuation_ == 0 &&
1540 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
1541 end_stream_when_done_)) {
1542 end_stream_when_done_ = false;
1543 visitor_->OnStreamEnd(current_frame_stream_id_);
1544 }
1545 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1546 }
1547 return original_len - len;
1548 }
1549
1550 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
1551 size_t original_len = len;
1552 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
1553 size_t amount_to_forward = std::min(
1554 remaining_data_length_ - remaining_padding_payload_length_, len);
1555 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1556 // Only inform the visitor if there is data.
1557 if (amount_to_forward) {
1558 visitor_->OnStreamFrameData(current_frame_stream_id_, data,
1559 amount_to_forward);
1560 }
1561 }
1562 data += amount_to_forward;
1563 len -= amount_to_forward;
1564 remaining_data_length_ -= amount_to_forward;
1565 }
1566
1567 if (remaining_data_length_ == remaining_padding_payload_length_) {
1568 CHANGE_STATE(SPDY_CONSUME_PADDING);
1569 }
1570 return original_len - len;
1571 }
1572
1573 size_t SpdyFramer::ProcessExtensionFramePayload(const char* data, size_t len) {
1574 DCHECK_EQ(SPDY_EXTENSION_FRAME_PAYLOAD, state_);
1575 DCHECK(extension_ != nullptr);
1576 size_t original_len = len;
1577 if (remaining_data_length_ > 0) {
1578 size_t amount_to_forward = std::min(remaining_data_length_, len);
1579 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
1580 // Only inform the visitor if there is data.
1581 extension_->OnFramePayload(data, amount_to_forward);
1582 }
1583 remaining_data_length_ -= amount_to_forward;
1584 len -= amount_to_forward;
1585 }
1586
1587 if (remaining_data_length_ == 0) {
1588 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1589 }
1590 return original_len - len;
1591 }
1592
1593 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
1594 size_t len) {
1595 size_t original_len = len;
1596 if (remaining_data_length_ > 0) {
1597 size_t amount_to_ignore = std::min(remaining_data_length_, len);
1598 len -= amount_to_ignore;
1599 remaining_data_length_ -= amount_to_ignore;
1600 }
1601
1602 if (remaining_data_length_ == 0) {
1603 CHANGE_STATE(SPDY_FRAME_COMPLETE);
1604 }
1605 return original_len - len;
1606 }
1607
1608 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
1609 size_t header_length,
1610 SpdyHeaderBlock* block) const {
1611 SpdyFrameReader reader(header_data, header_length);
1612
1613 // Read number of headers.
1614 uint32_t num_headers;
1615 if (!reader.ReadUInt32(&num_headers)) {
1616 DVLOG(1) << "Unable to read number of headers.";
1617 return false;
1618 }
1619
1620 // Read each header.
1621 for (uint32_t index = 0; index < num_headers; ++index) {
1622 SpdyStringPiece temp;
1623
1624 // Read header name.
1625 if (!reader.ReadStringPiece32(&temp)) {
1626 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
1627 << num_headers << ").";
1628 return false;
1629 }
1630 const char* begin = temp.data();
1631 const char* end = begin;
1632 std::advance(end, temp.size());
1633 if (std::any_of(begin, end, isupper)) {
1634 DVLOG(1) << "Malformed header: Header name " << temp
1635 << " contains upper-case characters.";
1636 return false;
1637 }
1638 SpdyString name(temp);
1639
1640 // Read header value.
1641 if (!reader.ReadStringPiece32(&temp)) {
1642 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
1643 << num_headers << ").";
1644 return false;
1645 }
1646 SpdyString value(temp);
1647
1648 // Ensure no duplicates.
1649 if (block->find(name) != block->end()) {
1650 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
1651 << num_headers << ").";
1652 return false;
1653 }
1654
1655 // Store header.
1656 (*block)[name] = value;
1657 }
1658 if (reader.GetBytesConsumed() != header_length) {
1659 SPDY_BUG << "Buffer expected to consist entirely of headers, but only "
1660 << reader.GetBytesConsumed() << " bytes consumed, from "
1661 << header_length;
1662 return false;
1663 }
1664
1665 return true;
1666 }
1667
1668 SpdyFramer::SpdyFrameIterator::SpdyFrameIterator(SpdyFramer* framer)
1669 : framer_(framer),
1670 is_first_frame_(true),
1671 has_next_frame_(true),
1672 debug_total_size_(0) {}
1673
1674 SpdyFramer::SpdyFrameIterator::~SpdyFrameIterator() {}
1675
1676 bool SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
1677 SpdyFrameWithHeaderBlockIR* frame_ir = GetIR();
1678 if (frame_ir == nullptr) {
1679 LOG(WARNING) << "frame_ir doesn't exist.";
1680 return false;
1681 }
1682 if (!has_next_frame_) {
1683 SPDY_BUG << "SpdyFramer::SpdyFrameIterator::NextFrame called without "
1684 << "a next frame.";
1685 return false;
1686 }
1687
1688 size_t size_without_block = is_first_frame_
1689 ? GetFrameSizeSansBlock()
1690 : framer_->GetContinuationMinimumSize();
1691 auto encoding = base::MakeUnique<SpdyString>();
1692 encoder_->Next(kMaxControlFrameSize - size_without_block, encoding.get());
1693 has_next_frame_ = encoder_->HasNext();
1694
1695 if (framer_->debug_visitor_ != nullptr) {
1696 debug_total_size_ += size_without_block;
1697 debug_total_size_ += encoding->size();
1698 if (!has_next_frame_) {
1699 // TODO(birenroy) are these (here and below) still necessary?
1700 // HTTP2 uses HPACK for header compression. However, continue to
1701 // use GetSerializedLength() for an apples-to-apples comparision of
1702 // compression performance between HPACK and SPDY w/ deflate.
1703 size_t debug_payload_len =
1704 framer_->GetSerializedLength(&frame_ir->header_block());
1705 framer_->debug_visitor_->OnSendCompressedFrame(
1706 frame_ir->stream_id(), frame_ir->frame_type(), debug_payload_len,
1707 debug_total_size_);
1708 }
1709 }
1710
1711 if (is_first_frame_) {
1712 is_first_frame_ = false;
1713 frame_ir->set_end_headers(!has_next_frame_);
1714 return SerializeGivenEncoding(*encoding, output);
1715 } else {
1716 SpdyContinuationIR continuation_ir(frame_ir->stream_id());
1717 continuation_ir.set_end_headers(!has_next_frame_);
1718 continuation_ir.take_encoding(std::move(encoding));
1719 return framer_->SerializeContinuation(continuation_ir, output);
1720 }
1721 }
1722
1723 bool SpdyFramer::SpdyFrameIterator::HasNextFrame() const {
1724 return has_next_frame_;
1725 }
1726
1727 SpdyFramer::SpdyHeaderFrameIterator::SpdyHeaderFrameIterator(
1728 SpdyFramer* framer,
1729 std::unique_ptr<SpdyHeadersIR> headers_ir)
1730 : SpdyFrameIterator(framer), headers_ir_(std::move(headers_ir)) {
1731 SetEncoder(headers_ir_.get());
1732 }
1733
1734 SpdyFramer::SpdyHeaderFrameIterator::~SpdyHeaderFrameIterator() {}
1735
1736 SpdyFrameWithHeaderBlockIR* SpdyFramer::SpdyHeaderFrameIterator::GetIR() const {
1737 return headers_ir_.get();
1738 }
1739
1740 size_t SpdyFramer::SpdyHeaderFrameIterator::GetFrameSizeSansBlock() const {
1741 return GetFramer()->GetHeaderFrameSizeSansBlock(*headers_ir_);
1742 }
1743
1744 bool SpdyFramer::SpdyHeaderFrameIterator::SerializeGivenEncoding(
1745 const SpdyString& encoding,
1746 ZeroCopyOutputBuffer* output) const {
1747 return GetFramer()->SerializeHeadersGivenEncoding(*headers_ir_, encoding,
1748 output);
1749 }
1750
1751 SpdyFramer::SpdyPushPromiseFrameIterator::SpdyPushPromiseFrameIterator(
1752 SpdyFramer* framer,
1753 std::unique_ptr<SpdyPushPromiseIR> push_promise_ir)
1754 : SpdyFrameIterator(framer), push_promise_ir_(std::move(push_promise_ir)) {
1755 SetEncoder(push_promise_ir_.get());
1756 }
1757
1758 SpdyFramer::SpdyPushPromiseFrameIterator::~SpdyPushPromiseFrameIterator() {}
1759
1760 SpdyFrameWithHeaderBlockIR* SpdyFramer::SpdyPushPromiseFrameIterator::GetIR()
1761 const {
1762 return push_promise_ir_.get();
1763 }
1764
1765 size_t SpdyFramer::SpdyPushPromiseFrameIterator::GetFrameSizeSansBlock() const {
1766 return GetFramer()->GetPushPromiseFrameSizeSansBlock(*push_promise_ir_);
1767 }
1768
1769 bool SpdyFramer::SpdyPushPromiseFrameIterator::SerializeGivenEncoding(
1770 const SpdyString& encoding,
1771 ZeroCopyOutputBuffer* output) const {
1772 return GetFramer()->SerializePushPromiseGivenEncoding(*push_promise_ir_,
1773 encoding, output);
1774 }
1775
1776 void SpdyFramer::SerializeDataBuilderHelper(const SpdyDataIR& data_ir,
1777 uint8_t* flags,
1778 int* num_padding_fields,
1779 size_t* size_with_padding) const {
1780 if (data_ir.fin()) {
1781 *flags = DATA_FLAG_FIN;
1782 }
1783
1784 if (data_ir.padded()) {
1785 *flags = *flags | DATA_FLAG_PADDED;
1786 ++*num_padding_fields;
1787 }
1788
1789 *size_with_padding = *num_padding_fields + data_ir.data_len() +
1790 data_ir.padding_payload_len() +
1791 GetDataFrameMinimumSize();
1792 }
1793
1794 SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const {
1795 uint8_t flags = DATA_FLAG_NONE;
1796 int num_padding_fields = 0;
1797 size_t size_with_padding = 0;
1798 SerializeDataBuilderHelper(data_ir, &flags, &num_padding_fields,
1799 &size_with_padding);
1800
1801 SpdyFrameBuilder builder(size_with_padding);
1802 builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags, data_ir.stream_id());
1803 if (data_ir.padded()) {
1804 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
1805 }
1806 builder.WriteBytes(data_ir.data(), data_ir.data_len());
1807 if (data_ir.padding_payload_len() > 0) {
1808 SpdyString padding(data_ir.padding_payload_len(), 0);
1809 builder.WriteBytes(padding.data(), padding.length());
1810 }
1811 DCHECK_EQ(size_with_padding, builder.length());
1812 return builder.take();
1813 }
1814
1815 void SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper(
1816 const SpdyDataIR& data_ir,
1817 uint8_t* flags,
1818 size_t* frame_size,
1819 size_t* num_padding_fields) const {
1820 *flags = DATA_FLAG_NONE;
1821 if (data_ir.fin()) {
1822 *flags = DATA_FLAG_FIN;
1823 }
1824
1825 *frame_size = GetDataFrameMinimumSize();
1826 if (data_ir.padded()) {
1827 *flags = *flags | DATA_FLAG_PADDED;
1828 ++(*num_padding_fields);
1829 *frame_size = *frame_size + *num_padding_fields;
1830 }
1831 }
1832
1833 SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
1834 const SpdyDataIR& data_ir) const {
1835 uint8_t flags = DATA_FLAG_NONE;
1836 size_t frame_size = 0;
1837 size_t num_padding_fields = 0;
1838 SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper(
1839 data_ir, &flags, &frame_size, &num_padding_fields);
1840
1841 SpdyFrameBuilder builder(frame_size);
1842 if (!skip_rewritelength_) {
1843 builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags,
1844 data_ir.stream_id());
1845 if (data_ir.padded()) {
1846 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
1847 }
1848 builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() +
1849 data_ir.padding_payload_len());
1850 } else {
1851 builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags,
1852 data_ir.stream_id(),
1853 num_padding_fields + data_ir.data_len() +
1854 data_ir.padding_payload_len());
1855 if (data_ir.padded()) {
1856 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
1857 }
1858 }
1859 DCHECK_EQ(frame_size, builder.length());
1860 return builder.take();
1861 }
1862
1863 SpdySerializedFrame SpdyFramer::SerializeRstStream(
1864 const SpdyRstStreamIR& rst_stream) const {
1865 size_t expected_length = GetRstStreamSize();
1866 SpdyFrameBuilder builder(expected_length);
1867
1868 builder.BeginNewFrame(*this, SpdyFrameType::RST_STREAM, 0,
1869 rst_stream.stream_id());
1870
1871 builder.WriteUInt32(rst_stream.error_code());
1872
1873 DCHECK_EQ(expected_length, builder.length());
1874 return builder.take();
1875 }
1876
1877 void SpdyFramer::SerializeSettingsBuilderHelper(const SpdySettingsIR& settings,
1878 uint8_t* flags,
1879 const SettingsMap* values,
1880 size_t* size) const {
1881 if (settings.is_ack()) {
1882 *flags = *flags | SETTINGS_FLAG_ACK;
1883 }
1884 *size =
1885 GetSettingsMinimumSize() + (values->size() * kOneSettingParameterSize);
1886 }
1887
1888 SpdySerializedFrame SpdyFramer::SerializeSettings(
1889 const SpdySettingsIR& settings) const {
1890 uint8_t flags = 0;
1891 // Size, in bytes, of this SETTINGS frame.
1892 size_t size = 0;
1893 const SettingsMap* values = &(settings.values());
1894 SerializeSettingsBuilderHelper(settings, &flags, values, &size);
1895 SpdyFrameBuilder builder(size);
1896 builder.BeginNewFrame(*this, SpdyFrameType::SETTINGS, flags, 0);
1897
1898 // If this is an ACK, payload should be empty.
1899 if (settings.is_ack()) {
1900 return builder.take();
1901 }
1902
1903 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
1904 for (SettingsMap::const_iterator it = values->begin(); it != values->end();
1905 ++it) {
1906 int setting_id = it->first;
1907 DCHECK_GE(setting_id, 0);
1908 builder.WriteUInt16(static_cast<uint16_t>(setting_id));
1909 builder.WriteUInt32(it->second);
1910 }
1911 DCHECK_EQ(size, builder.length());
1912 return builder.take();
1913 }
1914
1915 SpdySerializedFrame SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
1916 SpdyFrameBuilder builder(GetPingSize());
1917 uint8_t flags = 0;
1918 if (ping.is_ack()) {
1919 flags |= PING_FLAG_ACK;
1920 }
1921 builder.BeginNewFrame(*this, SpdyFrameType::PING, flags, 0);
1922 builder.WriteUInt64(ping.id());
1923 DCHECK_EQ(GetPingSize(), builder.length());
1924 return builder.take();
1925 }
1926
1927 SpdySerializedFrame SpdyFramer::SerializeGoAway(
1928 const SpdyGoAwayIR& goaway) const {
1929 // Compute the output buffer size, take opaque data into account.
1930 size_t expected_length = GetGoAwayMinimumSize();
1931 expected_length += goaway.description().size();
1932 SpdyFrameBuilder builder(expected_length);
1933
1934 // Serialize the GOAWAY frame.
1935 builder.BeginNewFrame(*this, SpdyFrameType::GOAWAY, 0, 0);
1936
1937 // GOAWAY frames specify the last good stream id.
1938 builder.WriteUInt32(goaway.last_good_stream_id());
1939
1940 // GOAWAY frames also specify the error code.
1941 builder.WriteUInt32(goaway.error_code());
1942
1943 // GOAWAY frames may also specify opaque data.
1944 if (!goaway.description().empty()) {
1945 builder.WriteBytes(goaway.description().data(),
1946 goaway.description().size());
1947 }
1948
1949 DCHECK_EQ(expected_length, builder.length());
1950 return builder.take();
1951 }
1952
1953 void SpdyFramer::SerializeHeadersBuilderHelper(const SpdyHeadersIR& headers,
1954 uint8_t* flags,
1955 size_t* size,
1956 SpdyString* hpack_encoding,
1957 int* weight,
1958 size_t* length_field) {
1959 if (headers.fin()) {
1960 *flags = *flags | CONTROL_FLAG_FIN;
1961 }
1962 // This will get overwritten if we overflow into a CONTINUATION frame.
1963 *flags = *flags | HEADERS_FLAG_END_HEADERS;
1964 if (headers.has_priority()) {
1965 *flags = *flags | HEADERS_FLAG_PRIORITY;
1966 }
1967 if (headers.padded()) {
1968 *flags = *flags | HEADERS_FLAG_PADDED;
1969 }
1970
1971 *size = GetHeadersMinimumSize();
1972
1973 if (headers.padded()) {
1974 *size = *size + kPadLengthFieldSize;
1975 *size = *size + headers.padding_payload_len();
1976 }
1977
1978 if (headers.has_priority()) {
1979 *weight = ClampHttp2Weight(headers.weight());
1980 *size = *size + 5;
1981 }
1982
1983 GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), hpack_encoding);
1984 *size = *size + hpack_encoding->size();
1985 if (*size > kMaxControlFrameSize) {
1986 *size = *size + GetNumberRequiredContinuationFrames(*size) *
1987 GetContinuationMinimumSize();
1988 *flags = *flags & ~HEADERS_FLAG_END_HEADERS;
1989 }
1990 // Compute frame length field.
1991 if (headers.padded()) {
1992 *length_field = *length_field + 1; // Padding length field.
1993 }
1994 if (headers.has_priority()) {
1995 *length_field = *length_field + 4; // Dependency field.
1996 *length_field = *length_field + 1; // Weight field.
1997 }
1998 *length_field = *length_field + headers.padding_payload_len();
1999 *length_field = *length_field + hpack_encoding->size();
2000 // If the HEADERS frame with payload would exceed the max frame size, then
2001 // WritePayloadWithContinuation() will serialize CONTINUATION frames as
2002 // necessary.
2003 *length_field =
2004 std::min(*length_field, kMaxControlFrameSize - GetFrameHeaderSize());
2005 }
2006
2007 SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) {
2008 uint8_t flags = 0;
2009 // The size of this frame, including padding (if there is any) and
2010 // variable-length header block.
2011 size_t size = 0;
2012 SpdyString hpack_encoding;
2013 int weight = 0;
2014 size_t length_field = 0;
2015 SerializeHeadersBuilderHelper(headers, &flags, &size, &hpack_encoding,
2016 &weight, &length_field);
2017
2018 SpdyFrameBuilder builder(size);
2019
2020 if (!skip_rewritelength_) {
2021 builder.BeginNewFrame(*this, SpdyFrameType::HEADERS, flags,
2022 headers.stream_id());
2023 } else {
2024 builder.BeginNewFrame(*this, SpdyFrameType::HEADERS, flags,
2025 headers.stream_id(), length_field);
2026 }
2027 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2028
2029 int padding_payload_len = 0;
2030 if (headers.padded()) {
2031 builder.WriteUInt8(headers.padding_payload_len());
2032 padding_payload_len = headers.padding_payload_len();
2033 }
2034 if (headers.has_priority()) {
2035 builder.WriteUInt32(PackStreamDependencyValues(headers.exclusive(),
2036 headers.parent_stream_id()));
2037 // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
2038 builder.WriteUInt8(weight - 1);
2039 }
2040 WritePayloadWithContinuation(&builder, hpack_encoding, headers.stream_id(),
2041 SpdyFrameType::HEADERS, padding_payload_len);
2042
2043 if (debug_visitor_) {
2044 // HTTP2 uses HPACK for header compression. However, continue to
2045 // use GetSerializedLength() for an apples-to-apples comparision of
2046 // compression performance between HPACK and SPDY w/ deflate.
2047 const size_t payload_len = GetSerializedLength(&(headers.header_block()));
2048 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2049 SpdyFrameType::HEADERS, payload_len,
2050 builder.length());
2051 }
2052
2053 return builder.take();
2054 }
2055
2056 SpdySerializedFrame SpdyFramer::SerializeWindowUpdate(
2057 const SpdyWindowUpdateIR& window_update) const {
2058 SpdyFrameBuilder builder(GetWindowUpdateSize());
2059 builder.BeginNewFrame(*this, SpdyFrameType::WINDOW_UPDATE, kNoFlags,
2060 window_update.stream_id());
2061 builder.WriteUInt32(window_update.delta());
2062 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2063 return builder.take();
2064 }
2065
2066 void SpdyFramer::SerializePushPromiseBuilderHelper(
2067 const SpdyPushPromiseIR& push_promise,
2068 uint8_t* flags,
2069 SpdyString* hpack_encoding,
2070 size_t* size) {
2071 *flags = 0;
2072 // This will get overwritten if we overflow into a CONTINUATION frame.
2073 *flags = *flags | PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2074 // The size of this frame, including variable-length name-value block.
2075 *size = GetPushPromiseMinimumSize();
2076
2077 if (push_promise.padded()) {
2078 *flags = *flags | PUSH_PROMISE_FLAG_PADDED;
2079 *size = *size + kPadLengthFieldSize;
2080 *size = *size + push_promise.padding_payload_len();
2081 }
2082
2083 GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(),
2084 hpack_encoding);
2085 *size = *size + hpack_encoding->size();
2086 if (*size > kMaxControlFrameSize) {
2087 *size = *size + GetNumberRequiredContinuationFrames(*size) *
2088 GetContinuationMinimumSize();
2089 *flags = *flags & ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2090 }
2091 }
2092
2093 SpdySerializedFrame SpdyFramer::SerializePushPromise(
2094 const SpdyPushPromiseIR& push_promise) {
2095 uint8_t flags = 0;
2096 size_t size = 0;
2097 SpdyString hpack_encoding;
2098 SerializePushPromiseBuilderHelper(push_promise, &flags, &hpack_encoding,
2099 &size);
2100
2101 SpdyFrameBuilder builder(size);
2102 if (!skip_rewritelength_) {
2103 builder.BeginNewFrame(*this, SpdyFrameType::PUSH_PROMISE, flags,
2104 push_promise.stream_id());
2105 } else {
2106 size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize();
2107 builder.BeginNewFrame(*this, SpdyFrameType::PUSH_PROMISE, flags,
2108 push_promise.stream_id(), length);
2109 }
2110 int padding_payload_len = 0;
2111 if (push_promise.padded()) {
2112 builder.WriteUInt8(push_promise.padding_payload_len());
2113 builder.WriteUInt32(push_promise.promised_stream_id());
2114 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2115 builder.length());
2116
2117 padding_payload_len = push_promise.padding_payload_len();
2118 } else {
2119 builder.WriteUInt32(push_promise.promised_stream_id());
2120 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2121 }
2122
2123 WritePayloadWithContinuation(
2124 &builder, hpack_encoding, push_promise.stream_id(),
2125 SpdyFrameType::PUSH_PROMISE, padding_payload_len);
2126
2127 if (debug_visitor_) {
2128 // HTTP2 uses HPACK for header compression. However, continue to
2129 // use GetSerializedLength() for an apples-to-apples comparision of
2130 // compression performance between HPACK and SPDY w/ deflate.
2131 const size_t payload_len =
2132 GetSerializedLength(&(push_promise.header_block()));
2133 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2134 SpdyFrameType::PUSH_PROMISE,
2135 payload_len, builder.length());
2136 }
2137
2138 return builder.take();
2139 }
2140
2141 bool SpdyFramer::SerializeHeadersGivenEncoding(
2142 const SpdyHeadersIR& headers,
2143 const SpdyString& encoding,
2144 ZeroCopyOutputBuffer* output) const {
2145 size_t frame_size = GetHeaderFrameSizeSansBlock(headers) + encoding.size();
2146 SpdyFrameBuilder builder(frame_size, output);
2147 bool ret = builder.BeginNewFrame(
2148 *this, SpdyFrameType::HEADERS, SerializeHeaderFrameFlags(headers),
2149 headers.stream_id(), frame_size - GetFrameHeaderSize());
2150 DCHECK_EQ(GetFrameHeaderSize(), builder.length());
2151
2152 if (ret && headers.padded()) {
2153 ret &= builder.WriteUInt8(headers.padding_payload_len());
2154 }
2155
2156 if (ret && headers.has_priority()) {
2157 int weight = ClampHttp2Weight(headers.weight());
2158 ret &= builder.WriteUInt32(PackStreamDependencyValues(
2159 headers.exclusive(), headers.parent_stream_id()));
2160 // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
2161 ret &= builder.WriteUInt8(weight - 1);
2162 }
2163
2164 if (ret) {
2165 ret &= builder.WriteBytes(encoding.data(), encoding.size());
2166 }
2167
2168 if (ret && headers.padding_payload_len() > 0) {
2169 SpdyString padding(headers.padding_payload_len(), 0);
2170 ret &= builder.WriteBytes(padding.data(), padding.length());
2171 }
2172
2173 if (!ret) {
2174 DLOG(WARNING) << "Failed to build HEADERS. Not enough space in output";
2175 }
2176 return ret;
2177 }
2178
2179 SpdySerializedFrame SpdyFramer::SerializeContinuation(
2180 const SpdyContinuationIR& continuation) const {
2181 const SpdyString& encoding = continuation.encoding();
2182 size_t frame_size = GetContinuationMinimumSize() + encoding.size();
2183 SpdyFrameBuilder builder(frame_size);
2184 uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
2185 builder.BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
2186 continuation.stream_id());
2187 DCHECK_EQ(GetFrameHeaderSize(), builder.length());
2188
2189 builder.WriteBytes(encoding.data(), encoding.size());
2190 return builder.take();
2191 }
2192
2193 void SpdyFramer::SerializeAltSvcBuilderHelper(const SpdyAltSvcIR& altsvc_ir,
2194 SpdyString* value,
2195 size_t* size) const {
2196 *size = GetAltSvcMinimumSize();
2197 *size = *size + altsvc_ir.origin().length();
2198 *value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
2199 altsvc_ir.altsvc_vector());
2200 *size = *size + value->length();
2201 }
2202
2203 SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) {
2204 SpdyString value;
2205 size_t size = 0;
2206 SerializeAltSvcBuilderHelper(altsvc_ir, &value, &size);
2207 SpdyFrameBuilder builder(size);
2208 builder.BeginNewFrame(*this, SpdyFrameType::ALTSVC, kNoFlags,
2209 altsvc_ir.stream_id());
2210
2211 builder.WriteUInt16(altsvc_ir.origin().length());
2212 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length());
2213 builder.WriteBytes(value.data(), value.length());
2214 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2215 return builder.take();
2216 }
2217
2218 SpdySerializedFrame SpdyFramer::SerializePriority(
2219 const SpdyPriorityIR& priority) const {
2220 size_t size = GetPrioritySize();
2221
2222 SpdyFrameBuilder builder(size);
2223 builder.BeginNewFrame(*this, SpdyFrameType::PRIORITY, kNoFlags,
2224 priority.stream_id());
2225
2226 builder.WriteUInt32(PackStreamDependencyValues(priority.exclusive(),
2227 priority.parent_stream_id()));
2228 // Per RFC 7540 section 6.3, serialized weight value is actual value - 1.
2229 builder.WriteUInt8(priority.weight() - 1);
2230 DCHECK_EQ(GetPrioritySize(), builder.length());
2231 return builder.take();
2232 }
2233
2234 namespace {
2235
2236 class FrameSerializationVisitor : public SpdyFrameVisitor {
2237 public:
2238 explicit FrameSerializationVisitor(SpdyFramer* framer)
2239 : framer_(framer), frame_() {}
2240 ~FrameSerializationVisitor() override {}
2241
2242 SpdySerializedFrame ReleaseSerializedFrame() { return std::move(frame_); }
2243
2244 void VisitData(const SpdyDataIR& data) override {
2245 frame_ = framer_->SerializeData(data);
2246 }
2247 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2248 frame_ = framer_->SerializeRstStream(rst_stream);
2249 }
2250 void VisitSettings(const SpdySettingsIR& settings) override {
2251 frame_ = framer_->SerializeSettings(settings);
2252 }
2253 void VisitPing(const SpdyPingIR& ping) override {
2254 frame_ = framer_->SerializePing(ping);
2255 }
2256 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2257 frame_ = framer_->SerializeGoAway(goaway);
2258 }
2259 void VisitHeaders(const SpdyHeadersIR& headers) override {
2260 frame_ = framer_->SerializeHeaders(headers);
2261 }
2262 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2263 frame_ = framer_->SerializeWindowUpdate(window_update);
2264 }
2265 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2266 frame_ = framer_->SerializePushPromise(push_promise);
2267 }
2268 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2269 frame_ = framer_->SerializeContinuation(continuation);
2270 }
2271 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2272 frame_ = framer_->SerializeAltSvc(altsvc);
2273 }
2274 void VisitPriority(const SpdyPriorityIR& priority) override {
2275 frame_ = framer_->SerializePriority(priority);
2276 }
2277
2278 private:
2279 SpdyFramer* framer_;
2280 SpdySerializedFrame frame_;
2281 };
2282
2283 // TODO(diannahu): Use also in frame serialization.
2284 class FlagsSerializationVisitor : public SpdyFrameVisitor {
2285 public:
2286 void VisitData(const SpdyDataIR& data) override {
2287 flags_ = DATA_FLAG_NONE;
2288 if (data.fin()) {
2289 flags_ |= DATA_FLAG_FIN;
2290 }
2291 if (data.padded()) {
2292 flags_ |= DATA_FLAG_PADDED;
2293 }
2294 }
2295
2296 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2297 flags_ = kNoFlags;
2298 }
2299
2300 void VisitSettings(const SpdySettingsIR& settings) override {
2301 flags_ = kNoFlags;
2302 if (settings.is_ack()) {
2303 flags_ |= SETTINGS_FLAG_ACK;
2304 }
2305 }
2306
2307 void VisitPing(const SpdyPingIR& ping) override {
2308 flags_ = kNoFlags;
2309 if (ping.is_ack()) {
2310 flags_ |= PING_FLAG_ACK;
2311 }
2312 }
2313
2314 void VisitGoAway(const SpdyGoAwayIR& goaway) override { flags_ = kNoFlags; }
2315
2316 // TODO(diannahu): The END_HEADERS flag is incorrect for HEADERS that require
2317 // CONTINUATION frames.
2318 void VisitHeaders(const SpdyHeadersIR& headers) override {
2319 flags_ = HEADERS_FLAG_END_HEADERS;
2320 if (headers.fin()) {
2321 flags_ |= CONTROL_FLAG_FIN;
2322 }
2323 if (headers.padded()) {
2324 flags_ |= HEADERS_FLAG_PADDED;
2325 }
2326 if (headers.has_priority()) {
2327 flags_ |= HEADERS_FLAG_PRIORITY;
2328 }
2329 }
2330
2331 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2332 flags_ = kNoFlags;
2333 }
2334
2335 // TODO(diannahu): The END_PUSH_PROMISE flag is incorrect for PUSH_PROMISEs
2336 // that require CONTINUATION frames.
2337 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2338 flags_ = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2339 if (push_promise.padded()) {
2340 flags_ |= PUSH_PROMISE_FLAG_PADDED;
2341 }
2342 }
2343
2344 // TODO(diannahu): The END_HEADERS flag is incorrect for CONTINUATIONs that
2345 // require CONTINUATION frames.
2346 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2347 flags_ = HEADERS_FLAG_END_HEADERS;
2348 }
2349
2350 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override { flags_ = kNoFlags; }
2351
2352 void VisitPriority(const SpdyPriorityIR& priority) override {
2353 flags_ = kNoFlags;
2354 }
2355
2356 uint8_t flags() const { return flags_; }
2357
2358 private:
2359 uint8_t flags_ = kNoFlags;
2360 };
2361
2362 } // namespace
2363
2364 SpdySerializedFrame SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2365 FrameSerializationVisitor visitor(this);
2366 frame.Visit(&visitor);
2367 return visitor.ReleaseSerializedFrame();
2368 }
2369
2370 uint8_t SpdyFramer::GetSerializedFlags(const SpdyFrameIR& frame) {
2371 FlagsSerializationVisitor visitor;
2372 frame.Visit(&visitor);
2373 return visitor.flags();
2374 }
2375
2376 bool SpdyFramer::SerializeData(const SpdyDataIR& data_ir,
2377 ZeroCopyOutputBuffer* output) const {
2378 uint8_t flags = DATA_FLAG_NONE;
2379 int num_padding_fields = 0;
2380 size_t size_with_padding = 0;
2381 SerializeDataBuilderHelper(data_ir, &flags, &num_padding_fields,
2382 &size_with_padding);
2383 SpdyFrameBuilder builder(size_with_padding, output);
2384
2385 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags,
2386 data_ir.stream_id());
2387
2388 if (data_ir.padded()) {
2389 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2390 }
2391
2392 ok = ok && builder.WriteBytes(data_ir.data(), data_ir.data_len());
2393 if (data_ir.padding_payload_len() > 0) {
2394 SpdyString padding;
2395 padding = SpdyString(data_ir.padding_payload_len(), 0);
2396 ok = ok && builder.WriteBytes(padding.data(), padding.length());
2397 }
2398 DCHECK_EQ(size_with_padding, builder.length());
2399 return ok;
2400 }
2401
2402 bool SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2403 const SpdyDataIR& data_ir,
2404 ZeroCopyOutputBuffer* output) const {
2405 uint8_t flags = DATA_FLAG_NONE;
2406 size_t frame_size = 0;
2407 size_t num_padding_fields = 0;
2408 SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper(
2409 data_ir, &flags, &frame_size, &num_padding_fields);
2410
2411 SpdyFrameBuilder builder(frame_size, output);
2412 bool ok = true;
2413 if (!skip_rewritelength_) {
2414 ok = builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags,
2415 data_ir.stream_id());
2416 if (data_ir.padded()) {
2417 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2418 }
2419 ok = ok && builder.OverwriteLength(*this,
2420 num_padding_fields + data_ir.data_len() +
2421 data_ir.padding_payload_len());
2422 } else {
2423 ok = ok && builder.BeginNewFrame(*this, SpdyFrameType::DATA, flags,
2424 data_ir.stream_id(),
2425 num_padding_fields + data_ir.data_len() +
2426 data_ir.padding_payload_len());
2427 if (data_ir.padded()) {
2428 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2429 }
2430 }
2431 DCHECK_EQ(frame_size, builder.length());
2432 return ok;
2433 }
2434
2435 bool SpdyFramer::SerializeRstStream(const SpdyRstStreamIR& rst_stream,
2436 ZeroCopyOutputBuffer* output) const {
2437 size_t expected_length = GetRstStreamSize();
2438 SpdyFrameBuilder builder(expected_length, output);
2439 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::RST_STREAM, 0,
2440 rst_stream.stream_id());
2441 ok = ok && builder.WriteUInt32(rst_stream.error_code());
2442
2443 DCHECK_EQ(expected_length, builder.length());
2444 return ok;
2445 }
2446
2447 bool SpdyFramer::SerializeSettings(const SpdySettingsIR& settings,
2448 ZeroCopyOutputBuffer* output) const {
2449 uint8_t flags = 0;
2450 // Size, in bytes, of this SETTINGS frame.
2451 size_t size = 0;
2452 const SettingsMap* values = &(settings.values());
2453 SerializeSettingsBuilderHelper(settings, &flags, values, &size);
2454 SpdyFrameBuilder builder(size, output);
2455 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::SETTINGS, flags, 0);
2456
2457 // If this is an ACK, payload should be empty.
2458 if (settings.is_ack()) {
2459 return ok;
2460 }
2461
2462 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2463 for (SettingsMap::const_iterator it = values->begin(); it != values->end();
2464 ++it) {
2465 int setting_id = it->first;
2466 DCHECK_GE(setting_id, 0);
2467 ok = ok && builder.WriteUInt16(static_cast<uint16_t>(setting_id)) &&
2468 builder.WriteUInt32(it->second);
2469 }
2470 DCHECK_EQ(size, builder.length());
2471 return ok;
2472 }
2473
2474 bool SpdyFramer::SerializePing(const SpdyPingIR& ping,
2475 ZeroCopyOutputBuffer* output) const {
2476 SpdyFrameBuilder builder(GetPingSize(), output);
2477 uint8_t flags = 0;
2478 if (ping.is_ack()) {
2479 flags |= PING_FLAG_ACK;
2480 }
2481 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::PING, flags, 0);
2482 ok = ok && builder.WriteUInt64(ping.id());
2483 DCHECK_EQ(GetPingSize(), builder.length());
2484 return ok;
2485 }
2486
2487 bool SpdyFramer::SerializeGoAway(const SpdyGoAwayIR& goaway,
2488 ZeroCopyOutputBuffer* output) const {
2489 // Compute the output buffer size, take opaque data into account.
2490 size_t expected_length = GetGoAwayMinimumSize();
2491 expected_length += goaway.description().size();
2492 SpdyFrameBuilder builder(expected_length, output);
2493
2494 // Serialize the GOAWAY frame.
2495 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::GOAWAY, 0, 0);
2496
2497 // GOAWAY frames specify the last good stream id.
2498 ok = ok && builder.WriteUInt32(goaway.last_good_stream_id()) &&
2499 // GOAWAY frames also specify the error status code.
2500 builder.WriteUInt32(goaway.error_code());
2501
2502 // GOAWAY frames may also specify opaque data.
2503 if (!goaway.description().empty()) {
2504 ok = ok && builder.WriteBytes(goaway.description().data(),
2505 goaway.description().size());
2506 }
2507
2508 DCHECK_EQ(expected_length, builder.length());
2509 return ok;
2510 }
2511
2512 bool SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers,
2513 ZeroCopyOutputBuffer* output) {
2514 uint8_t flags = 0;
2515 // The size of this frame, including padding (if there is any) and
2516 // variable-length header block.
2517 size_t size = 0;
2518 SpdyString hpack_encoding;
2519 int weight = 0;
2520 size_t length_field = 0;
2521 SerializeHeadersBuilderHelper(headers, &flags, &size, &hpack_encoding,
2522 &weight, &length_field);
2523
2524 bool ok = true;
2525 SpdyFrameBuilder builder(size, output);
2526 if (!skip_rewritelength_) {
2527 ok = builder.BeginNewFrame(*this, SpdyFrameType::HEADERS, flags,
2528 headers.stream_id());
2529 } else {
2530 ok = ok && builder.BeginNewFrame(*this, SpdyFrameType::HEADERS, flags,
2531 headers.stream_id(), length_field);
2532 }
2533 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2534
2535 int padding_payload_len = 0;
2536 if (headers.padded()) {
2537 ok = ok && builder.WriteUInt8(headers.padding_payload_len());
2538 padding_payload_len = headers.padding_payload_len();
2539 }
2540 if (headers.has_priority()) {
2541 ok = ok &&
2542 builder.WriteUInt32(PackStreamDependencyValues(
2543 headers.exclusive(), headers.parent_stream_id())) &&
2544 // Per RFC 7540 section 6.3, serialized weight value is weight - 1.
2545 builder.WriteUInt8(weight - 1);
2546 }
2547 ok = ok && WritePayloadWithContinuation(
2548 &builder, hpack_encoding, headers.stream_id(),
2549 SpdyFrameType::HEADERS, padding_payload_len);
2550
2551 if (debug_visitor_) {
2552 // HTTP2 uses HPACK for header compression. However, continue to
2553 // use GetSerializedLength() for an apples-to-apples comparision of
2554 // compression performance between HPACK and SPDY w/ deflate.
2555 const size_t payload_len = GetSerializedLength(&(headers.header_block()));
2556 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2557 SpdyFrameType::HEADERS, payload_len,
2558 builder.length());
2559 }
2560
2561 return ok;
2562 }
2563
2564 bool SpdyFramer::SerializeWindowUpdate(const SpdyWindowUpdateIR& window_update,
2565 ZeroCopyOutputBuffer* output) const {
2566 SpdyFrameBuilder builder(GetWindowUpdateSize(), output);
2567 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::WINDOW_UPDATE, kNoFlags,
2568 window_update.stream_id());
2569 ok = ok && builder.WriteUInt32(window_update.delta());
2570 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2571 return ok;
2572 }
2573
2574 bool SpdyFramer::SerializePushPromise(const SpdyPushPromiseIR& push_promise,
2575 ZeroCopyOutputBuffer* output) {
2576 uint8_t flags = 0;
2577 size_t size = 0;
2578 SpdyString hpack_encoding;
2579 SerializePushPromiseBuilderHelper(push_promise, &flags, &hpack_encoding,
2580 &size);
2581
2582 bool ok = true;
2583 SpdyFrameBuilder builder(size, output);
2584 if (!skip_rewritelength_) {
2585 ok = builder.BeginNewFrame(*this, SpdyFrameType::PUSH_PROMISE, flags,
2586 push_promise.stream_id());
2587 } else {
2588 size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize();
2589 ok = builder.BeginNewFrame(*this, SpdyFrameType::PUSH_PROMISE, flags,
2590 push_promise.stream_id(), length);
2591 }
2592
2593 int padding_payload_len = 0;
2594 if (push_promise.padded()) {
2595 ok = ok && builder.WriteUInt8(push_promise.padding_payload_len()) &&
2596 builder.WriteUInt32(push_promise.promised_stream_id());
2597 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize,
2598 builder.length());
2599
2600 padding_payload_len = push_promise.padding_payload_len();
2601 } else {
2602 ok = ok && builder.WriteUInt32(push_promise.promised_stream_id());
2603 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2604 }
2605
2606 ok = ok && WritePayloadWithContinuation(
2607 &builder, hpack_encoding, push_promise.stream_id(),
2608 SpdyFrameType::PUSH_PROMISE, padding_payload_len);
2609
2610 if (debug_visitor_) {
2611 // HTTP2 uses HPACK for header compression. However, continue to
2612 // use GetSerializedLength() for an apples-to-apples comparision of
2613 // compression performance between HPACK and SPDY w/ deflate.
2614 const size_t payload_len =
2615 GetSerializedLength(&(push_promise.header_block()));
2616 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2617 SpdyFrameType::PUSH_PROMISE,
2618 payload_len, builder.length());
2619 }
2620
2621 return ok;
2622 }
2623
2624 bool SpdyFramer::SerializePushPromiseGivenEncoding(
2625 const SpdyPushPromiseIR& push_promise,
2626 const SpdyString& encoding,
2627 ZeroCopyOutputBuffer* output) const {
2628 size_t const frame_size =
2629 GetPushPromiseFrameSizeSansBlock(push_promise) + encoding.size();
2630 SpdyFrameBuilder builder(frame_size, output);
2631 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::PUSH_PROMISE,
2632 SerializePushPromiseFrameFlags(push_promise),
2633 push_promise.stream_id(),
2634 frame_size - GetFrameHeaderSize());
2635
2636 if (push_promise.padded()) {
2637 ok = ok && builder.WriteUInt8(push_promise.padding_payload_len());
2638 }
2639 ok = ok && builder.WriteUInt32(push_promise.promised_stream_id()) &&
2640 builder.WriteBytes(encoding.data(), encoding.size());
2641 if (ok && push_promise.padding_payload_len() > 0) {
2642 SpdyString padding(push_promise.padding_payload_len(), 0);
2643 ok = builder.WriteBytes(padding.data(), padding.length());
2644 }
2645
2646 DLOG_IF(ERROR, !ok) << "Failed to write PUSH_PROMISE encoding, not enough "
2647 << "space in output";
2648 return ok;
2649 }
2650
2651 bool SpdyFramer::SerializeContinuation(const SpdyContinuationIR& continuation,
2652 ZeroCopyOutputBuffer* output) const {
2653 const SpdyString& encoding = continuation.encoding();
2654 size_t frame_size = GetContinuationMinimumSize() + encoding.size();
2655 SpdyFrameBuilder builder(frame_size, output);
2656 uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0;
2657 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
2658 continuation.stream_id(),
2659 frame_size - GetFrameHeaderSize());
2660 DCHECK_EQ(GetFrameHeaderSize(), builder.length());
2661
2662 ok = ok && builder.WriteBytes(encoding.data(), encoding.size());
2663 return ok;
2664 }
2665
2666 bool SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir,
2667 ZeroCopyOutputBuffer* output) {
2668 SpdyString value;
2669 size_t size = 0;
2670 SerializeAltSvcBuilderHelper(altsvc_ir, &value, &size);
2671 SpdyFrameBuilder builder(size, output);
2672 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::ALTSVC, kNoFlags,
2673 altsvc_ir.stream_id()) &&
2674 builder.WriteUInt16(altsvc_ir.origin().length()) &&
2675 builder.WriteBytes(altsvc_ir.origin().data(),
2676 altsvc_ir.origin().length()) &&
2677 builder.WriteBytes(value.data(), value.length());
2678 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2679 return ok;
2680 }
2681
2682 bool SpdyFramer::SerializePriority(const SpdyPriorityIR& priority,
2683 ZeroCopyOutputBuffer* output) const {
2684 size_t size = GetPrioritySize();
2685
2686 SpdyFrameBuilder builder(size, output);
2687 bool ok = builder.BeginNewFrame(*this, SpdyFrameType::PRIORITY, kNoFlags,
2688 priority.stream_id());
2689 ok = ok &&
2690 builder.WriteUInt32(PackStreamDependencyValues(
2691 priority.exclusive(), priority.parent_stream_id())) &&
2692 // Per RFC 7540 section 6.3, serialized weight value is actual value
2693 // - 1.
2694 builder.WriteUInt8(priority.weight() - 1);
2695 DCHECK_EQ(GetPrioritySize(), builder.length());
2696 return ok;
2697 }
2698
2699 namespace {
2700
2701 class FrameSerializationVisitorWithOutput : public SpdyFrameVisitor {
2702 public:
2703 explicit FrameSerializationVisitorWithOutput(SpdyFramer* framer,
2704 ZeroCopyOutputBuffer* output)
2705 : framer_(framer), output_(output), result_(false) {}
2706 ~FrameSerializationVisitorWithOutput() override {}
2707
2708 bool Result() { return result_; }
2709
2710 void VisitData(const SpdyDataIR& data) override {
2711 result_ = framer_->SerializeData(data, output_);
2712 }
2713 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override {
2714 result_ = framer_->SerializeRstStream(rst_stream, output_);
2715 }
2716 void VisitSettings(const SpdySettingsIR& settings) override {
2717 result_ = framer_->SerializeSettings(settings, output_);
2718 }
2719 void VisitPing(const SpdyPingIR& ping) override {
2720 result_ = framer_->SerializePing(ping, output_);
2721 }
2722 void VisitGoAway(const SpdyGoAwayIR& goaway) override {
2723 result_ = framer_->SerializeGoAway(goaway, output_);
2724 }
2725 void VisitHeaders(const SpdyHeadersIR& headers) override {
2726 result_ = framer_->SerializeHeaders(headers, output_);
2727 }
2728 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override {
2729 result_ = framer_->SerializeWindowUpdate(window_update, output_);
2730 }
2731 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override {
2732 result_ = framer_->SerializePushPromise(push_promise, output_);
2733 }
2734 void VisitContinuation(const SpdyContinuationIR& continuation) override {
2735 result_ = framer_->SerializeContinuation(continuation, output_);
2736 }
2737 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override {
2738 result_ = framer_->SerializeAltSvc(altsvc, output_);
2739 }
2740 void VisitPriority(const SpdyPriorityIR& priority) override {
2741 result_ = framer_->SerializePriority(priority, output_);
2742 }
2743
2744 private:
2745 SpdyFramer* framer_;
2746 ZeroCopyOutputBuffer* output_;
2747 bool result_;
2748 };
2749
2750 } // namespace
2751
2752 bool SpdyFramer::SerializeFrame(const SpdyFrameIR& frame,
2753 ZeroCopyOutputBuffer* output) {
2754 FrameSerializationVisitorWithOutput visitor(this, output);
2755 frame.Visit(&visitor);
2756 return visitor.Result();
2757 }
2758
2759 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2760 DCHECK_GT(size, kMaxControlFrameSize);
2761 size_t overflow = size - kMaxControlFrameSize;
2762 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize();
2763 // This is ceiling(overflow/payload_size) using integer arithmetics.
2764 return (overflow - 1) / payload_size + 1;
2765 }
2766
2767 size_t SpdyFramer::GetHeaderFrameSizeSansBlock(
2768 const SpdyHeadersIR& header_ir) const {
2769 size_t min_size = GetFrameHeaderSize();
2770
2771 if (header_ir.padded()) {
2772 min_size += 1;
2773 min_size += header_ir.padding_payload_len();
2774 }
2775
2776 if (header_ir.has_priority()) {
2777 min_size += 5;
2778 }
2779
2780 return min_size;
2781 }
2782
2783 size_t SpdyFramer::GetPushPromiseFrameSizeSansBlock(
2784 const SpdyPushPromiseIR& push_promise_ir) const {
2785 size_t size = GetPushPromiseMinimumSize();
2786
2787 if (push_promise_ir.padded()) {
2788 size += kPadLengthFieldSize + push_promise_ir.padding_payload_len();
2789 }
2790
2791 return size;
2792 }
2793
2794 uint8_t SpdyFramer::SerializeHeaderFrameFlags(
2795 const SpdyHeadersIR& header_ir) const {
2796 uint8_t flags = 0;
2797 if (header_ir.fin()) {
2798 flags |= CONTROL_FLAG_FIN;
2799 }
2800 if (header_ir.end_headers()) {
2801 flags |= HEADERS_FLAG_END_HEADERS;
2802 }
2803 if (header_ir.padded()) {
2804 flags |= HEADERS_FLAG_PADDED;
2805 }
2806 if (header_ir.has_priority()) {
2807 flags |= HEADERS_FLAG_PRIORITY;
2808 }
2809 return flags;
2810 }
2811
2812 uint8_t SpdyFramer::SerializePushPromiseFrameFlags(
2813 const SpdyPushPromiseIR& push_promise_ir) const {
2814 uint8_t flags = 0;
2815
2816 if (push_promise_ir.padded()) {
2817 flags = flags | PUSH_PROMISE_FLAG_PADDED;
2818 }
2819
2820 if (push_promise_ir.end_headers()) {
2821 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2822 }
2823
2824 return flags;
2825 }
2826
2827 bool SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2828 const SpdyString& hpack_encoding,
2829 SpdyStreamId stream_id,
2830 SpdyFrameType type,
2831 int padding_payload_len) {
2832 uint8_t end_flag = 0;
2833 uint8_t flags = 0;
2834 if (type == SpdyFrameType::HEADERS) {
2835 end_flag = HEADERS_FLAG_END_HEADERS;
2836 } else if (type == SpdyFrameType::PUSH_PROMISE) {
2837 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2838 } else {
2839 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2840 << FrameTypeToString(type);
2841 }
2842
2843 // Write all the padding payload and as much of the data payload as
2844 // possible into the initial frame.
2845 size_t bytes_remaining = 0;
2846 bytes_remaining =
2847 hpack_encoding.size() -
2848 std::min(hpack_encoding.size(),
2849 kMaxControlFrameSize - builder->length() - padding_payload_len);
2850 bool ret = builder->WriteBytes(&hpack_encoding[0],
2851 hpack_encoding.size() - bytes_remaining);
2852 if (padding_payload_len > 0) {
2853 SpdyString padding = SpdyString(padding_payload_len, 0);
2854 ret &= builder->WriteBytes(padding.data(), padding.length());
2855 }
2856 if (bytes_remaining > 0 && !skip_rewritelength_) {
2857 ret &= builder->OverwriteLength(
2858 *this, kMaxControlFrameSize - GetFrameHeaderSize());
2859 }
2860
2861 // Tack on CONTINUATION frames for the overflow.
2862 while (bytes_remaining > 0 && ret) {
2863 size_t bytes_to_write = std::min(
2864 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize());
2865 // Write CONTINUATION frame prefix.
2866 if (bytes_remaining == bytes_to_write) {
2867 flags |= end_flag;
2868 }
2869 if (!skip_rewritelength_) {
2870 ret &= builder->BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
2871 stream_id);
2872 } else {
2873 ret &= builder->BeginNewFrame(*this, SpdyFrameType::CONTINUATION, flags,
2874 stream_id, bytes_to_write);
2875 }
2876 // Write payload fragment.
2877 ret &= builder->WriteBytes(
2878 &hpack_encoding[hpack_encoding.size() - bytes_remaining],
2879 bytes_to_write);
2880 bytes_remaining -= bytes_to_write;
2881 }
2882 return ret;
2883 }
2884
2885 HpackEncoder* SpdyFramer::GetHpackEncoder() {
2886 if (hpack_encoder_.get() == nullptr) {
2887 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
2888 if (!compression_enabled()) {
2889 hpack_encoder_->DisableCompression();
2890 }
2891 }
2892 return hpack_encoder_.get();
2893 }
2894
2895 HpackDecoderInterface* SpdyFramer::GetHpackDecoder() {
2896 if (hpack_decoder_.get() == nullptr) {
2897 if (FLAGS_chromium_http2_flag_spdy_use_hpack_decoder3) {
2898 hpack_decoder_.reset(new HpackDecoder3());
2899 } else {
2900 hpack_decoder_.reset(new HpackDecoder());
2901 }
2902 }
2903 return hpack_decoder_.get();
2904 }
2905
2906 void SpdyFramer::SetDecoderHeaderTableDebugVisitor(
2907 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
2908 if (decoder_adapter_ != nullptr) {
2909 decoder_adapter_->SetDecoderHeaderTableDebugVisitor(std::move(visitor));
2910 } else {
2911 GetHpackDecoder()->SetHeaderTableDebugVisitor(std::move(visitor));
2912 }
2913 }
2914
2915 void SpdyFramer::SetEncoderHeaderTableDebugVisitor(
2916 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) {
2917 GetHpackEncoder()->SetHeaderTableDebugVisitor(std::move(visitor));
2918 }
2919
2920 size_t SpdyFramer::EstimateMemoryUsage() const {
2921 return SpdyEstimateMemoryUsage(current_frame_buffer_) +
2922 SpdyEstimateMemoryUsage(settings_scratch_) +
2923 SpdyEstimateMemoryUsage(altsvc_scratch_) +
2924 SpdyEstimateMemoryUsage(hpack_encoder_) +
2925 SpdyEstimateMemoryUsage(hpack_decoder_) +
2926 SpdyEstimateMemoryUsage(decoder_adapter_);
2927 }
2928
2929 void SpdyFramer::UpdateHeaderEncoderTableSize(uint32_t value) {
2930 GetHpackEncoder()->ApplyHeaderTableSizeSetting(value);
2931 }
2932
2933 void SpdyFramer::UpdateHeaderDecoderTableSize(uint32_t value) {
2934 GetHpackDecoder()->ApplyHeaderTableSizeSetting(value);
2935 }
2936
2937 size_t SpdyFramer::header_encoder_table_size() const {
2938 if (hpack_encoder_ == nullptr) {
2939 return kDefaultHeaderTableSizeSetting;
2940 } else {
2941 return hpack_encoder_->CurrentHeaderTableSizeSetting();
2942 }
2943 }
2944
2945 void SpdyFramer::SerializeHeaderBlockWithoutCompression(
2946 SpdyFrameBuilder* builder,
2947 const SpdyHeaderBlock& header_block) const {
2948 // Serialize number of headers.
2949 builder->WriteUInt32(header_block.size());
2950
2951 // Serialize each header.
2952 for (const auto& header : header_block) {
2953 builder->WriteStringPiece32(base::ToLowerASCII(header.first));
2954 builder->WriteStringPiece32(header.second);
2955 }
2956 }
2957
2958 } // namespace net
OLDNEW
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_decoder_adapter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698