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 "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/stats_counters.h"
10 #include "base/third_party/valgrind/memcheck.h"
11 #include "net/spdy/spdy_frame_builder.h"
12 #include "net/spdy/spdy_frame_reader.h"
13 #include "net/spdy/spdy_bitmasks.h"
14 #include "third_party/zlib/zlib.h"
15
16 using base::StringPiece;
17 using std::string;
18 using std::vector;
19
20 namespace net {
21
22 namespace {
23
24 // Compute the id of our dictionary so that we know we're using the
25 // right one when asked for it.
CalculateDictionaryId(const char * dictionary,const size_t dictionary_size)26 uLong CalculateDictionaryId(const char* dictionary,
27 const size_t dictionary_size) {
28 uLong initial_value = adler32(0L, Z_NULL, 0);
29 return adler32(initial_value,
30 reinterpret_cast<const Bytef*>(dictionary),
31 dictionary_size);
32 }
33
34 struct DictionaryIds {
DictionaryIdsnet::__anon1f0272040111::DictionaryIds35 DictionaryIds()
36 : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)),
37 v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize))
38 {}
39 const uLong v2_dictionary_id;
40 const uLong v3_dictionary_id;
41 };
42
43 // Adler ID for the SPDY header compressor dictionaries. Note that they are
44 // initialized lazily to avoid static initializers.
45 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids;
46
47 // Used to indicate no flags in a SPDY flags field.
48 const uint8 kNoFlags = 0;
49
50 // Wire sizes of priority payloads.
51 const size_t kPriorityDependencyPayloadSize = 4;
52 const size_t kPriorityWeightPayloadSize = 1;
53
54 } // namespace
55
56 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
57 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
58 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
59 // calculation details.
60 const size_t SpdyFramer::kControlFrameBufferSize = 18;
61
62 #ifdef DEBUG_SPDY_STATE_CHANGES
63 #define CHANGE_STATE(newstate) \
64 do { \
65 DVLOG(1) << "Changing state from: " \
66 << StateToString(state_) \
67 << " to " << StateToString(newstate) << "\n"; \
68 DCHECK(state_ != SPDY_ERROR); \
69 DCHECK_EQ(previous_state_, state_); \
70 previous_state_ = state_; \
71 state_ = newstate; \
72 } while (false)
73 #else
74 #define CHANGE_STATE(newstate) \
75 do { \
76 DCHECK(state_ != SPDY_ERROR); \
77 DCHECK_EQ(previous_state_, state_); \
78 previous_state_ = state_; \
79 state_ = newstate; \
80 } while (false)
81 #endif
82
FromWireFormat(SpdyMajorVersion version,uint32 wire)83 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(
84 SpdyMajorVersion version, uint32 wire) {
85 if (version < SPDY3) {
86 ConvertFlagsAndIdForSpdy2(&wire);
87 }
88 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
89 }
90
SettingsFlagsAndId(uint8 flags,uint32 id)91 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
92 : flags_(flags), id_(id & 0x00ffffff) {
93 LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id;
94 }
95
GetWireFormat(SpdyMajorVersion version) const96 uint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version)
97 const {
98 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
99 if (version < SPDY3) {
100 ConvertFlagsAndIdForSpdy2(&wire);
101 }
102 return wire;
103 }
104
105 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
106 // This method is used to preserve buggy behavior and works on both
107 // little-endian and big-endian hosts.
108 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
109 // as well as vice versa).
ConvertFlagsAndIdForSpdy2(uint32 * val)110 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
111 uint8* wire_array = reinterpret_cast<uint8*>(val);
112 std::swap(wire_array[0], wire_array[3]);
113 std::swap(wire_array[1], wire_array[2]);
114 }
115
SpdyAltSvcScratch()116 SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
~SpdyAltSvcScratch()117 SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
118
OnGoAwayFrameData(const char * goaway_data,size_t len)119 bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
120 size_t len) {
121 return true;
122 }
123
OnRstStreamFrameData(const char * rst_stream_data,size_t len)124 bool SpdyFramerVisitorInterface::OnRstStreamFrameData(
125 const char* rst_stream_data,
126 size_t len) {
127 return true;
128 }
129
SpdyFramer(SpdyMajorVersion version)130 SpdyFramer::SpdyFramer(SpdyMajorVersion version)
131 : current_frame_buffer_(new char[kControlFrameBufferSize]),
132 enable_compression_(true),
133 visitor_(NULL),
134 debug_visitor_(NULL),
135 display_protocol_("SPDY"),
136 spdy_version_(version),
137 syn_frame_processed_(false),
138 probable_http_response_(false),
139 expect_continuation_(0),
140 end_stream_when_done_(false) {
141 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
142 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
143 Reset();
144 }
145
~SpdyFramer()146 SpdyFramer::~SpdyFramer() {
147 if (header_compressor_.get()) {
148 deflateEnd(header_compressor_.get());
149 }
150 if (header_decompressor_.get()) {
151 inflateEnd(header_decompressor_.get());
152 }
153 }
154
Reset()155 void SpdyFramer::Reset() {
156 state_ = SPDY_RESET;
157 previous_state_ = SPDY_RESET;
158 error_code_ = SPDY_NO_ERROR;
159 remaining_data_length_ = 0;
160 remaining_control_header_ = 0;
161 current_frame_buffer_length_ = 0;
162 current_frame_type_ = DATA;
163 current_frame_flags_ = 0;
164 current_frame_length_ = 0;
165 current_frame_stream_id_ = kInvalidStream;
166 settings_scratch_.Reset();
167 altsvc_scratch_.Reset();
168 remaining_padding_payload_length_ = 0;
169 remaining_padding_length_fields_ = 0;
170 }
171
GetDataFrameMinimumSize() const172 size_t SpdyFramer::GetDataFrameMinimumSize() const {
173 return SpdyConstants::GetDataFrameMinimumSize();
174 }
175
176 // Size, in bytes, of the control frame header.
GetControlFrameHeaderSize() const177 size_t SpdyFramer::GetControlFrameHeaderSize() const {
178 return SpdyConstants::GetControlFrameHeaderSize(protocol_version());
179 }
180
GetSynStreamMinimumSize() const181 size_t SpdyFramer::GetSynStreamMinimumSize() const {
182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length
183 // name-value block.
184 if (protocol_version() <= SPDY3) {
185 // Calculated as:
186 // control frame header + 2 * 4 (stream IDs) + 1 (priority)
187 // + 1 (unused, was credential slot)
188 return GetControlFrameHeaderSize() + 10;
189 } else {
190 return GetControlFrameHeaderSize() +
191 kPriorityDependencyPayloadSize +
192 kPriorityWeightPayloadSize;
193 }
194 }
195
GetSynReplyMinimumSize() const196 size_t SpdyFramer::GetSynReplyMinimumSize() const {
197 // Size, in bytes, of a SYN_REPLY frame not including the variable-length
198 // name-value block.
199 size_t size = GetControlFrameHeaderSize();
200 if (protocol_version() <= SPDY3) {
201 // Calculated as:
202 // control frame header + 4 (stream IDs)
203 size += 4;
204 }
205
206 // In SPDY 2, there were 2 unused bytes before payload.
207 if (protocol_version() < SPDY3) {
208 size += 2;
209 }
210
211 return size;
212 }
213
GetRstStreamMinimumSize() const214 size_t SpdyFramer::GetRstStreamMinimumSize() const {
215 // Size, in bytes, of a RST_STREAM frame.
216 if (protocol_version() <= SPDY3) {
217 // Calculated as:
218 // control frame header + 4 (stream id) + 4 (status code)
219 return GetControlFrameHeaderSize() + 8;
220 } else {
221 // Calculated as:
222 // frame prefix + 4 (status code)
223 return GetControlFrameHeaderSize() + 4;
224 }
225 }
226
GetSettingsMinimumSize() const227 size_t SpdyFramer::GetSettingsMinimumSize() const {
228 // Size, in bytes, of a SETTINGS frame not including the IDs and values
229 // from the variable-length value block. Calculated as:
230 // control frame header + 4 (number of ID/value pairs)
231 if (protocol_version() <= SPDY3) {
232 return GetControlFrameHeaderSize() + 4;
233 } else {
234 return GetControlFrameHeaderSize();
235 }
236 }
237
GetPingSize() const238 size_t SpdyFramer::GetPingSize() const {
239 // Size, in bytes, of this PING frame.
240 if (protocol_version() <= SPDY3) {
241 // Calculated as:
242 // control frame header + 4 (id)
243 return GetControlFrameHeaderSize() + 4;
244 } else {
245 // Calculated as:
246 // control frame header + 8 (id)
247 return GetControlFrameHeaderSize() + 8;
248 }
249 }
250
GetGoAwayMinimumSize() const251 size_t SpdyFramer::GetGoAwayMinimumSize() const {
252 // Size, in bytes, of this GOAWAY frame. Calculated as:
253 // 1. Control frame header size
254 size_t size = GetControlFrameHeaderSize();
255
256 // 2. Last good stream id (4 bytes)
257 size += 4;
258
259 // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes)
260 if (protocol_version() >= SPDY3) {
261 size += 4;
262 }
263
264 return size;
265 }
266
GetHeadersMinimumSize() const267 size_t SpdyFramer::GetHeadersMinimumSize() const {
268 // Size, in bytes, of a HEADERS frame not including the variable-length
269 // name-value block.
270 size_t size = GetControlFrameHeaderSize();
271 if (protocol_version() <= SPDY3) {
272 // Calculated as:
273 // control frame header + 4 (stream IDs)
274 size += 4;
275 }
276
277 // In SPDY 2, there were 2 unused bytes before payload.
278 if (protocol_version() <= SPDY2) {
279 size += 2;
280 }
281
282 return size;
283 }
284
GetWindowUpdateSize() const285 size_t SpdyFramer::GetWindowUpdateSize() const {
286 // Size, in bytes, of a WINDOW_UPDATE frame.
287 if (protocol_version() <= SPDY3) {
288 // Calculated as:
289 // control frame header + 4 (stream id) + 4 (delta)
290 return GetControlFrameHeaderSize() + 8;
291 } else {
292 // Calculated as:
293 // frame prefix + 4 (delta)
294 return GetControlFrameHeaderSize() + 4;
295 }
296 }
297
GetBlockedSize() const298 size_t SpdyFramer::GetBlockedSize() const {
299 DCHECK_LT(SPDY3, protocol_version());
300 // Size, in bytes, of a BLOCKED frame.
301 // The BLOCKED frame has no payload beyond the control frame header.
302 return GetControlFrameHeaderSize();
303 }
304
GetPushPromiseMinimumSize() const305 size_t SpdyFramer::GetPushPromiseMinimumSize() const {
306 DCHECK_LT(SPDY3, protocol_version());
307 // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block.
308 // Calculated as frame prefix + 4 (promised stream id).
309 return GetControlFrameHeaderSize() + 4;
310 }
311
GetContinuationMinimumSize() const312 size_t SpdyFramer::GetContinuationMinimumSize() const {
313 // Size, in bytes, of a CONTINUATION frame not including the variable-length
314 // headers fragments.
315 return GetControlFrameHeaderSize();
316 }
317
GetAltSvcMinimumSize() const318 size_t SpdyFramer::GetAltSvcMinimumSize() const {
319 // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
320 // (optional) Origin fields, all of which can vary in length.
321 // Note that this gives a lower bound on the frame size rather than a true
322 // minimum; the actual frame should always be larger than this.
323 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
324 // + 1 (pid_len) + 1 (host_len).
325 return GetControlFrameHeaderSize() + 9;
326 }
327
GetPrioritySize() const328 size_t SpdyFramer::GetPrioritySize() const {
329 // Size, in bytes, of a PRIORITY frame.
330 return GetControlFrameHeaderSize() +
331 kPriorityDependencyPayloadSize +
332 kPriorityWeightPayloadSize;
333 }
334
GetFrameMinimumSize() const335 size_t SpdyFramer::GetFrameMinimumSize() const {
336 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
337 }
338
GetFrameMaximumSize() const339 size_t SpdyFramer::GetFrameMaximumSize() const {
340 return SpdyConstants::GetFrameMaximumSize(protocol_version());
341 }
342
GetDataFrameMaximumPayload() const343 size_t SpdyFramer::GetDataFrameMaximumPayload() const {
344 return GetFrameMaximumSize() - GetDataFrameMinimumSize();
345 }
346
GetPrefixLength(SpdyFrameType type) const347 size_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const {
348 return SpdyConstants::GetPrefixLength(type, protocol_version());
349 }
350
StateToString(int state)351 const char* SpdyFramer::StateToString(int state) {
352 switch (state) {
353 case SPDY_ERROR:
354 return "ERROR";
355 case SPDY_AUTO_RESET:
356 return "AUTO_RESET";
357 case SPDY_RESET:
358 return "RESET";
359 case SPDY_READING_COMMON_HEADER:
360 return "READING_COMMON_HEADER";
361 case SPDY_CONTROL_FRAME_PAYLOAD:
362 return "CONTROL_FRAME_PAYLOAD";
363 case SPDY_READ_PADDING_LENGTH:
364 return "SPDY_READ_PADDING_LENGTH";
365 case SPDY_CONSUME_PADDING:
366 return "SPDY_CONSUME_PADDING";
367 case SPDY_IGNORE_REMAINING_PAYLOAD:
368 return "IGNORE_REMAINING_PAYLOAD";
369 case SPDY_FORWARD_STREAM_FRAME:
370 return "FORWARD_STREAM_FRAME";
371 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
372 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
373 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
374 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
375 case SPDY_GOAWAY_FRAME_PAYLOAD:
376 return "SPDY_GOAWAY_FRAME_PAYLOAD";
377 case SPDY_RST_STREAM_FRAME_PAYLOAD:
378 return "SPDY_RST_STREAM_FRAME_PAYLOAD";
379 case SPDY_SETTINGS_FRAME_PAYLOAD:
380 return "SPDY_SETTINGS_FRAME_PAYLOAD";
381 case SPDY_ALTSVC_FRAME_PAYLOAD:
382 return "SPDY_ALTSVC_FRAME_PAYLOAD";
383 }
384 return "UNKNOWN_STATE";
385 }
386
set_error(SpdyError error)387 void SpdyFramer::set_error(SpdyError error) {
388 DCHECK(visitor_);
389 error_code_ = error;
390 // These values will usually get reset once we come to the end
391 // of a header block, but if we run into an error that
392 // might not happen, so reset them here.
393 expect_continuation_ = 0;
394 end_stream_when_done_ = false;
395
396 CHANGE_STATE(SPDY_ERROR);
397 visitor_->OnError(this);
398 }
399
ErrorCodeToString(int error_code)400 const char* SpdyFramer::ErrorCodeToString(int error_code) {
401 switch (error_code) {
402 case SPDY_NO_ERROR:
403 return "NO_ERROR";
404 case SPDY_INVALID_CONTROL_FRAME:
405 return "INVALID_CONTROL_FRAME";
406 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
407 return "CONTROL_PAYLOAD_TOO_LARGE";
408 case SPDY_ZLIB_INIT_FAILURE:
409 return "ZLIB_INIT_FAILURE";
410 case SPDY_UNSUPPORTED_VERSION:
411 return "UNSUPPORTED_VERSION";
412 case SPDY_DECOMPRESS_FAILURE:
413 return "DECOMPRESS_FAILURE";
414 case SPDY_COMPRESS_FAILURE:
415 return "COMPRESS_FAILURE";
416 case SPDY_INVALID_DATA_FRAME_FLAGS:
417 return "SPDY_INVALID_DATA_FRAME_FLAGS";
418 case SPDY_INVALID_CONTROL_FRAME_FLAGS:
419 return "SPDY_INVALID_CONTROL_FRAME_FLAGS";
420 case SPDY_UNEXPECTED_FRAME:
421 return "UNEXPECTED_FRAME";
422 }
423 return "UNKNOWN_ERROR";
424 }
425
StatusCodeToString(int status_code)426 const char* SpdyFramer::StatusCodeToString(int status_code) {
427 switch (status_code) {
428 case RST_STREAM_INVALID:
429 return "INVALID";
430 case RST_STREAM_PROTOCOL_ERROR:
431 return "PROTOCOL_ERROR";
432 case RST_STREAM_INVALID_STREAM:
433 return "INVALID_STREAM";
434 case RST_STREAM_REFUSED_STREAM:
435 return "REFUSED_STREAM";
436 case RST_STREAM_UNSUPPORTED_VERSION:
437 return "UNSUPPORTED_VERSION";
438 case RST_STREAM_CANCEL:
439 return "CANCEL";
440 case RST_STREAM_INTERNAL_ERROR:
441 return "INTERNAL_ERROR";
442 case RST_STREAM_FLOW_CONTROL_ERROR:
443 return "FLOW_CONTROL_ERROR";
444 case RST_STREAM_STREAM_IN_USE:
445 return "STREAM_IN_USE";
446 case RST_STREAM_STREAM_ALREADY_CLOSED:
447 return "STREAM_ALREADY_CLOSED";
448 case RST_STREAM_INVALID_CREDENTIALS:
449 return "INVALID_CREDENTIALS";
450 case RST_STREAM_FRAME_TOO_LARGE:
451 return "FRAME_TOO_LARGE";
452 case RST_STREAM_CONNECT_ERROR:
453 return "CONNECT_ERROR";
454 case RST_STREAM_ENHANCE_YOUR_CALM:
455 return "ENHANCE_YOUR_CALM";
456 }
457 return "UNKNOWN_STATUS";
458 }
459
FrameTypeToString(SpdyFrameType type)460 const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
461 switch (type) {
462 case DATA:
463 return "DATA";
464 case SYN_STREAM:
465 return "SYN_STREAM";
466 case SYN_REPLY:
467 return "SYN_REPLY";
468 case RST_STREAM:
469 return "RST_STREAM";
470 case SETTINGS:
471 return "SETTINGS";
472 case NOOP:
473 return "NOOP";
474 case PING:
475 return "PING";
476 case GOAWAY:
477 return "GOAWAY";
478 case HEADERS:
479 return "HEADERS";
480 case WINDOW_UPDATE:
481 return "WINDOW_UPDATE";
482 case CREDENTIAL:
483 return "CREDENTIAL";
484 case BLOCKED:
485 return "BLOCKED";
486 case PUSH_PROMISE:
487 return "PUSH_PROMISE";
488 case CONTINUATION:
489 return "CONTINUATION";
490 case ALTSVC:
491 return "ALTSVC";
492 case PRIORITY:
493 return "PRIORITY";
494 }
495 return "UNKNOWN_CONTROL_TYPE";
496 }
497
ProcessInput(const char * data,size_t len)498 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
499 DCHECK(visitor_);
500 DCHECK(data);
501
502 size_t original_len = len;
503 do {
504 previous_state_ = state_;
505 switch (state_) {
506 case SPDY_ERROR:
507 goto bottom;
508
509 case SPDY_AUTO_RESET:
510 case SPDY_RESET:
511 Reset();
512 if (len > 0) {
513 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
514 }
515 break;
516
517 case SPDY_READING_COMMON_HEADER: {
518 size_t bytes_read = ProcessCommonHeader(data, len);
519 len -= bytes_read;
520 data += bytes_read;
521 break;
522 }
523
524 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
525 // Control frames that contain header blocks
526 // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION)
527 // take a different path through the state machine - they
528 // will go:
529 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
530 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
531 //
532 // SETTINGS frames take a slightly modified route:
533 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
534 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
535 //
536 // All other control frames will use the alternate route directly to
537 // SPDY_CONTROL_FRAME_PAYLOAD
538 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
539 len -= bytes_read;
540 data += bytes_read;
541 break;
542 }
543
544 case SPDY_SETTINGS_FRAME_PAYLOAD: {
545 int bytes_read = ProcessSettingsFramePayload(data, len);
546 len -= bytes_read;
547 data += bytes_read;
548 break;
549 }
550
551 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
552 int bytes_read = ProcessControlFrameHeaderBlock(
553 data, len, protocol_version() > SPDY3);
554 len -= bytes_read;
555 data += bytes_read;
556 break;
557 }
558
559 case SPDY_RST_STREAM_FRAME_PAYLOAD: {
560 size_t bytes_read = ProcessRstStreamFramePayload(data, len);
561 len -= bytes_read;
562 data += bytes_read;
563 break;
564 }
565
566 case SPDY_GOAWAY_FRAME_PAYLOAD: {
567 size_t bytes_read = ProcessGoAwayFramePayload(data, len);
568 len -= bytes_read;
569 data += bytes_read;
570 break;
571 }
572
573 case SPDY_ALTSVC_FRAME_PAYLOAD: {
574 size_t bytes_read = ProcessAltSvcFramePayload(data, len);
575 len -= bytes_read;
576 data += bytes_read;
577 break;
578 }
579
580 case SPDY_CONTROL_FRAME_PAYLOAD: {
581 size_t bytes_read = ProcessControlFramePayload(data, len);
582 len -= bytes_read;
583 data += bytes_read;
584 break;
585 }
586
587 case SPDY_READ_PADDING_LENGTH: {
588 size_t bytes_read = ProcessFramePaddingLength(data, len);
589 len -= bytes_read;
590 data += bytes_read;
591 break;
592 }
593
594 case SPDY_CONSUME_PADDING: {
595 size_t bytes_read = ProcessFramePadding(data, len);
596 len -= bytes_read;
597 data += bytes_read;
598 break;
599 }
600
601 case SPDY_IGNORE_REMAINING_PAYLOAD: {
602 size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len);
603 len -= bytes_read;
604 data += bytes_read;
605 break;
606 }
607
608 case SPDY_FORWARD_STREAM_FRAME: {
609 size_t bytes_read = ProcessDataFramePayload(data, len);
610 len -= bytes_read;
611 data += bytes_read;
612 break;
613 }
614
615 default:
616 LOG(DFATAL) << "Invalid value for " << display_protocol_
617 << " framer state: " << state_;
618 // This ensures that we don't infinite-loop if state_ gets an
619 // invalid value somehow, such as due to a SpdyFramer getting deleted
620 // from a callback it calls.
621 goto bottom;
622 }
623 } while (state_ != previous_state_);
624 bottom:
625 DCHECK(len == 0 || state_ == SPDY_ERROR);
626 if (current_frame_buffer_length_ == 0 &&
627 remaining_data_length_ == 0 &&
628 remaining_control_header_ == 0) {
629 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR)
630 << "State: " << StateToString(state_);
631 }
632
633 return original_len - len;
634 }
635
ProcessCommonHeader(const char * data,size_t len)636 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
637 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
638 // state.
639 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
640
641 size_t original_len = len;
642
643 // Update current frame buffer as needed.
644 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
645 size_t bytes_desired =
646 GetControlFrameHeaderSize() - current_frame_buffer_length_;
647 UpdateCurrentFrameBuffer(&data, &len, bytes_desired);
648 }
649
650 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) {
651 // Not enough information to do anything meaningful.
652 return original_len - len;
653 }
654
655 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader
656 // when processing DATA frames below.
657 scoped_ptr<SpdyFrameReader> reader(
658 new SpdyFrameReader(current_frame_buffer_.get(),
659 current_frame_buffer_length_));
660
661 uint16 version = 0;
662 bool is_control_frame = false;
663
664 uint16 control_frame_type_field = DATA;
665 // ProcessControlFrameHeader() will set current_frame_type_ to the
666 // correct value if this is a valid control frame.
667 current_frame_type_ = DATA;
668 if (protocol_version() <= SPDY3) {
669 bool successful_read = reader->ReadUInt16(&version);
670 DCHECK(successful_read);
671 is_control_frame = (version & kControlFlagMask) != 0;
672 version &= ~kControlFlagMask; // Only valid for control frames.
673 if (is_control_frame) {
674 // We check version before we check validity: version can never be
675 // 'invalid', it can only be unsupported.
676 if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) ||
677 version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) ||
678 SpdyConstants::ParseMajorVersion(version) != protocol_version()) {
679 // Version does not match the version the framer was initialized with.
680 DVLOG(1) << "Unsupported SPDY version "
681 << version
682 << " (expected " << protocol_version() << ")";
683 set_error(SPDY_UNSUPPORTED_VERSION);
684 return 0;
685 } else {
686 // Convert version from wire format to SpdyMajorVersion.
687 version = SpdyConstants::ParseMajorVersion(version);
688 }
689 // We check control_frame_type_field's validity in
690 // ProcessControlFrameHeader().
691 successful_read = reader->ReadUInt16(&control_frame_type_field);
692 } else {
693 reader->Rewind();
694 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
695 }
696 DCHECK(successful_read);
697
698 successful_read = reader->ReadUInt8(¤t_frame_flags_);
699 DCHECK(successful_read);
700
701 uint32 length_field = 0;
702 successful_read = reader->ReadUInt24(&length_field);
703 DCHECK(successful_read);
704 remaining_data_length_ = length_field;
705 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed();
706 } else {
707 version = protocol_version();
708 uint16 length_field = 0;
709 bool successful_read = reader->ReadUInt16(&length_field);
710 DCHECK(successful_read);
711
712 uint8 control_frame_type_field_uint8 = DATA;
713 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8);
714 DCHECK(successful_read);
715 // We check control_frame_type_field's validity in
716 // ProcessControlFrameHeader().
717 control_frame_type_field = control_frame_type_field_uint8;
718 is_control_frame = (control_frame_type_field != DATA);
719
720 if (is_control_frame) {
721 current_frame_length_ = length_field + GetControlFrameHeaderSize();
722 } else {
723 current_frame_length_ = length_field + GetDataFrameMinimumSize();
724 }
725
726 successful_read = reader->ReadUInt8(¤t_frame_flags_);
727 DCHECK(successful_read);
728
729 successful_read = reader->ReadUInt31(¤t_frame_stream_id_);
730 DCHECK(successful_read);
731
732 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed();
733
734 // Before we accept a DATA frame, we need to make sure we're not in the
735 // middle of processing a header block.
736 const bool is_continuation_frame = (control_frame_type_field ==
737 SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION));
738 if ((expect_continuation_ != 0) != is_continuation_frame) {
739 if (expect_continuation_ != 0) {
740 DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION "
741 << "frame, but instead received frame type "
742 << control_frame_type_field;
743 } else {
744 DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame.";
745 }
746 set_error(SPDY_UNEXPECTED_FRAME);
747 return original_len - len;
748 }
749 }
750 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize()
751 : GetDataFrameMinimumSize(),
752 reader->GetBytesConsumed());
753 DCHECK_EQ(current_frame_length_,
754 remaining_data_length_ + reader->GetBytesConsumed());
755
756 // This is just a sanity check for help debugging early frame errors.
757 if (remaining_data_length_ > 1000000u) {
758 // The strncmp for 5 is safe because we only hit this point if we
759 // have kMinCommonHeader (8) bytes
760 if (!syn_frame_processed_ &&
761 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) {
762 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_
763 << " request";
764 probable_http_response_ = true;
765 } else {
766 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
767 << " session is likely corrupt.";
768 }
769 }
770
771 // if we're here, then we have the common header all received.
772 if (!is_control_frame) {
773 if (protocol_version() > SPDY3) {
774 // Catch bogus tests sending oversized DATA frames.
775 DCHECK_GE(GetFrameMaximumSize(), current_frame_length_)
776 << "DATA frame too large for SPDY >= 4.";
777 }
778
779 uint8 valid_data_flags = 0;
780 if (protocol_version() > SPDY3) {
781 valid_data_flags = DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT |
782 DATA_FLAG_PAD_LOW | DATA_FLAG_PAD_HIGH;
783 } else {
784 valid_data_flags = DATA_FLAG_FIN;
785 }
786
787 if (current_frame_flags_ & ~valid_data_flags) {
788 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
789 } else {
790 visitor_->OnDataFrameHeader(current_frame_stream_id_,
791 remaining_data_length_,
792 current_frame_flags_ & DATA_FLAG_FIN);
793 if (remaining_data_length_ > 0) {
794 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
795 } else {
796 // Empty data frame.
797 if (current_frame_flags_ & DATA_FLAG_FIN) {
798 visitor_->OnStreamFrameData(
799 current_frame_stream_id_, NULL, 0, true);
800 }
801 CHANGE_STATE(SPDY_AUTO_RESET);
802 }
803 }
804 } else {
805 ProcessControlFrameHeader(control_frame_type_field);
806 }
807
808 return original_len - len;
809 }
810
ProcessControlFrameHeader(uint16 control_frame_type_field)811 void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
812 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
813 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_);
814
815 // Early detection of deprecated frames that we ignore.
816 if (protocol_version() <= SPDY3) {
817 if (control_frame_type_field == NOOP) {
818 current_frame_type_ = NOOP;
819 DVLOG(1) << "NOOP control frame found. Ignoring.";
820 CHANGE_STATE(SPDY_AUTO_RESET);
821 return;
822 }
823
824 if (control_frame_type_field == CREDENTIAL) {
825 current_frame_type_ = CREDENTIAL;
826 DCHECK_EQ(SPDY3, protocol_version());
827 DVLOG(1) << "CREDENTIAL control frame found. Ignoring.";
828 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
829 return;
830 }
831 }
832
833 if (!SpdyConstants::IsValidFrameType(protocol_version(),
834 control_frame_type_field)) {
835 DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field
836 << " (protocol version: " << protocol_version() << ")";
837 set_error(SPDY_INVALID_CONTROL_FRAME);
838 return;
839 }
840
841 current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(),
842 control_frame_type_field);
843
844 // Do some sanity checking on the control frame sizes and flags.
845 switch (current_frame_type_) {
846 case SYN_STREAM:
847 if (current_frame_length_ < GetSynStreamMinimumSize()) {
848 set_error(SPDY_INVALID_CONTROL_FRAME);
849 } else if (current_frame_flags_ &
850 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) {
851 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
852 }
853 break;
854 case SYN_REPLY:
855 if (current_frame_length_ < GetSynReplyMinimumSize()) {
856 set_error(SPDY_INVALID_CONTROL_FRAME);
857 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) {
858 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
859 }
860 break;
861 case RST_STREAM:
862 // For SPDY versions < 4, the header has a fixed length.
863 // For SPDY version 4 and up, the RST_STREAM frame may include optional
864 // opaque data, so we only have a lower limit on the frame size.
865 if ((current_frame_length_ != GetRstStreamMinimumSize() &&
866 protocol_version() <= SPDY3) ||
867 (current_frame_length_ < GetRstStreamMinimumSize() &&
868 protocol_version() > SPDY3)) {
869 set_error(SPDY_INVALID_CONTROL_FRAME);
870 } else if (current_frame_flags_ != 0) {
871 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
872 }
873 break;
874 case SETTINGS:
875 {
876 // Make sure that we have an integral number of 8-byte key/value pairs,
877 // plus a 4-byte length field in SPDY3 and below.
878 size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0);
879 // Size of each key/value pair in bytes.
880 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
881 if (current_frame_length_ < GetSettingsMinimumSize() ||
882 (current_frame_length_ - GetControlFrameHeaderSize())
883 % setting_size != values_prefix_size) {
884 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
885 << current_frame_length_;
886 set_error(SPDY_INVALID_CONTROL_FRAME);
887 } else if (protocol_version() <= SPDY3 &&
888 current_frame_flags_ &
889 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) {
890 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
891 } else if (protocol_version() > SPDY3 &&
892 current_frame_flags_ & ~SETTINGS_FLAG_ACK) {
893 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
894 } else if (protocol_version() > SPDY3 &&
895 current_frame_flags_ & SETTINGS_FLAG_ACK &&
896 current_frame_length_ > GetSettingsMinimumSize()) {
897 set_error(SPDY_INVALID_CONTROL_FRAME);
898 }
899 break;
900 }
901 case PING:
902 if (current_frame_length_ != GetPingSize()) {
903 set_error(SPDY_INVALID_CONTROL_FRAME);
904 } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) ||
905 (current_frame_flags_ & ~PING_FLAG_ACK)) {
906 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
907 }
908 break;
909 case GOAWAY:
910 {
911 // For SPDY version < 4, there are only mandatory fields and the header
912 // has a fixed length. For SPDY version >= 4, optional opaque data may
913 // be appended to the GOAWAY frame, thus there is only a minimal length
914 // restriction.
915 if ((current_frame_length_ != GetGoAwayMinimumSize() &&
916 protocol_version() <= SPDY3) ||
917 (current_frame_length_ < GetGoAwayMinimumSize() &&
918 protocol_version() > SPDY3)) {
919 set_error(SPDY_INVALID_CONTROL_FRAME);
920 } else if (current_frame_flags_ != 0) {
921 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
922 }
923 break;
924 }
925 case HEADERS:
926 {
927 size_t min_size = GetHeadersMinimumSize();
928 if (protocol_version() > SPDY3 &&
929 (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) {
930 min_size += 4;
931 }
932 if (current_frame_length_ < min_size) {
933 set_error(SPDY_INVALID_CONTROL_FRAME);
934 } else if (protocol_version() <= SPDY3 &&
935 current_frame_flags_ & ~CONTROL_FLAG_FIN) {
936 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
937 } else if (protocol_version() > SPDY3 &&
938 current_frame_flags_ &
939 ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
940 HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
941 HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
942 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
943 }
944 }
945 break;
946 case WINDOW_UPDATE:
947 if (current_frame_length_ != GetWindowUpdateSize()) {
948 set_error(SPDY_INVALID_CONTROL_FRAME);
949 } else if (current_frame_flags_ != 0) {
950 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
951 }
952 break;
953 case BLOCKED:
954 if (current_frame_length_ != GetBlockedSize() ||
955 protocol_version() <= SPDY3) {
956 // TODO(mlavan): BLOCKED frames are no longer part of SPDY4.
957 set_error(SPDY_INVALID_CONTROL_FRAME);
958 } else if (current_frame_flags_ != 0) {
959 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
960 }
961 break;
962 case PUSH_PROMISE:
963 if (current_frame_length_ < GetPushPromiseMinimumSize()) {
964 set_error(SPDY_INVALID_CONTROL_FRAME);
965 } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
966 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
967 } else if (protocol_version() > SPDY3 &&
968 current_frame_flags_ &
969 ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
970 HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
971 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
972 }
973 break;
974 case CONTINUATION:
975 if (current_frame_length_ < GetContinuationMinimumSize() ||
976 protocol_version() <= SPDY3) {
977 set_error(SPDY_INVALID_CONTROL_FRAME);
978 } else if (current_frame_flags_ &
979 ~(HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PAD_LOW |
980 HEADERS_FLAG_PAD_HIGH)) {
981 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
982 }
983 break;
984 case ALTSVC:
985 if (current_frame_length_ <= GetAltSvcMinimumSize()) {
986 set_error(SPDY_INVALID_CONTROL_FRAME);
987 } else if (current_frame_flags_ != 0) {
988 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
989 }
990 break;
991 case PRIORITY:
992 if (current_frame_length_ != GetPrioritySize() ||
993 protocol_version() <= SPDY3) {
994 set_error(SPDY_INVALID_CONTROL_FRAME);
995 } else if (current_frame_flags_ != 0) {
996 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
997 }
998 break;
999 default:
1000 LOG(WARNING) << "Valid " << display_protocol_
1001 << " control frame with unhandled type: "
1002 << current_frame_type_;
1003 // This branch should be unreachable because of the frame type bounds
1004 // check above. However, we DLOG(FATAL) here in an effort to painfully
1005 // club the head of the developer who failed to keep this file in sync
1006 // with spdy_protocol.h.
1007 DLOG(FATAL);
1008 set_error(SPDY_INVALID_CONTROL_FRAME);
1009 break;
1010 }
1011
1012 if (state_ == SPDY_ERROR) {
1013 return;
1014 }
1015
1016 if (current_frame_length_ > GetControlFrameBufferMaxSize()) {
1017 DLOG(WARNING) << "Received control frame with way too big of a payload: "
1018 << current_frame_length_;
1019 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1020 return;
1021 }
1022
1023 if (current_frame_type_ == GOAWAY) {
1024 CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD);
1025 return;
1026 }
1027
1028 if (current_frame_type_ == RST_STREAM) {
1029 CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD);
1030 return;
1031 }
1032
1033 if (current_frame_type_ == ALTSVC) {
1034 CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
1035 return;
1036 }
1037 // Determine the frame size without variable-length data.
1038 int32 frame_size_without_variable_data;
1039 switch (current_frame_type_) {
1040 case SYN_STREAM:
1041 syn_frame_processed_ = true;
1042 frame_size_without_variable_data = GetSynStreamMinimumSize();
1043 break;
1044 case SYN_REPLY:
1045 syn_frame_processed_ = true;
1046 frame_size_without_variable_data = GetSynReplyMinimumSize();
1047 break;
1048 case SETTINGS:
1049 frame_size_without_variable_data = GetSettingsMinimumSize();
1050 break;
1051 case HEADERS:
1052 frame_size_without_variable_data = GetHeadersMinimumSize();
1053 if (protocol_version() > SPDY3 &&
1054 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1055 frame_size_without_variable_data +=
1056 kPriorityDependencyPayloadSize +
1057 kPriorityWeightPayloadSize;
1058 }
1059 break;
1060 case PUSH_PROMISE:
1061 frame_size_without_variable_data = GetPushPromiseMinimumSize();
1062 break;
1063 case CONTINUATION:
1064 frame_size_without_variable_data = GetContinuationMinimumSize();
1065 break;
1066 default:
1067 frame_size_without_variable_data = -1;
1068 break;
1069 }
1070
1071 if ((frame_size_without_variable_data == -1) &&
1072 (current_frame_length_ > kControlFrameBufferSize)) {
1073 // We should already be in an error state. Double-check.
1074 DCHECK_EQ(SPDY_ERROR, state_);
1075 if (state_ != SPDY_ERROR) {
1076 LOG(DFATAL) << display_protocol_
1077 << " control frame buffer too small for fixed-length frame.";
1078 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1079 }
1080 return;
1081 }
1082
1083 if (frame_size_without_variable_data > 0) {
1084 // We have a control frame with a header block. We need to parse the
1085 // remainder of the control frame's header before we can parse the header
1086 // block. The start of the header block varies with the control type.
1087 DCHECK_GE(frame_size_without_variable_data,
1088 static_cast<int32>(current_frame_buffer_length_));
1089 remaining_control_header_ = frame_size_without_variable_data -
1090 current_frame_buffer_length_;
1091
1092 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
1093 return;
1094 }
1095
1096 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
1097 }
1098
UpdateCurrentFrameBuffer(const char ** data,size_t * len,size_t max_bytes)1099 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
1100 size_t max_bytes) {
1101 size_t bytes_to_read = std::min(*len, max_bytes);
1102 if (bytes_to_read > 0) {
1103 DCHECK_GE(kControlFrameBufferSize,
1104 current_frame_buffer_length_ + bytes_to_read);
1105 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_,
1106 *data,
1107 bytes_to_read);
1108 current_frame_buffer_length_ += bytes_to_read;
1109 *data += bytes_to_read;
1110 *len -= bytes_to_read;
1111 }
1112 return bytes_to_read;
1113 }
1114
GetSerializedLength(const SpdyMajorVersion spdy_version,const SpdyHeaderBlock * headers)1115 size_t SpdyFramer::GetSerializedLength(
1116 const SpdyMajorVersion spdy_version,
1117 const SpdyHeaderBlock* headers) {
1118 const size_t num_name_value_pairs_size
1119 = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32);
1120 const size_t length_of_name_size = num_name_value_pairs_size;
1121 const size_t length_of_value_size = num_name_value_pairs_size;
1122
1123 size_t total_length = num_name_value_pairs_size;
1124 for (SpdyHeaderBlock::const_iterator it = headers->begin();
1125 it != headers->end();
1126 ++it) {
1127 // We add space for the length of the name and the length of the value as
1128 // well as the length of the name and the length of the value.
1129 total_length += length_of_name_size + it->first.size() +
1130 length_of_value_size + it->second.size();
1131 }
1132 return total_length;
1133 }
1134
WriteHeaderBlock(SpdyFrameBuilder * frame,const SpdyMajorVersion spdy_version,const SpdyHeaderBlock * headers)1135 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
1136 const SpdyMajorVersion spdy_version,
1137 const SpdyHeaderBlock* headers) {
1138 if (spdy_version < SPDY3) {
1139 frame->WriteUInt16(headers->size()); // Number of headers.
1140 } else {
1141 frame->WriteUInt32(headers->size()); // Number of headers.
1142 }
1143 SpdyHeaderBlock::const_iterator it;
1144 for (it = headers->begin(); it != headers->end(); ++it) {
1145 if (spdy_version < SPDY3) {
1146 frame->WriteString(it->first);
1147 frame->WriteString(it->second);
1148 } else {
1149 frame->WriteStringPiece32(it->first);
1150 frame->WriteStringPiece32(it->second);
1151 }
1152 }
1153 }
1154
1155 // TODO(phajdan.jr): Clean up after we no longer need
1156 // to workaround http://crbug.com/139744.
1157 #if !defined(USE_SYSTEM_ZLIB)
1158
1159 // These constants are used by zlib to differentiate between normal data and
1160 // cookie data. Cookie data is handled specially by zlib when compressing.
1161 enum ZDataClass {
1162 // kZStandardData is compressed normally, save that it will never match
1163 // against any other class of data in the window.
1164 kZStandardData = Z_CLASS_STANDARD,
1165 // kZCookieData is compressed in its own Huffman blocks and only matches in
1166 // its entirety and only against other kZCookieData blocks. Any matches must
1167 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching
1168 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent
1169 // prefix matches.
1170 kZCookieData = Z_CLASS_COOKIE,
1171 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed
1172 // against the window.
1173 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY,
1174 };
1175
1176 // WriteZ writes |data| to the deflate context |out|. WriteZ will flush as
1177 // needed when switching between classes of data.
WriteZ(const base::StringPiece & data,ZDataClass clas,z_stream * out)1178 static void WriteZ(const base::StringPiece& data,
1179 ZDataClass clas,
1180 z_stream* out) {
1181 int rv;
1182
1183 // If we are switching from standard to non-standard data then we need to end
1184 // the current Huffman context to avoid it leaking between them.
1185 if (out->clas == kZStandardData &&
1186 clas != kZStandardData) {
1187 out->avail_in = 0;
1188 rv = deflate(out, Z_PARTIAL_FLUSH);
1189 DCHECK_EQ(Z_OK, rv);
1190 DCHECK_EQ(0u, out->avail_in);
1191 DCHECK_LT(0u, out->avail_out);
1192 }
1193
1194 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data()));
1195 out->avail_in = data.size();
1196 out->clas = clas;
1197 if (clas == kZStandardData) {
1198 rv = deflate(out, Z_NO_FLUSH);
1199 } else {
1200 rv = deflate(out, Z_PARTIAL_FLUSH);
1201 }
1202 if (!data.empty()) {
1203 // If we didn't provide any data then zlib will return Z_BUF_ERROR.
1204 DCHECK_EQ(Z_OK, rv);
1205 }
1206 DCHECK_EQ(0u, out->avail_in);
1207 DCHECK_LT(0u, out->avail_out);
1208 }
1209
1210 // WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|.
WriteLengthZ(size_t n,unsigned length,ZDataClass clas,z_stream * out)1211 static void WriteLengthZ(size_t n,
1212 unsigned length,
1213 ZDataClass clas,
1214 z_stream* out) {
1215 char buf[4];
1216 DCHECK_LE(length, sizeof(buf));
1217 for (unsigned i = 1; i <= length; i++) {
1218 buf[length - i] = n;
1219 n >>= 8;
1220 }
1221 WriteZ(base::StringPiece(buf, length), clas, out);
1222 }
1223
1224 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a
1225 // manner that resists the length of the compressed data from compromising
1226 // cookie data.
WriteHeaderBlockToZ(const SpdyHeaderBlock * headers,z_stream * z) const1227 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers,
1228 z_stream* z) const {
1229 unsigned length_length = 4;
1230 if (spdy_version_ < 3)
1231 length_length = 2;
1232
1233 WriteLengthZ(headers->size(), length_length, kZStandardData, z);
1234
1235 std::map<std::string, std::string>::const_iterator it;
1236 for (it = headers->begin(); it != headers->end(); ++it) {
1237 WriteLengthZ(it->first.size(), length_length, kZStandardData, z);
1238 WriteZ(it->first, kZStandardData, z);
1239
1240 if (it->first == "cookie") {
1241 // We require the cookie values (save for the last) to end with a
1242 // semicolon and (save for the first) to start with a space. This is
1243 // typically the format that we are given them in but we reserialize them
1244 // to be sure.
1245
1246 std::vector<base::StringPiece> cookie_values;
1247 size_t cookie_length = 0;
1248 base::StringPiece cookie_data(it->second);
1249
1250 for (;;) {
1251 while (!cookie_data.empty() &&
1252 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) {
1253 cookie_data.remove_prefix(1);
1254 }
1255 if (cookie_data.empty())
1256 break;
1257
1258 size_t i;
1259 for (i = 0; i < cookie_data.size(); i++) {
1260 if (cookie_data[i] == ';')
1261 break;
1262 }
1263 if (i < cookie_data.size()) {
1264 cookie_values.push_back(cookie_data.substr(0, i));
1265 cookie_length += i + 2 /* semicolon and space */;
1266 cookie_data.remove_prefix(i + 1);
1267 } else {
1268 cookie_values.push_back(cookie_data);
1269 cookie_length += cookie_data.size();
1270 cookie_data.remove_prefix(i);
1271 }
1272 }
1273
1274 WriteLengthZ(cookie_length, length_length, kZStandardData, z);
1275 for (size_t i = 0; i < cookie_values.size(); i++) {
1276 std::string cookie;
1277 // Since zlib will only back-reference complete cookies, a cookie that
1278 // is currently last (and so doesn't have a trailing semicolon) won't
1279 // match if it's later in a non-final position. The same is true of
1280 // the first cookie.
1281 if (i == 0 && cookie_values.size() == 1) {
1282 cookie = cookie_values[i].as_string();
1283 } else if (i == 0) {
1284 cookie = cookie_values[i].as_string() + ";";
1285 } else if (i < cookie_values.size() - 1) {
1286 cookie = " " + cookie_values[i].as_string() + ";";
1287 } else {
1288 cookie = " " + cookie_values[i].as_string();
1289 }
1290 WriteZ(cookie, kZCookieData, z);
1291 }
1292 } else if (it->first == "accept" ||
1293 it->first == "accept-charset" ||
1294 it->first == "accept-encoding" ||
1295 it->first == "accept-language" ||
1296 it->first == "host" ||
1297 it->first == "version" ||
1298 it->first == "method" ||
1299 it->first == "scheme" ||
1300 it->first == ":host" ||
1301 it->first == ":version" ||
1302 it->first == ":method" ||
1303 it->first == ":scheme" ||
1304 it->first == "user-agent") {
1305 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1306 WriteZ(it->second, kZStandardData, z);
1307 } else {
1308 // Non-whitelisted headers are Huffman compressed in their own block, but
1309 // don't match against the window.
1310 WriteLengthZ(it->second.size(), length_length, kZStandardData, z);
1311 WriteZ(it->second, kZHuffmanOnlyData, z);
1312 }
1313 }
1314
1315 z->avail_in = 0;
1316 int rv = deflate(z, Z_SYNC_FLUSH);
1317 DCHECK_EQ(Z_OK, rv);
1318 z->clas = kZStandardData;
1319 }
1320 #endif // !defined(USE_SYSTEM_ZLIB)
1321
ProcessControlFrameBeforeHeaderBlock(const char * data,size_t len)1322 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
1323 size_t len) {
1324 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
1325 const size_t original_len = len;
1326
1327 if (remaining_control_header_ > 0) {
1328 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1329 remaining_control_header_);
1330 remaining_control_header_ -= bytes_read;
1331 remaining_data_length_ -= bytes_read;
1332 }
1333
1334 if (remaining_control_header_ == 0) {
1335 SpdyFrameReader reader(current_frame_buffer_.get(),
1336 current_frame_buffer_length_);
1337 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1338
1339 switch (current_frame_type_) {
1340 case SYN_STREAM:
1341 {
1342 DCHECK_GE(SPDY3, protocol_version());
1343 bool successful_read = true;
1344 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1345 DCHECK(successful_read);
1346 if (current_frame_stream_id_ == 0) {
1347 set_error(SPDY_INVALID_CONTROL_FRAME);
1348 break;
1349 }
1350
1351 SpdyStreamId associated_to_stream_id = kInvalidStream;
1352 successful_read = reader.ReadUInt31(&associated_to_stream_id);
1353 DCHECK(successful_read);
1354
1355 SpdyPriority priority = 0;
1356 successful_read = reader.ReadUInt8(&priority);
1357 DCHECK(successful_read);
1358 if (protocol_version() <= SPDY2) {
1359 priority = priority >> 6;
1360 } else {
1361 priority = priority >> 5;
1362 }
1363
1364 // Seek past unused byte; used to be credential slot in SPDY 3.
1365 reader.Seek(1);
1366
1367 DCHECK(reader.IsDoneReading());
1368 if (debug_visitor_) {
1369 debug_visitor_->OnReceiveCompressedFrame(
1370 current_frame_stream_id_,
1371 current_frame_type_,
1372 current_frame_length_);
1373 }
1374 visitor_->OnSynStream(
1375 current_frame_stream_id_,
1376 associated_to_stream_id,
1377 priority,
1378 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1379 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
1380 }
1381 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
1382 break;
1383 case SETTINGS:
1384 if (protocol_version() > SPDY3 &&
1385 current_frame_flags_ & SETTINGS_FLAG_ACK) {
1386 visitor_->OnSettingsAck();
1387 CHANGE_STATE(SPDY_AUTO_RESET);
1388 } else {
1389 visitor_->OnSettings(current_frame_flags_ &
1390 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS);
1391 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
1392 }
1393 break;
1394 case SYN_REPLY:
1395 case HEADERS:
1396 // SYN_REPLY and HEADERS are the same, save for the visitor call.
1397 {
1398 if (protocol_version() > SPDY3) {
1399 DCHECK_EQ(HEADERS, current_frame_type_);
1400 }
1401 bool successful_read = true;
1402 if (protocol_version() <= SPDY3) {
1403 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1404 DCHECK(successful_read);
1405 }
1406 if (current_frame_stream_id_ == 0) {
1407 set_error(SPDY_INVALID_CONTROL_FRAME);
1408 break;
1409 }
1410 if (protocol_version() <= SPDY2) {
1411 // SPDY 2 had two unused bytes here. Seek past them.
1412 reader.Seek(2);
1413 }
1414 if (protocol_version() > SPDY3 &&
1415 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) &&
1416 current_frame_type_ == HEADERS) {
1417 expect_continuation_ = current_frame_stream_id_;
1418 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN;
1419 }
1420 const bool has_priority =
1421 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0;
1422 uint32 priority = 0;
1423 if (protocol_version() > SPDY3 && has_priority) {
1424 // TODO(jgraettinger): Process dependency rather than ignoring it.
1425 reader.Seek(kPriorityDependencyPayloadSize);
1426 uint8 weight = 0;
1427 successful_read = reader.ReadUInt8(&weight);
1428 if (successful_read) {
1429 priority = MapWeightToPriority(weight);
1430 }
1431 }
1432 DCHECK(reader.IsDoneReading());
1433 if (debug_visitor_) {
1434 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM.
1435 SpdyFrameType reported_type = current_frame_type_;
1436 if (protocol_version() > SPDY3 && has_priority) {
1437 reported_type = SYN_STREAM;
1438 }
1439 debug_visitor_->OnReceiveCompressedFrame(
1440 current_frame_stream_id_,
1441 reported_type,
1442 current_frame_length_);
1443 }
1444 if (current_frame_type_ == SYN_REPLY) {
1445 visitor_->OnSynReply(
1446 current_frame_stream_id_,
1447 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0);
1448 } else if (protocol_version() > SPDY3 &&
1449 current_frame_flags_ & HEADERS_FLAG_PRIORITY) {
1450 // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes
1451 // can be made independent of wire changes.
1452 visitor_->OnSynStream(
1453 current_frame_stream_id_,
1454 0, // associated_to_stream_id
1455 priority,
1456 current_frame_flags_ & CONTROL_FLAG_FIN,
1457 false); // unidirectional
1458 } else {
1459 visitor_->OnHeaders(
1460 current_frame_stream_id_,
1461 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0,
1462 expect_continuation_ == 0);
1463 }
1464 }
1465 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1466 break;
1467 case PUSH_PROMISE:
1468 {
1469 DCHECK_LT(SPDY3, protocol_version());
1470 if (current_frame_stream_id_ == 0) {
1471 set_error(SPDY_INVALID_CONTROL_FRAME);
1472 break;
1473 }
1474 SpdyStreamId promised_stream_id = kInvalidStream;
1475 bool successful_read = reader.ReadUInt31(&promised_stream_id);
1476 DCHECK(successful_read);
1477 DCHECK(reader.IsDoneReading());
1478 if (promised_stream_id == 0) {
1479 set_error(SPDY_INVALID_CONTROL_FRAME);
1480 break;
1481 }
1482 if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) {
1483 expect_continuation_ = current_frame_stream_id_;
1484 }
1485 if (debug_visitor_) {
1486 debug_visitor_->OnReceiveCompressedFrame(
1487 current_frame_stream_id_,
1488 current_frame_type_,
1489 current_frame_length_);
1490 }
1491 visitor_->OnPushPromise(current_frame_stream_id_,
1492 promised_stream_id,
1493 (current_frame_flags_ &
1494 PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
1495 }
1496 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1497 break;
1498 case CONTINUATION:
1499 {
1500 // Check to make sure the stream id of the current frame is
1501 // the same as that of the preceding frame.
1502 // If we're at this point we should already know that
1503 // expect_continuation_ != 0, so this doubles as a check
1504 // that current_frame_stream_id != 0.
1505 if (current_frame_stream_id_ != expect_continuation_) {
1506 set_error(SPDY_INVALID_CONTROL_FRAME);
1507 break;
1508 }
1509 if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) {
1510 expect_continuation_ = 0;
1511 }
1512 if (debug_visitor_) {
1513 debug_visitor_->OnReceiveCompressedFrame(
1514 current_frame_stream_id_,
1515 current_frame_type_,
1516 current_frame_length_);
1517 }
1518 visitor_->OnContinuation(current_frame_stream_id_,
1519 (current_frame_flags_ &
1520 HEADERS_FLAG_END_HEADERS) != 0);
1521 }
1522 CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
1523 break;
1524 default:
1525 DCHECK(false);
1526 }
1527 }
1528 return original_len - len;
1529 }
1530
1531 // Does not buffer the control payload. Instead, either passes directly to the
1532 // visitor or decompresses and then passes directly to the visitor, via
1533 // IncrementallyDeliverControlFrameHeaderData() or
1534 // IncrementallyDecompressControlFrameHeaderData() respectively.
ProcessControlFrameHeaderBlock(const char * data,size_t data_len,bool is_hpack_header_block)1535 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
1536 size_t data_len,
1537 bool is_hpack_header_block) {
1538 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_);
1539
1540 bool processed_successfully = true;
1541 if (current_frame_type_ != SYN_STREAM &&
1542 current_frame_type_ != SYN_REPLY &&
1543 current_frame_type_ != HEADERS &&
1544 current_frame_type_ != PUSH_PROMISE &&
1545 current_frame_type_ != CONTINUATION) {
1546 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
1547 }
1548 size_t process_bytes = std::min(
1549 data_len, remaining_data_length_ - remaining_padding_payload_length_);
1550 if (is_hpack_header_block) {
1551 if (!GetHpackDecoder()->HandleControlFrameHeadersData(
1552 current_frame_stream_id_, data, process_bytes)) {
1553 // TODO(jgraettinger): Finer-grained HPACK error codes.
1554 set_error(SPDY_DECOMPRESS_FAILURE);
1555 processed_successfully = false;
1556 }
1557 } else if (process_bytes > 0) {
1558 if (enable_compression_ && protocol_version() <= SPDY3) {
1559 processed_successfully = IncrementallyDecompressControlFrameHeaderData(
1560 current_frame_stream_id_, data, process_bytes);
1561 } else {
1562 processed_successfully = IncrementallyDeliverControlFrameHeaderData(
1563 current_frame_stream_id_, data, process_bytes);
1564 }
1565 }
1566 remaining_data_length_ -= process_bytes;
1567
1568 // Handle the case that there is no futher data in this frame.
1569 if (remaining_data_length_ == remaining_padding_payload_length_ &&
1570 processed_successfully) {
1571 if (expect_continuation_ == 0) {
1572 if (is_hpack_header_block) {
1573 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
1574 current_frame_stream_id_)) {
1575 set_error(SPDY_DECOMPRESS_FAILURE);
1576 processed_successfully = false;
1577 } else {
1578 // TODO(jgraettinger): To be removed with migration to
1579 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3
1580 // block, delivered via reentrant call to
1581 // ProcessControlFrameHeaderBlock().
1582 DeliverHpackBlockAsSpdy3Block();
1583 return process_bytes;
1584 }
1585 } else {
1586 // The complete header block has been delivered. We send a zero-length
1587 // OnControlFrameHeaderData() to indicate this.
1588 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
1589 }
1590 }
1591 if (processed_successfully) {
1592 CHANGE_STATE(SPDY_CONSUME_PADDING);
1593 }
1594 }
1595
1596 // Handle error.
1597 if (!processed_successfully) {
1598 return data_len;
1599 }
1600
1601 // Return amount processed.
1602 return process_bytes;
1603 }
1604
ProcessSettingsFramePayload(const char * data,size_t data_len)1605 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
1606 size_t data_len) {
1607 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
1608 DCHECK_EQ(SETTINGS, current_frame_type_);
1609 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_);
1610 size_t processed_bytes = 0;
1611
1612 size_t setting_size = protocol_version() <= SPDY3 ? 8 : 5;
1613
1614 // Loop over our incoming data.
1615 while (unprocessed_bytes > 0) {
1616 // Process up to one setting at a time.
1617 size_t processing = std::min(
1618 unprocessed_bytes,
1619 static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len));
1620
1621 // Check if we have a complete setting in our input.
1622 if (processing == setting_size) {
1623 // Parse the setting directly out of the input without buffering.
1624 if (!ProcessSetting(data + processed_bytes)) {
1625 set_error(SPDY_INVALID_CONTROL_FRAME);
1626 return processed_bytes;
1627 }
1628 } else {
1629 // Continue updating settings_scratch_.setting_buf.
1630 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
1631 data + processed_bytes,
1632 processing);
1633 settings_scratch_.setting_buf_len += processing;
1634
1635 // Check if we have a complete setting buffered.
1636 if (settings_scratch_.setting_buf_len == setting_size) {
1637 if (!ProcessSetting(settings_scratch_.setting_buf)) {
1638 set_error(SPDY_INVALID_CONTROL_FRAME);
1639 return processed_bytes;
1640 }
1641 // Reset settings_scratch_.setting_buf for our next setting.
1642 settings_scratch_.setting_buf_len = 0;
1643 }
1644 }
1645
1646 // Iterate.
1647 unprocessed_bytes -= processing;
1648 processed_bytes += processing;
1649 }
1650
1651 // Check if we're done handling this SETTINGS frame.
1652 remaining_data_length_ -= processed_bytes;
1653 if (remaining_data_length_ == 0) {
1654 visitor_->OnSettingsEnd();
1655 CHANGE_STATE(SPDY_AUTO_RESET);
1656 }
1657
1658 return processed_bytes;
1659 }
1660
DeliverHpackBlockAsSpdy3Block()1661 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
1662 DCHECK_LT(SPDY3, protocol_version());
1663 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
1664
1665 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
1666 if (block.empty()) {
1667 // Special-case this to make tests happy.
1668 ProcessControlFrameHeaderBlock(NULL, 0, false);
1669 return;
1670 }
1671 SpdyFrameBuilder builder(
1672 GetSerializedLength(protocol_version(), &block),
1673 SPDY3);
1674
1675 SerializeNameValueBlockWithoutCompression(&builder, block);
1676 scoped_ptr<SpdyFrame> frame(builder.take());
1677
1678 // Preserve padding length, and reset it after the re-entrant call.
1679 size_t remaining_padding = remaining_padding_payload_length_;
1680
1681 remaining_padding_payload_length_ = 0;
1682 remaining_data_length_ = frame->size();
1683
1684 ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
1685
1686 remaining_padding_payload_length_ = remaining_padding;
1687 remaining_data_length_ = remaining_padding;
1688 }
1689
ProcessSetting(const char * data)1690 bool SpdyFramer::ProcessSetting(const char* data) {
1691 int id_field;
1692 SpdySettingsIds id;
1693 uint8 flags = 0;
1694 uint32 value;
1695
1696 // Extract fields.
1697 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
1698 if (protocol_version() <= SPDY3) {
1699 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
1700 SettingsFlagsAndId id_and_flags =
1701 SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire);
1702 id_field = id_and_flags.id();
1703 flags = id_and_flags.flags();
1704 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
1705 } else {
1706 id_field = *(reinterpret_cast<const uint8*>(data));
1707 value = ntohl(*(reinterpret_cast<const uint32*>(data + 1)));
1708 }
1709
1710 // Validate id.
1711 if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) {
1712 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field;
1713 return false;
1714 }
1715 id = SpdyConstants::ParseSettingId(protocol_version(), id_field);
1716
1717 if (protocol_version() <= SPDY3) {
1718 // Detect duplicates.
1719 if (id <= settings_scratch_.last_setting_id) {
1720 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
1721 << " in " << display_protocol_ << " SETTINGS frame "
1722 << "(last setting id was "
1723 << settings_scratch_.last_setting_id << ").";
1724 return false;
1725 }
1726 settings_scratch_.last_setting_id = id;
1727
1728 // Validate flags.
1729 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
1730 if ((flags & ~(kFlagsMask)) != 0) {
1731 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
1732 << flags;
1733 return false;
1734 }
1735 }
1736
1737 // Validation succeeded. Pass on to visitor.
1738 visitor_->OnSetting(id, flags, value);
1739 return true;
1740 }
1741
ProcessControlFramePayload(const char * data,size_t len)1742 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
1743 size_t original_len = len;
1744 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
1745 remaining_data_length_);
1746 remaining_data_length_ -= bytes_read;
1747 if (remaining_data_length_ == 0) {
1748 SpdyFrameReader reader(current_frame_buffer_.get(),
1749 current_frame_buffer_length_);
1750 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header.
1751
1752 // Use frame-specific handlers.
1753 switch (current_frame_type_) {
1754 case PING: {
1755 SpdyPingId id = 0;
1756 bool is_ack = protocol_version() > SPDY3 &&
1757 (current_frame_flags_ & PING_FLAG_ACK);
1758 bool successful_read = true;
1759 if (protocol_version() <= SPDY3) {
1760 uint32 id32 = 0;
1761 successful_read = reader.ReadUInt32(&id32);
1762 id = id32;
1763 } else {
1764 successful_read = reader.ReadUInt64(&id);
1765 }
1766 DCHECK(successful_read);
1767 DCHECK(reader.IsDoneReading());
1768 visitor_->OnPing(id, is_ack);
1769 }
1770 break;
1771 case WINDOW_UPDATE: {
1772 uint32 delta_window_size = 0;
1773 bool successful_read = true;
1774 if (protocol_version() <= SPDY3) {
1775 successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1776 DCHECK(successful_read);
1777 }
1778 successful_read = reader.ReadUInt32(&delta_window_size);
1779 DCHECK(successful_read);
1780 DCHECK(reader.IsDoneReading());
1781 visitor_->OnWindowUpdate(current_frame_stream_id_,
1782 delta_window_size);
1783 }
1784 break;
1785 case BLOCKED: {
1786 DCHECK_LT(SPDY3, protocol_version());
1787 DCHECK(reader.IsDoneReading());
1788 visitor_->OnBlocked(current_frame_stream_id_);
1789 }
1790 break;
1791 case PRIORITY: {
1792 DCHECK_LT(SPDY3, protocol_version());
1793 // TODO(hkhalil): Process PRIORITY frames rather than ignore them.
1794 reader.Seek(5);
1795 DCHECK(reader.IsDoneReading());
1796 }
1797 break;
1798 default:
1799 // Unreachable.
1800 LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
1801 }
1802
1803 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
1804 }
1805 return original_len - len;
1806 }
1807
ProcessGoAwayFramePayload(const char * data,size_t len)1808 size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) {
1809 if (len == 0) {
1810 return 0;
1811 }
1812 // Clamp to the actual remaining payload.
1813 if (len > remaining_data_length_) {
1814 len = remaining_data_length_;
1815 }
1816 size_t original_len = len;
1817
1818 // Check if we had already read enough bytes to parse the GOAWAY header.
1819 const size_t header_size = GetGoAwayMinimumSize();
1820 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1821 bool already_parsed_header = (unread_header_bytes == 0);
1822 if (!already_parsed_header) {
1823 // Buffer the new GOAWAY header bytes we got.
1824 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1825
1826 // Do we have enough to parse the constant size GOAWAY header?
1827 if (current_frame_buffer_length_ == header_size) {
1828 // Parse out the last good stream id.
1829 SpdyFrameReader reader(current_frame_buffer_.get(),
1830 current_frame_buffer_length_);
1831 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1832 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1833 DCHECK(successful_read);
1834
1835 // In SPDYv3 and up, frames also specify a status code - parse it out.
1836 SpdyGoAwayStatus status = GOAWAY_OK;
1837 if (protocol_version() >= SPDY3) {
1838 uint32 status_raw = GOAWAY_OK;
1839 successful_read = reader.ReadUInt32(&status_raw);
1840 DCHECK(successful_read);
1841 if (SpdyConstants::IsValidGoAwayStatus(protocol_version(),
1842 status_raw)) {
1843 status = SpdyConstants::ParseGoAwayStatus(protocol_version(),
1844 status_raw);
1845 } else {
1846 DCHECK(false);
1847 // Throw an error for SPDY4+, keep liberal behavior
1848 // for earlier versions.
1849 if (protocol_version() > SPDY3) {
1850 DLOG(WARNING) << "Invalid GO_AWAY status " << status_raw;
1851 set_error(SPDY_INVALID_CONTROL_FRAME);
1852 return 0;
1853 }
1854 }
1855 }
1856 // Finished parsing the GOAWAY header, call frame handler.
1857 visitor_->OnGoAway(current_frame_stream_id_, status);
1858 }
1859 }
1860
1861 // Handle remaining data as opaque.
1862 bool processed_successfully = true;
1863 if (len > 0) {
1864 processed_successfully = visitor_->OnGoAwayFrameData(data, len);
1865 }
1866 remaining_data_length_ -= original_len;
1867 if (!processed_successfully) {
1868 set_error(SPDY_GOAWAY_FRAME_CORRUPT);
1869 } else if (remaining_data_length_ == 0) {
1870 // Signal that there is not more opaque data.
1871 visitor_->OnGoAwayFrameData(NULL, 0);
1872 CHANGE_STATE(SPDY_AUTO_RESET);
1873 }
1874 return original_len;
1875 }
1876
ProcessRstStreamFramePayload(const char * data,size_t len)1877 size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
1878 if (len == 0) {
1879 return 0;
1880 }
1881 // Clamp to the actual remaining payload.
1882 if (len > remaining_data_length_) {
1883 len = remaining_data_length_;
1884 }
1885 size_t original_len = len;
1886
1887 // Check if we had already read enough bytes to parse the fixed-length portion
1888 // of the RST_STREAM frame.
1889 const size_t header_size = GetRstStreamMinimumSize();
1890 size_t unread_header_bytes = header_size - current_frame_buffer_length_;
1891 bool already_parsed_header = (unread_header_bytes == 0);
1892 if (!already_parsed_header) {
1893 // Buffer the new RST_STREAM header bytes we got.
1894 UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes);
1895
1896 // Do we have enough to parse the constant size RST_STREAM header?
1897 if (current_frame_buffer_length_ == header_size) {
1898 // Parse out the last good stream id.
1899 SpdyFrameReader reader(current_frame_buffer_.get(),
1900 current_frame_buffer_length_);
1901 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1902 if (protocol_version() <= SPDY3) {
1903 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_);
1904 DCHECK(successful_read);
1905 }
1906
1907 SpdyRstStreamStatus status = RST_STREAM_INVALID;
1908 uint32 status_raw = status;
1909 bool successful_read = reader.ReadUInt32(&status_raw);
1910 DCHECK(successful_read);
1911 if (SpdyConstants::IsValidRstStreamStatus(protocol_version(),
1912 status_raw)) {
1913 status = static_cast<SpdyRstStreamStatus>(status_raw);
1914 } else {
1915 // Throw an error for SPDY4+, keep liberal behavior
1916 // for earlier versions.
1917 if (protocol_version() > SPDY3) {
1918 DLOG(WARNING) << "Invalid RST_STREAM status " << status_raw;
1919 set_error(SPDY_INVALID_CONTROL_FRAME);
1920 return 0;
1921 }
1922 }
1923 // Finished parsing the RST_STREAM header, call frame handler.
1924 visitor_->OnRstStream(current_frame_stream_id_, status);
1925 }
1926 }
1927
1928 // Handle remaining data as opaque.
1929 bool processed_successfully = true;
1930 if (len > 0) {
1931 processed_successfully = visitor_->OnRstStreamFrameData(data, len);
1932 }
1933 remaining_data_length_ -= original_len;
1934 if (!processed_successfully) {
1935 set_error(SPDY_RST_STREAM_FRAME_CORRUPT);
1936 } else if (remaining_data_length_ == 0) {
1937 // Signal that there is not more opaque data.
1938 visitor_->OnRstStreamFrameData(NULL, 0);
1939 CHANGE_STATE(SPDY_AUTO_RESET);
1940 }
1941 return original_len;
1942 }
1943
ProcessAltSvcFramePayload(const char * data,size_t len)1944 size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
1945 if (len == 0) {
1946 return 0;
1947 }
1948
1949 // Clamp to the actual remaining payload.
1950 len = std::min(len, remaining_data_length_);
1951
1952 size_t processed_bytes = 0;
1953 size_t processing = 0;
1954 size_t bytes_remaining;
1955 char* buffer;
1956 size_t* buffer_len;
1957
1958 while (len > 0) {
1959 if (altsvc_scratch_.pid_len == 0) {
1960 // The size of the frame up to the PID_LEN field.
1961 size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
1962 bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
1963 processing = std::min(len, bytes_remaining);
1964 // Buffer the new ALTSVC bytes we got.
1965 UpdateCurrentFrameBuffer(&data, &len, processing);
1966
1967 // Do we have enough to parse the length of the protocol id?
1968 if (current_frame_buffer_length_ == fixed_len_portion) {
1969 // Parse out the max age, port, and pid_len.
1970 SpdyFrameReader reader(current_frame_buffer_.get(),
1971 current_frame_buffer_length_);
1972 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
1973 bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
1974 reader.ReadUInt16(&altsvc_scratch_.port);
1975 reader.Seek(1); // Reserved byte.
1976 successful_read = successful_read &&
1977 reader.ReadUInt8(&altsvc_scratch_.pid_len);
1978 DCHECK(successful_read);
1979 // Sanity check length value.
1980 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
1981 current_frame_length_) {
1982 set_error(SPDY_INVALID_CONTROL_FRAME);
1983 return 0;
1984 }
1985 altsvc_scratch_.protocol_id.reset(
1986 new char[size_t(altsvc_scratch_.pid_len)]);
1987 }
1988 processed_bytes += processing;
1989 continue;
1990 } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
1991 // Buffer protocol id field as in comes in.
1992 buffer = altsvc_scratch_.protocol_id.get();
1993 buffer_len = &altsvc_scratch_.pid_buf_len;
1994 bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
1995 } else if (altsvc_scratch_.host_len == 0) {
1996 // Parse out the host length.
1997 processing = 1;
1998 altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
1999 // Sanity check length value.
2000 if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
2001 altsvc_scratch_.host_len > current_frame_length_) {
2002 set_error(SPDY_INVALID_CONTROL_FRAME);
2003 return 0;
2004 }
2005 altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
2006 // Once we have host length, we can also determine the origin length
2007 // by process of elimination.
2008 altsvc_scratch_.origin_len = current_frame_length_ -
2009 GetAltSvcMinimumSize() -
2010 altsvc_scratch_.pid_len -
2011 altsvc_scratch_.host_len;
2012 if (altsvc_scratch_.origin_len > 0) {
2013 altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
2014 }
2015 data += processing;
2016 processed_bytes += processing;
2017 len -= processing;
2018 continue;
2019 } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
2020 // Buffer host field as it comes in.
2021 // TODO(mlavan): check formatting for host and origin
2022 buffer = altsvc_scratch_.host.get();
2023 buffer_len = &altsvc_scratch_.host_buf_len;
2024 bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
2025 } else {
2026 // Buffer (optional) origin field as it comes in.
2027 if (altsvc_scratch_.origin_len <= 0) {
2028 set_error(SPDY_INVALID_CONTROL_FRAME);
2029 return 0;
2030 }
2031 buffer = altsvc_scratch_.origin.get();
2032 buffer_len = &altsvc_scratch_.origin_buf_len;
2033 bytes_remaining = remaining_data_length_ -
2034 processed_bytes -
2035 altsvc_scratch_.origin_buf_len;
2036 if (len > bytes_remaining) {
2037 // This is our last field; there shouldn't be any more bytes.
2038 set_error(SPDY_INVALID_CONTROL_FRAME);
2039 return 0;
2040 }
2041 }
2042
2043 // Copy data bytes into the appropriate field.
2044 processing = std::min(len, bytes_remaining);
2045 memcpy(buffer + *buffer_len,
2046 data,
2047 processing);
2048 *buffer_len += processing;
2049 data += processing;
2050 processed_bytes += processing;
2051 len -= processing;
2052 }
2053
2054 remaining_data_length_ -= processed_bytes;
2055 if (remaining_data_length_ == 0) {
2056 visitor_->OnAltSvc(current_frame_stream_id_,
2057 altsvc_scratch_.max_age,
2058 altsvc_scratch_.port,
2059 StringPiece(altsvc_scratch_.protocol_id.get(),
2060 altsvc_scratch_.pid_len),
2061 StringPiece(altsvc_scratch_.host.get(),
2062 altsvc_scratch_.host_len),
2063 StringPiece(altsvc_scratch_.origin.get(),
2064 altsvc_scratch_.origin_len));
2065 CHANGE_STATE(SPDY_AUTO_RESET);
2066 }
2067
2068 return processed_bytes;
2069 }
2070
ProcessFramePaddingLength(const char * data,size_t len)2071 size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
2072 DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
2073
2074 size_t original_len = len;
2075 if (remaining_padding_length_fields_ == 0) {
2076 DCHECK_EQ(remaining_padding_payload_length_, 0u);
2077 bool pad_low = false;
2078 bool pad_high = false;
2079 if (current_frame_flags_ & DATA_FLAG_PAD_LOW) {
2080 pad_low = true;
2081 ++remaining_padding_length_fields_;
2082 }
2083 if (current_frame_flags_ & DATA_FLAG_PAD_HIGH) {
2084 pad_high = true;
2085 ++remaining_padding_length_fields_;
2086 }
2087 if ((pad_high && !pad_low) ||
2088 remaining_data_length_ < remaining_padding_length_fields_) {
2089 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2090 return 0;
2091 }
2092 }
2093
2094 // Parse the padding length.
2095 while (len != 0 && remaining_padding_length_fields_ != 0) {
2096 remaining_padding_payload_length_ =
2097 (remaining_padding_payload_length_ << 8) +
2098 *reinterpret_cast<const uint8*>(data);
2099 ++data;
2100 --len;
2101 --remaining_padding_length_fields_;
2102 --remaining_data_length_;
2103 }
2104
2105 if (remaining_padding_length_fields_ == 0) {
2106 if (remaining_padding_payload_length_ > remaining_data_length_) {
2107 set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
2108 return 0;
2109 }
2110 if (current_frame_type_ == DATA) {
2111 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
2112 } else {
2113 DCHECK(current_frame_type_ == HEADERS ||
2114 current_frame_type_ == PUSH_PROMISE ||
2115 current_frame_type_ == CONTINUATION ||
2116 current_frame_type_ == SYN_STREAM ||
2117 current_frame_type_ == SYN_REPLY)
2118 << current_frame_type_;
2119 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
2120 }
2121 }
2122 return original_len - len;
2123 }
2124
ProcessFramePadding(const char * data,size_t len)2125 size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
2126 DCHECK_EQ(SPDY_CONSUME_PADDING, state_);
2127
2128 size_t original_len = len;
2129 if (remaining_padding_payload_length_ > 0) {
2130 DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
2131 size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
2132 if (current_frame_type_ == DATA && amount_to_discard > 0) {
2133 // The visitor needs to know about padding so it can send window updates.
2134 // Communicate the padding to the visitor through a NULL data pointer,
2135 // with a nonzero size.
2136 visitor_->OnStreamFrameData(
2137 current_frame_stream_id_, NULL, amount_to_discard, false);
2138 }
2139 data += amount_to_discard;
2140 len -= amount_to_discard;
2141 remaining_padding_payload_length_ -= amount_to_discard;
2142 remaining_data_length_ -= amount_to_discard;
2143 }
2144
2145 if (remaining_data_length_ == 0) {
2146 // If the FIN flag is set, or this ends a header block which set FIN,
2147 // inform the visitor of EOF via a 0-length data frame.
2148 if (expect_continuation_ == 0 &&
2149 ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
2150 end_stream_when_done_)) {
2151 end_stream_when_done_ = false;
2152 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
2153 }
2154 CHANGE_STATE(SPDY_AUTO_RESET);
2155 }
2156 return original_len - len;
2157 }
2158
ProcessDataFramePayload(const char * data,size_t len)2159 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
2160 size_t original_len = len;
2161 if (remaining_data_length_ - remaining_padding_payload_length_ > 0) {
2162 size_t amount_to_forward = std::min(
2163 remaining_data_length_ - remaining_padding_payload_length_, len);
2164 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
2165 // Only inform the visitor if there is data.
2166 if (amount_to_forward) {
2167 visitor_->OnStreamFrameData(
2168 current_frame_stream_id_, data, amount_to_forward, false);
2169 }
2170 }
2171 data += amount_to_forward;
2172 len -= amount_to_forward;
2173 remaining_data_length_ -= amount_to_forward;
2174 }
2175
2176 if (remaining_data_length_ == remaining_padding_payload_length_) {
2177 CHANGE_STATE(SPDY_CONSUME_PADDING);
2178 }
2179 return original_len - len;
2180 }
2181
ProcessIgnoredControlFramePayload(size_t len)2182 size_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/
2183 size_t len) {
2184 size_t original_len = len;
2185 if (remaining_data_length_ > 0) {
2186 size_t amount_to_ignore = std::min(remaining_data_length_, len);
2187 len -= amount_to_ignore;
2188 remaining_data_length_ -= amount_to_ignore;
2189 }
2190
2191 if (remaining_data_length_ == 0) {
2192 CHANGE_STATE(SPDY_AUTO_RESET);
2193 }
2194 return original_len - len;
2195 }
2196
ParseHeaderBlockInBuffer(const char * header_data,size_t header_length,SpdyHeaderBlock * block) const2197 size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
2198 size_t header_length,
2199 SpdyHeaderBlock* block) const {
2200 SpdyFrameReader reader(header_data, header_length);
2201
2202 // Read number of headers.
2203 uint32 num_headers;
2204 if (protocol_version() <= SPDY2) {
2205 uint16 temp;
2206 if (!reader.ReadUInt16(&temp)) {
2207 DVLOG(1) << "Unable to read number of headers.";
2208 return 0;
2209 }
2210 num_headers = temp;
2211 } else {
2212 if (!reader.ReadUInt32(&num_headers)) {
2213 DVLOG(1) << "Unable to read number of headers.";
2214 return 0;
2215 }
2216 }
2217
2218 // Read each header.
2219 for (uint32 index = 0; index < num_headers; ++index) {
2220 base::StringPiece temp;
2221
2222 // Read header name.
2223 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2224 : !reader.ReadStringPiece32(&temp)) {
2225 DVLOG(1) << "Unable to read header name (" << index + 1 << " of "
2226 << num_headers << ").";
2227 return 0;
2228 }
2229 std::string name = temp.as_string();
2230
2231 // Read header value.
2232 if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp)
2233 : !reader.ReadStringPiece32(&temp)) {
2234 DVLOG(1) << "Unable to read header value (" << index + 1 << " of "
2235 << num_headers << ").";
2236 return 0;
2237 }
2238 std::string value = temp.as_string();
2239
2240 // Ensure no duplicates.
2241 if (block->find(name) != block->end()) {
2242 DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of "
2243 << num_headers << ").";
2244 return 0;
2245 }
2246
2247 // Store header.
2248 (*block)[name] = value;
2249 }
2250 return reader.GetBytesConsumed();
2251 }
2252
SerializeData(const SpdyDataIR & data_ir) const2253 SpdySerializedFrame* SpdyFramer::SerializeData(
2254 const SpdyDataIR& data_ir) const {
2255 uint8 flags = DATA_FLAG_NONE;
2256 if (data_ir.fin()) {
2257 flags = DATA_FLAG_FIN;
2258 }
2259
2260 if (protocol_version() > SPDY3) {
2261 int num_padding_fields = 0;
2262 if (data_ir.pad_low()) {
2263 flags |= DATA_FLAG_PAD_LOW;
2264 ++num_padding_fields;
2265 }
2266 if (data_ir.pad_high()) {
2267 flags |= DATA_FLAG_PAD_HIGH;
2268 ++num_padding_fields;
2269 }
2270
2271 const size_t size_with_padding = num_padding_fields +
2272 data_ir.data().length() + data_ir.padding_payload_len() +
2273 GetDataFrameMinimumSize();
2274 SpdyFrameBuilder builder(size_with_padding, protocol_version());
2275 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2276 if (data_ir.pad_high()) {
2277 builder.WriteUInt8(data_ir.padding_payload_len() >> 8);
2278 }
2279 if (data_ir.pad_low()) {
2280 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2281 }
2282 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2283 if (data_ir.padding_payload_len() > 0) {
2284 string padding = string(data_ir.padding_payload_len(), '0');
2285 builder.WriteBytes(padding.data(), padding.length());
2286 }
2287 DCHECK_EQ(size_with_padding, builder.length());
2288 return builder.take();
2289 } else {
2290 const size_t size = GetDataFrameMinimumSize() + data_ir.data().length();
2291 SpdyFrameBuilder builder(size, protocol_version());
2292 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2293 builder.WriteBytes(data_ir.data().data(), data_ir.data().length());
2294 DCHECK_EQ(size, builder.length());
2295 return builder.take();
2296 }
2297 }
2298
SerializeDataFrameHeaderWithPaddingLengthField(const SpdyDataIR & data_ir) const2299 SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
2300 const SpdyDataIR& data_ir) const {
2301 uint8 flags = DATA_FLAG_NONE;
2302 if (data_ir.fin()) {
2303 flags = DATA_FLAG_FIN;
2304 }
2305
2306 size_t frame_size = GetDataFrameMinimumSize();
2307 size_t num_padding_fields = 0;
2308 if (protocol_version() > SPDY3) {
2309 if (data_ir.pad_low()) {
2310 flags |= DATA_FLAG_PAD_LOW;
2311 ++num_padding_fields;
2312 }
2313 if (data_ir.pad_high()) {
2314 flags |= DATA_FLAG_PAD_HIGH;
2315 ++num_padding_fields;
2316 }
2317 frame_size += num_padding_fields;
2318 }
2319
2320 SpdyFrameBuilder builder(frame_size, protocol_version());
2321 builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags);
2322 if (protocol_version() > SPDY3) {
2323 if (data_ir.pad_high()) {
2324 builder.WriteUInt8(data_ir.padding_payload_len() >> 8);
2325 }
2326 if (data_ir.pad_low()) {
2327 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff);
2328 }
2329 builder.OverwriteLength(*this, num_padding_fields +
2330 data_ir.data().length() + data_ir.padding_payload_len());
2331 } else {
2332 builder.OverwriteLength(*this, data_ir.data().length());
2333 }
2334 DCHECK_EQ(frame_size, builder.length());
2335 return builder.take();
2336 }
2337
SerializeSynStream(const SpdySynStreamIR & syn_stream)2338 SpdySerializedFrame* SpdyFramer::SerializeSynStream(
2339 const SpdySynStreamIR& syn_stream) {
2340 uint8 flags = 0;
2341 if (syn_stream.fin()) {
2342 flags |= CONTROL_FLAG_FIN;
2343 }
2344 if (syn_stream.unidirectional()) {
2345 // TODO(hkhalil): invalid for HTTP2.
2346 flags |= CONTROL_FLAG_UNIDIRECTIONAL;
2347 }
2348 // In SPDY >= 4, SYN_STREAM frames are HEADERS frames, but for now
2349 // we never expect to have to overflow into a CONTINUATION frame.
2350 if (protocol_version() > SPDY3) {
2351 flags |= HEADERS_FLAG_PRIORITY;
2352 flags |= HEADERS_FLAG_END_HEADERS;
2353 }
2354
2355 // Sanitize priority.
2356 uint8 priority = syn_stream.priority();
2357 if (priority > GetLowestPriority()) {
2358 DLOG(DFATAL) << "Priority out-of-bounds.";
2359 priority = GetLowestPriority();
2360 }
2361
2362 // The size of this frame, including variable-length name-value block.
2363 size_t size = GetSynStreamMinimumSize();
2364
2365 string hpack_encoding;
2366 if (protocol_version() > SPDY3) {
2367 if (enable_compression_) {
2368 GetHpackEncoder()->EncodeHeaderSet(
2369 syn_stream.name_value_block(), &hpack_encoding);
2370 } else {
2371 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2372 syn_stream.name_value_block(), &hpack_encoding);
2373 }
2374 size += hpack_encoding.size();
2375 } else {
2376 size += GetSerializedLength(syn_stream.name_value_block());
2377 }
2378
2379 SpdyFrameBuilder builder(size, protocol_version());
2380 if (protocol_version() <= SPDY3) {
2381 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags);
2382 builder.WriteUInt32(syn_stream.stream_id());
2383 builder.WriteUInt32(syn_stream.associated_to_stream_id());
2384 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5));
2385 builder.WriteUInt8(0); // Unused byte where credential slot used to be.
2386 } else {
2387 builder.BeginNewFrame(*this,
2388 HEADERS,
2389 flags,
2390 syn_stream.stream_id());
2391 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2392 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2393 builder.WriteUInt8(MapPriorityToWeight(priority));
2394 }
2395 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length());
2396 if (protocol_version() > SPDY3) {
2397 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2398 } else {
2399 SerializeNameValueBlock(&builder, syn_stream);
2400 }
2401
2402 if (debug_visitor_) {
2403 const size_t payload_len = protocol_version() > SPDY3 ?
2404 hpack_encoding.size() :
2405 GetSerializedLength(protocol_version(),
2406 &(syn_stream.name_value_block()));
2407 // SPDY 4 reports this compression as a SYN_STREAM compression.
2408 debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(),
2409 SYN_STREAM,
2410 payload_len,
2411 builder.length());
2412 }
2413
2414 return builder.take();
2415 }
2416
SerializeSynReply(const SpdySynReplyIR & syn_reply)2417 SpdySerializedFrame* SpdyFramer::SerializeSynReply(
2418 const SpdySynReplyIR& syn_reply) {
2419 uint8 flags = 0;
2420 if (syn_reply.fin()) {
2421 flags |= CONTROL_FLAG_FIN;
2422 }
2423 // In SPDY >= 4, SYN_REPLY frames are HEADERS frames, but for now
2424 // we never expect to have to overflow into a CONTINUATION frame.
2425 if (protocol_version() > SPDY3) {
2426 flags |= HEADERS_FLAG_END_HEADERS;
2427 }
2428
2429 // The size of this frame, including variable-length name-value block.
2430 size_t size = GetSynReplyMinimumSize();
2431
2432 string hpack_encoding;
2433 if (protocol_version() > SPDY3) {
2434 if (enable_compression_) {
2435 GetHpackEncoder()->EncodeHeaderSet(
2436 syn_reply.name_value_block(), &hpack_encoding);
2437 } else {
2438 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2439 syn_reply.name_value_block(), &hpack_encoding);
2440 }
2441 size += hpack_encoding.size();
2442 } else {
2443 size += GetSerializedLength(syn_reply.name_value_block());
2444 }
2445
2446 SpdyFrameBuilder builder(size, protocol_version());
2447 if (protocol_version() <= SPDY3) {
2448 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags);
2449 builder.WriteUInt32(syn_reply.stream_id());
2450 } else {
2451 builder.BeginNewFrame(*this,
2452 HEADERS,
2453 flags,
2454 syn_reply.stream_id());
2455 }
2456 if (protocol_version() < SPDY3) {
2457 builder.WriteUInt16(0); // Unused.
2458 }
2459 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length());
2460 if (protocol_version() > SPDY3) {
2461 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2462 } else {
2463 SerializeNameValueBlock(&builder, syn_reply);
2464 }
2465
2466 if (debug_visitor_) {
2467 const size_t payload_len = protocol_version() > SPDY3 ?
2468 hpack_encoding.size() :
2469 GetSerializedLength(protocol_version(),
2470 &(syn_reply.name_value_block()));
2471 debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(),
2472 SYN_REPLY,
2473 payload_len,
2474 builder.length());
2475 }
2476
2477 return builder.take();
2478 }
2479
SerializeRstStream(const SpdyRstStreamIR & rst_stream) const2480 SpdySerializedFrame* SpdyFramer::SerializeRstStream(
2481 const SpdyRstStreamIR& rst_stream) const {
2482 // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM
2483 // payloads, but will not emit them. SPDY4 is used for draft HTTP/2,
2484 // which doesn't currently include RST_STREAM payloads. GFE flags have been
2485 // commented but left in place to simplify future patching.
2486 // Compute the output buffer size, taking opaque data into account.
2487 uint16 expected_length = GetRstStreamMinimumSize();
2488 if (protocol_version() > SPDY3) {
2489 expected_length += rst_stream.description().size();
2490 }
2491 SpdyFrameBuilder builder(expected_length, protocol_version());
2492
2493 // Serialize the RST_STREAM frame.
2494 if (protocol_version() <= SPDY3) {
2495 builder.WriteControlFrameHeader(*this, RST_STREAM, 0);
2496 builder.WriteUInt32(rst_stream.stream_id());
2497 } else {
2498 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id());
2499 }
2500
2501 builder.WriteUInt32(rst_stream.status());
2502
2503 // In SPDY4 and up, RST_STREAM frames may also specify opaque data.
2504 if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) {
2505 builder.WriteBytes(rst_stream.description().data(),
2506 rst_stream.description().size());
2507 }
2508
2509 DCHECK_EQ(expected_length, builder.length());
2510 return builder.take();
2511 }
2512
SerializeSettings(const SpdySettingsIR & settings) const2513 SpdySerializedFrame* SpdyFramer::SerializeSettings(
2514 const SpdySettingsIR& settings) const {
2515 uint8 flags = 0;
2516
2517 if (protocol_version() <= SPDY3) {
2518 if (settings.clear_settings()) {
2519 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS;
2520 }
2521 } else {
2522 if (settings.is_ack()) {
2523 flags |= SETTINGS_FLAG_ACK;
2524 }
2525 }
2526 const SpdySettingsIR::ValueMap* values = &(settings.values());
2527
2528 size_t setting_size = (protocol_version() <= SPDY3 ? 8 : 5);
2529 // Size, in bytes, of this SETTINGS frame.
2530 const size_t size = GetSettingsMinimumSize() +
2531 (values->size() * setting_size);
2532 SpdyFrameBuilder builder(size, protocol_version());
2533 if (protocol_version() <= SPDY3) {
2534 builder.WriteControlFrameHeader(*this, SETTINGS, flags);
2535 } else {
2536 builder.BeginNewFrame(*this, SETTINGS, flags, 0);
2537 }
2538
2539 // If this is an ACK, payload should be empty.
2540 if (protocol_version() > SPDY3 && settings.is_ack()) {
2541 return builder.take();
2542 }
2543
2544 if (protocol_version() <= SPDY3) {
2545 builder.WriteUInt32(values->size());
2546 }
2547 DCHECK_EQ(GetSettingsMinimumSize(), builder.length());
2548 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin();
2549 it != values->end();
2550 ++it) {
2551 if (protocol_version() <= SPDY3) {
2552 uint8 setting_flags = 0;
2553 if (it->second.persist_value) {
2554 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST;
2555 }
2556 if (it->second.persisted) {
2557 setting_flags |= SETTINGS_FLAG_PERSISTED;
2558 }
2559 SettingsFlagsAndId flags_and_id(
2560 setting_flags,
2561 SpdyConstants::SerializeSettingId(protocol_version(), it->first));
2562 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version());
2563 builder.WriteBytes(&id_and_flags_wire, 4);
2564 } else {
2565 builder.WriteUInt8(SpdyConstants::SerializeSettingId(protocol_version(),
2566 it->first));
2567 }
2568 builder.WriteUInt32(it->second.value);
2569 }
2570 DCHECK_EQ(size, builder.length());
2571 return builder.take();
2572 }
2573
SerializePing(const SpdyPingIR & ping) const2574 SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const {
2575 SpdyFrameBuilder builder(GetPingSize(), protocol_version());
2576 if (protocol_version() <= SPDY3) {
2577 builder.WriteControlFrameHeader(*this, PING, kNoFlags);
2578 builder.WriteUInt32(static_cast<uint32>(ping.id()));
2579 } else {
2580 uint8 flags = 0;
2581 if (ping.is_ack()) {
2582 flags |= PING_FLAG_ACK;
2583 }
2584 builder.BeginNewFrame(*this, PING, flags, 0);
2585 builder.WriteUInt64(ping.id());
2586 }
2587 DCHECK_EQ(GetPingSize(), builder.length());
2588 return builder.take();
2589 }
2590
SerializeGoAway(const SpdyGoAwayIR & goaway) const2591 SpdySerializedFrame* SpdyFramer::SerializeGoAway(
2592 const SpdyGoAwayIR& goaway) const {
2593
2594 // Compute the output buffer size, take opaque data into account.
2595 uint16 expected_length = GetGoAwayMinimumSize();
2596 if (protocol_version() > SPDY3) {
2597 expected_length += goaway.description().size();
2598 }
2599 SpdyFrameBuilder builder(expected_length, protocol_version());
2600
2601 // Serialize the GOAWAY frame.
2602 if (protocol_version() <= SPDY3) {
2603 builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags);
2604 } else {
2605 builder.BeginNewFrame(*this, GOAWAY, 0, 0);
2606 }
2607
2608 // GOAWAY frames specify the last good stream id for all SPDY versions.
2609 builder.WriteUInt32(goaway.last_good_stream_id());
2610
2611 // In SPDY3 and up, GOAWAY frames also specify the error status code.
2612 if (protocol_version() >= SPDY3) {
2613 // TODO(jgraettinger): Merge back to server-side.
2614 builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(),
2615 goaway.status()));
2616 }
2617
2618 // In SPDY4 and up, GOAWAY frames may also specify opaque data.
2619 if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) {
2620 builder.WriteBytes(goaway.description().data(),
2621 goaway.description().size());
2622 }
2623
2624 DCHECK_EQ(expected_length, builder.length());
2625 return builder.take();
2626 }
2627
SerializeHeaders(const SpdyHeadersIR & headers)2628 SpdySerializedFrame* SpdyFramer::SerializeHeaders(
2629 const SpdyHeadersIR& headers) {
2630 uint8 flags = 0;
2631 if (headers.fin()) {
2632 flags |= CONTROL_FLAG_FIN;
2633 }
2634 if (protocol_version() > SPDY3) {
2635 // This will get overwritten if we overflow into a CONTINUATION frame.
2636 flags |= HEADERS_FLAG_END_HEADERS;
2637 if (headers.has_priority()) {
2638 flags |= HEADERS_FLAG_PRIORITY;
2639 }
2640 }
2641
2642 // The size of this frame, including variable-length name-value block.
2643 size_t size = GetHeadersMinimumSize();
2644
2645 uint32 priority = headers.priority();
2646 if (headers.has_priority()) {
2647 if (priority > GetLowestPriority()) {
2648 DLOG(DFATAL) << "Priority out-of-bounds.";
2649 priority = GetLowestPriority();
2650 }
2651 size += 4;
2652 }
2653
2654 string hpack_encoding;
2655 if (protocol_version() > SPDY3) {
2656 if (enable_compression_) {
2657 GetHpackEncoder()->EncodeHeaderSet(
2658 headers.name_value_block(), &hpack_encoding);
2659 } else {
2660 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2661 headers.name_value_block(), &hpack_encoding);
2662 }
2663 size += hpack_encoding.size();
2664 if (size > GetControlFrameBufferMaxSize()) {
2665 size += GetNumberRequiredContinuationFrames(size) *
2666 GetContinuationMinimumSize();
2667 flags &= ~HEADERS_FLAG_END_HEADERS;
2668 }
2669 } else {
2670 size += GetSerializedLength(headers.name_value_block());
2671 }
2672
2673 SpdyFrameBuilder builder(size, protocol_version());
2674 if (protocol_version() <= SPDY3) {
2675 builder.WriteControlFrameHeader(*this, HEADERS, flags);
2676 builder.WriteUInt32(headers.stream_id());
2677 } else {
2678 builder.BeginNewFrame(*this,
2679 HEADERS,
2680 flags,
2681 headers.stream_id());
2682 if (headers.has_priority()) {
2683 // TODO(jgraettinger): Plumb priorities and stream dependencies.
2684 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID.
2685 builder.WriteUInt8(MapPriorityToWeight(priority));
2686 }
2687 }
2688 if (protocol_version() <= SPDY2) {
2689 builder.WriteUInt16(0); // Unused.
2690 }
2691 DCHECK_EQ(GetHeadersMinimumSize(), builder.length());
2692
2693 if (protocol_version() > SPDY3) {
2694 WritePayloadWithContinuation(&builder,
2695 hpack_encoding,
2696 headers.stream_id(),
2697 HEADERS);
2698 } else {
2699 SerializeNameValueBlock(&builder, headers);
2700 }
2701
2702 if (debug_visitor_) {
2703 const size_t payload_len = protocol_version() > SPDY3 ?
2704 hpack_encoding.size() :
2705 GetSerializedLength(protocol_version(),
2706 &(headers.name_value_block()));
2707 debug_visitor_->OnSendCompressedFrame(headers.stream_id(),
2708 HEADERS,
2709 payload_len,
2710 builder.length());
2711 }
2712
2713 return builder.take();
2714 }
2715
SerializeWindowUpdate(const SpdyWindowUpdateIR & window_update) const2716 SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate(
2717 const SpdyWindowUpdateIR& window_update) const {
2718 SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version());
2719 if (protocol_version() <= SPDY3) {
2720 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags);
2721 builder.WriteUInt32(window_update.stream_id());
2722 } else {
2723 builder.BeginNewFrame(*this,
2724 WINDOW_UPDATE,
2725 kNoFlags,
2726 window_update.stream_id());
2727 }
2728 builder.WriteUInt32(window_update.delta());
2729 DCHECK_EQ(GetWindowUpdateSize(), builder.length());
2730 return builder.take();
2731 }
2732
SerializeBlocked(const SpdyBlockedIR & blocked) const2733 SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const {
2734 DCHECK_LT(SPDY3, protocol_version());
2735 SpdyFrameBuilder builder(GetBlockedSize(), protocol_version());
2736 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id());
2737 return builder.take();
2738 }
2739
SerializePushPromise(const SpdyPushPromiseIR & push_promise)2740 SpdyFrame* SpdyFramer::SerializePushPromise(
2741 const SpdyPushPromiseIR& push_promise) {
2742 DCHECK_LT(SPDY3, protocol_version());
2743 uint8 flags = 0;
2744 // This will get overwritten if we overflow into a CONTINUATION frame.
2745 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2746 // The size of this frame, including variable-length name-value block.
2747 size_t size = GetPushPromiseMinimumSize();
2748
2749 string hpack_encoding;
2750 if (protocol_version() > SPDY3) {
2751 if (enable_compression_) {
2752 GetHpackEncoder()->EncodeHeaderSet(
2753 push_promise.name_value_block(), &hpack_encoding);
2754 } else {
2755 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2756 push_promise.name_value_block(), &hpack_encoding);
2757 }
2758 size += hpack_encoding.size();
2759 if (size > GetControlFrameBufferMaxSize()) {
2760 size += GetNumberRequiredContinuationFrames(size) *
2761 GetContinuationMinimumSize();
2762 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2763 }
2764 } else {
2765 size += GetSerializedLength(push_promise.name_value_block());
2766 }
2767
2768 SpdyFrameBuilder builder(size, protocol_version());
2769 builder.BeginNewFrame(*this,
2770 PUSH_PROMISE,
2771 flags,
2772 push_promise.stream_id());
2773 builder.WriteUInt32(push_promise.promised_stream_id());
2774 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length());
2775
2776 if (protocol_version() > SPDY3) {
2777 WritePayloadWithContinuation(&builder,
2778 hpack_encoding,
2779 push_promise.stream_id(),
2780 PUSH_PROMISE);
2781 } else {
2782 SerializeNameValueBlock(&builder, push_promise);
2783 }
2784
2785 if (debug_visitor_) {
2786 const size_t payload_len = protocol_version() > SPDY3 ?
2787 hpack_encoding.size() :
2788 GetSerializedLength(protocol_version(),
2789 &(push_promise.name_value_block()));
2790 debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(),
2791 PUSH_PROMISE, payload_len, builder.length());
2792 }
2793
2794 return builder.take();
2795 }
2796
2797 // TODO(jgraettinger): This implementation is incorrect. The continuation
2798 // frame continues a previously-begun HPACK encoding; it doesn't begin a
2799 // new one. Figure out whether it makes sense to keep SerializeContinuation().
SerializeContinuation(const SpdyContinuationIR & continuation)2800 SpdyFrame* SpdyFramer::SerializeContinuation(
2801 const SpdyContinuationIR& continuation) {
2802 CHECK_LT(SPDY3, protocol_version());
2803 uint8 flags = 0;
2804 if (continuation.end_headers()) {
2805 flags |= HEADERS_FLAG_END_HEADERS;
2806 }
2807
2808 // The size of this frame, including variable-length name-value block.
2809 size_t size = GetContinuationMinimumSize();
2810 string hpack_encoding;
2811 if (enable_compression_) {
2812 GetHpackEncoder()->EncodeHeaderSet(
2813 continuation.name_value_block(), &hpack_encoding);
2814 } else {
2815 GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
2816 continuation.name_value_block(), &hpack_encoding);
2817 }
2818 size += hpack_encoding.size();
2819
2820 SpdyFrameBuilder builder(size, protocol_version());
2821 builder.BeginNewFrame(*this, CONTINUATION, flags,
2822 continuation.stream_id());
2823 DCHECK_EQ(GetContinuationMinimumSize(), builder.length());
2824
2825 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size());
2826
2827 if (debug_visitor_) {
2828 const size_t payload_len = hpack_encoding.size();
2829 debug_visitor_->OnSendCompressedFrame(continuation.stream_id(),
2830 CONTINUATION, payload_len, builder.length());
2831 }
2832
2833 return builder.take();
2834 }
2835
SerializeAltSvc(const SpdyAltSvcIR & altsvc)2836 SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
2837 DCHECK_LT(SPDY3, protocol_version());
2838 size_t size = GetAltSvcMinimumSize();
2839 size += altsvc.protocol_id().length();
2840 size += altsvc.host().length();
2841 size += altsvc.origin().length();
2842
2843 SpdyFrameBuilder builder(size, protocol_version());
2844 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
2845
2846 builder.WriteUInt32(altsvc.max_age());
2847 builder.WriteUInt16(altsvc.port());
2848 builder.WriteUInt8(0); // Reserved.
2849 builder.WriteUInt8(altsvc.protocol_id().length());
2850 builder.WriteBytes(altsvc.protocol_id().data(),
2851 altsvc.protocol_id().length());
2852 builder.WriteUInt8(altsvc.host().length());
2853 builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
2854 builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
2855 DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
2856 return builder.take();
2857 }
2858
2859 namespace {
2860
2861 class FrameSerializationVisitor : public SpdyFrameVisitor {
2862 public:
FrameSerializationVisitor(SpdyFramer * framer)2863 explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {}
~FrameSerializationVisitor()2864 virtual ~FrameSerializationVisitor() {}
2865
ReleaseSerializedFrame()2866 SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); }
2867
VisitData(const SpdyDataIR & data)2868 virtual void VisitData(const SpdyDataIR& data) OVERRIDE {
2869 frame_.reset(framer_->SerializeData(data));
2870 }
VisitSynStream(const SpdySynStreamIR & syn_stream)2871 virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE {
2872 frame_.reset(framer_->SerializeSynStream(syn_stream));
2873 }
VisitSynReply(const SpdySynReplyIR & syn_reply)2874 virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE {
2875 frame_.reset(framer_->SerializeSynReply(syn_reply));
2876 }
VisitRstStream(const SpdyRstStreamIR & rst_stream)2877 virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE {
2878 frame_.reset(framer_->SerializeRstStream(rst_stream));
2879 }
VisitSettings(const SpdySettingsIR & settings)2880 virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE {
2881 frame_.reset(framer_->SerializeSettings(settings));
2882 }
VisitPing(const SpdyPingIR & ping)2883 virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE {
2884 frame_.reset(framer_->SerializePing(ping));
2885 }
VisitGoAway(const SpdyGoAwayIR & goaway)2886 virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE {
2887 frame_.reset(framer_->SerializeGoAway(goaway));
2888 }
VisitHeaders(const SpdyHeadersIR & headers)2889 virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE {
2890 frame_.reset(framer_->SerializeHeaders(headers));
2891 }
VisitWindowUpdate(const SpdyWindowUpdateIR & window_update)2892 virtual void VisitWindowUpdate(
2893 const SpdyWindowUpdateIR& window_update) OVERRIDE {
2894 frame_.reset(framer_->SerializeWindowUpdate(window_update));
2895 }
VisitBlocked(const SpdyBlockedIR & blocked)2896 virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE {
2897 frame_.reset(framer_->SerializeBlocked(blocked));
2898 }
VisitPushPromise(const SpdyPushPromiseIR & push_promise)2899 virtual void VisitPushPromise(
2900 const SpdyPushPromiseIR& push_promise) OVERRIDE {
2901 frame_.reset(framer_->SerializePushPromise(push_promise));
2902 }
VisitContinuation(const SpdyContinuationIR & continuation)2903 virtual void VisitContinuation(
2904 const SpdyContinuationIR& continuation) OVERRIDE {
2905 frame_.reset(framer_->SerializeContinuation(continuation));
2906 }
VisitAltSvc(const SpdyAltSvcIR & altsvc)2907 virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE {
2908 frame_.reset(framer_->SerializeAltSvc(altsvc));
2909 }
2910
2911 private:
2912 SpdyFramer* framer_;
2913 scoped_ptr<SpdySerializedFrame> frame_;
2914 };
2915
2916 } // namespace
2917
SerializeFrame(const SpdyFrameIR & frame)2918 SpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) {
2919 FrameSerializationVisitor visitor(this);
2920 frame.Visit(&visitor);
2921 return visitor.ReleaseSerializedFrame();
2922 }
2923
GetSerializedLength(const SpdyHeaderBlock & headers)2924 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
2925 CHECK_GE(SPDY3, protocol_version());
2926 const size_t uncompressed_length =
2927 GetSerializedLength(protocol_version(), &headers);
2928 if (!enable_compression_) {
2929 return uncompressed_length;
2930 }
2931 z_stream* compressor = GetHeaderCompressor();
2932 // Since we'll be performing lots of flushes when compressing the data,
2933 // zlib's lower bounds may be insufficient.
2934 return 2 * deflateBound(compressor, uncompressed_length);
2935 }
2936
GetNumberRequiredContinuationFrames(size_t size)2937 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) {
2938 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize();
2939 DCHECK_GT(protocol_version(), SPDY3);
2940 DCHECK_GT(size, kMaxControlFrameSize);
2941 size_t overflow = size - kMaxControlFrameSize;
2942 return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1;
2943 }
2944
WritePayloadWithContinuation(SpdyFrameBuilder * builder,const string & hpack_encoding,SpdyStreamId stream_id,SpdyFrameType type)2945 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder,
2946 const string& hpack_encoding,
2947 SpdyStreamId stream_id,
2948 SpdyFrameType type) {
2949 const size_t kMaxControlFrameSize = GetControlFrameBufferMaxSize();
2950
2951 // In addition to the prefix, fixed_field_size includes the size of
2952 // any fields that come before the variable-length name/value block.
2953 size_t fixed_field_size = 0;
2954 uint8 end_flag = 0;
2955 uint8 flags = 0;
2956 if (type == HEADERS) {
2957 fixed_field_size = GetHeadersMinimumSize();
2958 end_flag = HEADERS_FLAG_END_HEADERS;
2959 } else if (type == PUSH_PROMISE) {
2960 fixed_field_size = GetPushPromiseMinimumSize();
2961 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE;
2962 } else {
2963 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type "
2964 << FrameTypeToString(type);
2965 }
2966
2967 // Write as much of the payload as possible into the initial frame.
2968 size_t bytes_remaining = hpack_encoding.size() -
2969 std::min(hpack_encoding.size(),
2970 kMaxControlFrameSize - fixed_field_size);
2971 builder->WriteBytes(&hpack_encoding[0],
2972 hpack_encoding.size() - bytes_remaining);
2973
2974 if (bytes_remaining > 0) {
2975 builder->OverwriteLength(*this,
2976 kMaxControlFrameSize - GetControlFrameHeaderSize());
2977 }
2978
2979 // Tack on CONTINUATION frames for the overflow.
2980 while (bytes_remaining > 0) {
2981 size_t bytes_to_write = std::min(bytes_remaining,
2982 kMaxControlFrameSize -
2983 GetContinuationMinimumSize());
2984 // Write CONTINUATION frame prefix.
2985 if (bytes_remaining == bytes_to_write) {
2986 flags |= end_flag;
2987 }
2988 builder->BeginNewFrame(*this,
2989 CONTINUATION,
2990 flags,
2991 stream_id);
2992 // Write payload fragment.
2993 builder->WriteBytes(&hpack_encoding[hpack_encoding.size() -
2994 bytes_remaining],
2995 bytes_to_write);
2996 bytes_remaining -= bytes_to_write;
2997 }
2998 }
2999
3000 // The following compression setting are based on Brian Olson's analysis. See
3001 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
3002 // for more details.
3003 #if defined(USE_SYSTEM_ZLIB)
3004 // System zlib is not expected to have workaround for http://crbug.com/139744,
3005 // so disable compression in that case.
3006 // TODO(phajdan.jr): Remove the special case when it's no longer necessary.
3007 static const int kCompressorLevel = 0;
3008 #else // !defined(USE_SYSTEM_ZLIB)
3009 static const int kCompressorLevel = 9;
3010 #endif // !defined(USE_SYSTEM_ZLIB)
3011 static const int kCompressorWindowSizeInBits = 11;
3012 static const int kCompressorMemLevel = 1;
3013
GetHeaderCompressor()3014 z_stream* SpdyFramer::GetHeaderCompressor() {
3015 if (header_compressor_.get())
3016 return header_compressor_.get(); // Already initialized.
3017
3018 header_compressor_.reset(new z_stream);
3019 memset(header_compressor_.get(), 0, sizeof(z_stream));
3020
3021 int success = deflateInit2(header_compressor_.get(),
3022 kCompressorLevel,
3023 Z_DEFLATED,
3024 kCompressorWindowSizeInBits,
3025 kCompressorMemLevel,
3026 Z_DEFAULT_STRATEGY);
3027 if (success == Z_OK) {
3028 const char* dictionary = (protocol_version() <= SPDY2) ?
3029 kV2Dictionary : kV3Dictionary;
3030 const int dictionary_size = (protocol_version() <= SPDY2) ?
3031 kV2DictionarySize : kV3DictionarySize;
3032 success = deflateSetDictionary(header_compressor_.get(),
3033 reinterpret_cast<const Bytef*>(dictionary),
3034 dictionary_size);
3035 }
3036 if (success != Z_OK) {
3037 LOG(WARNING) << "deflateSetDictionary failure: " << success;
3038 header_compressor_.reset(NULL);
3039 return NULL;
3040 }
3041 return header_compressor_.get();
3042 }
3043
GetHeaderDecompressor()3044 z_stream* SpdyFramer::GetHeaderDecompressor() {
3045 if (header_decompressor_.get())
3046 return header_decompressor_.get(); // Already initialized.
3047
3048 header_decompressor_.reset(new z_stream);
3049 memset(header_decompressor_.get(), 0, sizeof(z_stream));
3050
3051 int success = inflateInit(header_decompressor_.get());
3052 if (success != Z_OK) {
3053 LOG(WARNING) << "inflateInit failure: " << success;
3054 header_decompressor_.reset(NULL);
3055 return NULL;
3056 }
3057 return header_decompressor_.get();
3058 }
3059
GetHpackEncoder()3060 HpackEncoder* SpdyFramer::GetHpackEncoder() {
3061 DCHECK_LT(SPDY3, spdy_version_);
3062 if (hpack_encoder_.get() == NULL) {
3063 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
3064 }
3065 return hpack_encoder_.get();
3066 }
3067
GetHpackDecoder()3068 HpackDecoder* SpdyFramer::GetHpackDecoder() {
3069 DCHECK_LT(SPDY3, spdy_version_);
3070 if (hpack_decoder_.get() == NULL) {
3071 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
3072 }
3073 return hpack_decoder_.get();
3074 }
3075
MapPriorityToWeight(SpdyPriority priority)3076 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) {
3077 const float kSteps = 255.9f / 7.f;
3078 return static_cast<uint8>(kSteps * (7.f - priority));
3079 }
3080
MapWeightToPriority(uint8 weight)3081 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) {
3082 const float kSteps = 255.9f / 7.f;
3083 return static_cast<SpdyPriority>(7.f - weight / kSteps);
3084 }
3085
3086 // Incrementally decompress the control frame's header block, feeding the
3087 // result to the visitor in chunks. Continue this until the visitor
3088 // indicates that it cannot process any more data, or (more commonly) we
3089 // run out of data to deliver.
IncrementallyDecompressControlFrameHeaderData(SpdyStreamId stream_id,const char * data,size_t len)3090 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
3091 SpdyStreamId stream_id,
3092 const char* data,
3093 size_t len) {
3094 // Get a decompressor or set error.
3095 z_stream* decomp = GetHeaderDecompressor();
3096 if (decomp == NULL) {
3097 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
3098 set_error(SPDY_DECOMPRESS_FAILURE);
3099 return false;
3100 }
3101
3102 bool processed_successfully = true;
3103 char buffer[kHeaderDataChunkMaxSize];
3104
3105 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
3106 decomp->avail_in = len;
3107 // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we
3108 // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've
3109 // reached this method successfully, stream_id should be nonzero.
3110 DCHECK_LT(0u, stream_id);
3111 while (decomp->avail_in > 0 && processed_successfully) {
3112 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
3113 decomp->avail_out = arraysize(buffer);
3114
3115 int rv = inflate(decomp, Z_SYNC_FLUSH);
3116 if (rv == Z_NEED_DICT) {
3117 const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary
3118 : kV3Dictionary;
3119 const int dictionary_size = (protocol_version() <= SPDY2) ?
3120 kV2DictionarySize : kV3DictionarySize;
3121 const DictionaryIds& ids = g_dictionary_ids.Get();
3122 const uLong dictionary_id = (protocol_version() <= SPDY2) ?
3123 ids.v2_dictionary_id : ids.v3_dictionary_id;
3124 // Need to try again with the right dictionary.
3125 if (decomp->adler == dictionary_id) {
3126 rv = inflateSetDictionary(decomp,
3127 reinterpret_cast<const Bytef*>(dictionary),
3128 dictionary_size);
3129 if (rv == Z_OK)
3130 rv = inflate(decomp, Z_SYNC_FLUSH);
3131 }
3132 }
3133
3134 // Inflate will generate a Z_BUF_ERROR if it runs out of input
3135 // without producing any output. The input is consumed and
3136 // buffered internally by zlib so we can detect this condition by
3137 // checking if avail_in is 0 after the call to inflate.
3138 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
3139 if ((rv == Z_OK) || input_exhausted) {
3140 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
3141 if (decompressed_len > 0) {
3142 processed_successfully = visitor_->OnControlFrameHeaderData(
3143 stream_id, buffer, decompressed_len);
3144 }
3145 if (!processed_successfully) {
3146 // Assume that the problem was the header block was too large for the
3147 // visitor.
3148 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3149 }
3150 } else {
3151 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
3152 set_error(SPDY_DECOMPRESS_FAILURE);
3153 processed_successfully = false;
3154 }
3155 }
3156 return processed_successfully;
3157 }
3158
IncrementallyDeliverControlFrameHeaderData(SpdyStreamId stream_id,const char * data,size_t len)3159 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
3160 SpdyStreamId stream_id, const char* data, size_t len) {
3161 bool read_successfully = true;
3162 while (read_successfully && len > 0) {
3163 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
3164 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
3165 bytes_to_deliver);
3166 data += bytes_to_deliver;
3167 len -= bytes_to_deliver;
3168 if (!read_successfully) {
3169 // Assume that the problem was the header block was too large for the
3170 // visitor.
3171 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
3172 }
3173 }
3174 return read_successfully;
3175 }
3176
SerializeNameValueBlockWithoutCompression(SpdyFrameBuilder * builder,const SpdyNameValueBlock & name_value_block) const3177 void SpdyFramer::SerializeNameValueBlockWithoutCompression(
3178 SpdyFrameBuilder* builder,
3179 const SpdyNameValueBlock& name_value_block) const {
3180 // Serialize number of headers.
3181 if (protocol_version() <= SPDY2) {
3182 builder->WriteUInt16(name_value_block.size());
3183 } else {
3184 builder->WriteUInt32(name_value_block.size());
3185 }
3186
3187 // Serialize each header.
3188 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin();
3189 it != name_value_block.end();
3190 ++it) {
3191 if (protocol_version() <= SPDY2) {
3192 builder->WriteString(it->first);
3193 builder->WriteString(it->second);
3194 } else {
3195 builder->WriteStringPiece32(it->first);
3196 builder->WriteStringPiece32(it->second);
3197 }
3198 }
3199 }
3200
SerializeNameValueBlock(SpdyFrameBuilder * builder,const SpdyFrameWithNameValueBlockIR & frame)3201 void SpdyFramer::SerializeNameValueBlock(
3202 SpdyFrameBuilder* builder,
3203 const SpdyFrameWithNameValueBlockIR& frame) {
3204 CHECK_GE(SPDY3, protocol_version());
3205 if (!enable_compression_) {
3206 return SerializeNameValueBlockWithoutCompression(builder,
3207 frame.name_value_block());
3208 }
3209
3210 // First build an uncompressed version to be fed into the compressor.
3211 const size_t uncompressed_len = GetSerializedLength(
3212 protocol_version(), &(frame.name_value_block()));
3213 SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version());
3214 SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
3215 frame.name_value_block());
3216 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
3217
3218 z_stream* compressor = GetHeaderCompressor();
3219 if (!compressor) {
3220 LOG(DFATAL) << "Could not obtain compressor.";
3221 return;
3222 }
3223
3224 base::StatsCounter compressed_frames("spdy.CompressedFrames");
3225 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
3226 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
3227
3228 // Create an output frame.
3229 // Since we'll be performing lots of flushes when compressing the data,
3230 // zlib's lower bounds may be insufficient.
3231 //
3232 // TODO(akalin): Avoid the duplicate calculation with
3233 // GetSerializedLength(const SpdyHeaderBlock&).
3234 const int compressed_max_size =
3235 2 * deflateBound(compressor, uncompressed_len);
3236
3237 // TODO(phajdan.jr): Clean up after we no longer need
3238 // to workaround http://crbug.com/139744.
3239 #if defined(USE_SYSTEM_ZLIB)
3240 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
3241 compressor->avail_in = uncompressed_len;
3242 #endif // defined(USE_SYSTEM_ZLIB)
3243 compressor->next_out = reinterpret_cast<Bytef*>(
3244 builder->GetWritableBuffer(compressed_max_size));
3245 compressor->avail_out = compressed_max_size;
3246
3247 // TODO(phajdan.jr): Clean up after we no longer need
3248 // to workaround http://crbug.com/139744.
3249 #if defined(USE_SYSTEM_ZLIB)
3250 int rv = deflate(compressor, Z_SYNC_FLUSH);
3251 if (rv != Z_OK) { // How can we know that it compressed everything?
3252 // This shouldn't happen, right?
3253 LOG(WARNING) << "deflate failure: " << rv;
3254 // TODO(akalin): Upstream this return.
3255 return;
3256 }
3257 #else
3258 WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
3259 #endif // defined(USE_SYSTEM_ZLIB)
3260
3261 int compressed_size = compressed_max_size - compressor->avail_out;
3262 builder->Seek(compressed_size);
3263 builder->RewriteLength(*this);
3264
3265 pre_compress_bytes.Add(uncompressed_len);
3266 post_compress_bytes.Add(compressed_size);
3267
3268 compressed_frames.Increment();
3269 }
3270
3271 } // namespace net
3272