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

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

Issue 9618002: SPDY - integration of spdy/3 code. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't 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- 6 // constantly adding and subtracting header sizes; this is ugly and error-
7 // prone. 7 // prone.
8 8
9 #include "net/spdy/spdy_framer.h" 9 #include "net/spdy/spdy_framer.h"
10 10
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/stats_counters.h" 12 #include "base/metrics/stats_counters.h"
13 #include "base/third_party/valgrind/memcheck.h" 13 #include "base/third_party/valgrind/memcheck.h"
14 #include "net/spdy/spdy_frame_builder.h" 14 #include "net/spdy/spdy_frame_builder.h"
15 #include "net/spdy/spdy_frame_reader.h"
15 #include "net/spdy/spdy_bitmasks.h" 16 #include "net/spdy/spdy_bitmasks.h"
16 17
17 #if defined(USE_SYSTEM_ZLIB) 18 #if defined(USE_SYSTEM_ZLIB)
18 #include <zlib.h> 19 #include <zlib.h>
19 #else 20 #else
20 #include "third_party/zlib/zlib.h" 21 #include "third_party/zlib/zlib.h"
21 #endif 22 #endif
22 23
23 using std::vector; 24 using std::vector;
24 25
25 namespace spdy { 26 namespace spdy {
26 27
27 SpdyCredential::SpdyCredential() : slot(0) { }
28 SpdyCredential::~SpdyCredential() { }
29
30 // Compute the id of our dictionary so that we know we're using the 28 // Compute the id of our dictionary so that we know we're using the
31 // right one when asked for it. 29 // right one when asked for it.
32 uLong CalculateDictionaryId() { 30 uLong CalculateDictionaryId(const char* dictionary,
31 const size_t dictionary_size) {
33 uLong initial_value = adler32(0L, Z_NULL, 0); 32 uLong initial_value = adler32(0L, Z_NULL, 0);
34 return adler32(initial_value, 33 return adler32(initial_value,
35 reinterpret_cast<const Bytef*>(SpdyFramer::kDictionary), 34 reinterpret_cast<const Bytef*>(dictionary),
36 SpdyFramer::kDictionarySize); 35 dictionary_size);
37 } 36 }
38 37
39 // Adler ID for the SPDY header compressor dictionary. 38 // Adler ID for the SPDY header compressor dictionaries.
40 const uLong kDictionaryId = CalculateDictionaryId(); 39 const uLong kV2DictionaryId = CalculateDictionaryId(kV2Dictionary,
41 40 kV2DictionarySize);
42 int DecompressHeaderBlockInZStream(z_stream* decompressor) { 41 const uLong kV3DictionaryId = CalculateDictionaryId(kV3Dictionary,
43 int rv = inflate(decompressor, Z_SYNC_FLUSH); 42 kV3DictionarySize);
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);
52 }
53 }
54 return rv;
55 }
56
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();
68 }
69 return total_length;
70 }
71
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);
81 }
82 }
83 43
84 // Creates a FlagsAndLength. 44 // Creates a FlagsAndLength.
85 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) { 45 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) {
86 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 46 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask));
87 FlagsAndLength flags_length; 47 FlagsAndLength flags_length;
88 flags_length.length_ = htonl(static_cast<uint32>(length)); 48 flags_length.length_ = htonl(static_cast<uint32>(length));
89 DCHECK_EQ(0, flags & ~kControlFlagsMask); 49 DCHECK_EQ(0, flags & ~kControlFlagsMask);
90 flags_length.flags_[0] = flags; 50 flags_length.flags_[0] = flags;
91 return flags_length; 51 return flags_length;
92 } 52 }
93 53
94 // By default is compression on or off. 54 // By default is compression on or off.
95 bool SpdyFramer::compression_default_ = true; 55 bool SpdyFramer::compression_default_ = true;
96 56
97 // The initial size of the control frame buffer; this is used internally 57 // 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 58 // as we parse through control frames. (It is exposed here for unit test
99 // purposes.) 59 // purposes.)
100 size_t SpdyFramer::kControlFrameBufferInitialSize = 32 * 1024; 60 size_t SpdyFramer::kControlFrameBufferInitialSize = 32 * 1024;
101 61
102 // The maximum size of the control frame buffer that we support. 62 // 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. 63 // TODO(mbelshe): We should make this stream-based so there are no limits.
104 size_t SpdyFramer::kControlFrameBufferMaxSize = 64 * 1024; 64 size_t SpdyFramer::kControlFrameBufferMaxSize = 64 * 1024;
105 65
106 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion;
107
108 const SpdyStreamId SpdyFramer::kInvalidStream = -1; 66 const SpdyStreamId SpdyFramer::kInvalidStream = -1;
109 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 67 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
68 size_t SpdyFramer::kUncompressedControlFrameBufferInitialSize = 18 + 16;
Ryan Hamilton 2012/03/09 19:09:58 Can you add a comment explaining why this is the r
ramant (doing other things) 2012/03/10 01:14:09 Done.
69
110 70
111 #ifdef DEBUG_SPDY_STATE_CHANGES 71 #ifdef DEBUG_SPDY_STATE_CHANGES
112 #define CHANGE_STATE(newstate) \ 72 #define CHANGE_STATE(newstate) \
113 { \ 73 { \
114 do { \ 74 do { \
115 LOG(INFO) << "Changing state from: " \ 75 LOG(INFO) << "Changing state from: " \
116 << StateToString(state_) \ 76 << StateToString(state_) \
117 << " to " << StateToString(newstate) << "\n"; \ 77 << " to " << StateToString(newstate) << "\n"; \
118 state_ = newstate; \ 78 state_ = newstate; \
119 } while (false); \ 79 } while (false); \
120 } 80 }
121 #else 81 #else
122 #define CHANGE_STATE(newstate) (state_ = newstate) 82 #define CHANGE_STATE(newstate) (state_ = newstate)
123 #endif 83 #endif
124 84
125 SpdyFramer::SpdyFramer() 85 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version,
86 uint32 wire) {
87 if (version < 3) {
88 ConvertFlagsAndIdForSpdy2(&wire);
89 }
90 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff);
91 }
92
93 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id)
94 : flags_(flags), id_(id & 0x00ffffff) {
95 DCHECK_GT(static_cast<uint32>(1 << 24), id);
96 }
97
98 uint32 SettingsFlagsAndId::GetWireFormat(int version) const {
99 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24);
100 if (version < 3) {
101 ConvertFlagsAndIdForSpdy2(&wire);
102 }
103 return wire;
104 }
105
106 // SPDY 2 had a bug in it with respect to byte ordering of id/flags field.
107 // This method is used to preserve buggy behavior and works on both
108 // little-endian and big-endian hosts.
109 // This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3
110 // as well as vice versa).
111 void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
112 uint8* wire_array = reinterpret_cast<uint8*>(val);
113 std::swap(wire_array[0], wire_array[3]);
114 std::swap(wire_array[1], wire_array[2]);
115 }
116
117 SpdyCredential::SpdyCredential() : slot(0) { }
118 SpdyCredential::~SpdyCredential() { }
119
120 SpdyFramer::SpdyFramer(int version)
126 : state_(SPDY_RESET), 121 : state_(SPDY_RESET),
127 error_code_(SPDY_NO_ERROR), 122 error_code_(SPDY_NO_ERROR),
128 remaining_data_(0), 123 remaining_data_(0),
129 remaining_control_payload_(0), 124 remaining_control_payload_(0),
130 remaining_control_header_(0), 125 remaining_control_header_(0),
131 current_frame_buffer_(NULL), 126 current_frame_buffer_(NULL),
132 current_frame_len_(0), 127 current_frame_len_(0),
133 current_frame_capacity_(0), 128 current_frame_capacity_(0),
134 validate_control_frame_sizes_(true), 129 validate_control_frame_sizes_(true),
135 enable_compression_(compression_default_), 130 enable_compression_(compression_default_),
136 visitor_(NULL), 131 visitor_(NULL),
137 display_protocol_("SPDY") { 132 display_protocol_("SPDY"),
133 spdy_version_(version),
134 syn_frame_processed_(false),
135 probable_http_response_(false) {
136 DCHECK_GE(3, version);
137 DCHECK_LE(2, version);
138 } 138 }
139 139
140 SpdyFramer::~SpdyFramer() { 140 SpdyFramer::~SpdyFramer() {
141 if (header_compressor_.get()) { 141 if (header_compressor_.get()) {
142 deflateEnd(header_compressor_.get()); 142 deflateEnd(header_compressor_.get());
143 } 143 }
144 if (header_decompressor_.get()) { 144 if (header_decompressor_.get()) {
145 inflateEnd(header_decompressor_.get()); 145 inflateEnd(header_decompressor_.get());
146 } 146 }
147 CleanupStreamCompressorsAndDecompressors(); 147 CleanupStreamCompressorsAndDecompressors();
148 delete [] current_frame_buffer_; 148 delete [] current_frame_buffer_;
149 } 149 }
150 150
151 void SpdyFramer::Reset() { 151 void SpdyFramer::Reset() {
152 state_ = SPDY_RESET; 152 state_ = SPDY_RESET;
153 error_code_ = SPDY_NO_ERROR; 153 error_code_ = SPDY_NO_ERROR;
154 remaining_data_ = 0; 154 remaining_data_ = 0;
155 remaining_control_payload_ = 0; 155 remaining_control_payload_ = 0;
156 remaining_control_header_ = 0; 156 remaining_control_header_ = 0;
157 current_frame_len_ = 0; 157 current_frame_len_ = 0;
158 settings_scratch_.Reset();
158 // TODO(hkhalil): Remove once initial_size == kControlFrameBufferInitialSize. 159 // TODO(hkhalil): Remove once initial_size == kControlFrameBufferInitialSize.
159 size_t initial_size = kControlFrameBufferInitialSize; 160 size_t initial_size = kControlFrameBufferInitialSize;
160 if (!enable_compression_) { 161 if (!enable_compression_) {
161 initial_size = kUncompressedControlFrameBufferInitialSize; 162 initial_size = kUncompressedControlFrameBufferInitialSize;
162 } 163 }
163 if (current_frame_capacity_ != initial_size) { 164 if (current_frame_capacity_ != initial_size) {
164 delete [] current_frame_buffer_; 165 delete [] current_frame_buffer_;
165 current_frame_buffer_ = 0; 166 current_frame_buffer_ = 0;
166 current_frame_capacity_ = 0; 167 current_frame_capacity_ = 0;
167 ExpandControlFrameBuffer(initial_size); 168 ExpandControlFrameBuffer(initial_size);
(...skipping 17 matching lines...) Expand all
185 case SPDY_IGNORE_REMAINING_PAYLOAD: 186 case SPDY_IGNORE_REMAINING_PAYLOAD:
186 return "IGNORE_REMAINING_PAYLOAD"; 187 return "IGNORE_REMAINING_PAYLOAD";
187 case SPDY_FORWARD_STREAM_FRAME: 188 case SPDY_FORWARD_STREAM_FRAME:
188 return "FORWARD_STREAM_FRAME"; 189 return "FORWARD_STREAM_FRAME";
189 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 190 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
190 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 191 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK";
191 case SPDY_CONTROL_FRAME_HEADER_BLOCK: 192 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
192 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 193 return "SPDY_CONTROL_FRAME_HEADER_BLOCK";
193 case SPDY_CREDENTIAL_FRAME_PAYLOAD: 194 case SPDY_CREDENTIAL_FRAME_PAYLOAD:
194 return "SPDY_CREDENTIAL_FRAME_PAYLOAD"; 195 return "SPDY_CREDENTIAL_FRAME_PAYLOAD";
196 case SPDY_SETTINGS_FRAME_PAYLOAD:
197 return "SPDY_SETTINGS_FRAME_PAYLOAD";
195 } 198 }
196 return "UNKNOWN_STATE"; 199 return "UNKNOWN_STATE";
197 } 200 }
198 201
199 void SpdyFramer::set_error(SpdyError error) { 202 void SpdyFramer::set_error(SpdyError error) {
200 DCHECK(visitor_); 203 DCHECK(visitor_);
201 error_code_ = error; 204 error_code_ = error;
202 CHANGE_STATE(SPDY_ERROR); 205 CHANGE_STATE(SPDY_ERROR);
203 visitor_->OnError(this); 206 visitor_->OnError(this);
204 } 207 }
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 continue; 300 continue;
298 } 301 }
299 302
300 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 303 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: {
301 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, 304 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY,
302 // HEADERS) take a different path through the state machine - they 305 // HEADERS) take a different path through the state machine - they
303 // will go: 306 // will go:
304 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 307 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
305 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK 308 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK
306 // 309 //
310 // SETTINGS frames take a slightly modified route:
311 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
312 // 2. SPDY_SETTINGS_FRAME_PAYLOAD
313 //
307 // All other control frames will use the alternate route directly to 314 // All other control frames will use the alternate route directly to
308 // SPDY_CONTROL_FRAME_PAYLOAD 315 // SPDY_CONTROL_FRAME_PAYLOAD
309 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 316 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len);
310 len -= bytes_read; 317 len -= bytes_read;
311 data += bytes_read; 318 data += bytes_read;
312 continue; 319 continue;
313 } 320 }
314 321
322 case SPDY_SETTINGS_FRAME_PAYLOAD: {
323 int bytes_read = ProcessSettingsFramePayload(data, len);
324 len -= bytes_read;
325 data += bytes_read;
326 continue;
327 }
328
315 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 329 case SPDY_CONTROL_FRAME_HEADER_BLOCK: {
316 int bytes_read = ProcessControlFrameHeaderBlock(data, len); 330 int bytes_read = ProcessControlFrameHeaderBlock(data, len);
317 len -= bytes_read; 331 len -= bytes_read;
318 data += bytes_read; 332 data += bytes_read;
319 continue; 333 continue;
320 } 334 }
321 335
322 case SPDY_CREDENTIAL_FRAME_PAYLOAD: { 336 case SPDY_CREDENTIAL_FRAME_PAYLOAD: {
323 size_t bytes_read = ProcessCredentialFramePayload(data, len); 337 size_t bytes_read = ProcessCredentialFramePayload(data, len);
324 len -= bytes_read; 338 len -= bytes_read;
325 data += bytes_read; 339 data += bytes_read;
326 continue;
327 } 340 }
328 341
329 case SPDY_CONTROL_FRAME_PAYLOAD: { 342 case SPDY_CONTROL_FRAME_PAYLOAD: {
330 size_t bytes_read = ProcessControlFramePayload(data, len); 343 size_t bytes_read = ProcessControlFramePayload(data, len);
331 len -= bytes_read; 344 len -= bytes_read;
332 data += bytes_read; 345 data += bytes_read;
333 } 346 }
334 // intentional fallthrough 347 // intentional fallthrough
335 case SPDY_IGNORE_REMAINING_PAYLOAD: 348 case SPDY_IGNORE_REMAINING_PAYLOAD:
336 // control frame has too-large payload 349 // control frame has too-large payload
337 // intentional fallthrough 350 // intentional fallthrough
338 case SPDY_FORWARD_STREAM_FRAME: { 351 case SPDY_FORWARD_STREAM_FRAME: {
339 size_t bytes_read = ProcessDataFramePayload(data, len); 352 size_t bytes_read = ProcessDataFramePayload(data, len);
340 len -= bytes_read; 353 len -= bytes_read;
341 data += bytes_read; 354 data += bytes_read;
342 continue; 355 continue;
343 } 356 }
344 default: 357 default:
358 LOG(ERROR) << "Invalid value for " << display_protocol_
359 << " framer state: " << state_;
345 // This ensures that we don't infinite-loop if state_ gets an 360 // This ensures that we don't infinite-loop if state_ gets an
346 // invalid value somehow, such as due to a SpdyFramer getting deleted 361 // invalid value somehow, such as due to a SpdyFramer getting deleted
347 // from a callback it calls. 362 // from a callback it calls.
348 goto bottom; 363 goto bottom;
349 } 364 }
350 } 365 }
351 bottom: 366 bottom:
352 return original_len - len; 367 return original_len - len;
353 } 368 }
354 369
(...skipping 21 matching lines...) Expand all
376 visitor_->OnDataFrameHeader(&data_frame); 391 visitor_->OnDataFrameHeader(&data_frame);
377 if (current_frame.flags() & DATA_FLAG_FIN) { 392 if (current_frame.flags() & DATA_FLAG_FIN) {
378 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); 393 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
379 } 394 }
380 CHANGE_STATE(SPDY_AUTO_RESET); 395 CHANGE_STATE(SPDY_AUTO_RESET);
381 } else { 396 } else {
382 remaining_data_ = current_frame.length(); 397 remaining_data_ = current_frame.length();
383 398
384 // This is just a sanity check for help debugging early frame errors. 399 // This is just a sanity check for help debugging early frame errors.
385 if (remaining_data_ > 1000000u) { 400 if (remaining_data_ > 1000000u) {
386 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ 401 // The strncmp for 5 is safe because we only hit this point if we
387 << " session is likely corrupt."; 402 // have SpdyFrame::kHeaderSize (8) bytes
403 if (!syn_frame_processed_ &&
404 strncmp(current_frame_buffer_, "HTTP/", 5) == 0) {
405 LOG(WARNING) << "Unexpected HTTP response to spdy request";
406 probable_http_response_ = true;
407 } else {
408 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_
409 << " session is likely corrupt.";
410 }
388 } 411 }
389 412
390 // if we're here, then we have the common header all received. 413 // if we're here, then we have the common header all received.
391 if (!current_frame.is_control_frame()) { 414 if (!current_frame.is_control_frame()) {
392 SpdyDataFrame data_frame(current_frame_buffer_, false); 415 SpdyDataFrame data_frame(current_frame_buffer_, false);
393 visitor_->OnDataFrameHeader(&data_frame); 416 visitor_->OnDataFrameHeader(&data_frame);
394 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 417 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
395 } else { 418 } else {
396 ProcessControlFrameHeader(); 419 ProcessControlFrameHeader();
397 } 420 }
398 } 421 }
399 return original_len - len; 422 return original_len - len;
400 } 423 }
401 424
402 void SpdyFramer::ProcessControlFrameHeader() { 425 void SpdyFramer::ProcessControlFrameHeader() {
403 DCHECK_EQ(SPDY_NO_ERROR, error_code_); 426 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
404 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize), current_frame_len_); 427 DCHECK_LE(static_cast<size_t>(SpdyFrame::kHeaderSize), current_frame_len_);
405 SpdyControlFrame current_control_frame(current_frame_buffer_, false); 428 SpdyControlFrame current_control_frame(current_frame_buffer_, false);
406 429
407 // We check version before we check validity: version can never be 'invalid', 430 // We check version before we check validity: version can never be 'invalid',
408 // it can only be unsupported. 431 // it can only be unsupported.
409 if (current_control_frame.version() != spdy_version_) { 432 if (current_control_frame.version() != spdy_version_) {
433 DLOG(INFO) << "Unsupported SPDY version " << current_control_frame.version()
434 << " (expected " << spdy_version_ << ")";
410 set_error(SPDY_UNSUPPORTED_VERSION); 435 set_error(SPDY_UNSUPPORTED_VERSION);
411 return; 436 return;
412 } 437 }
413 438
414 // Next up, check to see if we have valid data. This should be after version 439 // 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 440 // 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 441 // upgrade we would misclassify the error) and before checking the type
417 // (type can definitely be out of bounds) 442 // (type can definitely be out of bounds)
418 if (!current_control_frame.AppearsToBeAValidControlFrame()) { 443 if (!current_control_frame.AppearsToBeAValidControlFrame()) {
419 set_error(SPDY_INVALID_CONTROL_FRAME); 444 set_error(SPDY_INVALID_CONTROL_FRAME);
(...skipping 18 matching lines...) Expand all
438 if (current_control_frame.length() < 463 if (current_control_frame.length() <
439 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize) 464 SpdySynReplyControlFrame::size() - SpdyControlFrame::kHeaderSize)
440 set_error(SPDY_INVALID_CONTROL_FRAME); 465 set_error(SPDY_INVALID_CONTROL_FRAME);
441 break; 466 break;
442 case RST_STREAM: 467 case RST_STREAM:
443 if (current_control_frame.length() != 468 if (current_control_frame.length() !=
444 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize) 469 SpdyRstStreamControlFrame::size() - SpdyFrame::kHeaderSize)
445 set_error(SPDY_INVALID_CONTROL_FRAME); 470 set_error(SPDY_INVALID_CONTROL_FRAME);
446 break; 471 break;
447 case SETTINGS: 472 case SETTINGS:
473 // Make sure that we have an integral number of 8-byte key/value pairs,
474 // plus a 4-byte length field.
448 if (current_control_frame.length() < 475 if (current_control_frame.length() <
449 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize) 476 SpdySettingsControlFrame::size() - SpdyControlFrame::kHeaderSize ||
477 (current_control_frame.length() % 8 != 4)) {
478 DLOG(WARNING) << "Invalid length for SETTINGS frame: "
479 << current_control_frame.length();
450 set_error(SPDY_INVALID_CONTROL_FRAME); 480 set_error(SPDY_INVALID_CONTROL_FRAME);
481 }
451 break; 482 break;
452 case GOAWAY: 483 case GOAWAY:
453 if (current_control_frame.length() != 484 if (current_control_frame.length() !=
454 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize) 485 SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize)
455 set_error(SPDY_INVALID_CONTROL_FRAME); 486 set_error(SPDY_INVALID_CONTROL_FRAME);
456 break; 487 break;
457 case HEADERS: 488 case HEADERS:
458 if (current_control_frame.length() < 489 if (current_control_frame.length() <
459 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize) 490 SpdyHeadersControlFrame::size() - SpdyControlFrame::kHeaderSize)
460 set_error(SPDY_INVALID_CONTROL_FRAME); 491 set_error(SPDY_INVALID_CONTROL_FRAME);
(...skipping 17 matching lines...) Expand all
478 default: 509 default:
479 LOG(WARNING) << "Valid " << display_protocol_ 510 LOG(WARNING) << "Valid " << display_protocol_
480 << " control frame with unhandled type: " 511 << " control frame with unhandled type: "
481 << current_control_frame.type(); 512 << current_control_frame.type();
482 DCHECK(false); 513 DCHECK(false);
483 set_error(SPDY_INVALID_CONTROL_FRAME); 514 set_error(SPDY_INVALID_CONTROL_FRAME);
484 break; 515 break;
485 } 516 }
486 } 517 }
487 518
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;
492 }
493
494 remaining_control_payload_ = current_control_frame.length(); 519 remaining_control_payload_ = current_control_frame.length();
495 if (remaining_control_payload_ > 520 if (remaining_control_payload_ >
496 kControlFrameBufferMaxSize - SpdyFrame::kHeaderSize) { 521 kControlFrameBufferMaxSize - SpdyFrame::kHeaderSize) {
497 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 522 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
498 return; 523 return;
499 } 524 }
500 525
501 if (current_control_frame.type() == CREDENTIAL) { 526 if (current_control_frame.type() == CREDENTIAL) {
502 visitor_->OnControl(&current_control_frame); 527 visitor_->OnControl(&current_control_frame);
503 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD); 528 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD);
504 return; 529 return;
505 } 530 }
506 531
507 int32 frame_size_without_header_block; 532 // Determine the frame size without variable-length data.
533 int32 frame_size_without_variable_data;
508 switch (current_control_frame.type()) { 534 switch (current_control_frame.type()) {
509 case SYN_STREAM: 535 case SYN_STREAM:
510 frame_size_without_header_block = SpdySynStreamControlFrame::size(); 536 syn_frame_processed_ = true;
537 frame_size_without_variable_data = SpdySynStreamControlFrame::size();
511 break; 538 break;
512 case SYN_REPLY: 539 case SYN_REPLY:
513 frame_size_without_header_block = SpdySynReplyControlFrame::size(); 540 syn_frame_processed_ = true;
541 frame_size_without_variable_data = SpdySynReplyControlFrame::size();
542 // SPDY 2 had two bytes of unused space preceeding payload.
543 if (spdy_version_ < 3) {
544 frame_size_without_variable_data += 2;
545 }
514 break; 546 break;
515 case HEADERS: 547 case HEADERS:
516 frame_size_without_header_block = SpdyHeadersControlFrame::size(); 548 frame_size_without_variable_data = SpdyHeadersControlFrame::size();
549 // SPDY 2 had two bytes of unused space preceeding payload.
550 if (spdy_version_ < 3) {
551 frame_size_without_variable_data += 2;
552 }
553 break;
554 case SETTINGS:
555 frame_size_without_variable_data = SpdySettingsControlFrame::size();
517 break; 556 break;
518 default: 557 default:
519 frame_size_without_header_block = -1; 558 frame_size_without_variable_data = -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; 559 break;
526 } 560 }
527 561
528 if (frame_size_without_header_block > 0) { 562 if (frame_size_without_variable_data == -1) {
563 LOG_IF(ERROR, remaining_control_payload_ + SpdyFrame::kHeaderSize >
564 current_frame_capacity_)
565 << display_protocol_
566 << " control frame buffer too small for fixed-length frame.";
567 // TODO(hkhalil): Remove ExpandControlFrameBuffer().
568 ExpandControlFrameBuffer(remaining_control_payload_);
569 }
570 if (frame_size_without_variable_data > 0) {
529 // We have a control frame with a header block. We need to parse the 571 // 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 572 // 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. 573 // block. The start of the header block varies with the control type.
532 DCHECK_GE(static_cast<uint32>(frame_size_without_header_block), 574 DCHECK_GE(frame_size_without_variable_data,
533 current_frame_len_); 575 static_cast<int32>(current_frame_len_));
534 remaining_control_header_ = frame_size_without_header_block - 576 remaining_control_header_ = frame_size_without_variable_data -
535 current_frame_len_; 577 current_frame_len_;
536 remaining_control_payload_ += SpdyFrame::kHeaderSize - 578 remaining_control_payload_ += SpdyFrame::kHeaderSize -
537 frame_size_without_header_block; 579 frame_size_without_variable_data;
538 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 580 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK);
539 return; 581 return;
540 } 582 }
541 583
542 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 584 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
543 } 585 }
544 586
545 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 587 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len,
546 size_t max_bytes) { 588 size_t max_bytes) {
547 size_t bytes_to_read = std::min(*len, max_bytes); 589 size_t bytes_to_read = std::min(*len, max_bytes);
548 DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read); 590 DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read);
549 memcpy(&current_frame_buffer_[current_frame_len_], *data, bytes_to_read); 591 memcpy(&current_frame_buffer_[current_frame_len_], *data, bytes_to_read);
550 current_frame_len_ += bytes_to_read; 592 current_frame_len_ += bytes_to_read;
551 *data += bytes_to_read; 593 *data += bytes_to_read;
552 *len -= bytes_to_read; 594 *len -= bytes_to_read;
553 return bytes_to_read; 595 return bytes_to_read;
554 } 596 }
555 597
598 size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock* headers) const {
599 const size_t num_name_value_pairs_size
600 = (spdy_version_ < 3) ? sizeof(uint16) : sizeof(uint32);
601 const size_t length_of_name_size = num_name_value_pairs_size;
602 const size_t length_of_value_size = num_name_value_pairs_size;
603
604 size_t total_length = num_name_value_pairs_size;
605 for (SpdyHeaderBlock::const_iterator it = headers->begin();
606 it != headers->end();
607 ++it) {
608 // We add space for the length of the name and the length of the value as
609 // well as the length of the name and the length of the value.
610 total_length += length_of_name_size + it->first.size() +
611 length_of_value_size + it->second.size();
612 }
613 return total_length;
614 }
615
616 void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame,
617 const SpdyHeaderBlock* headers) const {
618 if (spdy_version_ < 3) {
619 frame->WriteUInt16(headers->size()); // Number of headers.
620 } else {
621 frame->WriteUInt32(headers->size()); // Number of headers.
622 }
623 SpdyHeaderBlock::const_iterator it;
624 for (it = headers->begin(); it != headers->end(); ++it) {
625 bool wrote_header;
626 if (spdy_version_ < 3) {
627 wrote_header = frame->WriteString(it->first);
628 wrote_header &= frame->WriteString(it->second);
629 } else {
630 wrote_header = frame->WriteStringPiece32(it->first);
631 wrote_header &= frame->WriteStringPiece32(it->second);
632 }
633 DCHECK(wrote_header);
634 }
635 }
636
637
556 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 638 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
557 size_t len) { 639 size_t len) {
558 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 640 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_);
559 DCHECK_GT(remaining_control_header_, 0u); 641 DCHECK_GT(remaining_control_header_, 0u);
560 size_t original_len = len; 642 size_t original_len = len;
561 643
562 if (remaining_control_header_) { 644 if (remaining_control_header_) {
563 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 645 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
564 remaining_control_header_); 646 remaining_control_header_);
565 remaining_control_header_ -= bytes_read; 647 remaining_control_header_ -= bytes_read;
566 if (remaining_control_header_ == 0) { 648 if (remaining_control_header_ == 0) {
567 SpdyControlFrame control_frame(current_frame_buffer_, false); 649 SpdyControlFrame control_frame(current_frame_buffer_, false);
568 DCHECK(control_frame.type() == SYN_STREAM || 650 DCHECK(control_frame.type() == SYN_STREAM ||
569 control_frame.type() == SYN_REPLY || 651 control_frame.type() == SYN_REPLY ||
570 control_frame.type() == HEADERS); 652 control_frame.type() == HEADERS ||
653 control_frame.type() == SETTINGS);
571 visitor_->OnControl(&control_frame); 654 visitor_->OnControl(&control_frame);
572 655
573 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 656 if (control_frame.type() == SETTINGS) {
657 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD);
658 } else {
659 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
660 }
574 } 661 }
575 } 662 }
576 return original_len - len; 663 return original_len - len;
577 } 664 }
578 665
579 // Does not buffer the control payload. Instead, either passes directly to the 666 // Does not buffer the control payload. Instead, either passes directly to the
580 // visitor or decompresses and then passes directly to the visitor, via 667 // visitor or decompresses and then passes directly to the visitor, via
581 // IncrementallyDeliverControlFrameHeaderData() or 668 // IncrementallyDeliverControlFrameHeaderData() or
582 // IncrementallyDecompressControlFrameHeaderData() respectively. 669 // IncrementallyDecompressControlFrameHeaderData() respectively.
583 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 670 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 705
619 // Handle error. 706 // Handle error.
620 if (!processed_successfully) { 707 if (!processed_successfully) {
621 return data_len; 708 return data_len;
622 } 709 }
623 710
624 // Return amount processed. 711 // Return amount processed.
625 return process_bytes; 712 return process_bytes;
626 } 713 }
627 714
715 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
716 size_t data_len) {
717 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_);
718 SpdyControlFrame control_frame(current_frame_buffer_, false);
719 DCHECK_EQ(control_frame.type(), SETTINGS);
720 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_);
721 size_t processed_bytes = 0;
722 DCHECK_GT(unprocessed_bytes, 0u);
723
724 // Loop over our incoming data.
725 while (unprocessed_bytes > 0) {
726 // Process up to one setting at a time.
727 size_t processing = std::min(
728 unprocessed_bytes,
729 static_cast<size_t>(8 - settings_scratch_.setting_buf_len));
730
731 // Check if we have a complete setting in our input.
732 if (processing == 8) {
733 // Parse the setting directly out of the input without buffering.
734 if (!ProcessSetting(data + processed_bytes)) {
735 set_error(SPDY_INVALID_CONTROL_FRAME);
736 return processed_bytes;
737 }
738 } else {
739 // Continue updating settings_scratch_.setting_buf.
740 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len,
741 data + processed_bytes,
742 processing);
743 settings_scratch_.setting_buf_len += processing;
744
745 // Check if we have a complete setting buffered.
746 if (settings_scratch_.setting_buf_len == 8) {
747 if (!ProcessSetting(settings_scratch_.setting_buf)) {
748 set_error(SPDY_INVALID_CONTROL_FRAME);
749 return processed_bytes;
750 }
751 // Reset settings_scratch_.setting_buf for our next setting.
752 settings_scratch_.setting_buf_len = 0;
753 }
754 }
755
756 // Iterate.
757 unprocessed_bytes -= processing;
758 processed_bytes += processing;
759 }
760
761 // Check if we're done handling this SETTINGS frame.
762 remaining_control_payload_ -= processed_bytes;
763 if (remaining_control_payload_ == 0) {
764 CHANGE_STATE(SPDY_AUTO_RESET);
765 }
766
767 return processed_bytes;
768 }
769
770 bool SpdyFramer::ProcessSetting(const char* data) {
771 // Extract fields.
772 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id.
773 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data));
774 SettingsFlagsAndId id_and_flags =
775 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire);
776 uint8 flags = id_and_flags.flags();
777 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4)));
778
779 // Validate id.
780 switch (id_and_flags.id()) {
781 case SETTINGS_UPLOAD_BANDWIDTH:
782 case SETTINGS_DOWNLOAD_BANDWIDTH:
783 case SETTINGS_ROUND_TRIP_TIME:
784 case SETTINGS_MAX_CONCURRENT_STREAMS:
785 case SETTINGS_CURRENT_CWND:
786 case SETTINGS_DOWNLOAD_RETRANS_RATE:
787 case SETTINGS_INITIAL_WINDOW_SIZE:
788 // Valid values.
789 break;
790 default:
791 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id();
792 return false;
793 }
794 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id());
795
796 // Detect duplciates.
797 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) {
798 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id
799 << " in " << display_protocol_ << " SETTINGS frame "
800 << "(last settikng id was "
801 << settings_scratch_.last_setting_id << ").";
802 return false;
803 }
804 settings_scratch_.last_setting_id = id;
805
806 // Validate flags.
807 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED;
808 if ((flags & ~(kFlagsMask)) != 0) {
809 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": "
810 << flags;
811 return false;
812 }
813
814 // Validation succeeded. Pass on to visitor.
815 visitor_->OnSetting(id, flags, value);
816 return true;
817 }
818
628 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 819 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
629 size_t original_len = len; 820 size_t original_len = len;
630 if (remaining_control_payload_) { 821 if (remaining_control_payload_) {
631 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 822 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len,
632 remaining_control_payload_); 823 remaining_control_payload_);
633 remaining_control_payload_ -= bytes_read; 824 remaining_control_payload_ -= bytes_read;
634 remaining_data_ -= bytes_read; 825 remaining_data_ -= bytes_read;
635 if (remaining_control_payload_ == 0) { 826 if (remaining_control_payload_ == 0) {
636 SpdyControlFrame control_frame(current_frame_buffer_, false); 827 SpdyControlFrame control_frame(current_frame_buffer_, false);
637 DCHECK(!control_frame.has_header_block()); 828 DCHECK(!control_frame.has_header_block());
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 DCHECK_LE(alloc_size, kControlFrameBufferMaxSize); 913 DCHECK_LE(alloc_size, kControlFrameBufferMaxSize);
723 if (alloc_size <= current_frame_capacity_) 914 if (alloc_size <= current_frame_capacity_)
724 return; 915 return;
725 char* new_buffer = new char[alloc_size]; 916 char* new_buffer = new char[alloc_size];
726 memcpy(new_buffer, current_frame_buffer_, current_frame_len_); 917 memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
727 delete [] current_frame_buffer_; 918 delete [] current_frame_buffer_;
728 current_frame_capacity_ = alloc_size; 919 current_frame_capacity_ = alloc_size;
729 current_frame_buffer_ = new_buffer; 920 current_frame_buffer_ = new_buffer;
730 } 921 }
731 922
732 /* static */
733 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 923 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data,
734 size_t header_length, 924 size_t header_length,
735 SpdyHeaderBlock* block) { 925 SpdyHeaderBlock* block) {
736 SpdyFrameBuilder builder(header_data, header_length); 926 SpdyFrameReader reader(header_data, header_length);
737 void* iter = NULL; 927
738 uint16 num_headers; 928 // Read number of headers.
739 if (builder.ReadUInt16(&iter, &num_headers)) { 929 uint32 num_headers;
740 for (int index = 0; index < num_headers; ++index) { 930 if (spdy_version_ < 3) {
741 std::string name; 931 uint16 temp;
742 std::string value; 932 if (!reader.ReadUInt16(&temp)) {
743 if (!builder.ReadString(&iter, &name)) 933 DLOG(INFO) << "Unable to read number of headers.";
744 return false; 934 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;
751 }
752 } 935 }
753 return true; 936 num_headers = temp;
754 } 937 } else {
755 return false; 938 if (!reader.ReadUInt32(&num_headers)) {
756 } 939 DLOG(INFO) << "Unable to read number of headers.";
757 940 return false;
758 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, 941 }
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;
764
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;
769
770 const char *header_data = NULL;
771 int header_length = 0;
772
773 switch (type) {
774 case SYN_STREAM:
775 {
776 SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false);
777 header_data = syn_frame.header_block();
778 header_length = syn_frame.header_block_len();
779 }
780 break;
781 case SYN_REPLY:
782 {
783 SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false);
784 header_data = syn_frame.header_block();
785 header_length = syn_frame.header_block_len();
786 }
787 break;
788 case HEADERS:
789 {
790 SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false);
791 header_data = header_frame.header_block();
792 header_length = header_frame.header_block_len();
793 }
794 break;
795 } 942 }
796 943
797 SpdyFrameBuilder builder(header_data, header_length); 944 // Read each header.
798 void* iter = NULL; 945 for (uint32 index = 0; index < num_headers; ++index) {
799 uint16 num_headers; 946 base::StringPiece temp;
800 if (builder.ReadUInt16(&iter, &num_headers)) { 947
801 int index; 948 // Read header name.
802 for (index = 0; index < num_headers; ++index) { 949 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
803 std::string name; 950 : !reader.ReadStringPiece32(&temp)) {
804 std::string value; 951 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of "
805 if (!builder.ReadString(&iter, &name)) 952 << num_headers << ").";
806 break; 953 return false;
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;
815 }
816 } 954 }
817 return index == num_headers && 955 std::string name;
818 iter == header_data + header_length; 956 temp.CopyToString(&name);
957
958 // Read header value.
959 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp)
960 : !reader.ReadStringPiece32(&temp)) {
961 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of "
962 << num_headers << ").";
963 return false;
964 }
965 std::string value;
966 temp.CopyToString(&value);
967
968 // Ensure no duplicates.
969 if (block->find(name) != block->end()) {
970 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of "
971 << num_headers << ").";
972 return false;
973 }
974
975 // Store header.
976 (*block)[name] = value;
819 } 977 }
820 return false; 978 return true;
821 } 979 }
822 980
823 /* static */ 981 /* static */
824 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, 982 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
825 SpdySettings* settings) { 983 SpdySettings* settings) {
826 DCHECK_EQ(frame->type(), SETTINGS); 984 DCHECK_EQ(frame->type(), SETTINGS);
827 DCHECK(settings); 985 DCHECK(settings);
828 986
829 SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len()); 987 SpdyFrameReader parser(frame->header_block(), frame->header_block_len());
830 void* iter = NULL;
831 for (size_t index = 0; index < frame->num_entries(); ++index) { 988 for (size_t index = 0; index < frame->num_entries(); ++index) {
832 uint32 id; 989 uint32 id_and_flags_wire;
833 uint32 value; 990 uint32 value;
834 if (!parser.ReadUInt32(&iter, &id)) 991 // SettingsFlagsAndId accepts off-the-wire (network byte order) data, so we
992 // use ReadBytes() instead of ReadUInt32() as the latter calls ntohl().
993 if (!parser.ReadBytes(&id_and_flags_wire, 4)) {
835 return false; 994 return false;
836 if (!parser.ReadUInt32(&iter, &value)) 995 }
996 if (!parser.ReadUInt32(&value))
837 return false; 997 return false;
838 settings->insert(settings->end(), std::make_pair(id, value)); 998 SettingsFlagsAndId id_and_flags =
999 SettingsFlagsAndId::FromWireFormat(frame->version(), id_and_flags_wire);
1000 settings->insert(settings->end(), std::make_pair(id_and_flags, value));
839 } 1001 }
840 return true; 1002 return true;
841 } 1003 }
842 1004
843 /* static */ 1005 /* static */
844 bool SpdyFramer::ParseCredentialData(const char* data, size_t len, 1006 bool SpdyFramer::ParseCredentialData(const char* data, size_t len,
845 SpdyCredential* credential) { 1007 SpdyCredential* credential) {
846 DCHECK(credential); 1008 DCHECK(credential);
847 1009
848 void* iter = NULL; 1010 SpdyFrameReader parser(data, len);
849 SpdyFrameBuilder parser(data, len); 1011 base::StringPiece temp;
850 if (!parser.ReadUInt16(&iter, &credential->slot)) 1012 if (!parser.ReadUInt16(&credential->slot)) {
851 return false; 1013 return false;
1014 }
852 1015
853 uint32 proof_len; 1016 if (!parser.ReadStringPiece32(&temp)) {
854 const char* proof_data;
855 if (!parser.ReadReadLen32PrefixedData(&iter, &proof_data, &proof_len))
856 return false; 1017 return false;
857 credential->proof.assign(proof_data, proof_len); 1018 }
1019 temp.CopyToString(&credential->proof);
858 1020
859 while (parser.IteratorHasRoomFor(iter, 1)) { 1021 while (!parser.IsDoneReading()) {
860 uint32 cert_len; 1022 if (!parser.ReadStringPiece32(&temp)) {
861 const char* cert_data;
862 if (!parser.ReadReadLen32PrefixedData(&iter, &cert_data, &cert_len))
863 return false; 1023 return false;
864 credential->certs.push_back(""); 1024 }
865 credential->certs.back().assign(cert_data, cert_len); 1025 std::string cert;
1026 temp.CopyToString(&cert);
1027 credential->certs.push_back(cert);
866 } 1028 }
867 return true; 1029 return true;
868 } 1030 }
869 1031
870 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( 1032 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
871 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, 1033 SpdyStreamId stream_id,
872 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 1034 SpdyStreamId associated_stream_id,
873 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); 1035 SpdyPriority priority,
1036 SpdyControlFlags flags,
1037 bool compressed,
1038 const SpdyHeaderBlock* headers) {
874 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1039 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
875 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); 1040 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
876 1041
877 // Find our length. 1042 // Find our length.
878 size_t expected_frame_size = SpdySynStreamControlFrame::size() + 1043 size_t expected_frame_size = SpdySynStreamControlFrame::size() +
879 GetSerializedLength(headers); 1044 GetSerializedLength(headers);
880 1045
881 // Create our FlagsAndLength. 1046 // Create our FlagsAndLength.
882 FlagsAndLength flags_length = CreateFlagsAndLength( 1047 FlagsAndLength flags_length = CreateFlagsAndLength(
883 flags, 1048 flags,
884 expected_frame_size - SpdyFrame::kHeaderSize); 1049 expected_frame_size - SpdyFrame::kHeaderSize);
885 1050
886 SpdyFrameBuilder frame(expected_frame_size); 1051 SpdyFrameBuilder frame(expected_frame_size);
887 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1052 frame.WriteUInt16(kControlFlagMask | spdy_version_);
888 frame.WriteUInt16(SYN_STREAM); 1053 frame.WriteUInt16(SYN_STREAM);
889 frame.WriteBytes(&flags_length, sizeof(flags_length)); 1054 frame.WriteBytes(&flags_length, sizeof(flags_length));
890 frame.WriteUInt32(stream_id); 1055 frame.WriteUInt32(stream_id);
891 frame.WriteUInt32(associated_stream_id); 1056 frame.WriteUInt32(associated_stream_id);
892 frame.WriteUInt16(ntohs(priority) << 6); // Priority. 1057 // Cap as appropriate.
1058 if (priority > GetLowestPriority()) {
1059 DLOG(ERROR) << "Priority out-of-bounds.";
1060 priority = GetLowestPriority();
1061 }
1062 // Priority is 2 bits for <spdy3, 3 bits otherwise.
1063 frame.WriteUInt16(ntohs(priority) << (spdy_version_ < 3 ? 6 : 5));
893 WriteHeaderBlock(&frame, headers); 1064 WriteHeaderBlock(&frame, headers);
894 1065
895 scoped_ptr<SpdySynStreamControlFrame> syn_frame( 1066 scoped_ptr<SpdySynStreamControlFrame> syn_frame(
896 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); 1067 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take()));
897 if (compressed) { 1068 if (compressed) {
898 return reinterpret_cast<SpdySynStreamControlFrame*>( 1069 return reinterpret_cast<SpdySynStreamControlFrame*>(
899 CompressControlFrame(*syn_frame.get())); 1070 CompressControlFrame(*syn_frame.get()));
900 } 1071 }
901 return syn_frame.release(); 1072 return syn_frame.release();
902 } 1073 }
903 1074
904 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id, 1075 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(
905 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 1076 SpdyStreamId stream_id,
1077 SpdyControlFlags flags,
1078 bool compressed,
1079 const SpdyHeaderBlock* headers) {
906 DCHECK_GT(stream_id, 0u); 1080 DCHECK_GT(stream_id, 0u);
907 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1081 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
908 1082
909 // Find our length. 1083 // Find our length.
910 size_t expected_frame_size = SpdySynReplyControlFrame::size() + 1084 size_t expected_frame_size = SpdySynReplyControlFrame::size() +
911 GetSerializedLength(headers); 1085 GetSerializedLength(headers);
1086 // In SPDY 2, there were 2 unused bytes before payload.
1087 if (spdy_version_ < 3) {
1088 expected_frame_size += 2;
1089 }
912 1090
913 // Create our FlagsAndLength. 1091 // Create our FlagsAndLength.
914 FlagsAndLength flags_length = CreateFlagsAndLength( 1092 FlagsAndLength flags_length = CreateFlagsAndLength(
915 flags, 1093 flags,
916 expected_frame_size - SpdyFrame::kHeaderSize); 1094 expected_frame_size - SpdyFrame::kHeaderSize);
917 1095
918 SpdyFrameBuilder frame(expected_frame_size); 1096 SpdyFrameBuilder frame(expected_frame_size);
919 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1097 frame.WriteUInt16(kControlFlagMask | spdy_version_);
920 frame.WriteUInt16(SYN_REPLY); 1098 frame.WriteUInt16(SYN_REPLY);
921 frame.WriteBytes(&flags_length, sizeof(flags_length)); 1099 frame.WriteBytes(&flags_length, sizeof(flags_length));
922 frame.WriteUInt32(stream_id); 1100 frame.WriteUInt32(stream_id);
923 frame.WriteUInt16(0); // Unused 1101 if (spdy_version_ < 3) {
1102 frame.WriteUInt16(0); // Unused
1103 }
924 WriteHeaderBlock(&frame, headers); 1104 WriteHeaderBlock(&frame, headers);
925 1105
926 scoped_ptr<SpdySynReplyControlFrame> reply_frame( 1106 scoped_ptr<SpdySynReplyControlFrame> reply_frame(
927 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); 1107 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take()));
928 if (compressed) { 1108 if (compressed) {
929 return reinterpret_cast<SpdySynReplyControlFrame*>( 1109 return reinterpret_cast<SpdySynReplyControlFrame*>(
930 CompressControlFrame(*reply_frame.get())); 1110 CompressControlFrame(*reply_frame.get()));
931 } 1111 }
932 return reply_frame.release(); 1112 return reply_frame.release();
933 } 1113 }
934 1114
935 /* static */ 1115 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(
936 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id, 1116 SpdyStreamId stream_id,
937 SpdyStatusCodes status) { 1117 SpdyStatusCodes status) const {
938 DCHECK_GT(stream_id, 0u); 1118 DCHECK_GT(stream_id, 0u);
939 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1119 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
940 DCHECK_NE(status, INVALID); 1120 DCHECK_NE(status, INVALID);
941 DCHECK_LT(status, NUM_STATUS_CODES); 1121 DCHECK_LT(status, NUM_STATUS_CODES);
942 1122
943 SpdyFrameBuilder frame(SpdyRstStreamControlFrame::size()); 1123 SpdyFrameBuilder frame(SpdyRstStreamControlFrame::size());
944 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1124 frame.WriteUInt16(kControlFlagMask | spdy_version_);
945 frame.WriteUInt16(RST_STREAM); 1125 frame.WriteUInt16(RST_STREAM);
946 frame.WriteUInt32(8); 1126 frame.WriteUInt32(8);
947 frame.WriteUInt32(stream_id); 1127 frame.WriteUInt32(stream_id);
948 frame.WriteUInt32(status); 1128 frame.WriteUInt32(status);
949 return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); 1129 return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take());
950 } 1130 }
951 1131
952 /* static */
953 SpdySettingsControlFrame* SpdyFramer::CreateSettings( 1132 SpdySettingsControlFrame* SpdyFramer::CreateSettings(
954 const SpdySettings& values) { 1133 const SpdySettings& values) const {
955 SpdyFrameBuilder frame(SpdySettingsControlFrame::size() + 8 * values.size()); 1134 SpdyFrameBuilder frame(SpdySettingsControlFrame::size() + 8 * values.size());
956 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1135 frame.WriteUInt16(kControlFlagMask | spdy_version_);
957 frame.WriteUInt16(SETTINGS); 1136 frame.WriteUInt16(SETTINGS);
958 size_t settings_size = 1137 size_t settings_size =
959 SpdySettingsControlFrame::size() - SpdyFrame::kHeaderSize + 1138 SpdySettingsControlFrame::size() - SpdyFrame::kHeaderSize +
960 8 * values.size(); 1139 8 * values.size();
961 frame.WriteUInt32(settings_size); 1140 frame.WriteUInt32(settings_size);
962 frame.WriteUInt32(values.size()); 1141 frame.WriteUInt32(values.size());
963 SpdySettings::const_iterator it = values.begin(); 1142 SpdySettings::const_iterator it = values.begin();
964 while (it != values.end()) { 1143 while (it != values.end()) {
965 frame.WriteUInt32(it->first.id_); 1144 uint32 id_and_flags_wire = it->first.GetWireFormat(spdy_version_);
1145 frame.WriteBytes(&id_and_flags_wire, 4);
966 frame.WriteUInt32(it->second); 1146 frame.WriteUInt32(it->second);
967 ++it; 1147 ++it;
968 } 1148 }
969 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); 1149 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take());
970 } 1150 }
971 1151
972 /* static */ 1152 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const {
973 SpdyNoOpControlFrame* SpdyFramer::CreateNopFrame() {
974 SpdyFrameBuilder frame(SpdyNoOpControlFrame::size());
975 frame.WriteUInt16(kControlFlagMask | spdy_version_);
976 frame.WriteUInt16(NOOP);
977 frame.WriteUInt32(0);
978 return reinterpret_cast<SpdyNoOpControlFrame*>(frame.take());
979 }
980
981 /* static */
982 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) {
983 SpdyFrameBuilder frame(SpdyPingControlFrame::size()); 1153 SpdyFrameBuilder frame(SpdyPingControlFrame::size());
984 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1154 frame.WriteUInt16(kControlFlagMask | spdy_version_);
985 frame.WriteUInt16(PING); 1155 frame.WriteUInt16(PING);
986 size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::kHeaderSize; 1156 size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::kHeaderSize;
987 frame.WriteUInt32(ping_size); 1157 frame.WriteUInt32(ping_size);
988 frame.WriteUInt32(unique_id); 1158 frame.WriteUInt32(unique_id);
989 return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); 1159 return reinterpret_cast<SpdyPingControlFrame*>(frame.take());
990 } 1160 }
991 1161
992 /* static */
993 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( 1162 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway(
994 SpdyStreamId last_accepted_stream_id) { 1163 SpdyStreamId last_accepted_stream_id) const {
995 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); 1164 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask);
996 1165
997 SpdyFrameBuilder frame(SpdyGoAwayControlFrame::size()); 1166 SpdyFrameBuilder frame(SpdyGoAwayControlFrame::size());
998 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1167 frame.WriteUInt16(kControlFlagMask | spdy_version_);
999 frame.WriteUInt16(GOAWAY); 1168 frame.WriteUInt16(GOAWAY);
1000 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize; 1169 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::kHeaderSize;
1001 frame.WriteUInt32(go_away_size); 1170 frame.WriteUInt32(go_away_size);
1002 frame.WriteUInt32(last_accepted_stream_id); 1171 frame.WriteUInt32(last_accepted_stream_id);
1003 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); 1172 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take());
1004 } 1173 }
1005 1174
1006 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id, 1175 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(
1007 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 1176 SpdyStreamId stream_id,
1177 SpdyControlFlags flags,
1178 bool compressed,
1179 const SpdyHeaderBlock* headers) {
1008 // Basically the same as CreateSynReply(). 1180 // Basically the same as CreateSynReply().
1009 DCHECK_GT(stream_id, 0u); 1181 DCHECK_GT(stream_id, 0u);
1010 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1182 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
1011 1183
1012 // Find our length. 1184 // Find our length.
1013 size_t expected_frame_size = SpdyHeadersControlFrame::size() + 1185 size_t expected_frame_size = SpdyHeadersControlFrame::size() +
1014 GetSerializedLength(headers); 1186 GetSerializedLength(headers);
1187 // In SPDY 2, there were 2 unused bytes before payload.
1188 if (spdy_version_ < 3) {
1189 expected_frame_size += 2;
1190 }
1015 1191
1016 // Create our FlagsAndLength. 1192 // Create our FlagsAndLength.
1017 FlagsAndLength flags_length = CreateFlagsAndLength( 1193 FlagsAndLength flags_length = CreateFlagsAndLength(
1018 flags, 1194 flags,
1019 expected_frame_size - SpdyFrame::kHeaderSize); 1195 expected_frame_size - SpdyFrame::kHeaderSize);
1020 1196
1021 SpdyFrameBuilder frame(expected_frame_size); 1197 SpdyFrameBuilder frame(expected_frame_size);
1022 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1198 frame.WriteUInt16(kControlFlagMask | spdy_version_);
1023 frame.WriteUInt16(HEADERS); 1199 frame.WriteUInt16(HEADERS);
1024 frame.WriteBytes(&flags_length, sizeof(flags_length)); 1200 frame.WriteBytes(&flags_length, sizeof(flags_length));
1025 frame.WriteUInt32(stream_id); 1201 frame.WriteUInt32(stream_id);
1026 frame.WriteUInt16(0); // Unused 1202 if (spdy_version_ < 3) {
1203 frame.WriteUInt16(0); // Unused
1204 }
1027 WriteHeaderBlock(&frame, headers); 1205 WriteHeaderBlock(&frame, headers);
1028 DCHECK_EQ(static_cast<size_t>(frame.length()), expected_frame_size); 1206 DCHECK_EQ(static_cast<size_t>(frame.length()), expected_frame_size);
1029 1207
1030 scoped_ptr<SpdyHeadersControlFrame> headers_frame( 1208 scoped_ptr<SpdyHeadersControlFrame> headers_frame(
1031 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); 1209 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take()));
1032 if (compressed) { 1210 if (compressed) {
1033 return reinterpret_cast<SpdyHeadersControlFrame*>( 1211 return reinterpret_cast<SpdyHeadersControlFrame*>(
1034 CompressControlFrame(*headers_frame.get())); 1212 CompressControlFrame(*headers_frame.get()));
1035 } 1213 }
1036 return headers_frame.release(); 1214 return headers_frame.release();
1037 } 1215 }
1038 1216
1039 /* static */
1040 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( 1217 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate(
1041 SpdyStreamId stream_id, 1218 SpdyStreamId stream_id,
1042 uint32 delta_window_size) { 1219 uint32 delta_window_size) const {
1043 DCHECK_GT(stream_id, 0u); 1220 DCHECK_GT(stream_id, 0u);
1044 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1221 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
1045 DCHECK_GT(delta_window_size, 0u); 1222 DCHECK_GT(delta_window_size, 0u);
1046 DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize); 1223 DCHECK_LE(delta_window_size,
1224 static_cast<uint32>(spdy::kSpdyStreamMaximumWindowSize));
1047 1225
1048 SpdyFrameBuilder frame(SpdyWindowUpdateControlFrame::size()); 1226 SpdyFrameBuilder frame(SpdyWindowUpdateControlFrame::size());
1049 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1227 frame.WriteUInt16(kControlFlagMask | spdy_version_);
1050 frame.WriteUInt16(WINDOW_UPDATE); 1228 frame.WriteUInt16(WINDOW_UPDATE);
1051 size_t window_update_size = SpdyWindowUpdateControlFrame::size() - 1229 size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
1052 SpdyFrame::kHeaderSize; 1230 SpdyFrame::kHeaderSize;
1053 frame.WriteUInt32(window_update_size); 1231 frame.WriteUInt32(window_update_size);
1054 frame.WriteUInt32(stream_id); 1232 frame.WriteUInt32(stream_id);
1055 frame.WriteUInt32(delta_window_size); 1233 frame.WriteUInt32(delta_window_size);
1056 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); 1234 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
1057 } 1235 }
1058 1236
1059 /* static */
1060 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( 1237 SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame(
1061 const SpdyCredential& credential) { 1238 const SpdyCredential& credential) const {
1062 // Calculate the size of the frame by adding the size of the 1239 // Calculate the size of the frame by adding the size of the
1063 // variable length data to the size of the fixed length data. 1240 // variable length data to the size of the fixed length data.
1064 size_t frame_size = SpdyCredentialControlFrame::size() + 1241 size_t frame_size = SpdyCredentialControlFrame::size() +
1065 credential.proof.length(); 1242 credential.proof.length();
1066 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u); 1243 DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u);
1067 for (vector<std::string>::const_iterator cert = credential.certs.begin(); 1244 for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
1068 cert != credential.certs.end(); 1245 cert != credential.certs.end();
1069 cert++) { 1246 ++cert) {
1070 frame_size += sizeof(uint32); // size of the cert_length field 1247 frame_size += sizeof(uint32); // size of the cert_length field
1071 frame_size += cert->length(); // size of the cert_data field 1248 frame_size += cert->length(); // size of the cert_data field
1072 } 1249 }
1073 size_t payload_size = frame_size - SpdyFrame::kHeaderSize; 1250 size_t payload_size = frame_size - SpdyFrame::kHeaderSize;
1074 1251
1075 SpdyFrameBuilder frame(frame_size); 1252 SpdyFrameBuilder frame(frame_size);
1076 // Create our FlagsAndLength. 1253 // Create our FlagsAndLength.
1077 SpdyControlFlags flags = spdy::CONTROL_FLAG_NONE; 1254 SpdyControlFlags flags = CONTROL_FLAG_NONE;
1078 FlagsAndLength flags_length = CreateFlagsAndLength(flags, payload_size); 1255 FlagsAndLength flags_length = CreateFlagsAndLength(flags, payload_size);
1079 1256
1080 frame.WriteUInt16(kControlFlagMask | spdy_version_); 1257 frame.WriteUInt16(kControlFlagMask | spdy_version_);
1081 frame.WriteUInt16(CREDENTIAL); 1258 frame.WriteUInt16(CREDENTIAL);
1082 frame.WriteBytes(&flags_length, sizeof(flags_length)); 1259 frame.WriteBytes(&flags_length, sizeof(flags_length));
1083 frame.WriteUInt16(credential.slot); 1260 frame.WriteUInt16(credential.slot);
1084 frame.WriteUInt32(credential.proof.size()); 1261 frame.WriteUInt32(credential.proof.size());
1085 frame.WriteBytes(credential.proof.c_str(), credential.proof.size()); 1262 frame.WriteBytes(credential.proof.c_str(), credential.proof.size());
1086 for (vector<std::string>::const_iterator cert = credential.certs.begin(); 1263 for (std::vector<std::string>::const_iterator cert = credential.certs.begin();
1087 cert != credential.certs.end(); 1264 cert != credential.certs.end();
1088 cert++) { 1265 ++cert) {
1089 frame.WriteUInt32(cert->length()); 1266 frame.WriteUInt32(cert->length());
1090 frame.WriteBytes(cert->c_str(), cert->length()); 1267 frame.WriteBytes(cert->c_str(), cert->length());
1091 } 1268 }
1092 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); 1269 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take());
1093 } 1270 }
1094 1271
1095 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, 1272 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
1096 const char* data, 1273 const char* data,
1097 uint32 len, SpdyDataFlags flags) { 1274 uint32 len, SpdyDataFlags flags) {
1098 DCHECK_GT(stream_id, 0u);
1099 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 1275 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
1100 1276
1101 SpdyFrameBuilder frame(SpdyDataFrame::size() + len); 1277 SpdyFrameBuilder frame(SpdyDataFrame::size() + len);
1102 frame.WriteUInt32(stream_id); 1278 frame.WriteUInt32(stream_id);
1103 1279
1104 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask)); 1280 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
1105 FlagsAndLength flags_length; 1281 FlagsAndLength flags_length;
1106 flags_length.length_ = htonl(len); 1282 flags_length.length_ = htonl(len);
1107 DCHECK_EQ(0, flags & ~kDataFlagsMask); 1283 DCHECK_EQ(0, flags & ~kDataFlagsMask);
1108 flags_length.flags_[0] = flags; 1284 flags_length.flags_[0] = flags;
1109 frame.WriteBytes(&flags_length, sizeof(flags_length)); 1285 frame.WriteBytes(&flags_length, sizeof(flags_length));
1110 1286
1111 frame.WriteBytes(data, len); 1287 frame.WriteBytes(data, len);
1112 scoped_ptr<SpdyFrame> data_frame(frame.take()); 1288 scoped_ptr<SpdyFrame> data_frame(frame.take());
1113 SpdyDataFrame* rv; 1289 SpdyDataFrame* rv;
1114 if (flags & DATA_FLAG_COMPRESSED) { 1290 if (flags & DATA_FLAG_COMPRESSED) {
1115 rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get())); 1291 LOG(DFATAL) << "DATA_FLAG_COMPRESSED invalid for " << display_protocol_
1116 } else { 1292 << ".";
1117 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
1118 } 1293 }
1294 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
1119 1295
1120 if (flags & DATA_FLAG_FIN) { 1296 if (flags & DATA_FLAG_FIN) {
1121 CleanupCompressorForStream(stream_id); 1297 CleanupCompressorForStream(stream_id);
1122 } 1298 }
1123 1299
1124 return rv; 1300 return rv;
1125 } 1301 }
1126 1302
1127 // The following compression setting are based on Brian Olson's analysis. See 1303 // The following compression setting are based on Brian Olson's analysis. See
1128 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 1304 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2
1129 // for more details. 1305 // for more details.
1130 static const int kCompressorLevel = 9; 1306 static const int kCompressorLevel = 9;
1131 static const int kCompressorWindowSizeInBits = 11; 1307 static const int kCompressorWindowSizeInBits = 11;
1132 static const int kCompressorMemLevel = 1; 1308 static const int kCompressorMemLevel = 1;
1133 1309
1134 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
1135 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
1136 const char SpdyFramer::kDictionary[] =
1137 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
1138 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
1139 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
1140 "-agent10010120020120220320420520630030130230330430530630740040140240340440"
1141 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
1142 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
1143 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
1144 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
1145 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
1146 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
1147 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
1148 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
1149 ".1statusversionurl";
1150 const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
1151
1152 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) { 1310 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
1153 if (frame.is_control_frame()) { 1311 if (frame.is_control_frame()) {
1154 return CompressControlFrame( 1312 return CompressControlFrame(
1155 reinterpret_cast<const SpdyControlFrame&>(frame)); 1313 reinterpret_cast<const SpdyControlFrame&>(frame));
1156 } 1314 }
1157 return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame)); 1315 return NULL;
1158 }
1159
1160 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
1161 if (frame.is_control_frame()) {
1162 return DecompressControlFrame(
1163 reinterpret_cast<const SpdyControlFrame&>(frame));
1164 }
1165 return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
1166 } 1316 }
1167 1317
1168 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const { 1318 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
1169 // The important frames to compress are those which contain large 1319 // The important frames to compress are those which contain large
1170 // amounts of compressible data - namely the headers in the SYN_STREAM 1320 // amounts of compressible data - namely the headers in the SYN_STREAM
1171 // and SYN_REPLY. 1321 // and SYN_REPLY.
1172 // TODO(mbelshe): Reconcile this with the spec when the spec is
1173 // explicit about which frames compress and which do not.
1174 if (frame.is_control_frame()) { 1322 if (frame.is_control_frame()) {
1175 const SpdyControlFrame& control_frame = 1323 const SpdyControlFrame& control_frame =
1176 reinterpret_cast<const SpdyControlFrame&>(frame); 1324 reinterpret_cast<const SpdyControlFrame&>(frame);
1177 return control_frame.type() == SYN_STREAM || 1325 return control_frame.type() == SYN_STREAM ||
1178 control_frame.type() == SYN_REPLY; 1326 control_frame.type() == SYN_REPLY;
1179 } 1327 }
1180 1328
1181 const SpdyDataFrame& data_frame = 1329 // We don't compress Data frames.
1182 reinterpret_cast<const SpdyDataFrame&>(frame); 1330 return false;
1183 return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
1184 } 1331 }
1185 1332
1186 z_stream* SpdyFramer::GetHeaderCompressor() { 1333 z_stream* SpdyFramer::GetHeaderCompressor() {
1187 if (header_compressor_.get()) 1334 if (header_compressor_.get())
1188 return header_compressor_.get(); // Already initialized. 1335 return header_compressor_.get(); // Already initialized.
1189 1336
1190 header_compressor_.reset(new z_stream); 1337 header_compressor_.reset(new z_stream);
1191 memset(header_compressor_.get(), 0, sizeof(z_stream)); 1338 memset(header_compressor_.get(), 0, sizeof(z_stream));
1192 1339
1193 int success = deflateInit2(header_compressor_.get(), 1340 int success = deflateInit2(header_compressor_.get(),
1194 kCompressorLevel, 1341 kCompressorLevel,
1195 Z_DEFLATED, 1342 Z_DEFLATED,
1196 kCompressorWindowSizeInBits, 1343 kCompressorWindowSizeInBits,
1197 kCompressorMemLevel, 1344 kCompressorMemLevel,
1198 Z_DEFAULT_STRATEGY); 1345 Z_DEFAULT_STRATEGY);
1199 if (success == Z_OK) 1346 if (success == Z_OK) {
1347 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
1348 : kV3Dictionary;
1349 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
1350 : kV3DictionarySize;
1200 success = deflateSetDictionary(header_compressor_.get(), 1351 success = deflateSetDictionary(header_compressor_.get(),
1201 reinterpret_cast<const Bytef*>(kDictionary), 1352 reinterpret_cast<const Bytef*>(dictionary),
1202 kDictionarySize); 1353 dictionary_size);
1354 }
1203 if (success != Z_OK) { 1355 if (success != Z_OK) {
1204 LOG(WARNING) << "deflateSetDictionary failure: " << success; 1356 LOG(WARNING) << "deflateSetDictionary failure: " << success;
1205 header_compressor_.reset(NULL); 1357 header_compressor_.reset(NULL);
1206 return NULL; 1358 return NULL;
1207 } 1359 }
1208 return header_compressor_.get(); 1360 return header_compressor_.get();
1209 } 1361 }
1210 1362
1211 z_stream* SpdyFramer::GetHeaderDecompressor() { 1363 z_stream* SpdyFramer::GetHeaderDecompressor() {
1212 if (header_decompressor_.get()) 1364 if (header_decompressor_.get())
1213 return header_decompressor_.get(); // Already initialized. 1365 return header_decompressor_.get(); // Already initialized.
1214 1366
1215 header_decompressor_.reset(new z_stream); 1367 header_decompressor_.reset(new z_stream);
1216 memset(header_decompressor_.get(), 0, sizeof(z_stream)); 1368 memset(header_decompressor_.get(), 0, sizeof(z_stream));
1217 1369
1218 int success = inflateInit(header_decompressor_.get()); 1370 int success = inflateInit(header_decompressor_.get());
1219 if (success != Z_OK) { 1371 if (success != Z_OK) {
1220 LOG(WARNING) << "inflateInit failure: " << success; 1372 LOG(WARNING) << "inflateInit failure: " << success;
1221 header_decompressor_.reset(NULL); 1373 header_decompressor_.reset(NULL);
1222 return NULL; 1374 return NULL;
1223 } 1375 }
1224 return header_decompressor_.get(); 1376 return header_decompressor_.get();
1225 } 1377 }
1226 1378
1227 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) {
1228 CompressorMap::iterator it = stream_compressors_.find(stream_id);
1229 if (it != stream_compressors_.end())
1230 return it->second; // Already initialized.
1231
1232 scoped_ptr<z_stream> compressor(new z_stream);
1233 memset(compressor.get(), 0, sizeof(z_stream));
1234
1235 int success = deflateInit2(compressor.get(),
1236 kCompressorLevel,
1237 Z_DEFLATED,
1238 kCompressorWindowSizeInBits,
1239 kCompressorMemLevel,
1240 Z_DEFAULT_STRATEGY);
1241 if (success != Z_OK) {
1242 LOG(WARNING) << "deflateInit failure: " << success;
1243 return NULL;
1244 }
1245 return stream_compressors_[stream_id] = compressor.release();
1246 }
1247
1248 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) { 1379 z_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) {
1249 CompressorMap::iterator it = stream_decompressors_.find(stream_id); 1380 CompressorMap::iterator it = stream_decompressors_.find(stream_id);
1250 if (it != stream_decompressors_.end()) 1381 if (it != stream_decompressors_.end())
1251 return it->second; // Already initialized. 1382 return it->second; // Already initialized.
1252 1383
1253 scoped_ptr<z_stream> decompressor(new z_stream); 1384 scoped_ptr<z_stream> decompressor(new z_stream);
1254 memset(decompressor.get(), 0, sizeof(z_stream)); 1385 memset(decompressor.get(), 0, sizeof(z_stream));
1255 1386
1256 int success = inflateInit(decompressor.get()); 1387 int success = inflateInit(decompressor.get());
1257 if (success != Z_OK) { 1388 if (success != Z_OK) {
(...skipping 23 matching lines...) Expand all
1281 } 1412 }
1282 break; 1413 break;
1283 case SYN_REPLY: 1414 case SYN_REPLY:
1284 { 1415 {
1285 const SpdySynReplyControlFrame& syn_frame = 1416 const SpdySynReplyControlFrame& syn_frame =
1286 reinterpret_cast<const SpdySynReplyControlFrame&>(frame); 1417 reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
1287 frame_size = SpdySynReplyControlFrame::size(); 1418 frame_size = SpdySynReplyControlFrame::size();
1288 *payload_length = syn_frame.header_block_len(); 1419 *payload_length = syn_frame.header_block_len();
1289 *header_length = frame_size; 1420 *header_length = frame_size;
1290 *payload = frame.data() + *header_length; 1421 *payload = frame.data() + *header_length;
1422 // SPDY 2 had two bytes of unused space preceeding payload.
1423 if (spdy_version_ < 3) {
1424 *header_length += 2;
1425 *payload += 2;
1426 }
1291 } 1427 }
1292 break; 1428 break;
1293 case HEADERS: 1429 case HEADERS:
1294 { 1430 {
1295 const SpdyHeadersControlFrame& headers_frame = 1431 const SpdyHeadersControlFrame& headers_frame =
1296 reinterpret_cast<const SpdyHeadersControlFrame&>(frame); 1432 reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
1297 frame_size = SpdyHeadersControlFrame::size(); 1433 frame_size = SpdyHeadersControlFrame::size();
1298 *payload_length = headers_frame.header_block_len(); 1434 *payload_length = headers_frame.header_block_len();
1299 *header_length = frame_size; 1435 *header_length = frame_size;
1300 *payload = frame.data() + *header_length; 1436 *payload = frame.data() + *header_length;
1437 // SPDY 2 had two bytes of unused space preceeding payload.
1438 if (spdy_version_ < 3) {
1439 *header_length += 2;
1440 *payload += 2;
1441 }
1301 } 1442 }
1302 break; 1443 break;
1303 default: 1444 default:
1304 // TODO(mbelshe): set an error? 1445 // TODO(mbelshe): set an error?
1305 return false; // We can't compress this frame! 1446 return false; // We can't compress this frame!
1306 } 1447 }
1307 } else { 1448 } else {
1308 frame_size = SpdyFrame::kHeaderSize; 1449 frame_size = SpdyFrame::kHeaderSize;
1309 *header_length = frame_size; 1450 *header_length = frame_size;
1310 *payload_length = frame.length(); 1451 *payload_length = frame.length();
1311 *payload = frame.data() + SpdyFrame::kHeaderSize; 1452 *payload = frame.data() + SpdyFrame::kHeaderSize;
1312 } 1453 }
1313 return true; 1454 return true;
1314 } 1455 }
1315 1456
1316 SpdyControlFrame* SpdyFramer::CompressControlFrame( 1457 SpdyControlFrame* SpdyFramer::CompressControlFrame(
1317 const SpdyControlFrame& frame) { 1458 const SpdyControlFrame& frame) {
1318 z_stream* compressor = GetHeaderCompressor(); 1459 z_stream* compressor = GetHeaderCompressor();
1319 if (!compressor) 1460 if (!compressor)
1320 return NULL; 1461 return NULL;
1321 return reinterpret_cast<SpdyControlFrame*>(
1322 CompressFrameWithZStream(frame, compressor));
1323 }
1324 1462
1325 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
1326 z_stream* compressor = GetStreamCompressor(frame.stream_id());
1327 if (!compressor)
1328 return NULL;
1329 return reinterpret_cast<SpdyDataFrame*>(
1330 CompressFrameWithZStream(frame, compressor));
1331 }
1332
1333 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
1334 const SpdyControlFrame& frame) {
1335 z_stream* decompressor = GetHeaderDecompressor();
1336 if (!decompressor) {
1337 LOG(DFATAL) << "Couldn't get decompressor for handling control frame.";
1338 set_error(SPDY_DECOMPRESS_FAILURE);
1339 return NULL;
1340 }
1341 return reinterpret_cast<SpdyControlFrame*>(
1342 DecompressFrameWithZStream(frame, decompressor));
1343 }
1344
1345 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
1346 z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
1347 if (!decompressor)
1348 return NULL;
1349 return reinterpret_cast<SpdyDataFrame*>(
1350 DecompressFrameWithZStream(frame, decompressor));
1351 }
1352
1353 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame,
1354 z_stream* compressor) {
1355 int payload_length; 1463 int payload_length;
1356 int header_length; 1464 int header_length;
1357 const char* payload; 1465 const char* payload;
1358 1466
1359 base::StatsCounter compressed_frames("spdy.CompressedFrames"); 1467 base::StatsCounter compressed_frames("spdy.CompressedFrames");
1360 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 1468 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
1361 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 1469 base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
1362 1470
1363 if (!enable_compression_) 1471 if (!enable_compression_)
1364 return DuplicateFrame(frame); 1472 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame));
1365 1473
1366 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) 1474 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
1367 return NULL; 1475 return NULL;
1368 1476
1369 // Create an output frame. 1477 // Create an output frame.
1370 int compressed_max_size = deflateBound(compressor, payload_length); 1478 int compressed_max_size = deflateBound(compressor, payload_length);
1371 int new_frame_size = header_length + compressed_max_size; 1479 int new_frame_size = header_length + compressed_max_size;
1372 scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size)); 1480 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) &&
1481 spdy_version_ < 3) {
1482 new_frame_size += 2;
1483 }
1484 DCHECK_GE(new_frame_size,
1485 static_cast<int>(frame.length() + SpdyFrame::kHeaderSize));
1486 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size));
1373 memcpy(new_frame->data(), frame.data(), 1487 memcpy(new_frame->data(), frame.data(),
1374 frame.length() + SpdyFrame::kHeaderSize); 1488 frame.length() + SpdyFrame::kHeaderSize);
1375 1489
1376 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); 1490 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
1377 compressor->avail_in = payload_length; 1491 compressor->avail_in = payload_length;
1378 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + 1492 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
1379 header_length; 1493 header_length;
1380 compressor->avail_out = compressed_max_size; 1494 compressor->avail_out = compressed_max_size;
1381 1495
1382 // Data packets have a 'compressed' flag. 1496 // Data packets have a 'compressed' flag.
1497 // TODO(hkhalil): Remove post code-yellow. It's impossible to execute this
1498 // branch given that SpdyControlFrame::is_control_frame always returns true.
1499 DCHECK(new_frame->is_control_frame());
1383 if (!new_frame->is_control_frame()) { 1500 if (!new_frame->is_control_frame()) {
1384 SpdyDataFrame* data_frame = 1501 SpdyDataFrame* data_frame =
1385 reinterpret_cast<SpdyDataFrame*>(new_frame.get()); 1502 reinterpret_cast<SpdyDataFrame*>(new_frame.get());
1386 data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED); 1503 data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED);
1387 } 1504 }
1388 1505
1389 // Make sure that all the data we pass to zlib is defined. 1506 // Make sure that all the data we pass to zlib is defined.
1390 // This way, all Valgrind reports on the compressed data are zlib's fault. 1507 // This way, all Valgrind reports on the compressed data are zlib's fault.
1391 (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in, 1508 (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in,
1392 compressor->avail_in); 1509 compressor->avail_in);
(...skipping 16 matching lines...) Expand all
1409 header_length + compressed_size - SpdyFrame::kHeaderSize); 1526 header_length + compressed_size - SpdyFrame::kHeaderSize);
1410 1527
1411 pre_compress_bytes.Add(payload_length); 1528 pre_compress_bytes.Add(payload_length);
1412 post_compress_bytes.Add(new_frame->length()); 1529 post_compress_bytes.Add(new_frame->length());
1413 1530
1414 compressed_frames.Increment(); 1531 compressed_frames.Increment();
1415 1532
1416 return new_frame.release(); 1533 return new_frame.release();
1417 } 1534 }
1418 1535
1419 SpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame,
1420 z_stream* decompressor) {
1421 int payload_length;
1422 int header_length;
1423 const char* payload;
1424
1425 base::StatsCounter decompressed_frames("spdy.DecompressedFrames");
1426 base::StatsCounter pre_decompress_bytes("spdy.PreDeCompressSize");
1427 base::StatsCounter post_decompress_bytes("spdy.PostDeCompressSize");
1428
1429 if (!enable_compression_)
1430 return DuplicateFrame(frame);
1431
1432 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload))
1433 return NULL;
1434
1435 if (!frame.is_control_frame()) {
1436 const SpdyDataFrame& data_frame =
1437 reinterpret_cast<const SpdyDataFrame&>(frame);
1438 if ((data_frame.flags() & DATA_FLAG_COMPRESSED) == 0)
1439 return DuplicateFrame(frame);
1440 }
1441
1442 // Create an output frame. Assume it does not need to be longer than
1443 // the input data.
1444 size_t decompressed_max_size = kControlFrameBufferInitialSize;
1445 int new_frame_size = header_length + decompressed_max_size;
1446 if (frame.length() > decompressed_max_size)
1447 return NULL;
1448 scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size));
1449 memcpy(new_frame->data(), frame.data(),
1450 frame.length() + SpdyFrame::kHeaderSize);
1451
1452 decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
1453 decompressor->avail_in = payload_length;
1454 decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
1455 header_length;
1456 decompressor->avail_out = decompressed_max_size;
1457
1458 int rv = inflate(decompressor, Z_SYNC_FLUSH);
1459 if (rv == Z_NEED_DICT) {
1460 // Need to try again with the right dictionary.
1461 if (decompressor->adler == kDictionaryId) {
1462 rv = inflateSetDictionary(decompressor,
1463 (const Bytef*)SpdyFramer::kDictionary,
1464 SpdyFramer::kDictionarySize);
1465 if (rv == Z_OK)
1466 rv = inflate(decompressor, Z_SYNC_FLUSH);
1467 }
1468 }
1469 if (rv != Z_OK) { // How can we know that it decompressed everything?
1470 LOG(WARNING) << "inflate failure: " << rv;
1471 return NULL;
1472 }
1473
1474 // Unset the compressed flag for data frames.
1475 if (!new_frame->is_control_frame()) {
1476 SpdyDataFrame* data_frame =
1477 reinterpret_cast<SpdyDataFrame*>(new_frame.get());
1478 data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED);
1479 }
1480
1481 int decompressed_size = decompressed_max_size - decompressor->avail_out;
1482 new_frame->set_length(
1483 header_length + decompressed_size - SpdyFrame::kHeaderSize);
1484
1485 // If there is data left, then the frame didn't fully decompress. This
1486 // means that there is stranded data at the end of this frame buffer which
1487 // will be ignored.
1488 DCHECK_EQ(decompressor->avail_in, 0u);
1489
1490 pre_decompress_bytes.Add(frame.length());
1491 post_decompress_bytes.Add(new_frame->length());
1492
1493 decompressed_frames.Increment();
1494
1495 return new_frame.release();
1496 }
1497
1498 // Incrementally decompress the control frame's header block, feeding the 1536 // Incrementally decompress the control frame's header block, feeding the
1499 // result to the visitor in chunks. Continue this until the visitor 1537 // result to the visitor in chunks. Continue this until the visitor
1500 // indicates that it cannot process any more data, or (more commonly) we 1538 // indicates that it cannot process any more data, or (more commonly) we
1501 // run out of data to deliver. 1539 // run out of data to deliver.
1502 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 1540 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
1503 const SpdyControlFrame* control_frame, 1541 const SpdyControlFrame* control_frame,
1504 const char* data, 1542 const char* data,
1505 size_t len) { 1543 size_t len) {
1506 // Get a decompressor or set error. 1544 // Get a decompressor or set error.
1507 z_stream* decomp = GetHeaderDecompressor(); 1545 z_stream* decomp = GetHeaderDecompressor();
1508 if (decomp == NULL) { 1546 if (decomp == NULL) {
1509 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 1547 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
1510 set_error(SPDY_DECOMPRESS_FAILURE); 1548 set_error(SPDY_DECOMPRESS_FAILURE);
1511 return false; 1549 return false;
1512 } 1550 }
1513 1551
1514 bool processed_successfully = true; 1552 bool processed_successfully = true;
1515 char buffer[kHeaderDataChunkMaxSize]; 1553 char buffer[kHeaderDataChunkMaxSize];
1516 1554
1517 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 1555 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data));
1518 decomp->avail_in = len; 1556 decomp->avail_in = len;
1519 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); 1557 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame);
1520 DCHECK_LT(0u, stream_id); 1558 DCHECK_LT(0u, stream_id);
1521 while (decomp->avail_in > 0 && processed_successfully) { 1559 while (decomp->avail_in > 0 && processed_successfully) {
1522 decomp->next_out = reinterpret_cast<Bytef*>(buffer); 1560 decomp->next_out = reinterpret_cast<Bytef*>(buffer);
1523 decomp->avail_out = arraysize(buffer); 1561 decomp->avail_out = arraysize(buffer);
1524 int rv = DecompressHeaderBlockInZStream(decomp); 1562
1525 if (rv != Z_OK && rv != Z_BUF_ERROR) { 1563 int rv = inflate(decomp, Z_SYNC_FLUSH);
1526 set_error(SPDY_DECOMPRESS_FAILURE); 1564 if (rv == Z_NEED_DICT) {
1527 DLOG(WARNING) << "inflate failure: " << rv; 1565 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary
1528 processed_successfully = false; 1566 : kV3Dictionary;
1529 } else { 1567 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
1568 : kV3DictionarySize;
1569 const uLong dictionary_id = (spdy_version_ < 3) ? kV2DictionaryId
1570 : kV3DictionaryId;
1571 // Need to try again with the right dictionary.
1572 if (decomp->adler == dictionary_id) {
1573 rv = inflateSetDictionary(decomp,
1574 reinterpret_cast<const Bytef*>(dictionary),
1575 dictionary_size);
1576 if (rv == Z_OK)
1577 rv = inflate(decomp, Z_SYNC_FLUSH);
1578 }
1579 }
1580
1581 // Inflate will generate a Z_BUF_ERROR if it runs out of input
1582 // without producing any output. The input is consumed and
1583 // buffered internally by zlib so we can detect this condition by
1584 // checking if avail_in is 0 after the call to inflate.
1585 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0));
1586 if ((rv == Z_OK) || input_exhausted) {
1530 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 1587 size_t decompressed_len = arraysize(buffer) - decomp->avail_out;
1531 if (decompressed_len > 0) { 1588 if (decompressed_len > 0) {
1532 processed_successfully = visitor_->OnControlFrameHeaderData( 1589 processed_successfully = visitor_->OnControlFrameHeaderData(
1533 stream_id, buffer, decompressed_len); 1590 stream_id, buffer, decompressed_len);
1534 } 1591 }
1535 if (!processed_successfully) { 1592 if (!processed_successfully) {
1536 // Assume that the problem was the header block was too large for the 1593 // Assume that the problem was the header block was too large for the
1537 // visitor. 1594 // visitor.
1538 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 1595 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
1539 } 1596 }
1597 } else {
1598 DLOG(WARNING) << "inflate failure: " << rv << " " << len;
1599 set_error(SPDY_DECOMPRESS_FAILURE);
1600 processed_successfully = false;
1540 } 1601 }
1541 } 1602 }
1542 return processed_successfully; 1603 return processed_successfully;
1543 } 1604 }
1544 1605
1545 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 1606 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData(
1546 const SpdyControlFrame* control_frame, const char* data, size_t len) { 1607 const SpdyControlFrame* control_frame, const char* data, size_t len) {
1547 bool read_successfully = true; 1608 bool read_successfully = true;
1548 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); 1609 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame);
1549 DCHECK_LT(0u, stream_id);
1550 while (read_successfully && len > 0) { 1610 while (read_successfully && len > 0) {
1551 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 1611 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize);
1552 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 1612 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data,
1553 bytes_to_deliver); 1613 bytes_to_deliver);
1554 data += bytes_to_deliver; 1614 data += bytes_to_deliver;
1555 len -= bytes_to_deliver; 1615 len -= bytes_to_deliver;
1556 if (!read_successfully) { 1616 if (!read_successfully) {
1557 // Assume that the problem was the header block was too large for the 1617 // Assume that the problem was the header block was too large for the
1558 // visitor. 1618 // visitor.
1559 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 1619 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1615 switch (type) { 1675 switch (type) {
1616 case SYN_STREAM: 1676 case SYN_STREAM:
1617 return SpdySynStreamControlFrame::size(); 1677 return SpdySynStreamControlFrame::size();
1618 case SYN_REPLY: 1678 case SYN_REPLY:
1619 return SpdySynReplyControlFrame::size(); 1679 return SpdySynReplyControlFrame::size();
1620 case RST_STREAM: 1680 case RST_STREAM:
1621 return SpdyRstStreamControlFrame::size(); 1681 return SpdyRstStreamControlFrame::size();
1622 case SETTINGS: 1682 case SETTINGS:
1623 return SpdySettingsControlFrame::size(); 1683 return SpdySettingsControlFrame::size();
1624 case NOOP: 1684 case NOOP:
1625 return SpdyNoOpControlFrame::size(); 1685 // Even though NOOP is no longer supported, we still correctly report its
1686 // size so that it can be handled correctly as incoming data if
1687 // implementations so desire.
1688 return SpdyFrame::kHeaderSize;
1626 case PING: 1689 case PING:
1627 return SpdyPingControlFrame::size(); 1690 return SpdyPingControlFrame::size();
1628 case GOAWAY: 1691 case GOAWAY:
1629 return SpdyGoAwayControlFrame::size(); 1692 return SpdyGoAwayControlFrame::size();
1630 case HEADERS: 1693 case HEADERS:
1631 return SpdyHeadersControlFrame::size(); 1694 return SpdyHeadersControlFrame::size();
1632 case WINDOW_UPDATE: 1695 case WINDOW_UPDATE:
1633 return SpdyWindowUpdateControlFrame::size(); 1696 return SpdyWindowUpdateControlFrame::size();
1634 case CREDENTIAL: 1697 case CREDENTIAL:
1635 return SpdyCredentialControlFrame::size(); 1698 return SpdyCredentialControlFrame::size();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 case PING: 1738 case PING:
1676 case GOAWAY: 1739 case GOAWAY:
1677 case CREDENTIAL: 1740 case CREDENTIAL:
1678 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy 1741 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy
1679 break; 1742 break;
1680 } 1743 }
1681 } 1744 }
1682 return stream_id; 1745 return stream_id;
1683 } 1746 }
1684 1747
1685 size_t SpdyFramer::BytesSafeToRead() const {
1686 switch (state_) {
1687 case SPDY_ERROR:
1688 case SPDY_DONE:
1689 case SPDY_AUTO_RESET:
1690 case SPDY_RESET:
1691 return 0;
1692 case SPDY_READING_COMMON_HEADER:
1693 DCHECK_LT(current_frame_len_,
1694 static_cast<size_t>(SpdyFrame::kHeaderSize));
1695 return SpdyFrame::kHeaderSize - current_frame_len_;
1696 // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK
1697 // and SPDY_CONTROL_FRAME_HEADER_BLOCK.
1698 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK:
1699 case SPDY_CONTROL_FRAME_HEADER_BLOCK:
1700 return 0;
1701 case SPDY_CONTROL_FRAME_PAYLOAD:
1702 case SPDY_CREDENTIAL_FRAME_PAYLOAD:
1703 case SPDY_IGNORE_REMAINING_PAYLOAD:
1704 case SPDY_FORWARD_STREAM_FRAME:
1705 return remaining_data_;
1706 }
1707 // We should never get to here.
1708 return 0;
1709 }
1710
1711 void SpdyFramer::set_enable_compression(bool value) { 1748 void SpdyFramer::set_enable_compression(bool value) {
1712 enable_compression_ = value; 1749 enable_compression_ = value;
1713 } 1750 }
1714 1751
1752 void SpdyFramer::set_validate_control_frame_sizes(bool value) {
1753 validate_control_frame_sizes_ = value;
1754 }
1755
1715 void SpdyFramer::set_enable_compression_default(bool value) { 1756 void SpdyFramer::set_enable_compression_default(bool value) {
1716 compression_default_ = value; 1757 compression_default_ = value;
1717 } 1758 }
1718 1759
1719 void SpdyFramer::set_validate_control_frame_sizes(bool value) {
1720 validate_control_frame_sizes_ = value;
1721 }
1722
1723 } // namespace spdy 1760 } // namespace spdy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698