chromeos: bluetooth: add BluetoothInputClient
[chromium-blink-merge.git] / net / spdy / spdy_framer.cc
blobf476c84ed190a897ba9330d2523eae90fea98034
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-
7 // prone.
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)
18 #include <zlib.h>
19 #else
20 #include "third_party/zlib/zlib.h"
21 #endif
23 using std::vector;
25 namespace spdy {
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);
50 if (rv == Z_OK)
51 rv = inflate(decompressor, Z_SYNC_FLUSH);
54 return rv;
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 +
65 it->first.size() +
66 SpdyControlFrame::kLengthOfValueSize +
67 it->second.size();
69 return total_length;
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) {
77 bool wrote_header;
78 wrote_header = frame->WriteString(it->first);
79 wrote_header &= frame->WriteString(it->second);
80 DCHECK(wrote_header);
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;
91 return flags_length;
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
99 // purposes.)
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) \
114 do { \
115 LOG(INFO) << "Changing state from: " \
116 << StateToString(state_) \
117 << " to " << StateToString(newstate) << "\n"; \
118 state_ = newstate; \
119 } while (false); \
121 #else
122 #define CHANGE_STATE(newstate) (state_ = newstate)
123 #endif
125 SpdyFramer::SpdyFramer()
126 : state_(SPDY_RESET),
127 error_code_(SPDY_NO_ERROR),
128 remaining_data_(0),
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_),
136 visitor_(NULL),
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() {
152 state_ = SPDY_RESET;
153 error_code_ = SPDY_NO_ERROR;
154 remaining_data_ = 0;
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) {
172 switch (state) {
173 case SPDY_ERROR:
174 return "ERROR";
175 case SPDY_DONE:
176 return "DONE";
177 case SPDY_AUTO_RESET:
178 return "AUTO_RESET";
179 case SPDY_RESET:
180 return "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) {
200 DCHECK(visitor_);
201 error_code_ = error;
202 CHANGE_STATE(SPDY_ERROR);
203 visitor_->OnError(this);
206 const char* SpdyFramer::ErrorCodeToString(int error_code) {
207 switch (error_code) {
208 case SPDY_NO_ERROR:
209 return "NO_ERROR";
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) {
228 case INVALID:
229 return "INVALID";
230 case PROTOCOL_ERROR:
231 return "PROTOCOL_ERROR";
232 case INVALID_STREAM:
233 return "INVALID_STREAM";
234 case REFUSED_STREAM:
235 return "REFUSED_STREAM";
236 case UNSUPPORTED_VERSION:
237 return "UNSUPPORTED_VERSION";
238 case CANCEL:
239 return "CANCEL";
240 case INTERNAL_ERROR:
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) {
249 switch (type) {
250 case SYN_STREAM:
251 return "SYN_STREAM";
252 case SYN_REPLY:
253 return "SYN_REPLY";
254 case RST_STREAM:
255 return "RST_STREAM";
256 case SETTINGS:
257 return "SETTINGS";
258 case NOOP:
259 return "NOOP";
260 case PING:
261 return "PING";
262 case GOAWAY:
263 return "GOAWAY";
264 case HEADERS:
265 return "HEADERS";
266 case WINDOW_UPDATE:
267 return "WINDOW_UPDATE";
268 case CREDENTIAL:
269 return "CREDENTIAL";
270 case NUM_CONTROL_FRAME_TYPES:
271 break;
273 return "UNKNOWN_CONTROL_TYPE";
276 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
277 DCHECK(visitor_);
278 DCHECK(data);
280 size_t original_len = len;
281 while (len != 0) {
282 switch (state_) {
283 case SPDY_ERROR:
284 case SPDY_DONE:
285 goto bottom;
287 case SPDY_AUTO_RESET:
288 case SPDY_RESET:
289 Reset();
290 CHANGE_STATE(SPDY_READING_COMMON_HEADER);
291 continue;
293 case SPDY_READING_COMMON_HEADER: {
294 size_t bytes_read = ProcessCommonHeader(data, len);
295 len -= bytes_read;
296 data += bytes_read;
297 continue;
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
303 // will go:
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);
310 len -= bytes_read;
311 data += bytes_read;
312 continue;
315 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
316 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
317 len -= bytes_read;
318 data += bytes_read;
319 continue;
322 case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
323 size_t bytes_read = ProcessCredentialFramePayload(data, len);
324 len -= bytes_read;
325 data += bytes_read;
326 continue;
329 case SPDY_CONTROL_FRAME_PAYLOAD: {
330 size_t bytes_read = ProcessControlFramePayload(data, len);
331 len -= bytes_read;
332 data += bytes_read;
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);
340 len -= bytes_read;
341 data += bytes_read;
342 continue;
344 default:
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.
348 goto bottom;
351 bottom:
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
357 // state.
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) {
370 // Do nothing.
371 } else if (current_frame_len_ == SpdyFrame::kHeaderSize &&
372 !current_frame.is_control_frame() &&
373 current_frame.length() == 0) {
374 // Empty data frame.
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);
381 } else {
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);
395 } else {
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);
411 return;
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);
420 return;
423 if (current_control_frame.type() == NOOP) {
424 DLOG(INFO) << "NOOP control frame found. Ignoring.";
425 CHANGE_STATE(SPDY_AUTO_RESET);
426 return;
429 if (validate_control_frame_sizes_) {
430 // Do some sanity checking on the control frame sizes.
431 switch (current_control_frame.type()) {
432 case SYN_STREAM:
433 if (current_control_frame.length() <
434 SpdySynStreamControlFrame::size() - SpdyControlFrame::kHeaderSize)
435 set_error(SPDY_INVALID_CONTROL_FRAME);
436 break;
437 case SYN_REPLY:
438 if (current_control_frame.length() <
439 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize)
440 set_error(SPDY_INVALID_CONTROL_FRAME);
441 break;
442 case RST_STREAM:
443 if (current_control_frame.length() !=
444 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize)
445 set_error(SPDY_INVALID_CONTROL_FRAME);
446 break;
447 case SETTINGS:
448 if (current_control_frame.length() <
449 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize)
450 set_error(SPDY_INVALID_CONTROL_FRAME);
451 break;
452 case GOAWAY:
453 if (current_control_frame.length() !=
454 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize)
455 set_error(SPDY_INVALID_CONTROL_FRAME);
456 break;
457 case HEADERS:
458 if (current_control_frame.length() <
459 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize)
460 set_error(SPDY_INVALID_CONTROL_FRAME);
461 break;
462 case WINDOW_UPDATE:
463 if (current_control_frame.length() !=
464 SpdyWindowUpdateControlFrame::size() -
465 SpdyControlFrame::kHeaderSize)
466 set_error(SPDY_INVALID_CONTROL_FRAME);
467 break;
468 case PING:
469 if (current_control_frame.length() !=
470 SpdyPingControlFrame::size() - SpdyControlFrame::kHeaderSize)
471 set_error(SPDY_INVALID_CONTROL_FRAME);
472 break;
473 case CREDENTIAL:
474 if (current_control_frame.length() <
475 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize)
476 set_error(SPDY_INVALID_CONTROL_FRAME);
477 break;
478 default:
479 LOG(WARNING) << "Valid " << display_protocol_
480 << " control frame with unhandled type: "
481 << current_control_frame.type();
482 DCHECK(false);
483 set_error(SPDY_INVALID_CONTROL_FRAME);
484 break;
488 // We only support version 1 of this protocol.
489 if (current_control_frame.version() != spdy_version_) {
490 set_error(SPDY_UNSUPPORTED_VERSION);
491 return;
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);
498 return;
501 if (current_control_frame.type() == CREDENTIAL) {
502 visitor_->OnControl(&current_control_frame);
503 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
504 return;
507 int32 frame_size_without_header_block;
508 switch (current_control_frame.type()) {
509 case SYN_STREAM:
510 frame_size_without_header_block = SpdySynStreamControlFrame::size();
511 break;
512 case SYN_REPLY:
513 frame_size_without_header_block = SpdySynReplyControlFrame::size();
514 break;
515 case HEADERS:
516 frame_size_without_header_block = SpdyHeadersControlFrame::size();
517 break;
518 default:
519 frame_size_without_header_block = -1;
520 LOG_IF(DFATAL, remaining_control_payload_ + SpdyFrame::kHeaderSize >
521 current_frame_capacity_)
522 << display_protocol_
523 << " control frame buffer too small for fixed-length frame.";
524 ExpandControlFrameBuffer(remaining_control_payload_);
525 break;
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),
533 current_frame_len_);
534 remaining_control_header_ = frame_size_without_header_block -
535 current_frame_len_;
536 remaining_control_payload_ += SpdyFrame::kHeaderSize -
537 frame_size_without_header_block;
538 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
539 return;
542 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
545 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
546 size_t max_bytes) {
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(&current_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,
557 size_t len) {
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,
584 size_t data_len) {
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);
597 } else {
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),
613 NULL, 0);
616 CHANGE_STATE(SPDY_RESET);
619 // Handle error.
620 if (!processed_successfully) {
621 return data_len;
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);
655 return len;
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());
668 if (!decompressor)
669 return 0;
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);
681 if (rv != Z_OK) {
682 LOG(WARNING) << "inflate failure: " << rv;
683 set_error(SPDY_DECOMPRESS_FAILURE);
684 return 0;
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(),
692 decompressed.get(),
693 decompressed_size);
694 amount_to_forward -= decompressor->avail_in;
695 } else {
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());
714 } else {
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_)
724 return;
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;
732 /* static */
733 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
734 size_t header_length,
735 SpdyHeaderBlock* block) {
736 SpdyFrameBuilder builder(header_data, header_length);
737 void* iter = NULL;
738 uint16 num_headers;
739 if (builder.ReadUInt16(&iter, &num_headers)) {
740 for (int index = 0; index < num_headers; ++index) {
741 std::string name;
742 std::string value;
743 if (!builder.ReadString(&iter, &name))
744 return false;
745 if (!builder.ReadString(&iter, &value))
746 return false;
747 if (block->find(name) == block->end()) {
748 (*block)[name] = value;
749 } else {
750 return false;
753 return true;
755 return false;
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)
763 return false;
765 // Find the header data within the control frame.
766 scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame));
767 if (!decompressed_frame.get())
768 return false;
770 const char *header_data = NULL;
771 int header_length = 0;
773 switch (type) {
774 case SYN_STREAM:
776 SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
777 header_data = syn_frame.header_block();
778 header_length = syn_frame.header_block_len();
780 break;
781 case SYN_REPLY:
783 SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
784 header_data = syn_frame.header_block();
785 header_length = syn_frame.header_block_len();
787 break;
788 case HEADERS:
790 SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
791 header_data = header_frame.header_block();
792 header_length = header_frame.header_block_len();
794 break;
797 SpdyFrameBuilder builder(header_data, header_length);
798 void* iter = NULL;
799 uint16 num_headers;
800 if (builder.ReadUInt16(&iter, &num_headers)) {
801 int index;
802 for (index = 0; index < num_headers; ++index) {
803 std::string name;
804 std::string value;
805 if (!builder.ReadString(&iter, &name))
806 break;
807 if (!builder.ReadString(&iter, &value))
808 break;
809 if (!name.size() || !value.size())
810 return false;
811 if (block->find(name) == block->end()) {
812 (*block)[name] = value;
813 } else {
814 return false;
817 return index == num_headers &&
818 iter == header_data + header_length;
820 return false;
823 /* static */
824 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
825 SpdySettings* settings) {
826 DCHECK_EQ(frame->type(), SETTINGS);
827 DCHECK(settings);
829 SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
830 void* iter = NULL;
831 for (size_t index = 0; index < frame->num_entries(); ++index) {
832 uint32 id;
833 uint32 value;
834 if (!parser.ReadUInt32(&iter, &id))
835 return false;
836 if (!parser.ReadUInt32(&iter, &value))
837 return false;
838 settings->insert(settings->end(), std::make_pair(id, value));
840 return true;
843 /* static */
844 bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
845 SpdyCredential* credential) {
846 DCHECK(credential);
848 void* iter = NULL;
849 SpdyFrameBuilder parser(data, len);
850 if (!parser.ReadUInt16(&iter, &credential->slot))
851 return false;
853 uint16 origin_len;
854 const char* origin_data;
855 if (!parser.ReadData(&iter, &origin_data, &origin_len))
856 return false;
857 credential->origin.assign(origin_data, origin_len);
859 uint32 proof_len;
860 const char* proof_data;
861 if (!parser.ReadReadLen32PrefixedData(&iter, &proof_data, &proof_len))
862 return false;
863 credential->proof.assign(proof_data, proof_len);
865 while (parser.IteratorHasRoomFor(iter, 1)) {
866 uint32 cert_len;
867 const char* cert_data;
868 if (!parser.ReadReadLen32PrefixedData(&iter, &cert_data, &cert_len))
869 return false;
870 credential->certs.push_back("");
871 credential->certs.back().assign(cert_data, cert_len);
873 return true;
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);
883 // Find our length.
884 size_t expected_frame_size = SpdySynStreamControlFrame::size() +
885 GetSerializedLength(headers);
887 // Create our FlagsAndLength.
888 FlagsAndLength flags_length = CreateFlagsAndLength(
889 flags,
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()));
903 if (compressed) {
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);
915 // Find our length.
916 size_t expected_frame_size = SpdySynReplyControlFrame::size() +
917 GetSerializedLength(headers);
919 // Create our FlagsAndLength.
920 FlagsAndLength flags_length = CreateFlagsAndLength(
921 flags,
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()));
934 if (compressed) {
935 return reinterpret_cast<SpdySynReplyControlFrame*>(
936 CompressControlFrame(*reply_frame.get()));
938 return reply_frame.release();
941 /* static */
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());
958 /* static */
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 +
966 8 * values.size();
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);
973 ++it;
975 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
978 /* static */
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());
987 /* static */
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());
998 /* static */
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);
1018 // Find our length.
1019 size_t expected_frame_size = SpdyHeadersControlFrame::size() +
1020 GetSerializedLength(headers);
1022 // Create our FlagsAndLength.
1023 FlagsAndLength flags_length = CreateFlagsAndLength(
1024 flags,
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()));
1038 if (compressed) {
1039 return reinterpret_cast<SpdyHeadersControlFrame*>(
1040 CompressControlFrame(*headers_frame.get()));
1042 return headers_frame.release();
1045 /* static */
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());
1065 /* static */
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();
1075 cert++) {
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();
1096 cert++) {
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,
1104 const char* data,
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());
1121 SpdyDataFrame* rv;
1122 if (flags & DATA_FLAG_COMPRESSED) {
1123 rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get()));
1124 } else {
1125 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
1128 if (flags & DATA_FLAG_FIN) {
1129 CleanupCompressorForStream(stream_id);
1132 return rv;
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
1179 // and SYN_REPLY.
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(),
1202 kCompressorLevel,
1203 Z_DEFLATED,
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),
1210 kDictionarySize);
1211 if (success != Z_OK) {
1212 LOG(WARNING) << "deflateSetDictionary failure: " << success;
1213 header_compressor_.reset(NULL);
1214 return 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);
1230 return 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(),
1244 kCompressorLevel,
1245 Z_DEFLATED,
1246 kCompressorWindowSizeInBits,
1247 kCompressorMemLevel,
1248 Z_DEFAULT_STRATEGY);
1249 if (success != Z_OK) {
1250 LOG(WARNING) << "deflateInit failure: " << success;
1251 return NULL;
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;
1267 return NULL;
1269 return stream_decompressors_[stream_id] = decompressor.release();
1272 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
1273 int* payload_length,
1274 int* header_length,
1275 const char** payload) const {
1276 size_t frame_size;
1277 if (frame.is_control_frame()) {
1278 const SpdyControlFrame& control_frame =
1279 reinterpret_cast<const SpdyControlFrame&>(frame);
1280 switch (control_frame.type()) {
1281 case SYN_STREAM:
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;
1290 break;
1291 case SYN_REPLY:
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;
1300 break;
1301 case HEADERS:
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;
1310 break;
1311 default:
1312 // TODO(mbelshe): set an error?
1313 return false; // We can't compress this frame!
1315 } else {
1316 frame_size = SpdyFrame::kHeaderSize;
1317 *header_length = frame_size;
1318 *payload_length = frame.length();
1319 *payload = frame.data() + SpdyFrame::kHeaderSize;
1321 return true;
1324 SpdyControlFrame* SpdyFramer::CompressControlFrame(
1325 const SpdyControlFrame& frame) {
1326 z_stream* compressor = GetHeaderCompressor();
1327 if (!compressor)
1328 return NULL;
1329 return reinterpret_cast<SpdyControlFrame*>(
1330 CompressFrameWithZStream(frame, compressor));
1333 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
1334 z_stream* compressor = GetStreamCompressor(frame.stream_id());
1335 if (!compressor)
1336 return NULL;
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);
1347 return NULL;
1349 return reinterpret_cast<SpdyControlFrame*>(
1350 DecompressFrameWithZStream(frame, decompressor));
1353 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
1354 z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
1355 if (!decompressor)
1356 return NULL;
1357 return reinterpret_cast<SpdyDataFrame*>(
1358 DecompressFrameWithZStream(frame, decompressor));
1361 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame,
1362 z_stream* compressor) {
1363 int payload_length;
1364 int header_length;
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))
1375 return NULL;
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()) +
1387 header_length;
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;
1406 return NULL;
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,
1414 compressed_size);
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) {
1429 int payload_length;
1430 int header_length;
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))
1441 return NULL;
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
1451 // the input data.
1452 size_t decompressed_max_size = kControlFrameBufferInitialSize;
1453 int new_frame_size = header_length + decompressed_max_size;
1454 if (frame.length() > decompressed_max_size)
1455 return NULL;
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()) +
1463 header_length;
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);
1473 if (rv == Z_OK)
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;
1479 return NULL;
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
1495 // will be ignored.
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,
1512 const char* data,
1513 size_t len) {
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);
1519 return false;
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;
1537 } else {
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
1545 // visitor.
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,
1561 bytes_to_deliver);
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
1566 // visitor.
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);
1578 delete 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);
1600 delete compressor;
1601 ++it;
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;
1610 ++it;
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);
1619 return new_frame;
1622 size_t SpdyFramer::GetMinimumControlFrameSize(SpdyControlType type) {
1623 switch (type) {
1624 case SYN_STREAM:
1625 return SpdySynStreamControlFrame::size();
1626 case SYN_REPLY:
1627 return SpdySynReplyControlFrame::size();
1628 case RST_STREAM:
1629 return SpdyRstStreamControlFrame::size();
1630 case SETTINGS:
1631 return SpdySettingsControlFrame::size();
1632 case NOOP:
1633 return SpdyNoOpControlFrame::size();
1634 case PING:
1635 return SpdyPingControlFrame::size();
1636 case GOAWAY:
1637 return SpdyGoAwayControlFrame::size();
1638 case HEADERS:
1639 return SpdyHeadersControlFrame::size();
1640 case WINDOW_UPDATE:
1641 return SpdyWindowUpdateControlFrame::size();
1642 case CREDENTIAL:
1643 return SpdyCredentialControlFrame::size();
1644 case NUM_CONTROL_FRAME_TYPES:
1645 break;
1647 LOG(ERROR) << "Unknown control frame type " << type;
1648 return 0x7FFFFFFF; // Max signed 32bit int
1651 /* static */
1652 SpdyStreamId SpdyFramer::GetControlFrameStreamId(
1653 const SpdyControlFrame* control_frame) {
1654 SpdyStreamId stream_id = kInvalidStream;
1655 if (control_frame != NULL) {
1656 switch (control_frame->type()) {
1657 case SYN_STREAM:
1658 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>(
1659 control_frame)->stream_id();
1660 break;
1661 case SYN_REPLY:
1662 stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>(
1663 control_frame)->stream_id();
1664 break;
1665 case HEADERS:
1666 stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>(
1667 control_frame)->stream_id();
1668 break;
1669 case RST_STREAM:
1670 stream_id = reinterpret_cast<const SpdyRstStreamControlFrame*>(
1671 control_frame)->stream_id();
1672 break;
1673 case WINDOW_UPDATE:
1674 stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame*>(
1675 control_frame)->stream_id();
1676 break;
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.)
1681 case SETTINGS:
1682 case NOOP:
1683 case PING:
1684 case GOAWAY:
1685 case CREDENTIAL:
1686 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy
1687 break;
1690 return stream_id;
1693 size_t SpdyFramer::BytesSafeToRead() const {
1694 switch (state_) {
1695 case SPDY_ERROR:
1696 case SPDY_DONE:
1697 case SPDY_AUTO_RESET:
1698 case SPDY_RESET:
1699 return 0;
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:
1708 return 0;
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.
1716 return 0;
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;
1731 } // namespace spdy