| 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 #include "net/spdy/spdy_framer.h" |     5 #include "net/spdy/spdy_framer.h" | 
|     6  |     6  | 
|     7 #include "base/lazy_instance.h" |     7 #include "base/lazy_instance.h" | 
|     8 #include "base/memory/scoped_ptr.h" |     8 #include "base/memory/scoped_ptr.h" | 
|     9 #include "base/metrics/stats_counters.h" |     9 #include "base/metrics/stats_counters.h" | 
|    10 #include "base/third_party/valgrind/memcheck.h" |    10 #include "base/third_party/valgrind/memcheck.h" | 
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   151     size_t len) { |   151     size_t len) { | 
|   152   return true; |   152   return true; | 
|   153 } |   153 } | 
|   154  |   154  | 
|   155 SpdyFramer::SpdyFramer(SpdyMajorVersion version) |   155 SpdyFramer::SpdyFramer(SpdyMajorVersion version) | 
|   156     : current_frame_buffer_(new char[kControlFrameBufferSize]), |   156     : current_frame_buffer_(new char[kControlFrameBufferSize]), | 
|   157       enable_compression_(true), |   157       enable_compression_(true), | 
|   158       visitor_(NULL), |   158       visitor_(NULL), | 
|   159       debug_visitor_(NULL), |   159       debug_visitor_(NULL), | 
|   160       display_protocol_("SPDY"), |   160       display_protocol_("SPDY"), | 
|   161       spdy_version_(version), |   161       protocol_version_(version), | 
|   162       syn_frame_processed_(false), |   162       syn_frame_processed_(false), | 
|   163       probable_http_response_(false), |   163       probable_http_response_(false), | 
|   164       expect_continuation_(0), |   164       expect_continuation_(0), | 
|   165       end_stream_when_done_(false) { |   165       end_stream_when_done_(false) { | 
|   166   DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); |   166   DCHECK_GE(protocol_version_, SPDY_MIN_VERSION); | 
|   167   DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); |   167   DCHECK_LE(protocol_version_, SPDY_MAX_VERSION); | 
|   168   DCHECK_LE(kMaxControlFrameSize, |   168   DCHECK_LE(kMaxControlFrameSize, | 
|   169             SpdyConstants::GetFrameMaximumSize(spdy_version_) + |   169             SpdyConstants::GetFrameMaximumSize(protocol_version_) + | 
|   170                 SpdyConstants::GetControlFrameHeaderSize(spdy_version_)); |   170                 SpdyConstants::GetControlFrameHeaderSize(protocol_version_)); | 
|   171   Reset(); |   171   Reset(); | 
|   172 } |   172 } | 
|   173  |   173  | 
|   174 SpdyFramer::~SpdyFramer() { |   174 SpdyFramer::~SpdyFramer() { | 
|   175   if (header_compressor_.get()) { |   175   if (header_compressor_.get()) { | 
|   176     deflateEnd(header_compressor_.get()); |   176     deflateEnd(header_compressor_.get()); | 
|   177   } |   177   } | 
|   178   if (header_decompressor_.get()) { |   178   if (header_decompressor_.get()) { | 
|   179     inflateEnd(header_decompressor_.get()); |   179     inflateEnd(header_decompressor_.get()); | 
|   180   } |   180   } | 
| (...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1053       break; |  1053       break; | 
|  1054   } |  1054   } | 
|  1055  |  1055  | 
|  1056   if (state_ == SPDY_ERROR) { |  1056   if (state_ == SPDY_ERROR) { | 
|  1057     return; |  1057     return; | 
|  1058   } |  1058   } | 
|  1059  |  1059  | 
|  1060   if (current_frame_length_ > |  1060   if (current_frame_length_ > | 
|  1061       SpdyConstants::GetFrameMaximumSize(protocol_version()) + |  1061       SpdyConstants::GetFrameMaximumSize(protocol_version()) + | 
|  1062           SpdyConstants::GetControlFrameHeaderSize(protocol_version())) { |  1062           SpdyConstants::GetControlFrameHeaderSize(protocol_version())) { | 
|  1063     DLOG(WARNING) << "Received control frame with way too big of a payload: " |  1063     DLOG(WARNING) << "Received control frame of type " << current_frame_type_ | 
 |  1064                   << " with way too big of a payload: " | 
|  1064                   << current_frame_length_; |  1065                   << current_frame_length_; | 
|  1065     set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |  1066     set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 
|  1066     return; |  1067     return; | 
|  1067   } |  1068   } | 
|  1068  |  1069  | 
|  1069   if (current_frame_type_ == GOAWAY) { |  1070   if (current_frame_type_ == GOAWAY) { | 
|  1070     CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); |  1071     CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); | 
|  1071     return; |  1072     return; | 
|  1072   } |  1073   } | 
|  1073  |  1074  | 
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  1274   } |  1275   } | 
|  1275   WriteZ(base::StringPiece(buf, length), clas, out); |  1276   WriteZ(base::StringPiece(buf, length), clas, out); | 
|  1276 } |  1277 } | 
|  1277  |  1278  | 
|  1278 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a |  1279 // WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a | 
|  1279 // manner that resists the length of the compressed data from compromising |  1280 // manner that resists the length of the compressed data from compromising | 
|  1280 // cookie data. |  1281 // cookie data. | 
|  1281 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, |  1282 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, | 
|  1282                                      z_stream* z) const { |  1283                                      z_stream* z) const { | 
|  1283   unsigned length_length = 4; |  1284   unsigned length_length = 4; | 
|  1284   if (spdy_version_ < 3) |  1285   if (protocol_version() < 3) | 
|  1285     length_length = 2; |  1286     length_length = 2; | 
|  1286  |  1287  | 
|  1287   WriteLengthZ(headers->size(), length_length, kZStandardData, z); |  1288   WriteLengthZ(headers->size(), length_length, kZStandardData, z); | 
|  1288  |  1289  | 
|  1289   std::map<std::string, std::string>::const_iterator it; |  1290   std::map<std::string, std::string>::const_iterator it; | 
|  1290   for (it = headers->begin(); it != headers->end(); ++it) { |  1291   for (it = headers->begin(); it != headers->end(); ++it) { | 
|  1291     WriteLengthZ(it->first.size(), length_length, kZStandardData, z); |  1292     WriteLengthZ(it->first.size(), length_length, kZStandardData, z); | 
|  1292     WriteZ(it->first, kZStandardData, z); |  1293     WriteZ(it->first, kZStandardData, z); | 
|  1293  |  1294  | 
|  1294     if (it->first == "cookie") { |  1295     if (it->first == "cookie") { | 
| (...skipping 1674 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  2969   DCHECK_GT(size, kMaxControlFrameSize); |  2970   DCHECK_GT(size, kMaxControlFrameSize); | 
|  2970   size_t overflow = size - kMaxControlFrameSize; |  2971   size_t overflow = size - kMaxControlFrameSize; | 
|  2971   return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; |  2972   return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; | 
|  2972 } |  2973 } | 
|  2973  |  2974  | 
|  2974 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |  2975 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, | 
|  2975                                               const string& hpack_encoding, |  2976                                               const string& hpack_encoding, | 
|  2976                                               SpdyStreamId stream_id, |  2977                                               SpdyStreamId stream_id, | 
|  2977                                               SpdyFrameType type, |  2978                                               SpdyFrameType type, | 
|  2978                                               int padding_payload_len) { |  2979                                               int padding_payload_len) { | 
|  2979     uint8 end_flag = 0; |  2980   uint8 end_flag = 0; | 
|  2980     uint8 flags = 0; |  2981   uint8 flags = 0; | 
|  2981     if (type == HEADERS) { |  2982   if (type == HEADERS) { | 
|  2982       end_flag = HEADERS_FLAG_END_HEADERS; |  2983     end_flag = HEADERS_FLAG_END_HEADERS; | 
|  2983     } else if (type == PUSH_PROMISE) { |  2984   } else if (type == PUSH_PROMISE) { | 
|  2984       end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |  2985     end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 
|  2985     } else { |  2986   } else { | 
|  2986       DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |  2987     DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " | 
|  2987                   << FrameTypeToString(type); |  2988                 << FrameTypeToString(type); | 
 |  2989   } | 
 |  2990  | 
 |  2991   // Write all the padding payload and as much of the data payload as possible | 
 |  2992   // into the initial frame. | 
 |  2993   size_t bytes_remaining = 0; | 
 |  2994   bytes_remaining = | 
 |  2995       hpack_encoding.size() - | 
 |  2996       std::min(hpack_encoding.size(), | 
 |  2997                kMaxControlFrameSize - builder->length() - padding_payload_len); | 
 |  2998   builder->WriteBytes(&hpack_encoding[0], | 
 |  2999                       hpack_encoding.size() - bytes_remaining); | 
 |  3000   if (padding_payload_len > 0) { | 
 |  3001     string padding = string(padding_payload_len, 0); | 
 |  3002     builder->WriteBytes(padding.data(), padding.length()); | 
 |  3003   } | 
 |  3004   if (bytes_remaining > 0) { | 
 |  3005     builder->OverwriteLength( | 
 |  3006         *this, kMaxControlFrameSize - GetControlFrameHeaderSize()); | 
 |  3007   } | 
 |  3008  | 
 |  3009   // Tack on CONTINUATION frames for the overflow. | 
 |  3010   while (bytes_remaining > 0) { | 
 |  3011     size_t bytes_to_write = std::min( | 
 |  3012         bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize()); | 
 |  3013     // Write CONTINUATION frame prefix. | 
 |  3014     if (bytes_remaining == bytes_to_write) { | 
 |  3015       flags |= end_flag; | 
|  2988     } |  3016     } | 
|  2989  |  3017     builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id); | 
|  2990     // Write all the padding payload and as much of the data payload as possible |  3018     // Write payload fragment. | 
|  2991     // into the initial frame. |  3019     builder->WriteBytes( | 
|  2992     size_t bytes_remaining = 0; |  3020         &hpack_encoding[hpack_encoding.size() - bytes_remaining], | 
|  2993     bytes_remaining = hpack_encoding.size() - |  3021         bytes_to_write); | 
|  2994                       std::min(hpack_encoding.size(), |  3022     bytes_remaining -= bytes_to_write; | 
|  2995                                kMaxControlFrameSize - builder->length() - |  3023   } | 
|  2996                                    padding_payload_len); |  | 
|  2997     builder->WriteBytes(&hpack_encoding[0], |  | 
|  2998                         hpack_encoding.size() - bytes_remaining); |  | 
|  2999     if (padding_payload_len > 0) { |  | 
|  3000       string padding = string(padding_payload_len, 0); |  | 
|  3001       builder->WriteBytes(padding.data(), padding.length()); |  | 
|  3002     } |  | 
|  3003     if (bytes_remaining > 0) { |  | 
|  3004       builder->OverwriteLength(*this, |  | 
|  3005           kMaxControlFrameSize - GetControlFrameHeaderSize()); |  | 
|  3006     } |  | 
|  3007  |  | 
|  3008     // Tack on CONTINUATION frames for the overflow. |  | 
|  3009     while (bytes_remaining > 0) { |  | 
|  3010       size_t bytes_to_write = std::min(bytes_remaining, |  | 
|  3011                                        kMaxControlFrameSize - |  | 
|  3012                                        GetContinuationMinimumSize()); |  | 
|  3013       // Write CONTINUATION frame prefix. |  | 
|  3014       if (bytes_remaining == bytes_to_write) { |  | 
|  3015         flags |= end_flag; |  | 
|  3016       } |  | 
|  3017       builder->BeginNewFrame(*this, |  | 
|  3018                              CONTINUATION, |  | 
|  3019                              flags, |  | 
|  3020                              stream_id); |  | 
|  3021       // Write payload fragment. |  | 
|  3022       builder->WriteBytes(&hpack_encoding[hpack_encoding.size() - |  | 
|  3023                                           bytes_remaining], |  | 
|  3024                           bytes_to_write); |  | 
|  3025       bytes_remaining -= bytes_to_write; |  | 
|  3026     } |  | 
|  3027 } |  3024 } | 
|  3028  |  3025  | 
|  3029 // The following compression setting are based on Brian Olson's analysis. See |  3026 // The following compression setting are based on Brian Olson's analysis. See | 
|  3030 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
      2 |  3027 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
      2 | 
|  3031 // for more details. |  3028 // for more details. | 
|  3032 #if defined(USE_SYSTEM_ZLIB) |  3029 #if defined(USE_SYSTEM_ZLIB) | 
|  3033 // System zlib is not expected to have workaround for http://crbug.com/139744, |  3030 // System zlib is not expected to have workaround for http://crbug.com/139744, | 
|  3034 // so disable compression in that case. |  3031 // so disable compression in that case. | 
|  3035 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. |  3032 // TODO(phajdan.jr): Remove the special case when it's no longer necessary. | 
|  3036 static const int kCompressorLevel = 0; |  3033 static const int kCompressorLevel = 0; | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3080   int success = inflateInit(header_decompressor_.get()); |  3077   int success = inflateInit(header_decompressor_.get()); | 
|  3081   if (success != Z_OK) { |  3078   if (success != Z_OK) { | 
|  3082     LOG(WARNING) << "inflateInit failure: " << success; |  3079     LOG(WARNING) << "inflateInit failure: " << success; | 
|  3083     header_decompressor_.reset(NULL); |  3080     header_decompressor_.reset(NULL); | 
|  3084     return NULL; |  3081     return NULL; | 
|  3085   } |  3082   } | 
|  3086   return header_decompressor_.get(); |  3083   return header_decompressor_.get(); | 
|  3087 } |  3084 } | 
|  3088  |  3085  | 
|  3089 HpackEncoder* SpdyFramer::GetHpackEncoder() { |  3086 HpackEncoder* SpdyFramer::GetHpackEncoder() { | 
|  3090   DCHECK_LT(SPDY3, spdy_version_); |  3087   DCHECK_LT(SPDY3, protocol_version()); | 
|  3091   if (hpack_encoder_.get() == NULL) { |  3088   if (hpack_encoder_.get() == nullptr) { | 
|  3092     hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); |  3089     hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); | 
|  3093   } |  3090   } | 
|  3094   return hpack_encoder_.get(); |  3091   return hpack_encoder_.get(); | 
|  3095 } |  3092 } | 
|  3096  |  3093  | 
|  3097 HpackDecoder* SpdyFramer::GetHpackDecoder() { |  3094 HpackDecoder* SpdyFramer::GetHpackDecoder() { | 
|  3098   DCHECK_LT(SPDY3, spdy_version_); |  3095   DCHECK_LT(SPDY3, protocol_version()); | 
|  3099   if (hpack_decoder_.get() == NULL) { |  3096   if (hpack_decoder_.get() == nullptr) { | 
|  3100     hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); |  3097     hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); | 
|  3101   } |  3098   } | 
|  3102   return hpack_decoder_.get(); |  3099   return hpack_decoder_.get(); | 
|  3103 } |  3100 } | 
|  3104  |  3101  | 
|  3105 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) { |  3102 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) { | 
|  3106   const float kSteps = 255.9f / 7.f; |  3103   const float kSteps = 255.9f / 7.f; | 
|  3107   return static_cast<uint8>(kSteps * (7.f - priority)); |  3104   return static_cast<uint8>(kSteps * (7.f - priority)); | 
|  3108 } |  3105 } | 
|  3109  |  3106  | 
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  3291   builder->Seek(compressed_size); |  3288   builder->Seek(compressed_size); | 
|  3292   builder->RewriteLength(*this); |  3289   builder->RewriteLength(*this); | 
|  3293  |  3290  | 
|  3294   pre_compress_bytes.Add(uncompressed_len); |  3291   pre_compress_bytes.Add(uncompressed_len); | 
|  3295   post_compress_bytes.Add(compressed_size); |  3292   post_compress_bytes.Add(compressed_size); | 
|  3296  |  3293  | 
|  3297   compressed_frames.Increment(); |  3294   compressed_frames.Increment(); | 
|  3298 } |  3295 } | 
|  3299  |  3296  | 
|  3300 }  // namespace net |  3297 }  // namespace net | 
| OLD | NEW |