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