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

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

Issue 6263010: More net/ header/implementation method reordering. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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/metrics/stats_counters.h" 11 #include "base/metrics/stats_counters.h"
12 #include "base/scoped_ptr.h" 12 #include "base/scoped_ptr.h"
13 #include "net/spdy/spdy_frame_builder.h" 13 #include "net/spdy/spdy_frame_builder.h"
14 #include "net/spdy/spdy_bitmasks.h" 14 #include "net/spdy/spdy_bitmasks.h"
15 15
16 #if defined(USE_SYSTEM_ZLIB) 16 #if defined(USE_SYSTEM_ZLIB)
17 #include <zlib.h> 17 #include <zlib.h>
18 #else 18 #else
19 #include "third_party/zlib/zlib.h" 19 #include "third_party/zlib/zlib.h"
20 #endif 20 #endif
21 21
22 namespace {
23
24 // The following compression setting are based on Brian Olson's analysis. See
25 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2
26 // for more details.
27 const int kCompressorLevel = 9;
28 const int kCompressorWindowSizeInBits = 11;
29 const int kCompressorMemLevel = 1;
30
31 uLong dictionary_id = 0;
32
33 } // namespace
34
22 namespace spdy { 35 namespace spdy {
23 36
37 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
38 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
39 const char SpdyFramer::kDictionary[] =
40 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
41 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
42 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser"
43 "-agent10010120020120220320420520630030130230330430530630740040140240340440"
44 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta"
45 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic"
46 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran"
47 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati"
48 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo"
49 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe"
50 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic"
51 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1"
52 ".1statusversionurl";
53 const int SpdyFramer::kDictionarySize = arraysize(kDictionary);
54
24 // By default is compression on or off. 55 // By default is compression on or off.
25 bool SpdyFramer::compression_default_ = true; 56 bool SpdyFramer::compression_default_ = true;
26 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion; 57 int SpdyFramer::spdy_version_ = kSpdyProtocolVersion;
27 58
28 // The initial size of the control frame buffer; this is used internally 59 // The initial size of the control frame buffer; this is used internally
29 // as we parse through control frames. (It is exposed here for unit test 60 // as we parse through control frames. (It is exposed here for unit test
30 // purposes.) 61 // purposes.)
31 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024; 62 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024;
32 63
33 // The maximum size of the control frame buffer that we support. 64 // The maximum size of the control frame buffer that we support.
(...skipping 30 matching lines...) Expand all
64 if (header_compressor_.get()) { 95 if (header_compressor_.get()) {
65 deflateEnd(header_compressor_.get()); 96 deflateEnd(header_compressor_.get());
66 } 97 }
67 if (header_decompressor_.get()) { 98 if (header_decompressor_.get()) {
68 inflateEnd(header_decompressor_.get()); 99 inflateEnd(header_decompressor_.get());
69 } 100 }
70 CleanupStreamCompressorsAndDecompressors(); 101 CleanupStreamCompressorsAndDecompressors();
71 delete [] current_frame_buffer_; 102 delete [] current_frame_buffer_;
72 } 103 }
73 104
74 void SpdyFramer::Reset() {
75 state_ = SPDY_RESET;
76 error_code_ = SPDY_NO_ERROR;
77 remaining_payload_ = 0;
78 remaining_control_payload_ = 0;
79 current_frame_len_ = 0;
80 if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
81 delete [] current_frame_buffer_;
82 current_frame_buffer_ = 0;
83 current_frame_capacity_ = 0;
84 ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
85 }
86 }
87
88 const char* SpdyFramer::StateToString(int state) {
89 switch (state) {
90 case SPDY_ERROR:
91 return "ERROR";
92 case SPDY_DONE:
93 return "DONE";
94 case SPDY_AUTO_RESET:
95 return "AUTO_RESET";
96 case SPDY_RESET:
97 return "RESET";
98 case SPDY_READING_COMMON_HEADER:
99 return "READING_COMMON_HEADER";
100 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
101 return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
102 case SPDY_CONTROL_FRAME_PAYLOAD:
103 return "CONTROL_FRAME_PAYLOAD";
104 case SPDY_IGNORE_REMAINING_PAYLOAD:
105 return "IGNORE_REMAINING_PAYLOAD";
106 case SPDY_FORWARD_STREAM_FRAME:
107 return "FORWARD_STREAM_FRAME";
108 }
109 return "UNKNOWN_STATE";
110 }
111
112 size_t SpdyFramer::BytesSafeToRead() const {
113 switch (state_) {
114 case SPDY_ERROR:
115 case SPDY_DONE:
116 case SPDY_AUTO_RESET:
117 case SPDY_RESET:
118 return 0;
119 case SPDY_READING_COMMON_HEADER:
120 DCHECK_LT(current_frame_len_, SpdyFrame::size());
121 return SpdyFrame::size() - current_frame_len_;
122 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
123 return 0;
124 case SPDY_CONTROL_FRAME_PAYLOAD:
125 case SPDY_IGNORE_REMAINING_PAYLOAD:
126 case SPDY_FORWARD_STREAM_FRAME:
127 return remaining_payload_;
128 }
129 // We should never get to here.
130 return 0;
131 }
132
133 void SpdyFramer::set_error(SpdyError error) {
134 DCHECK(visitor_);
135 error_code_ = error;
136 CHANGE_STATE(SPDY_ERROR);
137 visitor_->OnError(this);
138 }
139
140 const char* SpdyFramer::ErrorCodeToString(int error_code) {
141 switch (error_code) {
142 case SPDY_NO_ERROR:
143 return "NO_ERROR";
144 case SPDY_INVALID_CONTROL_FRAME:
145 return "INVALID_CONTROL_FRAME";
146 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
147 return "CONTROL_PAYLOAD_TOO_LARGE";
148 case SPDY_ZLIB_INIT_FAILURE:
149 return "ZLIB_INIT_FAILURE";
150 case SPDY_UNSUPPORTED_VERSION:
151 return "UNSUPPORTED_VERSION";
152 case SPDY_DECOMPRESS_FAILURE:
153 return "DECOMPRESS_FAILURE";
154 case SPDY_COMPRESS_FAILURE:
155 return "COMPRESS_FAILURE";
156 }
157 return "UNKNOWN_ERROR";
158 }
159
160 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 105 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
161 DCHECK(visitor_); 106 DCHECK(visitor_);
162 DCHECK(data); 107 DCHECK(data);
163 108
164 size_t original_len = len; 109 size_t original_len = len;
165 while (len != 0) { 110 while (len != 0) {
166 switch (state_) { 111 switch (state_) {
167 case SPDY_ERROR: 112 case SPDY_ERROR:
168 case SPDY_DONE: 113 case SPDY_DONE:
169 goto bottom; 114 goto bottom;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 continue; 149 continue;
205 } 150 }
206 default: 151 default:
207 break; 152 break;
208 } 153 }
209 } 154 }
210 bottom: 155 bottom:
211 return original_len - len; 156 return original_len - len;
212 } 157 }
213 158
214 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 159 void SpdyFramer::Reset() {
215 // This should only be called when we're in the SPDY_READING_COMMON_HEADER 160 state_ = SPDY_RESET;
216 // state. 161 error_code_ = SPDY_NO_ERROR;
217 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 162 remaining_payload_ = 0;
218 163 remaining_control_payload_ = 0;
219 size_t original_len = len; 164 current_frame_len_ = 0;
220 SpdyFrame current_frame(current_frame_buffer_, false); 165 if (current_frame_capacity_ != kControlFrameBufferInitialSize) {
221 166 delete [] current_frame_buffer_;
222 do { 167 current_frame_buffer_ = 0;
223 if (current_frame_len_ < SpdyFrame::size()) { 168 current_frame_capacity_ = 0;
224 size_t bytes_desired = SpdyFrame::size() - current_frame_len_; 169 ExpandControlFrameBuffer(kControlFrameBufferInitialSize);
225 size_t bytes_to_append = std::min(bytes_desired, len);
226 char* header_buffer = current_frame_buffer_;
227 memcpy(&header_buffer[current_frame_len_], data, bytes_to_append);
228 current_frame_len_ += bytes_to_append;
229 data += bytes_to_append;
230 len -= bytes_to_append;
231 // Check for an empty data frame.
232 if (current_frame_len_ == SpdyFrame::size() &&
233 !current_frame.is_control_frame() &&
234 current_frame.length() == 0) {
235 if (current_frame.flags() & CONTROL_FLAG_FIN) {
236 SpdyDataFrame data_frame(current_frame_buffer_, false);
237 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
238 }
239 CHANGE_STATE(SPDY_AUTO_RESET);
240 }
241 break;
242 }
243 remaining_payload_ = current_frame.length();
244
245 // This is just a sanity check for help debugging early frame errors.
246 if (remaining_payload_ > 1000000u) {
247 LOG(WARNING) <<
248 "Unexpectedly large frame. Spdy session is likely corrupt.";
249 }
250
251 // if we're here, then we have the common header all received.
252 if (!current_frame.is_control_frame())
253 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
254 else
255 CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
256 } while (false);
257
258 return original_len - len;
259 }
260
261 void SpdyFramer::ProcessControlFrameHeader() {
262 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
263 DCHECK_LE(SpdyFrame::size(), current_frame_len_);
264 SpdyControlFrame current_control_frame(current_frame_buffer_, false);
265
266 // We check version before we check validity: version can never be 'invalid',
267 // it can only be unsupported.
268 if (current_control_frame.version() != spdy_version_) {
269 set_error(SPDY_UNSUPPORTED_VERSION);
270 return;
271 } 170 }
272
273 // Next up, check to see if we have valid data. This should be after version
274 // checking (otherwise if the the type were out of bounds due to a version
275 // upgrade we would misclassify the error) and before checking the type
276 // (type can definitely be out of bounds)
277 if (!current_control_frame.AppearsToBeAValidControlFrame()) {
278 set_error(SPDY_INVALID_CONTROL_FRAME);
279 return;
280 }
281
282 // Do some sanity checking on the control frame sizes.
283 switch (current_control_frame.type()) {
284 case SYN_STREAM:
285 if (current_control_frame.length() <
286 SpdySynStreamControlFrame::size() - SpdyControlFrame::size())
287 set_error(SPDY_INVALID_CONTROL_FRAME);
288 break;
289 case SYN_REPLY:
290 if (current_control_frame.length() <
291 SpdySynReplyControlFrame::size() - SpdyControlFrame::size())
292 set_error(SPDY_INVALID_CONTROL_FRAME);
293 break;
294 case RST_STREAM:
295 if (current_control_frame.length() !=
296 SpdyRstStreamControlFrame::size() - SpdyFrame::size())
297 set_error(SPDY_INVALID_CONTROL_FRAME);
298 break;
299 case SETTINGS:
300 if (current_control_frame.length() <
301 SpdySettingsControlFrame::size() - SpdyControlFrame::size())
302 set_error(SPDY_INVALID_CONTROL_FRAME);
303 break;
304 case NOOP:
305 // NOOP. Swallow it.
306 CHANGE_STATE(SPDY_AUTO_RESET);
307 return;
308 case GOAWAY:
309 if (current_control_frame.length() !=
310 SpdyGoAwayControlFrame::size() - SpdyFrame::size())
311 set_error(SPDY_INVALID_CONTROL_FRAME);
312 break;
313 case HEADERS:
314 if (current_control_frame.length() <
315 SpdyHeadersControlFrame::size() - SpdyControlFrame::size())
316 set_error(SPDY_INVALID_CONTROL_FRAME);
317 break;
318 case WINDOW_UPDATE:
319 if (current_control_frame.length() !=
320 SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size())
321 set_error(SPDY_INVALID_CONTROL_FRAME);
322 break;
323 default:
324 LOG(WARNING) << "Valid spdy control frame with unknown type: "
325 << current_control_frame.type();
326 DCHECK(false);
327 set_error(SPDY_INVALID_CONTROL_FRAME);
328 break;
329 }
330
331 remaining_control_payload_ = current_control_frame.length();
332 if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
333 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
334 return;
335 }
336
337 ExpandControlFrameBuffer(remaining_control_payload_);
338 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
339 }
340
341 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
342 size_t original_len = len;
343 do {
344 if (remaining_control_payload_) {
345 size_t amount_to_consume = std::min(remaining_control_payload_, len);
346 memcpy(&current_frame_buffer_[current_frame_len_], data,
347 amount_to_consume);
348 current_frame_len_ += amount_to_consume;
349 data += amount_to_consume;
350 len -= amount_to_consume;
351 remaining_control_payload_ -= amount_to_consume;
352 remaining_payload_ -= amount_to_consume;
353 if (remaining_control_payload_)
354 break;
355 }
356 SpdyControlFrame control_frame(current_frame_buffer_, false);
357 visitor_->OnControl(&control_frame);
358
359 // If this is a FIN, tell the caller.
360 if (control_frame.type() == SYN_REPLY &&
361 control_frame.flags() & CONTROL_FLAG_FIN) {
362 visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
363 &control_frame)->stream_id(),
364 NULL, 0);
365 }
366
367 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
368 } while (false);
369 return original_len - len;
370 }
371
372 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
373 size_t original_len = len;
374
375 SpdyDataFrame current_data_frame(current_frame_buffer_, false);
376 if (remaining_payload_) {
377 size_t amount_to_forward = std::min(remaining_payload_, len);
378 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
379 if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) {
380 z_stream* decompressor =
381 GetStreamDecompressor(current_data_frame.stream_id());
382 if (!decompressor)
383 return 0;
384
385 size_t decompressed_max_size = amount_to_forward * 100;
386 scoped_array<char> decompressed(new char[decompressed_max_size]);
387 decompressor->next_in = reinterpret_cast<Bytef*>(
388 const_cast<char*>(data));
389 decompressor->avail_in = amount_to_forward;
390 decompressor->next_out =
391 reinterpret_cast<Bytef*>(decompressed.get());
392 decompressor->avail_out = decompressed_max_size;
393
394 int rv = inflate(decompressor, Z_SYNC_FLUSH);
395 if (rv != Z_OK) {
396 LOG(WARNING) << "inflate failure: " << rv;
397 set_error(SPDY_DECOMPRESS_FAILURE);
398 return 0;
399 }
400 size_t decompressed_size = decompressed_max_size -
401 decompressor->avail_out;
402
403 // Only inform the visitor if there is data.
404 if (decompressed_size)
405 visitor_->OnStreamFrameData(current_data_frame.stream_id(),
406 decompressed.get(),
407 decompressed_size);
408 amount_to_forward -= decompressor->avail_in;
409 } else {
410 // The data frame was not compressed.
411 // Only inform the visitor if there is data.
412 if (amount_to_forward)
413 visitor_->OnStreamFrameData(current_data_frame.stream_id(),
414 data, amount_to_forward);
415 }
416 }
417 data += amount_to_forward;
418 len -= amount_to_forward;
419 remaining_payload_ -= amount_to_forward;
420
421 // If the FIN flag is set, and there is no more data in this data
422 // frame, inform the visitor of EOF via a 0-length data frame.
423 if (!remaining_payload_ &&
424 current_data_frame.flags() & DATA_FLAG_FIN) {
425 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0);
426 CleanupDecompressorForStream(current_data_frame.stream_id());
427 }
428 } else {
429 CHANGE_STATE(SPDY_AUTO_RESET);
430 }
431 return original_len - len;
432 }
433
434 void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
435 size_t alloc_size = size + SpdyFrame::size();
436 DCHECK_LT(alloc_size, kControlFrameBufferMaxSize);
437 if (alloc_size <= current_frame_capacity_)
438 return;
439 char* new_buffer = new char[alloc_size];
440 memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
441 delete [] current_frame_buffer_;
442 current_frame_capacity_ = alloc_size;
443 current_frame_buffer_ = new_buffer;
444 } 171 }
445 172
446 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, 173 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame,
447 SpdyHeaderBlock* block) { 174 SpdyHeaderBlock* block) {
448 SpdyControlFrame control_frame(frame->data(), false); 175 SpdyControlFrame control_frame(frame->data(), false);
449 uint32 type = control_frame.type(); 176 uint32 type = control_frame.type();
450 if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS) 177 if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS)
451 return false; 178 return false;
452 179
453 // Find the header data within the control frame. 180 // Find the header data within the control frame.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 } else { 228 } else {
502 return false; 229 return false;
503 } 230 }
504 } 231 }
505 return index == num_headers && 232 return index == num_headers &&
506 iter == header_data + header_length; 233 iter == header_data + header_length;
507 } 234 }
508 return false; 235 return false;
509 } 236 }
510 237
511 /* static */
512 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
513 SpdySettings* settings) {
514 DCHECK_EQ(frame->type(), SETTINGS);
515 DCHECK(settings);
516
517 SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
518 void* iter = NULL;
519 for (size_t index = 0; index < frame->num_entries(); ++index) {
520 uint32 id;
521 uint32 value;
522 if (!parser.ReadUInt32(&iter, &id))
523 return false;
524 if (!parser.ReadUInt32(&iter, &value))
525 return false;
526 settings->insert(settings->end(), std::make_pair(id, value));
527 }
528 return true;
529 }
530
531 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( 238 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream(
532 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, 239 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority,
533 SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) { 240 SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) {
534 SpdyFrameBuilder frame; 241 SpdyFrameBuilder frame;
535 242
536 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); 243 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0));
537 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 244 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
538 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); 245 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask);
539 246
540 frame.WriteUInt16(kControlFlagMask | spdy_version_); 247 frame.WriteUInt16(kControlFlagMask | spdy_version_);
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
720 frame.WriteUInt16(kControlFlagMask | spdy_version_); 427 frame.WriteUInt16(kControlFlagMask | spdy_version_);
721 frame.WriteUInt16(WINDOW_UPDATE); 428 frame.WriteUInt16(WINDOW_UPDATE);
722 size_t window_update_size = SpdyWindowUpdateControlFrame::size() - 429 size_t window_update_size = SpdyWindowUpdateControlFrame::size() -
723 SpdyFrame::size(); 430 SpdyFrame::size();
724 frame.WriteUInt32(window_update_size); 431 frame.WriteUInt32(window_update_size);
725 frame.WriteUInt32(stream_id); 432 frame.WriteUInt32(stream_id);
726 frame.WriteUInt32(delta_window_size); 433 frame.WriteUInt32(delta_window_size);
727 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); 434 return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take());
728 } 435 }
729 436
437 /* static */
438 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame,
439 SpdySettings* settings) {
440 DCHECK_EQ(frame->type(), SETTINGS);
441 DCHECK(settings);
442
443 SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len());
444 void* iter = NULL;
445 for (size_t index = 0; index < frame->num_entries(); ++index) {
446 uint32 id;
447 uint32 value;
448 if (!parser.ReadUInt32(&iter, &id))
449 return false;
450 if (!parser.ReadUInt32(&iter, &value))
451 return false;
452 settings->insert(settings->end(), std::make_pair(id, value));
453 }
454 return true;
455 }
456
730 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, 457 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
731 const char* data, 458 const char* data,
732 uint32 len, SpdyDataFlags flags) { 459 uint32 len, SpdyDataFlags flags) {
733 SpdyFrameBuilder frame; 460 SpdyFrameBuilder frame;
734 461
735 DCHECK_GT(stream_id, 0u); 462 DCHECK_GT(stream_id, 0u);
736 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 463 DCHECK_EQ(0u, stream_id & ~kStreamIdMask);
737 frame.WriteUInt32(stream_id); 464 frame.WriteUInt32(stream_id);
738 465
739 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask)); 466 DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask));
(...skipping 12 matching lines...) Expand all
752 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); 479 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release());
753 } 480 }
754 481
755 if (flags & DATA_FLAG_FIN) { 482 if (flags & DATA_FLAG_FIN) {
756 CleanupCompressorForStream(stream_id); 483 CleanupCompressorForStream(stream_id);
757 } 484 }
758 485
759 return rv; 486 return rv;
760 } 487 }
761 488
762 // The following compression setting are based on Brian Olson's analysis. See 489 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
763 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 490 if (frame.is_control_frame()) {
764 // for more details. 491 return CompressControlFrame(
765 static const int kCompressorLevel = 9; 492 reinterpret_cast<const SpdyControlFrame&>(frame));
766 static const int kCompressorWindowSizeInBits = 11; 493 }
767 static const int kCompressorMemLevel = 1; 494 return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
768 495 }
769 // This is just a hacked dictionary to use for shrinking HTTP-like headers. 496
770 // TODO(mbelshe): Use a scientific methodology for computing the dictionary. 497 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
771 const char SpdyFramer::kDictionary[] = 498 if (frame.is_control_frame()) {
772 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" 499 return DecompressControlFrame(
773 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" 500 reinterpret_cast<const SpdyControlFrame&>(frame));
774 "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" 501 }
775 "-agent10010120020120220320420520630030130230330430530630740040140240340440" 502 return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
776 "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" 503 }
777 "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" 504
778 "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" 505 SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) {
779 "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" 506 int size = SpdyFrame::size() + frame.length();
780 "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" 507 SpdyFrame* new_frame = new SpdyFrame(size);
781 "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" 508 memcpy(new_frame->data(), frame.data(), size);
782 "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" 509 return new_frame;
783 "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" 510 }
784 ".1statusversionurl"; 511
785 const int SpdyFramer::kDictionarySize = arraysize(kDictionary); 512 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const {
786 513 // The important frames to compress are those which contain large
787 static uLong dictionary_id = 0; 514 // amounts of compressible data - namely the headers in the SYN_STREAM
515 // and SYN_REPLY.
516 // TODO(mbelshe): Reconcile this with the spec when the spec is
517 // explicit about which frames compress and which do not.
518 if (frame.is_control_frame()) {
519 const SpdyControlFrame& control_frame =
520 reinterpret_cast<const SpdyControlFrame&>(frame);
521 return control_frame.type() == SYN_STREAM ||
522 control_frame.type() == SYN_REPLY;
523 }
524
525 const SpdyDataFrame& data_frame =
526 reinterpret_cast<const SpdyDataFrame&>(frame);
527 return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
528 }
529
530 const char* SpdyFramer::StateToString(int state) {
531 switch (state) {
532 case SPDY_ERROR:
533 return "ERROR";
534 case SPDY_DONE:
535 return "DONE";
536 case SPDY_AUTO_RESET:
537 return "AUTO_RESET";
538 case SPDY_RESET:
539 return "RESET";
540 case SPDY_READING_COMMON_HEADER:
541 return "READING_COMMON_HEADER";
542 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
543 return "INTERPRET_CONTROL_FRAME_COMMON_HEADER";
544 case SPDY_CONTROL_FRAME_PAYLOAD:
545 return "CONTROL_FRAME_PAYLOAD";
546 case SPDY_IGNORE_REMAINING_PAYLOAD:
547 return "IGNORE_REMAINING_PAYLOAD";
548 case SPDY_FORWARD_STREAM_FRAME:
549 return "FORWARD_STREAM_FRAME";
550 }
551 return "UNKNOWN_STATE";
552 }
553
554 const char* SpdyFramer::ErrorCodeToString(int error_code) {
555 switch (error_code) {
556 case SPDY_NO_ERROR:
557 return "NO_ERROR";
558 case SPDY_INVALID_CONTROL_FRAME:
559 return "INVALID_CONTROL_FRAME";
560 case SPDY_CONTROL_PAYLOAD_TOO_LARGE:
561 return "CONTROL_PAYLOAD_TOO_LARGE";
562 case SPDY_ZLIB_INIT_FAILURE:
563 return "ZLIB_INIT_FAILURE";
564 case SPDY_UNSUPPORTED_VERSION:
565 return "UNSUPPORTED_VERSION";
566 case SPDY_DECOMPRESS_FAILURE:
567 return "DECOMPRESS_FAILURE";
568 case SPDY_COMPRESS_FAILURE:
569 return "COMPRESS_FAILURE";
570 }
571 return "UNKNOWN_ERROR";
572 }
573
574 void SpdyFramer::set_enable_compression(bool value) {
575 enable_compression_ = value;
576 }
577
578 void SpdyFramer::set_enable_compression_default(bool value) {
579 compression_default_ = value;
580 }
581
582 size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) {
583 // This should only be called when we're in the SPDY_READING_COMMON_HEADER
584 // state.
585 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER);
586
587 size_t original_len = len;
588 SpdyFrame current_frame(current_frame_buffer_, false);
589
590 do {
591 if (current_frame_len_ < SpdyFrame::size()) {
592 size_t bytes_desired = SpdyFrame::size() - current_frame_len_;
593 size_t bytes_to_append = std::min(bytes_desired, len);
594 char* header_buffer = current_frame_buffer_;
595 memcpy(&header_buffer[current_frame_len_], data, bytes_to_append);
596 current_frame_len_ += bytes_to_append;
597 data += bytes_to_append;
598 len -= bytes_to_append;
599 // Check for an empty data frame.
600 if (current_frame_len_ == SpdyFrame::size() &&
601 !current_frame.is_control_frame() &&
602 current_frame.length() == 0) {
603 if (current_frame.flags() & CONTROL_FLAG_FIN) {
604 SpdyDataFrame data_frame(current_frame_buffer_, false);
605 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0);
606 }
607 CHANGE_STATE(SPDY_AUTO_RESET);
608 }
609 break;
610 }
611 remaining_payload_ = current_frame.length();
612
613 // This is just a sanity check for help debugging early frame errors.
614 if (remaining_payload_ > 1000000u) {
615 LOG(WARNING) <<
616 "Unexpectedly large frame. Spdy session is likely corrupt.";
617 }
618
619 // if we're here, then we have the common header all received.
620 if (!current_frame.is_control_frame())
621 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
622 else
623 CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER);
624 } while (false);
625
626 return original_len - len;
627 }
628
629 void SpdyFramer::ProcessControlFrameHeader() {
630 DCHECK_EQ(SPDY_NO_ERROR, error_code_);
631 DCHECK_LE(SpdyFrame::size(), current_frame_len_);
632 SpdyControlFrame current_control_frame(current_frame_buffer_, false);
633
634 // We check version before we check validity: version can never be 'invalid',
635 // it can only be unsupported.
636 if (current_control_frame.version() != spdy_version_) {
637 set_error(SPDY_UNSUPPORTED_VERSION);
638 return;
639 }
640
641 // Next up, check to see if we have valid data. This should be after version
642 // checking (otherwise if the the type were out of bounds due to a version
643 // upgrade we would misclassify the error) and before checking the type
644 // (type can definitely be out of bounds)
645 if (!current_control_frame.AppearsToBeAValidControlFrame()) {
646 set_error(SPDY_INVALID_CONTROL_FRAME);
647 return;
648 }
649
650 // Do some sanity checking on the control frame sizes.
651 switch (current_control_frame.type()) {
652 case SYN_STREAM:
653 if (current_control_frame.length() <
654 SpdySynStreamControlFrame::size() - SpdyControlFrame::size())
655 set_error(SPDY_INVALID_CONTROL_FRAME);
656 break;
657 case SYN_REPLY:
658 if (current_control_frame.length() <
659 SpdySynReplyControlFrame::size() - SpdyControlFrame::size())
660 set_error(SPDY_INVALID_CONTROL_FRAME);
661 break;
662 case RST_STREAM:
663 if (current_control_frame.length() !=
664 SpdyRstStreamControlFrame::size() - SpdyFrame::size())
665 set_error(SPDY_INVALID_CONTROL_FRAME);
666 break;
667 case SETTINGS:
668 if (current_control_frame.length() <
669 SpdySettingsControlFrame::size() - SpdyControlFrame::size())
670 set_error(SPDY_INVALID_CONTROL_FRAME);
671 break;
672 case NOOP:
673 // NOOP. Swallow it.
674 CHANGE_STATE(SPDY_AUTO_RESET);
675 return;
676 case GOAWAY:
677 if (current_control_frame.length() !=
678 SpdyGoAwayControlFrame::size() - SpdyFrame::size())
679 set_error(SPDY_INVALID_CONTROL_FRAME);
680 break;
681 case HEADERS:
682 if (current_control_frame.length() <
683 SpdyHeadersControlFrame::size() - SpdyControlFrame::size())
684 set_error(SPDY_INVALID_CONTROL_FRAME);
685 break;
686 case WINDOW_UPDATE:
687 if (current_control_frame.length() !=
688 SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size())
689 set_error(SPDY_INVALID_CONTROL_FRAME);
690 break;
691 default:
692 LOG(WARNING) << "Valid spdy control frame with unknown type: "
693 << current_control_frame.type();
694 DCHECK(false);
695 set_error(SPDY_INVALID_CONTROL_FRAME);
696 break;
697 }
698
699 remaining_control_payload_ = current_control_frame.length();
700 if (remaining_control_payload_ > kControlFrameBufferMaxSize) {
701 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE);
702 return;
703 }
704
705 ExpandControlFrameBuffer(remaining_control_payload_);
706 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD);
707 }
708
709 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
710 size_t original_len = len;
711 do {
712 if (remaining_control_payload_) {
713 size_t amount_to_consume = std::min(remaining_control_payload_, len);
714 memcpy(&current_frame_buffer_[current_frame_len_], data,
715 amount_to_consume);
716 current_frame_len_ += amount_to_consume;
717 data += amount_to_consume;
718 len -= amount_to_consume;
719 remaining_control_payload_ -= amount_to_consume;
720 remaining_payload_ -= amount_to_consume;
721 if (remaining_control_payload_)
722 break;
723 }
724 SpdyControlFrame control_frame(current_frame_buffer_, false);
725 visitor_->OnControl(&control_frame);
726
727 // If this is a FIN, tell the caller.
728 if (control_frame.type() == SYN_REPLY &&
729 control_frame.flags() & CONTROL_FLAG_FIN) {
730 visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>(
731 &control_frame)->stream_id(),
732 NULL, 0);
733 }
734
735 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD);
736 } while (false);
737 return original_len - len;
738 }
739
740 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) {
741 size_t original_len = len;
742
743 SpdyDataFrame current_data_frame(current_frame_buffer_, false);
744 if (remaining_payload_) {
745 size_t amount_to_forward = std::min(remaining_payload_, len);
746 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) {
747 if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) {
748 z_stream* decompressor =
749 GetStreamDecompressor(current_data_frame.stream_id());
750 if (!decompressor)
751 return 0;
752
753 size_t decompressed_max_size = amount_to_forward * 100;
754 scoped_array<char> decompressed(new char[decompressed_max_size]);
755 decompressor->next_in = reinterpret_cast<Bytef*>(
756 const_cast<char*>(data));
757 decompressor->avail_in = amount_to_forward;
758 decompressor->next_out =
759 reinterpret_cast<Bytef*>(decompressed.get());
760 decompressor->avail_out = decompressed_max_size;
761
762 int rv = inflate(decompressor, Z_SYNC_FLUSH);
763 if (rv != Z_OK) {
764 LOG(WARNING) << "inflate failure: " << rv;
765 set_error(SPDY_DECOMPRESS_FAILURE);
766 return 0;
767 }
768 size_t decompressed_size = decompressed_max_size -
769 decompressor->avail_out;
770
771 // Only inform the visitor if there is data.
772 if (decompressed_size)
773 visitor_->OnStreamFrameData(current_data_frame.stream_id(),
774 decompressed.get(),
775 decompressed_size);
776 amount_to_forward -= decompressor->avail_in;
777 } else {
778 // The data frame was not compressed.
779 // Only inform the visitor if there is data.
780 if (amount_to_forward)
781 visitor_->OnStreamFrameData(current_data_frame.stream_id(),
782 data, amount_to_forward);
783 }
784 }
785 data += amount_to_forward;
786 len -= amount_to_forward;
787 remaining_payload_ -= amount_to_forward;
788
789 // If the FIN flag is set, and there is no more data in this data
790 // frame, inform the visitor of EOF via a 0-length data frame.
791 if (!remaining_payload_ &&
792 current_data_frame.flags() & DATA_FLAG_FIN) {
793 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0);
794 CleanupDecompressorForStream(current_data_frame.stream_id());
795 }
796 } else {
797 CHANGE_STATE(SPDY_AUTO_RESET);
798 }
799 return original_len - len;
800 }
788 801
789 z_stream* SpdyFramer::GetHeaderCompressor() { 802 z_stream* SpdyFramer::GetHeaderCompressor() {
790 if (header_compressor_.get()) 803 if (header_compressor_.get())
791 return header_compressor_.get(); // Already initialized. 804 return header_compressor_.get(); // Already initialized.
792 805
793 header_compressor_.reset(new z_stream); 806 header_compressor_.reset(new z_stream);
794 memset(header_compressor_.get(), 0, sizeof(z_stream)); 807 memset(header_compressor_.get(), 0, sizeof(z_stream));
795 808
796 int success = deflateInit2(header_compressor_.get(), 809 int success = deflateInit2(header_compressor_.get(),
797 kCompressorLevel, 810 kCompressorLevel,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 memset(decompressor.get(), 0, sizeof(z_stream)); 879 memset(decompressor.get(), 0, sizeof(z_stream));
867 880
868 int success = inflateInit(decompressor.get()); 881 int success = inflateInit(decompressor.get());
869 if (success != Z_OK) { 882 if (success != Z_OK) {
870 LOG(WARNING) << "inflateInit failure: " << success; 883 LOG(WARNING) << "inflateInit failure: " << success;
871 return NULL; 884 return NULL;
872 } 885 }
873 return stream_decompressors_[stream_id] = decompressor.release(); 886 return stream_decompressors_[stream_id] = decompressor.release();
874 } 887 }
875 888
876 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
877 int* payload_length,
878 int* header_length,
879 const char** payload) const {
880 size_t frame_size;
881 if (frame.is_control_frame()) {
882 const SpdyControlFrame& control_frame =
883 reinterpret_cast<const SpdyControlFrame&>(frame);
884 switch (control_frame.type()) {
885 case SYN_STREAM:
886 {
887 const SpdySynStreamControlFrame& syn_frame =
888 reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
889 frame_size = SpdySynStreamControlFrame::size();
890 *payload_length = syn_frame.header_block_len();
891 *header_length = frame_size;
892 *payload = frame.data() + *header_length;
893 }
894 break;
895 case SYN_REPLY:
896 {
897 const SpdySynReplyControlFrame& syn_frame =
898 reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
899 frame_size = SpdySynReplyControlFrame::size();
900 *payload_length = syn_frame.header_block_len();
901 *header_length = frame_size;
902 *payload = frame.data() + *header_length;
903 }
904 break;
905 case HEADERS:
906 {
907 const SpdyHeadersControlFrame& headers_frame =
908 reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
909 frame_size = SpdyHeadersControlFrame::size();
910 *payload_length = headers_frame.header_block_len();
911 *header_length = frame_size;
912 *payload = frame.data() + *header_length;
913 }
914 break;
915 default:
916 // TODO(mbelshe): set an error?
917 return false; // We can't compress this frame!
918 }
919 } else {
920 frame_size = SpdyFrame::size();
921 *header_length = frame_size;
922 *payload_length = frame.length();
923 *payload = frame.data() + SpdyFrame::size();
924 }
925 return true;
926 }
927
928 SpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) {
929 if (frame.is_control_frame()) {
930 return CompressControlFrame(
931 reinterpret_cast<const SpdyControlFrame&>(frame));
932 }
933 return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
934 }
935
936 SpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) {
937 if (frame.is_control_frame()) {
938 return DecompressControlFrame(
939 reinterpret_cast<const SpdyControlFrame&>(frame));
940 }
941 return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame));
942 }
943
944 SpdyControlFrame* SpdyFramer::CompressControlFrame( 889 SpdyControlFrame* SpdyFramer::CompressControlFrame(
945 const SpdyControlFrame& frame) { 890 const SpdyControlFrame& frame) {
946 z_stream* compressor = GetHeaderCompressor(); 891 z_stream* compressor = GetHeaderCompressor();
947 if (!compressor) 892 if (!compressor)
948 return NULL; 893 return NULL;
949 return reinterpret_cast<SpdyControlFrame*>( 894 return reinterpret_cast<SpdyControlFrame*>(
950 CompressFrameWithZStream(frame, compressor)); 895 CompressFrameWithZStream(frame, compressor));
951 } 896 }
952 897
898 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
899 z_stream* compressor = GetStreamCompressor(frame.stream_id());
900 if (!compressor)
901 return NULL;
902 return reinterpret_cast<SpdyDataFrame*>(
903 CompressFrameWithZStream(frame, compressor));
904 }
905
953 SpdyControlFrame* SpdyFramer::DecompressControlFrame( 906 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
954 const SpdyControlFrame& frame) { 907 const SpdyControlFrame& frame) {
955 z_stream* decompressor = GetHeaderDecompressor(); 908 z_stream* decompressor = GetHeaderDecompressor();
956 if (!decompressor) 909 if (!decompressor)
957 return NULL; 910 return NULL;
958 return reinterpret_cast<SpdyControlFrame*>( 911 return reinterpret_cast<SpdyControlFrame*>(
959 DecompressFrameWithZStream(frame, decompressor)); 912 DecompressFrameWithZStream(frame, decompressor));
960 } 913 }
961 914
962 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
963 z_stream* compressor = GetStreamCompressor(frame.stream_id());
964 if (!compressor)
965 return NULL;
966 return reinterpret_cast<SpdyDataFrame*>(
967 CompressFrameWithZStream(frame, compressor));
968 }
969
970 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { 915 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
971 z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); 916 z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
972 if (!decompressor) 917 if (!decompressor)
973 return NULL; 918 return NULL;
974 return reinterpret_cast<SpdyDataFrame*>( 919 return reinterpret_cast<SpdyDataFrame*>(
975 DecompressFrameWithZStream(frame, decompressor)); 920 DecompressFrameWithZStream(frame, decompressor));
976 } 921 }
977 922
978 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame, 923 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame,
979 z_stream* compressor) { 924 z_stream* compressor) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1138 it = stream_decompressors_.begin(); 1083 it = stream_decompressors_.begin();
1139 while (it != stream_decompressors_.end()) { 1084 while (it != stream_decompressors_.end()) {
1140 z_stream* decompressor = it->second; 1085 z_stream* decompressor = it->second;
1141 inflateEnd(decompressor); 1086 inflateEnd(decompressor);
1142 delete decompressor; 1087 delete decompressor;
1143 ++it; 1088 ++it;
1144 } 1089 }
1145 stream_decompressors_.clear(); 1090 stream_decompressors_.clear();
1146 } 1091 }
1147 1092
1148 SpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) { 1093 size_t SpdyFramer::BytesSafeToRead() const {
1149 int size = SpdyFrame::size() + frame.length(); 1094 switch (state_) {
1150 SpdyFrame* new_frame = new SpdyFrame(size); 1095 case SPDY_ERROR:
1151 memcpy(new_frame->data(), frame.data(), size); 1096 case SPDY_DONE:
1152 return new_frame; 1097 case SPDY_AUTO_RESET:
1098 case SPDY_RESET:
1099 return 0;
1100 case SPDY_READING_COMMON_HEADER:
1101 DCHECK_LT(current_frame_len_, SpdyFrame::size());
1102 return SpdyFrame::size() - current_frame_len_;
1103 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER:
1104 return 0;
1105 case SPDY_CONTROL_FRAME_PAYLOAD:
1106 case SPDY_IGNORE_REMAINING_PAYLOAD:
1107 case SPDY_FORWARD_STREAM_FRAME:
1108 return remaining_payload_;
1109 }
1110 // We should never get to here.
1111 return 0;
1153 } 1112 }
1154 1113
1155 bool SpdyFramer::IsCompressible(const SpdyFrame& frame) const { 1114 void SpdyFramer::set_error(SpdyError error) {
1156 // The important frames to compress are those which contain large 1115 DCHECK(visitor_);
1157 // amounts of compressible data - namely the headers in the SYN_STREAM 1116 error_code_ = error;
1158 // and SYN_REPLY. 1117 CHANGE_STATE(SPDY_ERROR);
1159 // TODO(mbelshe): Reconcile this with the spec when the spec is 1118 visitor_->OnError(this);
1160 // explicit about which frames compress and which do not. 1119 }
1120
1121 void SpdyFramer::ExpandControlFrameBuffer(size_t size) {
1122 size_t alloc_size = size + SpdyFrame::size();
1123 DCHECK_LT(alloc_size, kControlFrameBufferMaxSize);
1124 if (alloc_size <= current_frame_capacity_)
1125 return;
1126 char* new_buffer = new char[alloc_size];
1127 memcpy(new_buffer, current_frame_buffer_, current_frame_len_);
1128 delete [] current_frame_buffer_;
1129 current_frame_capacity_ = alloc_size;
1130 current_frame_buffer_ = new_buffer;
1131 }
1132
1133 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame,
1134 int* payload_length,
1135 int* header_length,
1136 const char** payload) const {
1137 size_t frame_size;
1161 if (frame.is_control_frame()) { 1138 if (frame.is_control_frame()) {
1162 const SpdyControlFrame& control_frame = 1139 const SpdyControlFrame& control_frame =
1163 reinterpret_cast<const SpdyControlFrame&>(frame); 1140 reinterpret_cast<const SpdyControlFrame&>(frame);
1164 return control_frame.type() == SYN_STREAM || 1141 switch (control_frame.type()) {
1165 control_frame.type() == SYN_REPLY; 1142 case SYN_STREAM:
1143 {
1144 const SpdySynStreamControlFrame& syn_frame =
1145 reinterpret_cast<const SpdySynStreamControlFrame&>(frame);
1146 frame_size = SpdySynStreamControlFrame::size();
1147 *payload_length = syn_frame.header_block_len();
1148 *header_length = frame_size;
1149 *payload = frame.data() + *header_length;
1150 }
1151 break;
1152 case SYN_REPLY:
1153 {
1154 const SpdySynReplyControlFrame& syn_frame =
1155 reinterpret_cast<const SpdySynReplyControlFrame&>(frame);
1156 frame_size = SpdySynReplyControlFrame::size();
1157 *payload_length = syn_frame.header_block_len();
1158 *header_length = frame_size;
1159 *payload = frame.data() + *header_length;
1160 }
1161 break;
1162 case HEADERS:
1163 {
1164 const SpdyHeadersControlFrame& headers_frame =
1165 reinterpret_cast<const SpdyHeadersControlFrame&>(frame);
1166 frame_size = SpdyHeadersControlFrame::size();
1167 *payload_length = headers_frame.header_block_len();
1168 *header_length = frame_size;
1169 *payload = frame.data() + *header_length;
1170 }
1171 break;
1172 default:
1173 // TODO(mbelshe): set an error?
1174 return false; // We can't compress this frame!
1175 }
1176 } else {
1177 frame_size = SpdyFrame::size();
1178 *header_length = frame_size;
1179 *payload_length = frame.length();
1180 *payload = frame.data() + SpdyFrame::size();
1166 } 1181 }
1167 1182 return true;
1168 const SpdyDataFrame& data_frame =
1169 reinterpret_cast<const SpdyDataFrame&>(frame);
1170 return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0;
1171 }
1172
1173 void SpdyFramer::set_enable_compression(bool value) {
1174 enable_compression_ = value;
1175 }
1176
1177 void SpdyFramer::set_enable_compression_default(bool value) {
1178 compression_default_ = value;
1179 } 1183 }
1180 1184
1181 } // namespace spdy 1185 } // namespace spdy
OLDNEW
« net/disk_cache/bitmap.h ('K') | « net/socket_stream/socket_stream_metrics.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698