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.
5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't
6 // constantly adding and subtracting header sizes; this is ugly and error-
9 #include "net/spdy/spdy_framer.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/stats_counters.h"
13 #include "base/third_party/valgrind/memcheck.h"
14 #include "net/spdy/spdy_frame_builder.h"
15 #include "net/spdy/spdy_bitmasks.h"
17 #if defined(USE_SYSTEM_ZLIB)
20 #include "third_party/zlib/zlib.h"
27 SpdyCredential::SpdyCredential() : slot(0) { }
28 SpdyCredential::~SpdyCredential() { }
30 // Compute the id of our dictionary so that we know we're using the
31 // right one when asked for it.
32 uLong
CalculateDictionaryId() {
33 uLong initial_value
= adler32(0L, Z_NULL
, 0);
34 return adler32(initial_value
,
35 reinterpret_cast<const Bytef
*>(SpdyFramer::kDictionary
),
36 SpdyFramer::kDictionarySize
);
39 // Adler ID for the SPDY header compressor dictionary.
40 const uLong kDictionaryId
= CalculateDictionaryId();
42 int DecompressHeaderBlockInZStream(z_stream
* decompressor
) {
43 int rv
= inflate(decompressor
, Z_SYNC_FLUSH
);
44 if (rv
== Z_NEED_DICT
) {
45 // Need to try again with the right dictionary.
46 if (decompressor
->adler
== kDictionaryId
) {
47 rv
= inflateSetDictionary(decompressor
,
48 (const Bytef
*)SpdyFramer::kDictionary
,
49 SpdyFramer::kDictionarySize
);
51 rv
= inflate(decompressor
, Z_SYNC_FLUSH
);
57 // Retrieve serialized length of SpdyHeaderBlock.
58 size_t GetSerializedLength(const SpdyHeaderBlock
* headers
) {
59 size_t total_length
= SpdyControlFrame::kNumNameValuePairsSize
;
60 SpdyHeaderBlock::const_iterator it
;
61 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
62 // We add space for the length of the name and the length of the value as
63 // well as the length of the name and the length of the value.
64 total_length
+= SpdyControlFrame::kLengthOfNameSize
+
66 SpdyControlFrame::kLengthOfValueSize
+
72 // Serializes a SpdyHeaderBlock.
73 void WriteHeaderBlock(SpdyFrameBuilder
* frame
, const SpdyHeaderBlock
* headers
) {
74 frame
->WriteUInt16(headers
->size()); // Number of headers.
75 SpdyHeaderBlock::const_iterator it
;
76 for (it
= headers
->begin(); it
!= headers
->end(); ++it
) {
78 wrote_header
= frame
->WriteString(it
->first
);
79 wrote_header
&= frame
->WriteString(it
->second
);
84 // Creates a FlagsAndLength.
85 FlagsAndLength
CreateFlagsAndLength(SpdyControlFlags flags
, size_t length
) {
86 DCHECK_EQ(0u, length
& ~static_cast<size_t>(kLengthMask
));
87 FlagsAndLength flags_length
;
88 flags_length
.length_
= htonl(static_cast<uint32
>(length
));
89 DCHECK_EQ(0, flags
& ~kControlFlagsMask
);
90 flags_length
.flags_
[0] = flags
;
94 // By default is compression on or off.
95 bool SpdyFramer::compression_default_
= true;
97 // The initial size of the control frame buffer; this is used internally
98 // as we parse through control frames. (It is exposed here for unit test
100 size_t SpdyFramer::kControlFrameBufferInitialSize
= 32 * 1024;
102 // The maximum size of the control frame buffer that we support.
103 // TODO(mbelshe): We should make this stream-based so there are no limits.
104 size_t SpdyFramer::kControlFrameBufferMaxSize
= 64 * 1024;
106 int SpdyFramer::spdy_version_
= kSpdyProtocolVersion
;
108 const SpdyStreamId
SpdyFramer::kInvalidStream
= -1;
109 const size_t SpdyFramer::kHeaderDataChunkMaxSize
= 1024;
111 #ifdef DEBUG_SPDY_STATE_CHANGES
112 #define CHANGE_STATE(newstate) \
115 LOG(INFO) << "Changing state from: " \
116 << StateToString(state_) \
117 << " to " << StateToString(newstate) << "\n"; \
122 #define CHANGE_STATE(newstate) (state_ = newstate)
125 SpdyFramer::SpdyFramer()
126 : state_(SPDY_RESET
),
127 error_code_(SPDY_NO_ERROR
),
129 remaining_control_payload_(0),
130 remaining_control_header_(0),
131 current_frame_buffer_(NULL
),
132 current_frame_len_(0),
133 current_frame_capacity_(0),
134 validate_control_frame_sizes_(true),
135 enable_compression_(compression_default_
),
137 display_protocol_("SPDY") {
140 SpdyFramer::~SpdyFramer() {
141 if (header_compressor_
.get()) {
142 deflateEnd(header_compressor_
.get());
144 if (header_decompressor_
.get()) {
145 inflateEnd(header_decompressor_
.get());
147 CleanupStreamCompressorsAndDecompressors();
148 delete [] current_frame_buffer_
;
151 void SpdyFramer::Reset() {
153 error_code_
= SPDY_NO_ERROR
;
155 remaining_control_payload_
= 0;
156 remaining_control_header_
= 0;
157 current_frame_len_
= 0;
158 // TODO(hkhalil): Remove once initial_size == kControlFrameBufferInitialSize.
159 size_t initial_size
= kControlFrameBufferInitialSize
;
160 if (!enable_compression_
) {
161 initial_size
= kUncompressedControlFrameBufferInitialSize
;
163 if (current_frame_capacity_
!= initial_size
) {
164 delete [] current_frame_buffer_
;
165 current_frame_buffer_
= 0;
166 current_frame_capacity_
= 0;
167 ExpandControlFrameBuffer(initial_size
);
171 const char* SpdyFramer::StateToString(int state
) {
177 case SPDY_AUTO_RESET
:
181 case SPDY_READING_COMMON_HEADER
:
182 return "READING_COMMON_HEADER";
183 case SPDY_CONTROL_FRAME_PAYLOAD
:
184 return "CONTROL_FRAME_PAYLOAD";
185 case SPDY_IGNORE_REMAINING_PAYLOAD
:
186 return "IGNORE_REMAINING_PAYLOAD";
187 case SPDY_FORWARD_STREAM_FRAME
:
188 return "FORWARD_STREAM_FRAME";
189 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
190 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
191 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
192 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
193 case SPDY_CREDENTIAL_FRAME_PAYLOAD
:
194 return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
196 return "UNKNOWN_STATE";
199 void SpdyFramer::set_error(SpdyError error
) {
202 CHANGE_STATE(SPDY_ERROR
);
203 visitor_
->OnError(this);
206 const char* SpdyFramer::ErrorCodeToString(int error_code
) {
207 switch (error_code
) {
210 case SPDY_INVALID_CONTROL_FRAME
:
211 return "INVALID_CONTROL_FRAME";
212 case SPDY_CONTROL_PAYLOAD_TOO_LARGE
:
213 return "CONTROL_PAYLOAD_TOO_LARGE";
214 case SPDY_ZLIB_INIT_FAILURE
:
215 return "ZLIB_INIT_FAILURE";
216 case SPDY_UNSUPPORTED_VERSION
:
217 return "UNSUPPORTED_VERSION";
218 case SPDY_DECOMPRESS_FAILURE
:
219 return "DECOMPRESS_FAILURE";
220 case SPDY_COMPRESS_FAILURE
:
221 return "COMPRESS_FAILURE";
223 return "UNKNOWN_ERROR";
226 const char* SpdyFramer::StatusCodeToString(int status_code
) {
227 switch (status_code
) {
231 return "PROTOCOL_ERROR";
233 return "INVALID_STREAM";
235 return "REFUSED_STREAM";
236 case UNSUPPORTED_VERSION
:
237 return "UNSUPPORTED_VERSION";
241 return "INTERNAL_ERROR";
242 case FLOW_CONTROL_ERROR
:
243 return "FLOW_CONTROL_ERROR";
245 return "UNKNOWN_STATUS";
248 const char* SpdyFramer::ControlTypeToString(SpdyControlType type
) {
267 return "WINDOW_UPDATE";
270 case NUM_CONTROL_FRAME_TYPES
:
273 return "UNKNOWN_CONTROL_TYPE";
276 size_t SpdyFramer::ProcessInput(const char* data
, size_t len
) {
280 size_t original_len
= len
;
287 case SPDY_AUTO_RESET
:
290 CHANGE_STATE(SPDY_READING_COMMON_HEADER
);
293 case SPDY_READING_COMMON_HEADER
: {
294 size_t bytes_read
= ProcessCommonHeader(data
, len
);
300 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
: {
301 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY,
302 // HEADERS) take a different path through the state machine - they
304 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
305 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
307 // All other control frames will use the alternate route directly to
308 // SPDY_CONTROL_FRAME_PAYLOAD
309 int bytes_read
= ProcessControlFrameBeforeHeaderBlock(data
, len
);
315 case SPDY_CONTROL_FRAME_HEADER_BLOCK
: {
316 int bytes_read
= ProcessControlFrameHeaderBlock(data
, len
);
322 case SPDY_CREDENTIAL_FRAME_PAYLOAD
: {
323 size_t bytes_read
= ProcessCredentialFramePayload(data
, len
);
329 case SPDY_CONTROL_FRAME_PAYLOAD
: {
330 size_t bytes_read
= ProcessControlFramePayload(data
, len
);
334 // intentional fallthrough
335 case SPDY_IGNORE_REMAINING_PAYLOAD
:
336 // control frame has too-large payload
337 // intentional fallthrough
338 case SPDY_FORWARD_STREAM_FRAME
: {
339 size_t bytes_read
= ProcessDataFramePayload(data
, len
);
345 // This ensures that we don't infinite-loop if state_ gets an
346 // invalid value somehow, such as due to a SpdyFramer getting deleted
347 // from a callback it calls.
352 return original_len
- len
;
355 size_t SpdyFramer::ProcessCommonHeader(const char* data
, size_t len
) {
356 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
358 DCHECK_EQ(state_
, SPDY_READING_COMMON_HEADER
);
360 size_t original_len
= len
;
361 SpdyFrame
current_frame(current_frame_buffer_
, false);
363 // Update current frame buffer as needed.
364 if (current_frame_len_
< SpdyFrame::kHeaderSize
) {
365 size_t bytes_desired
= SpdyFrame::kHeaderSize
- current_frame_len_
;
366 UpdateCurrentFrameBuffer(&data
, &len
, bytes_desired
);
369 if (current_frame_len_
< SpdyFrame::kHeaderSize
) {
371 } else if (current_frame_len_
== SpdyFrame::kHeaderSize
&&
372 !current_frame
.is_control_frame() &&
373 current_frame
.length() == 0) {
375 SpdyDataFrame
data_frame(current_frame_buffer_
, false);
376 visitor_
->OnDataFrameHeader(&data_frame
);
377 if (current_frame
.flags() & DATA_FLAG_FIN
) {
378 visitor_
->OnStreamFrameData(data_frame
.stream_id(), NULL
, 0);
380 CHANGE_STATE(SPDY_AUTO_RESET
);
382 remaining_data_
= current_frame
.length();
384 // This is just a sanity check for help debugging early frame errors.
385 if (remaining_data_
> 1000000u) {
386 LOG(WARNING
) << "Unexpectedly large frame. " << display_protocol_
387 << " session is likely corrupt.";
390 // if we're here, then we have the common header all received.
391 if (!current_frame
.is_control_frame()) {
392 SpdyDataFrame
data_frame(current_frame_buffer_
, false);
393 visitor_
->OnDataFrameHeader(&data_frame
);
394 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME
);
396 ProcessControlFrameHeader();
399 return original_len
- len
;
402 void SpdyFramer::ProcessControlFrameHeader() {
403 DCHECK_EQ(SPDY_NO_ERROR
, error_code_
);
404 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize
), current_frame_len_
);
405 SpdyControlFrame
current_control_frame(current_frame_buffer_
, false);
407 // We check version before we check validity: version can never be 'invalid',
408 // it can only be unsupported.
409 if (current_control_frame
.version() != spdy_version_
) {
410 set_error(SPDY_UNSUPPORTED_VERSION
);
414 // Next up, check to see if we have valid data. This should be after version
415 // checking (otherwise if the the type were out of bounds due to a version
416 // upgrade we would misclassify the error) and before checking the type
417 // (type can definitely be out of bounds)
418 if (!current_control_frame
.AppearsToBeAValidControlFrame()) {
419 set_error(SPDY_INVALID_CONTROL_FRAME
);
423 if (current_control_frame
.type() == NOOP
) {
424 DLOG(INFO
) << "NOOP control frame found. Ignoring.";
425 CHANGE_STATE(SPDY_AUTO_RESET
);
429 if (validate_control_frame_sizes_
) {
430 // Do some sanity checking on the control frame sizes.
431 switch (current_control_frame
.type()) {
433 if (current_control_frame
.length() <
434 SpdySynStreamControlFrame::size() - SpdyControlFrame::kHeaderSize
)
435 set_error(SPDY_INVALID_CONTROL_FRAME
);
438 if (current_control_frame
.length() <
439 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize
)
440 set_error(SPDY_INVALID_CONTROL_FRAME
);
443 if (current_control_frame
.length() !=
444 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize
)
445 set_error(SPDY_INVALID_CONTROL_FRAME
);
448 if (current_control_frame
.length() <
449 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize
)
450 set_error(SPDY_INVALID_CONTROL_FRAME
);
453 if (current_control_frame
.length() !=
454 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize
)
455 set_error(SPDY_INVALID_CONTROL_FRAME
);
458 if (current_control_frame
.length() <
459 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize
)
460 set_error(SPDY_INVALID_CONTROL_FRAME
);
463 if (current_control_frame
.length() !=
464 SpdyWindowUpdateControlFrame::size() -
465 SpdyControlFrame::kHeaderSize
)
466 set_error(SPDY_INVALID_CONTROL_FRAME
);
469 if (current_control_frame
.length() !=
470 SpdyPingControlFrame::size() - SpdyControlFrame::kHeaderSize
)
471 set_error(SPDY_INVALID_CONTROL_FRAME
);
474 if (current_control_frame
.length() <
475 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize
)
476 set_error(SPDY_INVALID_CONTROL_FRAME
);
479 LOG(WARNING
) << "Valid " << display_protocol_
480 << " control frame with unhandled type: "
481 << current_control_frame
.type();
483 set_error(SPDY_INVALID_CONTROL_FRAME
);
488 // We only support version 1 of this protocol.
489 if (current_control_frame
.version() != spdy_version_
) {
490 set_error(SPDY_UNSUPPORTED_VERSION
);
494 remaining_control_payload_
= current_control_frame
.length();
495 if (remaining_control_payload_
>
496 kControlFrameBufferMaxSize
- SpdyFrame::kHeaderSize
) {
497 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
501 if (current_control_frame
.type() == CREDENTIAL
) {
502 visitor_
->OnControl(¤t_control_frame
);
503 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD
);
507 int32 frame_size_without_header_block
;
508 switch (current_control_frame
.type()) {
510 frame_size_without_header_block
= SpdySynStreamControlFrame::size();
513 frame_size_without_header_block
= SpdySynReplyControlFrame::size();
516 frame_size_without_header_block
= SpdyHeadersControlFrame::size();
519 frame_size_without_header_block
= -1;
520 LOG_IF(DFATAL
, remaining_control_payload_
+ SpdyFrame::kHeaderSize
>
521 current_frame_capacity_
)
523 << " control frame buffer too small for fixed-length frame.";
524 ExpandControlFrameBuffer(remaining_control_payload_
);
528 if (frame_size_without_header_block
> 0) {
529 // We have a control frame with a header block. We need to parse the
530 // remainder of the control frame's header before we can parse the header
531 // block. The start of the header block varies with the control type.
532 DCHECK_GE(static_cast<uint32
>(frame_size_without_header_block
),
534 remaining_control_header_
= frame_size_without_header_block
-
536 remaining_control_payload_
+= SpdyFrame::kHeaderSize
-
537 frame_size_without_header_block
;
538 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
);
542 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD
);
545 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data
, size_t* len
,
547 size_t bytes_to_read
= std::min(*len
, max_bytes
);
548 DCHECK_GE(current_frame_capacity_
, current_frame_len_
+ bytes_to_read
);
549 memcpy(¤t_frame_buffer_
[current_frame_len_
], *data
, bytes_to_read
);
550 current_frame_len_
+= bytes_to_read
;
551 *data
+= bytes_to_read
;
552 *len
-= bytes_to_read
;
553 return bytes_to_read
;
556 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data
,
558 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
, state_
);
559 DCHECK_GT(remaining_control_header_
, 0u);
560 size_t original_len
= len
;
562 if (remaining_control_header_
) {
563 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
564 remaining_control_header_
);
565 remaining_control_header_
-= bytes_read
;
566 if (remaining_control_header_
== 0) {
567 SpdyControlFrame
control_frame(current_frame_buffer_
, false);
568 DCHECK(control_frame
.type() == SYN_STREAM
||
569 control_frame
.type() == SYN_REPLY
||
570 control_frame
.type() == HEADERS
);
571 visitor_
->OnControl(&control_frame
);
573 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK
);
576 return original_len
- len
;
579 // Does not buffer the control payload. Instead, either passes directly to the
580 // visitor or decompresses and then passes directly to the visitor, via
581 // IncrementallyDeliverControlFrameHeaderData() or
582 // IncrementallyDecompressControlFrameHeaderData() respectively.
583 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data
,
585 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK
, state_
);
586 SpdyControlFrame
control_frame(current_frame_buffer_
, false);
587 bool processed_successfully
= true;
588 DCHECK(control_frame
.type() == SYN_STREAM
||
589 control_frame
.type() == SYN_REPLY
||
590 control_frame
.type() == HEADERS
);
591 size_t process_bytes
= std::min(data_len
, remaining_control_payload_
);
592 DCHECK_GT(process_bytes
, 0u);
594 if (enable_compression_
) {
595 processed_successfully
= IncrementallyDecompressControlFrameHeaderData(
596 &control_frame
, data
, process_bytes
);
598 processed_successfully
= IncrementallyDeliverControlFrameHeaderData(
599 &control_frame
, data
, process_bytes
);
601 remaining_control_payload_
-= process_bytes
;
603 // Handle the case that there is no futher data in this frame.
604 if (remaining_control_payload_
== 0 && processed_successfully
) {
605 // The complete header block has been delivered. We send a zero-length
606 // OnControlFrameHeaderData() to indicate this.
607 visitor_
->OnControlFrameHeaderData(
608 GetControlFrameStreamId(&control_frame
), NULL
, 0);
610 // If this is a FIN, tell the caller.
611 if (control_frame
.flags() & CONTROL_FLAG_FIN
) {
612 visitor_
->OnStreamFrameData(GetControlFrameStreamId(&control_frame
),
616 CHANGE_STATE(SPDY_RESET
);
620 if (!processed_successfully
) {
624 // Return amount processed.
625 return process_bytes
;
628 size_t SpdyFramer::ProcessControlFramePayload(const char* data
, size_t len
) {
629 size_t original_len
= len
;
630 if (remaining_control_payload_
) {
631 size_t bytes_read
= UpdateCurrentFrameBuffer(&data
, &len
,
632 remaining_control_payload_
);
633 remaining_control_payload_
-= bytes_read
;
634 remaining_data_
-= bytes_read
;
635 if (remaining_control_payload_
== 0) {
636 SpdyControlFrame
control_frame(current_frame_buffer_
, false);
637 DCHECK(!control_frame
.has_header_block());
638 visitor_
->OnControl(&control_frame
);
640 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD
);
643 return original_len
- len
;
646 size_t SpdyFramer::ProcessCredentialFramePayload(const char* data
, size_t len
) {
647 bool processed_succesfully
= visitor_
->OnCredentialFrameData(data
, len
);
648 remaining_control_payload_
-= len
;
649 remaining_data_
-= len
;
650 if (!processed_succesfully
) {
651 set_error(SPDY_CREDENTIAL_FRAME_CORRUPT
);
652 } else if (remaining_control_payload_
== 0) {
653 visitor_
->OnCredentialFrameData(NULL
, 0);
658 size_t SpdyFramer::ProcessDataFramePayload(const char* data
, size_t len
) {
659 size_t original_len
= len
;
661 SpdyDataFrame
current_data_frame(current_frame_buffer_
, false);
662 if (remaining_data_
) {
663 size_t amount_to_forward
= std::min(remaining_data_
, len
);
664 if (amount_to_forward
&& state_
!= SPDY_IGNORE_REMAINING_PAYLOAD
) {
665 if (current_data_frame
.flags() & DATA_FLAG_COMPRESSED
) {
666 z_stream
* decompressor
=
667 GetStreamDecompressor(current_data_frame
.stream_id());
671 size_t decompressed_max_size
= amount_to_forward
* 100;
672 scoped_array
<char> decompressed(new char[decompressed_max_size
]);
673 decompressor
->next_in
= reinterpret_cast<Bytef
*>(
674 const_cast<char*>(data
));
675 decompressor
->avail_in
= amount_to_forward
;
676 decompressor
->next_out
=
677 reinterpret_cast<Bytef
*>(decompressed
.get());
678 decompressor
->avail_out
= decompressed_max_size
;
680 int rv
= inflate(decompressor
, Z_SYNC_FLUSH
);
682 LOG(WARNING
) << "inflate failure: " << rv
;
683 set_error(SPDY_DECOMPRESS_FAILURE
);
686 size_t decompressed_size
= decompressed_max_size
-
687 decompressor
->avail_out
;
689 // Only inform the visitor if there is data.
690 if (decompressed_size
)
691 visitor_
->OnStreamFrameData(current_data_frame
.stream_id(),
694 amount_to_forward
-= decompressor
->avail_in
;
696 // The data frame was not compressed.
697 // Only inform the visitor if there is data.
698 if (amount_to_forward
)
699 visitor_
->OnStreamFrameData(current_data_frame
.stream_id(),
700 data
, amount_to_forward
);
703 data
+= amount_to_forward
;
704 len
-= amount_to_forward
;
705 remaining_data_
-= amount_to_forward
;
707 // If the FIN flag is set, and there is no more data in this data
708 // frame, inform the visitor of EOF via a 0-length data frame.
709 if (!remaining_data_
&&
710 current_data_frame
.flags() & DATA_FLAG_FIN
) {
711 visitor_
->OnStreamFrameData(current_data_frame
.stream_id(), NULL
, 0);
712 CleanupDecompressorForStream(current_data_frame
.stream_id());
715 CHANGE_STATE(SPDY_AUTO_RESET
);
717 return original_len
- len
;
720 void SpdyFramer::ExpandControlFrameBuffer(size_t size
) {
721 size_t alloc_size
= size
+ SpdyFrame::kHeaderSize
;
722 DCHECK_LE(alloc_size
, kControlFrameBufferMaxSize
);
723 if (alloc_size
<= current_frame_capacity_
)
725 char* new_buffer
= new char[alloc_size
];
726 memcpy(new_buffer
, current_frame_buffer_
, current_frame_len_
);
727 delete [] current_frame_buffer_
;
728 current_frame_capacity_
= alloc_size
;
729 current_frame_buffer_
= new_buffer
;
733 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data
,
734 size_t header_length
,
735 SpdyHeaderBlock
* block
) {
736 SpdyFrameBuilder
builder(header_data
, header_length
);
739 if (builder
.ReadUInt16(&iter
, &num_headers
)) {
740 for (int index
= 0; index
< num_headers
; ++index
) {
743 if (!builder
.ReadString(&iter
, &name
))
745 if (!builder
.ReadString(&iter
, &value
))
747 if (block
->find(name
) == block
->end()) {
748 (*block
)[name
] = value
;
758 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame
* frame
,
759 SpdyHeaderBlock
* block
) {
760 SpdyControlFrame
control_frame(frame
->data(), false);
761 uint32 type
= control_frame
.type();
762 if (type
!= SYN_STREAM
&& type
!= SYN_REPLY
&& type
!= HEADERS
)
765 // Find the header data within the control frame.
766 scoped_ptr
<SpdyFrame
> decompressed_frame(DecompressFrame(*frame
));
767 if (!decompressed_frame
.get())
770 const char *header_data
= NULL
;
771 int header_length
= 0;
776 SpdySynStreamControlFrame
syn_frame(decompressed_frame
->data(), false);
777 header_data
= syn_frame
.header_block();
778 header_length
= syn_frame
.header_block_len();
783 SpdySynReplyControlFrame
syn_frame(decompressed_frame
->data(), false);
784 header_data
= syn_frame
.header_block();
785 header_length
= syn_frame
.header_block_len();
790 SpdyHeadersControlFrame
header_frame(decompressed_frame
->data(), false);
791 header_data
= header_frame
.header_block();
792 header_length
= header_frame
.header_block_len();
797 SpdyFrameBuilder
builder(header_data
, header_length
);
800 if (builder
.ReadUInt16(&iter
, &num_headers
)) {
802 for (index
= 0; index
< num_headers
; ++index
) {
805 if (!builder
.ReadString(&iter
, &name
))
807 if (!builder
.ReadString(&iter
, &value
))
809 if (!name
.size() || !value
.size())
811 if (block
->find(name
) == block
->end()) {
812 (*block
)[name
] = value
;
817 return index
== num_headers
&&
818 iter
== header_data
+ header_length
;
824 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame
* frame
,
825 SpdySettings
* settings
) {
826 DCHECK_EQ(frame
->type(), SETTINGS
);
829 SpdyFrameBuilder
parser(frame
->header_block(), frame
->header_block_len());
831 for (size_t index
= 0; index
< frame
->num_entries(); ++index
) {
834 if (!parser
.ReadUInt32(&iter
, &id
))
836 if (!parser
.ReadUInt32(&iter
, &value
))
838 settings
->insert(settings
->end(), std::make_pair(id
, value
));
844 bool SpdyFramer::ParseCredentialData(const char* data
, size_t len
,
845 SpdyCredential
* credential
) {
849 SpdyFrameBuilder
parser(data
, len
);
850 if (!parser
.ReadUInt16(&iter
, &credential
->slot
))
854 const char* origin_data
;
855 if (!parser
.ReadData(&iter
, &origin_data
, &origin_len
))
857 credential
->origin
.assign(origin_data
, origin_len
);
860 const char* proof_data
;
861 if (!parser
.ReadReadLen32PrefixedData(&iter
, &proof_data
, &proof_len
))
863 credential
->proof
.assign(proof_data
, proof_len
);
865 while (parser
.IteratorHasRoomFor(iter
, 1)) {
867 const char* cert_data
;
868 if (!parser
.ReadReadLen32PrefixedData(&iter
, &cert_data
, &cert_len
))
870 credential
->certs
.push_back("");
871 credential
->certs
.back().assign(cert_data
, cert_len
);
876 SpdySynStreamControlFrame
* SpdyFramer::CreateSynStream(
877 SpdyStreamId stream_id
, SpdyStreamId associated_stream_id
, int priority
,
878 SpdyControlFlags flags
, bool compressed
, const SpdyHeaderBlock
* headers
) {
879 DCHECK_GT(stream_id
, static_cast<SpdyStreamId
>(0));
880 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
881 DCHECK_EQ(0u, associated_stream_id
& ~kStreamIdMask
);
884 size_t expected_frame_size
= SpdySynStreamControlFrame::size() +
885 GetSerializedLength(headers
);
887 // Create our FlagsAndLength.
888 FlagsAndLength flags_length
= CreateFlagsAndLength(
890 expected_frame_size
- SpdyFrame::kHeaderSize
);
892 SpdyFrameBuilder
frame(expected_frame_size
);
893 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
894 frame
.WriteUInt16(SYN_STREAM
);
895 frame
.WriteBytes(&flags_length
, sizeof(flags_length
));
896 frame
.WriteUInt32(stream_id
);
897 frame
.WriteUInt32(associated_stream_id
);
898 frame
.WriteUInt16(ntohs(priority
) << 6); // Priority.
899 WriteHeaderBlock(&frame
, headers
);
901 scoped_ptr
<SpdySynStreamControlFrame
> syn_frame(
902 reinterpret_cast<SpdySynStreamControlFrame
*>(frame
.take()));
904 return reinterpret_cast<SpdySynStreamControlFrame
*>(
905 CompressControlFrame(*syn_frame
.get()));
907 return syn_frame
.release();
910 SpdySynReplyControlFrame
* SpdyFramer::CreateSynReply(SpdyStreamId stream_id
,
911 SpdyControlFlags flags
, bool compressed
, const SpdyHeaderBlock
* headers
) {
912 DCHECK_GT(stream_id
, 0u);
913 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
916 size_t expected_frame_size
= SpdySynReplyControlFrame::size() +
917 GetSerializedLength(headers
);
919 // Create our FlagsAndLength.
920 FlagsAndLength flags_length
= CreateFlagsAndLength(
922 expected_frame_size
- SpdyFrame::kHeaderSize
);
924 SpdyFrameBuilder
frame(expected_frame_size
);
925 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
926 frame
.WriteUInt16(SYN_REPLY
);
927 frame
.WriteBytes(&flags_length
, sizeof(flags_length
));
928 frame
.WriteUInt32(stream_id
);
929 frame
.WriteUInt16(0); // Unused
930 WriteHeaderBlock(&frame
, headers
);
932 scoped_ptr
<SpdySynReplyControlFrame
> reply_frame(
933 reinterpret_cast<SpdySynReplyControlFrame
*>(frame
.take()));
935 return reinterpret_cast<SpdySynReplyControlFrame
*>(
936 CompressControlFrame(*reply_frame
.get()));
938 return reply_frame
.release();
942 SpdyRstStreamControlFrame
* SpdyFramer::CreateRstStream(SpdyStreamId stream_id
,
943 SpdyStatusCodes status
) {
944 DCHECK_GT(stream_id
, 0u);
945 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
946 DCHECK_NE(status
, INVALID
);
947 DCHECK_LT(status
, NUM_STATUS_CODES
);
949 SpdyFrameBuilder
frame(SpdyRstStreamControlFrame::size());
950 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
951 frame
.WriteUInt16(RST_STREAM
);
952 frame
.WriteUInt32(8);
953 frame
.WriteUInt32(stream_id
);
954 frame
.WriteUInt32(status
);
955 return reinterpret_cast<SpdyRstStreamControlFrame
*>(frame
.take());
959 SpdySettingsControlFrame
* SpdyFramer::CreateSettings(
960 const SpdySettings
& values
) {
961 SpdyFrameBuilder
frame(SpdySettingsControlFrame::size() + 8 * values
.size());
962 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
963 frame
.WriteUInt16(SETTINGS
);
964 size_t settings_size
=
965 SpdySettingsControlFrame::size() - SpdyFrame::kHeaderSize
+
967 frame
.WriteUInt32(settings_size
);
968 frame
.WriteUInt32(values
.size());
969 SpdySettings::const_iterator it
= values
.begin();
970 while (it
!= values
.end()) {
971 frame
.WriteUInt32(it
->first
.id_
);
972 frame
.WriteUInt32(it
->second
);
975 return reinterpret_cast<SpdySettingsControlFrame
*>(frame
.take());
979 SpdyNoOpControlFrame
* SpdyFramer::CreateNopFrame() {
980 SpdyFrameBuilder
frame(SpdyNoOpControlFrame::size());
981 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
982 frame
.WriteUInt16(NOOP
);
983 frame
.WriteUInt32(0);
984 return reinterpret_cast<SpdyNoOpControlFrame
*>(frame
.take());
988 SpdyPingControlFrame
* SpdyFramer::CreatePingFrame(uint32 unique_id
) {
989 SpdyFrameBuilder
frame(SpdyPingControlFrame::size());
990 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
991 frame
.WriteUInt16(PING
);
992 size_t ping_size
= SpdyPingControlFrame::size() - SpdyFrame::kHeaderSize
;
993 frame
.WriteUInt32(ping_size
);
994 frame
.WriteUInt32(unique_id
);
995 return reinterpret_cast<SpdyPingControlFrame
*>(frame
.take());
999 SpdyGoAwayControlFrame
* SpdyFramer::CreateGoAway(
1000 SpdyStreamId last_accepted_stream_id
) {
1001 DCHECK_EQ(0u, last_accepted_stream_id
& ~kStreamIdMask
);
1003 SpdyFrameBuilder
frame(SpdyGoAwayControlFrame::size());
1004 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
1005 frame
.WriteUInt16(GOAWAY
);
1006 size_t go_away_size
= SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize
;
1007 frame
.WriteUInt32(go_away_size
);
1008 frame
.WriteUInt32(last_accepted_stream_id
);
1009 return reinterpret_cast<SpdyGoAwayControlFrame
*>(frame
.take());
1012 SpdyHeadersControlFrame
* SpdyFramer::CreateHeaders(SpdyStreamId stream_id
,
1013 SpdyControlFlags flags
, bool compressed
, const SpdyHeaderBlock
* headers
) {
1014 // Basically the same as CreateSynReply().
1015 DCHECK_GT(stream_id
, 0u);
1016 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1019 size_t expected_frame_size
= SpdyHeadersControlFrame::size() +
1020 GetSerializedLength(headers
);
1022 // Create our FlagsAndLength.
1023 FlagsAndLength flags_length
= CreateFlagsAndLength(
1025 expected_frame_size
- SpdyFrame::kHeaderSize
);
1027 SpdyFrameBuilder
frame(expected_frame_size
);
1028 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
1029 frame
.WriteUInt16(HEADERS
);
1030 frame
.WriteBytes(&flags_length
, sizeof(flags_length
));
1031 frame
.WriteUInt32(stream_id
);
1032 frame
.WriteUInt16(0); // Unused
1033 WriteHeaderBlock(&frame
, headers
);
1034 DCHECK_EQ(static_cast<size_t>(frame
.length()), expected_frame_size
);
1036 scoped_ptr
<SpdyHeadersControlFrame
> headers_frame(
1037 reinterpret_cast<SpdyHeadersControlFrame
*>(frame
.take()));
1039 return reinterpret_cast<SpdyHeadersControlFrame
*>(
1040 CompressControlFrame(*headers_frame
.get()));
1042 return headers_frame
.release();
1046 SpdyWindowUpdateControlFrame
* SpdyFramer::CreateWindowUpdate(
1047 SpdyStreamId stream_id
,
1048 uint32 delta_window_size
) {
1049 DCHECK_GT(stream_id
, 0u);
1050 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1051 DCHECK_GT(delta_window_size
, 0u);
1052 DCHECK_LE(delta_window_size
, spdy::kSpdyStreamMaximumWindowSize
);
1054 SpdyFrameBuilder
frame(SpdyWindowUpdateControlFrame::size());
1055 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
1056 frame
.WriteUInt16(WINDOW_UPDATE
);
1057 size_t window_update_size
= SpdyWindowUpdateControlFrame::size() -
1058 SpdyFrame::kHeaderSize
;
1059 frame
.WriteUInt32(window_update_size
);
1060 frame
.WriteUInt32(stream_id
);
1061 frame
.WriteUInt32(delta_window_size
);
1062 return reinterpret_cast<SpdyWindowUpdateControlFrame
*>(frame
.take());
1066 SpdyCredentialControlFrame
* SpdyFramer::CreateCredentialFrame(
1067 const SpdyCredential
& credential
) {
1068 // Calculate the size of the frame by adding the size of the
1069 // variable length data to the size of the fixed length data.
1070 size_t frame_size
= SpdyCredentialControlFrame::size() +
1071 credential
.origin
.length() + credential
.proof
.length();
1072 DCHECK_EQ(SpdyCredentialControlFrame::size(), 16u);
1073 for (vector
<std::string
>::const_iterator cert
= credential
.certs
.begin();
1074 cert
!= credential
.certs
.end();
1076 frame_size
+= sizeof(uint32
); // size of the cert_length field
1077 frame_size
+= cert
->length(); // size of the cert_data field
1079 size_t payload_size
= frame_size
- SpdyFrame::kHeaderSize
;
1081 SpdyFrameBuilder
frame(frame_size
);
1082 // Create our FlagsAndLength.
1083 SpdyControlFlags flags
= spdy::CONTROL_FLAG_NONE
;
1084 FlagsAndLength flags_length
= CreateFlagsAndLength(flags
, payload_size
);
1086 frame
.WriteUInt16(kControlFlagMask
| spdy_version_
);
1087 frame
.WriteUInt16(CREDENTIAL
);
1088 frame
.WriteBytes(&flags_length
, sizeof(flags_length
));
1089 frame
.WriteUInt16(credential
.slot
);
1090 frame
.WriteUInt16(credential
.origin
.size());
1091 frame
.WriteBytes(credential
.origin
.c_str(), credential
.origin
.size());
1092 frame
.WriteUInt32(credential
.proof
.size());
1093 frame
.WriteBytes(credential
.proof
.c_str(), credential
.proof
.size());
1094 for (vector
<std::string
>::const_iterator cert
= credential
.certs
.begin();
1095 cert
!= credential
.certs
.end();
1097 frame
.WriteUInt32(cert
->length());
1098 frame
.WriteBytes(cert
->c_str(), cert
->length());
1100 return reinterpret_cast<SpdyCredentialControlFrame
*>(frame
.take());
1103 SpdyDataFrame
* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id
,
1105 uint32 len
, SpdyDataFlags flags
) {
1106 DCHECK_GT(stream_id
, 0u);
1107 DCHECK_EQ(0u, stream_id
& ~kStreamIdMask
);
1109 SpdyFrameBuilder
frame(SpdyDataFrame::size() + len
);
1110 frame
.WriteUInt32(stream_id
);
1112 DCHECK_EQ(0u, len
& ~static_cast<size_t>(kLengthMask
));
1113 FlagsAndLength flags_length
;
1114 flags_length
.length_
= htonl(len
);
1115 DCHECK_EQ(0, flags
& ~kDataFlagsMask
);
1116 flags_length
.flags_
[0] = flags
;
1117 frame
.WriteBytes(&flags_length
, sizeof(flags_length
));
1119 frame
.WriteBytes(data
, len
);
1120 scoped_ptr
<SpdyFrame
> data_frame(frame
.take());
1122 if (flags
& DATA_FLAG_COMPRESSED
) {
1123 rv
= reinterpret_cast<SpdyDataFrame
*>(CompressFrame(*data_frame
.get()));
1125 rv
= reinterpret_cast<SpdyDataFrame
*>(data_frame
.release());
1128 if (flags
& DATA_FLAG_FIN
) {
1129 CleanupCompressorForStream(stream_id
);
1135 // The following compression setting are based on Brian Olson's analysis. See
1136 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792
1137 // for more details.
1138 static const int kCompressorLevel
= 9;
1139 static const int kCompressorWindowSizeInBits
= 11;
1140 static const int kCompressorMemLevel
= 1;
1142 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
1143 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
1144 const char SpdyFramer::kDictionary
[] =
1145 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
1146 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
1147 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
1148 "-agent10010120020120220320420520630030130230330430530630740040140240340440"
1149 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
1150 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
1151 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
1152 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
1153 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
1154 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
1155 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
1156 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
1157 ".1statusversionurl";
1158 const int SpdyFramer::kDictionarySize
= arraysize(kDictionary
);
1160 SpdyFrame
* SpdyFramer::CompressFrame(const SpdyFrame
& frame
) {
1161 if (frame
.is_control_frame()) {
1162 return CompressControlFrame(
1163 reinterpret_cast<const SpdyControlFrame
&>(frame
));
1165 return CompressDataFrame(reinterpret_cast<const SpdyDataFrame
&>(frame
));
1168 SpdyFrame
* SpdyFramer::DecompressFrame(const SpdyFrame
& frame
) {
1169 if (frame
.is_control_frame()) {
1170 return DecompressControlFrame(
1171 reinterpret_cast<const SpdyControlFrame
&>(frame
));
1173 return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame
&>(frame
));
1176 bool SpdyFramer::IsCompressible(const SpdyFrame
& frame
) const {
1177 // The important frames to compress are those which contain large
1178 // amounts of compressible data - namely the headers in the SYN_STREAM
1180 // TODO(mbelshe): Reconcile this with the spec when the spec is
1181 // explicit about which frames compress and which do not.
1182 if (frame
.is_control_frame()) {
1183 const SpdyControlFrame
& control_frame
=
1184 reinterpret_cast<const SpdyControlFrame
&>(frame
);
1185 return control_frame
.type() == SYN_STREAM
||
1186 control_frame
.type() == SYN_REPLY
;
1189 const SpdyDataFrame
& data_frame
=
1190 reinterpret_cast<const SpdyDataFrame
&>(frame
);
1191 return (data_frame
.flags() & DATA_FLAG_COMPRESSED
) != 0;
1194 z_stream
* SpdyFramer::GetHeaderCompressor() {
1195 if (header_compressor_
.get())
1196 return header_compressor_
.get(); // Already initialized.
1198 header_compressor_
.reset(new z_stream
);
1199 memset(header_compressor_
.get(), 0, sizeof(z_stream
));
1201 int success
= deflateInit2(header_compressor_
.get(),
1204 kCompressorWindowSizeInBits
,
1205 kCompressorMemLevel
,
1206 Z_DEFAULT_STRATEGY
);
1207 if (success
== Z_OK
)
1208 success
= deflateSetDictionary(header_compressor_
.get(),
1209 reinterpret_cast<const Bytef
*>(kDictionary
),
1211 if (success
!= Z_OK
) {
1212 LOG(WARNING
) << "deflateSetDictionary failure: " << success
;
1213 header_compressor_
.reset(NULL
);
1216 return header_compressor_
.get();
1219 z_stream
* SpdyFramer::GetHeaderDecompressor() {
1220 if (header_decompressor_
.get())
1221 return header_decompressor_
.get(); // Already initialized.
1223 header_decompressor_
.reset(new z_stream
);
1224 memset(header_decompressor_
.get(), 0, sizeof(z_stream
));
1226 int success
= inflateInit(header_decompressor_
.get());
1227 if (success
!= Z_OK
) {
1228 LOG(WARNING
) << "inflateInit failure: " << success
;
1229 header_decompressor_
.reset(NULL
);
1232 return header_decompressor_
.get();
1235 z_stream
* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id
) {
1236 CompressorMap::iterator it
= stream_compressors_
.find(stream_id
);
1237 if (it
!= stream_compressors_
.end())
1238 return it
->second
; // Already initialized.
1240 scoped_ptr
<z_stream
> compressor(new z_stream
);
1241 memset(compressor
.get(), 0, sizeof(z_stream
));
1243 int success
= deflateInit2(compressor
.get(),
1246 kCompressorWindowSizeInBits
,
1247 kCompressorMemLevel
,
1248 Z_DEFAULT_STRATEGY
);
1249 if (success
!= Z_OK
) {
1250 LOG(WARNING
) << "deflateInit failure: " << success
;
1253 return stream_compressors_
[stream_id
] = compressor
.release();
1256 z_stream
* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id
) {
1257 CompressorMap::iterator it
= stream_decompressors_
.find(stream_id
);
1258 if (it
!= stream_decompressors_
.end())
1259 return it
->second
; // Already initialized.
1261 scoped_ptr
<z_stream
> decompressor(new z_stream
);
1262 memset(decompressor
.get(), 0, sizeof(z_stream
));
1264 int success
= inflateInit(decompressor
.get());
1265 if (success
!= Z_OK
) {
1266 LOG(WARNING
) << "inflateInit failure: " << success
;
1269 return stream_decompressors_
[stream_id
] = decompressor
.release();
1272 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame
& frame
,
1273 int* payload_length
,
1275 const char** payload
) const {
1277 if (frame
.is_control_frame()) {
1278 const SpdyControlFrame
& control_frame
=
1279 reinterpret_cast<const SpdyControlFrame
&>(frame
);
1280 switch (control_frame
.type()) {
1283 const SpdySynStreamControlFrame
& syn_frame
=
1284 reinterpret_cast<const SpdySynStreamControlFrame
&>(frame
);
1285 frame_size
= SpdySynStreamControlFrame::size();
1286 *payload_length
= syn_frame
.header_block_len();
1287 *header_length
= frame_size
;
1288 *payload
= frame
.data() + *header_length
;
1293 const SpdySynReplyControlFrame
& syn_frame
=
1294 reinterpret_cast<const SpdySynReplyControlFrame
&>(frame
);
1295 frame_size
= SpdySynReplyControlFrame::size();
1296 *payload_length
= syn_frame
.header_block_len();
1297 *header_length
= frame_size
;
1298 *payload
= frame
.data() + *header_length
;
1303 const SpdyHeadersControlFrame
& headers_frame
=
1304 reinterpret_cast<const SpdyHeadersControlFrame
&>(frame
);
1305 frame_size
= SpdyHeadersControlFrame::size();
1306 *payload_length
= headers_frame
.header_block_len();
1307 *header_length
= frame_size
;
1308 *payload
= frame
.data() + *header_length
;
1312 // TODO(mbelshe): set an error?
1313 return false; // We can't compress this frame!
1316 frame_size
= SpdyFrame::kHeaderSize
;
1317 *header_length
= frame_size
;
1318 *payload_length
= frame
.length();
1319 *payload
= frame
.data() + SpdyFrame::kHeaderSize
;
1324 SpdyControlFrame
* SpdyFramer::CompressControlFrame(
1325 const SpdyControlFrame
& frame
) {
1326 z_stream
* compressor
= GetHeaderCompressor();
1329 return reinterpret_cast<SpdyControlFrame
*>(
1330 CompressFrameWithZStream(frame
, compressor
));
1333 SpdyDataFrame
* SpdyFramer::CompressDataFrame(const SpdyDataFrame
& frame
) {
1334 z_stream
* compressor
= GetStreamCompressor(frame
.stream_id());
1337 return reinterpret_cast<SpdyDataFrame
*>(
1338 CompressFrameWithZStream(frame
, compressor
));
1341 SpdyControlFrame
* SpdyFramer::DecompressControlFrame(
1342 const SpdyControlFrame
& frame
) {
1343 z_stream
* decompressor
= GetHeaderDecompressor();
1344 if (!decompressor
) {
1345 LOG(DFATAL
) << "Couldn't get decompressor for handling control frame.";
1346 set_error(SPDY_DECOMPRESS_FAILURE
);
1349 return reinterpret_cast<SpdyControlFrame
*>(
1350 DecompressFrameWithZStream(frame
, decompressor
));
1353 SpdyDataFrame
* SpdyFramer::DecompressDataFrame(const SpdyDataFrame
& frame
) {
1354 z_stream
* decompressor
= GetStreamDecompressor(frame
.stream_id());
1357 return reinterpret_cast<SpdyDataFrame
*>(
1358 DecompressFrameWithZStream(frame
, decompressor
));
1361 SpdyFrame
* SpdyFramer::CompressFrameWithZStream(const SpdyFrame
& frame
,
1362 z_stream
* compressor
) {
1365 const char* payload
;
1367 base::StatsCounter
compressed_frames("spdy.CompressedFrames");
1368 base::StatsCounter
pre_compress_bytes("spdy.PreCompressSize");
1369 base::StatsCounter
post_compress_bytes("spdy.PostCompressSize");
1371 if (!enable_compression_
)
1372 return DuplicateFrame(frame
);
1374 if (!GetFrameBoundaries(frame
, &payload_length
, &header_length
, &payload
))
1377 // Create an output frame.
1378 int compressed_max_size
= deflateBound(compressor
, payload_length
);
1379 int new_frame_size
= header_length
+ compressed_max_size
;
1380 scoped_ptr
<SpdyFrame
> new_frame(new SpdyFrame(new_frame_size
));
1381 memcpy(new_frame
->data(), frame
.data(),
1382 frame
.length() + SpdyFrame::kHeaderSize
);
1384 compressor
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(payload
));
1385 compressor
->avail_in
= payload_length
;
1386 compressor
->next_out
= reinterpret_cast<Bytef
*>(new_frame
->data()) +
1388 compressor
->avail_out
= compressed_max_size
;
1390 // Data packets have a 'compressed' flag.
1391 if (!new_frame
->is_control_frame()) {
1392 SpdyDataFrame
* data_frame
=
1393 reinterpret_cast<SpdyDataFrame
*>(new_frame
.get());
1394 data_frame
->set_flags(data_frame
->flags() | DATA_FLAG_COMPRESSED
);
1397 // Make sure that all the data we pass to zlib is defined.
1398 // This way, all Valgrind reports on the compressed data are zlib's fault.
1399 (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor
->next_in
,
1400 compressor
->avail_in
);
1402 int rv
= deflate(compressor
, Z_SYNC_FLUSH
);
1403 if (rv
!= Z_OK
) { // How can we know that it compressed everything?
1404 // This shouldn't happen, right?
1405 LOG(WARNING
) << "deflate failure: " << rv
;
1409 int compressed_size
= compressed_max_size
- compressor
->avail_out
;
1411 // We trust zlib. Also, we can't do anything about it.
1412 // See http://www.zlib.net/zlib_faq.html#faq36
1413 (void)VALGRIND_MAKE_MEM_DEFINED(new_frame
->data() + header_length
,
1416 new_frame
->set_length(
1417 header_length
+ compressed_size
- SpdyFrame::kHeaderSize
);
1419 pre_compress_bytes
.Add(payload_length
);
1420 post_compress_bytes
.Add(new_frame
->length());
1422 compressed_frames
.Increment();
1424 return new_frame
.release();
1427 SpdyFrame
* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame
& frame
,
1428 z_stream
* decompressor
) {
1431 const char* payload
;
1433 base::StatsCounter
decompressed_frames("spdy.DecompressedFrames");
1434 base::StatsCounter
pre_decompress_bytes("spdy.PreDeCompressSize");
1435 base::StatsCounter
post_decompress_bytes("spdy.PostDeCompressSize");
1437 if (!enable_compression_
)
1438 return DuplicateFrame(frame
);
1440 if (!GetFrameBoundaries(frame
, &payload_length
, &header_length
, &payload
))
1443 if (!frame
.is_control_frame()) {
1444 const SpdyDataFrame
& data_frame
=
1445 reinterpret_cast<const SpdyDataFrame
&>(frame
);
1446 if ((data_frame
.flags() & DATA_FLAG_COMPRESSED
) == 0)
1447 return DuplicateFrame(frame
);
1450 // Create an output frame. Assume it does not need to be longer than
1452 size_t decompressed_max_size
= kControlFrameBufferInitialSize
;
1453 int new_frame_size
= header_length
+ decompressed_max_size
;
1454 if (frame
.length() > decompressed_max_size
)
1456 scoped_ptr
<SpdyFrame
> new_frame(new SpdyFrame(new_frame_size
));
1457 memcpy(new_frame
->data(), frame
.data(),
1458 frame
.length() + SpdyFrame::kHeaderSize
);
1460 decompressor
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(payload
));
1461 decompressor
->avail_in
= payload_length
;
1462 decompressor
->next_out
= reinterpret_cast<Bytef
*>(new_frame
->data()) +
1464 decompressor
->avail_out
= decompressed_max_size
;
1466 int rv
= inflate(decompressor
, Z_SYNC_FLUSH
);
1467 if (rv
== Z_NEED_DICT
) {
1468 // Need to try again with the right dictionary.
1469 if (decompressor
->adler
== kDictionaryId
) {
1470 rv
= inflateSetDictionary(decompressor
,
1471 (const Bytef
*)SpdyFramer::kDictionary
,
1472 SpdyFramer::kDictionarySize
);
1474 rv
= inflate(decompressor
, Z_SYNC_FLUSH
);
1477 if (rv
!= Z_OK
) { // How can we know that it decompressed everything?
1478 LOG(WARNING
) << "inflate failure: " << rv
;
1482 // Unset the compressed flag for data frames.
1483 if (!new_frame
->is_control_frame()) {
1484 SpdyDataFrame
* data_frame
=
1485 reinterpret_cast<SpdyDataFrame
*>(new_frame
.get());
1486 data_frame
->set_flags(data_frame
->flags() & ~DATA_FLAG_COMPRESSED
);
1489 int decompressed_size
= decompressed_max_size
- decompressor
->avail_out
;
1490 new_frame
->set_length(
1491 header_length
+ decompressed_size
- SpdyFrame::kHeaderSize
);
1493 // If there is data left, then the frame didn't fully decompress. This
1494 // means that there is stranded data at the end of this frame buffer which
1496 DCHECK_EQ(decompressor
->avail_in
, 0u);
1498 pre_decompress_bytes
.Add(frame
.length());
1499 post_decompress_bytes
.Add(new_frame
->length());
1501 decompressed_frames
.Increment();
1503 return new_frame
.release();
1506 // Incrementally decompress the control frame's header block, feeding the
1507 // result to the visitor in chunks. Continue this until the visitor
1508 // indicates that it cannot process any more data, or (more commonly) we
1509 // run out of data to deliver.
1510 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
1511 const SpdyControlFrame
* control_frame
,
1514 // Get a decompressor or set error.
1515 z_stream
* decomp
= GetHeaderDecompressor();
1516 if (decomp
== NULL
) {
1517 LOG(DFATAL
) << "Couldn't get decompressor for handling compressed headers.";
1518 set_error(SPDY_DECOMPRESS_FAILURE
);
1522 bool processed_successfully
= true;
1523 char buffer
[kHeaderDataChunkMaxSize
];
1525 decomp
->next_in
= reinterpret_cast<Bytef
*>(const_cast<char*>(data
));
1526 decomp
->avail_in
= len
;
1527 const SpdyStreamId stream_id
= GetControlFrameStreamId(control_frame
);
1528 DCHECK_LT(0u, stream_id
);
1529 while (decomp
->avail_in
> 0 && processed_successfully
) {
1530 decomp
->next_out
= reinterpret_cast<Bytef
*>(buffer
);
1531 decomp
->avail_out
= arraysize(buffer
);
1532 int rv
= DecompressHeaderBlockInZStream(decomp
);
1533 if (rv
!= Z_OK
&& rv
!= Z_BUF_ERROR
) {
1534 set_error(SPDY_DECOMPRESS_FAILURE
);
1535 DLOG(WARNING
) << "inflate failure: " << rv
;
1536 processed_successfully
= false;
1538 size_t decompressed_len
= arraysize(buffer
) - decomp
->avail_out
;
1539 if (decompressed_len
> 0) {
1540 processed_successfully
= visitor_
->OnControlFrameHeaderData(
1541 stream_id
, buffer
, decompressed_len
);
1543 if (!processed_successfully
) {
1544 // Assume that the problem was the header block was too large for the
1546 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1550 return processed_successfully
;
1553 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
1554 const SpdyControlFrame
* control_frame
, const char* data
, size_t len
) {
1555 bool read_successfully
= true;
1556 const SpdyStreamId stream_id
= GetControlFrameStreamId(control_frame
);
1557 DCHECK_LT(0u, stream_id
);
1558 while (read_successfully
&& len
> 0) {
1559 size_t bytes_to_deliver
= std::min(len
, kHeaderDataChunkMaxSize
);
1560 read_successfully
= visitor_
->OnControlFrameHeaderData(stream_id
, data
,
1562 data
+= bytes_to_deliver
;
1563 len
-= bytes_to_deliver
;
1564 if (!read_successfully
) {
1565 // Assume that the problem was the header block was too large for the
1567 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE
);
1570 return read_successfully
;
1573 void SpdyFramer::CleanupCompressorForStream(SpdyStreamId id
) {
1574 CompressorMap::iterator it
= stream_compressors_
.find(id
);
1575 if (it
!= stream_compressors_
.end()) {
1576 z_stream
* compressor
= it
->second
;
1577 deflateEnd(compressor
);
1579 stream_compressors_
.erase(it
);
1583 void SpdyFramer::CleanupDecompressorForStream(SpdyStreamId id
) {
1584 CompressorMap::iterator it
= stream_decompressors_
.find(id
);
1585 if (it
!= stream_decompressors_
.end()) {
1586 z_stream
* decompressor
= it
->second
;
1587 inflateEnd(decompressor
);
1588 delete decompressor
;
1589 stream_decompressors_
.erase(it
);
1593 void SpdyFramer::CleanupStreamCompressorsAndDecompressors() {
1594 CompressorMap::iterator it
;
1596 it
= stream_compressors_
.begin();
1597 while (it
!= stream_compressors_
.end()) {
1598 z_stream
* compressor
= it
->second
;
1599 deflateEnd(compressor
);
1603 stream_compressors_
.clear();
1605 it
= stream_decompressors_
.begin();
1606 while (it
!= stream_decompressors_
.end()) {
1607 z_stream
* decompressor
= it
->second
;
1608 inflateEnd(decompressor
);
1609 delete decompressor
;
1612 stream_decompressors_
.clear();
1615 SpdyFrame
* SpdyFramer::DuplicateFrame(const SpdyFrame
& frame
) {
1616 int size
= SpdyFrame::kHeaderSize
+ frame
.length();
1617 SpdyFrame
* new_frame
= new SpdyFrame(size
);
1618 memcpy(new_frame
->data(), frame
.data(), size
);
1622 size_t SpdyFramer::GetMinimumControlFrameSize(SpdyControlType type
) {
1625 return SpdySynStreamControlFrame::size();
1627 return SpdySynReplyControlFrame::size();
1629 return SpdyRstStreamControlFrame::size();
1631 return SpdySettingsControlFrame::size();
1633 return SpdyNoOpControlFrame::size();
1635 return SpdyPingControlFrame::size();
1637 return SpdyGoAwayControlFrame::size();
1639 return SpdyHeadersControlFrame::size();
1641 return SpdyWindowUpdateControlFrame::size();
1643 return SpdyCredentialControlFrame::size();
1644 case NUM_CONTROL_FRAME_TYPES
:
1647 LOG(ERROR
) << "Unknown control frame type " << type
;
1648 return 0x7FFFFFFF; // Max signed 32bit int
1652 SpdyStreamId
SpdyFramer::GetControlFrameStreamId(
1653 const SpdyControlFrame
* control_frame
) {
1654 SpdyStreamId stream_id
= kInvalidStream
;
1655 if (control_frame
!= NULL
) {
1656 switch (control_frame
->type()) {
1658 stream_id
= reinterpret_cast<const SpdySynStreamControlFrame
*>(
1659 control_frame
)->stream_id();
1662 stream_id
= reinterpret_cast<const SpdySynReplyControlFrame
*>(
1663 control_frame
)->stream_id();
1666 stream_id
= reinterpret_cast<const SpdyHeadersControlFrame
*>(
1667 control_frame
)->stream_id();
1670 stream_id
= reinterpret_cast<const SpdyRstStreamControlFrame
*>(
1671 control_frame
)->stream_id();
1674 stream_id
= reinterpret_cast<const SpdyWindowUpdateControlFrame
*>(
1675 control_frame
)->stream_id();
1677 // All of the following types are not part of a particular stream.
1678 // They all fall through to the invalid control frame type case.
1679 // (The default case isn't used so that the compile will break if a new
1680 // control frame type is added but not included here.)
1686 case NUM_CONTROL_FRAME_TYPES
: // makes compiler happy
1693 size_t SpdyFramer::BytesSafeToRead() const {
1697 case SPDY_AUTO_RESET
:
1700 case SPDY_READING_COMMON_HEADER
:
1701 DCHECK_LT(current_frame_len_
,
1702 static_cast<size_t>(SpdyFrame::kHeaderSize
));
1703 return SpdyFrame::kHeaderSize
- current_frame_len_
;
1704 // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
1705 // and SPDY_CONTROL_FRAME_HEADER_BLOCK.
1706 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
:
1707 case SPDY_CONTROL_FRAME_HEADER_BLOCK
:
1709 case SPDY_CONTROL_FRAME_PAYLOAD
:
1710 case SPDY_CREDENTIAL_FRAME_PAYLOAD
:
1711 case SPDY_IGNORE_REMAINING_PAYLOAD
:
1712 case SPDY_FORWARD_STREAM_FRAME
:
1713 return remaining_data_
;
1715 // We should never get to here.
1719 void SpdyFramer::set_enable_compression(bool value
) {
1720 enable_compression_
= value
;
1723 void SpdyFramer::set_enable_compression_default(bool value
) {
1724 compression_default_
= value
;
1727 void SpdyFramer::set_validate_control_frame_sizes(bool value
) {
1728 validate_control_frame_sizes_
= value
;