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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
127 debug_visitor_(NULL), | 127 debug_visitor_(NULL), |
128 display_protocol_("SPDY"), | 128 display_protocol_("SPDY"), |
129 spdy_version_(version), | 129 spdy_version_(version), |
130 syn_frame_processed_(false), | 130 syn_frame_processed_(false), |
131 probable_http_response_(false), | 131 probable_http_response_(false), |
132 expect_continuation_(0), | 132 expect_continuation_(0), |
133 end_stream_when_done_(false) { | 133 end_stream_when_done_(false) { |
134 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); | 134 DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); |
135 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); | 135 DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); |
136 Reset(); | 136 Reset(); |
137 | |
138 // SPDY4 and up use HPACK. Allocate instances for these protocol versions. | |
139 if (spdy_version_ > SPDY3) { | |
140 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); | |
141 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); | |
142 } | |
143 } | 137 } |
144 | 138 |
145 SpdyFramer::~SpdyFramer() { | 139 SpdyFramer::~SpdyFramer() { |
146 if (header_compressor_.get()) { | 140 if (header_compressor_.get()) { |
147 deflateEnd(header_compressor_.get()); | 141 deflateEnd(header_compressor_.get()); |
148 } | 142 } |
149 if (header_decompressor_.get()) { | 143 if (header_decompressor_.get()) { |
150 inflateEnd(header_decompressor_.get()); | 144 inflateEnd(header_decompressor_.get()); |
151 } | 145 } |
152 } | 146 } |
(...skipping 1321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1474 bool processed_successfully = true; | 1468 bool processed_successfully = true; |
1475 if (current_frame_type_ != SYN_STREAM && | 1469 if (current_frame_type_ != SYN_STREAM && |
1476 current_frame_type_ != SYN_REPLY && | 1470 current_frame_type_ != SYN_REPLY && |
1477 current_frame_type_ != HEADERS && | 1471 current_frame_type_ != HEADERS && |
1478 current_frame_type_ != PUSH_PROMISE && | 1472 current_frame_type_ != PUSH_PROMISE && |
1479 current_frame_type_ != CONTINUATION) { | 1473 current_frame_type_ != CONTINUATION) { |
1480 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; | 1474 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; |
1481 } | 1475 } |
1482 size_t process_bytes = std::min(data_len, remaining_data_length_); | 1476 size_t process_bytes = std::min(data_len, remaining_data_length_); |
1483 if (is_hpack_header_block) { | 1477 if (is_hpack_header_block) { |
1484 if (!hpack_decoder_->HandleControlFrameHeadersData(current_frame_stream_id_, | 1478 if (!GetHpackDecoder()->HandleControlFrameHeadersData( |
1485 data, | 1479 current_frame_stream_id_, data, process_bytes)) { |
1486 process_bytes)) { | |
1487 // TODO(jgraettinger): Finer-grained HPACK error codes. | 1480 // TODO(jgraettinger): Finer-grained HPACK error codes. |
1488 set_error(SPDY_DECOMPRESS_FAILURE); | 1481 set_error(SPDY_DECOMPRESS_FAILURE); |
1489 processed_successfully = false; | 1482 processed_successfully = false; |
1490 } | 1483 } |
1491 } else if (process_bytes > 0) { | 1484 } else if (process_bytes > 0) { |
1492 if (enable_compression_ && protocol_version() <= SPDY3) { | 1485 if (enable_compression_ && protocol_version() <= SPDY3) { |
1493 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 1486 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
1494 current_frame_stream_id_, data, process_bytes); | 1487 current_frame_stream_id_, data, process_bytes); |
1495 } else { | 1488 } else { |
1496 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 1489 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
1497 current_frame_stream_id_, data, process_bytes); | 1490 current_frame_stream_id_, data, process_bytes); |
1498 } | 1491 } |
1499 } | 1492 } |
1500 remaining_data_length_ -= process_bytes; | 1493 remaining_data_length_ -= process_bytes; |
1501 | 1494 |
1502 // Handle the case that there is no futher data in this frame. | 1495 // Handle the case that there is no futher data in this frame. |
1503 if (remaining_data_length_ == 0 && processed_successfully) { | 1496 if (remaining_data_length_ == 0 && processed_successfully) { |
1504 if (expect_continuation_ == 0) { | 1497 if (expect_continuation_ == 0) { |
1505 if (is_hpack_header_block) { | 1498 if (is_hpack_header_block) { |
1506 if (!hpack_decoder_->HandleControlFrameHeadersComplete( | 1499 if (!GetHpackDecoder()->HandleControlFrameHeadersComplete( |
1507 current_frame_stream_id_)) { | 1500 current_frame_stream_id_)) { |
1508 set_error(SPDY_DECOMPRESS_FAILURE); | 1501 set_error(SPDY_DECOMPRESS_FAILURE); |
1509 processed_successfully = false; | 1502 processed_successfully = false; |
1510 } else { | 1503 } else { |
1511 // TODO(jgraettinger): To be removed with migration to | 1504 // TODO(jgraettinger): To be removed with migration to |
1512 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 | 1505 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 |
1513 // block, delivered via reentrant call to | 1506 // block, delivered via reentrant call to |
1514 // ProcessControlFrameHeaderBlock(). | 1507 // ProcessControlFrameHeaderBlock(). |
1515 DeliverHpackBlockAsSpdy3Block(); | 1508 DeliverHpackBlockAsSpdy3Block(); |
1516 return process_bytes; | 1509 return process_bytes; |
1517 } | 1510 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 CHANGE_STATE(SPDY_AUTO_RESET); | 1585 CHANGE_STATE(SPDY_AUTO_RESET); |
1593 } | 1586 } |
1594 | 1587 |
1595 return processed_bytes; | 1588 return processed_bytes; |
1596 } | 1589 } |
1597 | 1590 |
1598 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { | 1591 void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { |
1599 DCHECK_LT(SPDY3, protocol_version()); | 1592 DCHECK_LT(SPDY3, protocol_version()); |
1600 DCHECK_EQ(0u, remaining_data_length_); | 1593 DCHECK_EQ(0u, remaining_data_length_); |
1601 | 1594 |
1602 const SpdyNameValueBlock& block = hpack_decoder_->decoded_block(); | 1595 const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block(); |
1603 if (block.empty()) { | 1596 if (block.empty()) { |
1604 // Special-case this to make tests happy. | 1597 // Special-case this to make tests happy. |
1605 ProcessControlFrameHeaderBlock(NULL, 0, false); | 1598 ProcessControlFrameHeaderBlock(NULL, 0, false); |
1606 return; | 1599 return; |
1607 } | 1600 } |
1608 SpdyFrameBuilder builder( | 1601 SpdyFrameBuilder builder( |
1609 GetSerializedLength(protocol_version(), &block), | 1602 GetSerializedLength(protocol_version(), &block), |
1610 SPDY3); | 1603 SPDY3); |
1611 | 1604 |
1612 SerializeNameValueBlockWithoutCompression(&builder, block); | 1605 SerializeNameValueBlockWithoutCompression(&builder, block); |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2141 DLOG(DFATAL) << "Priority out-of-bounds."; | 2134 DLOG(DFATAL) << "Priority out-of-bounds."; |
2142 priority = GetLowestPriority(); | 2135 priority = GetLowestPriority(); |
2143 } | 2136 } |
2144 | 2137 |
2145 // The size of this frame, including variable-length name-value block. | 2138 // The size of this frame, including variable-length name-value block. |
2146 size_t size = GetSynStreamMinimumSize(); | 2139 size_t size = GetSynStreamMinimumSize(); |
2147 | 2140 |
2148 string hpack_encoding; | 2141 string hpack_encoding; |
2149 if (protocol_version() > SPDY3) { | 2142 if (protocol_version() > SPDY3) { |
2150 if (enable_compression_) { | 2143 if (enable_compression_) { |
2151 hpack_encoder_->EncodeHeaderSet( | 2144 GetHpackEncoder()->EncodeHeaderSet( |
2152 syn_stream.name_value_block(), &hpack_encoding); | 2145 syn_stream.name_value_block(), &hpack_encoding); |
2153 } else { | 2146 } else { |
2154 hpack_encoder_->EncodeHeaderSetWithoutCompression( | 2147 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2155 syn_stream.name_value_block(), &hpack_encoding); | 2148 syn_stream.name_value_block(), &hpack_encoding); |
2156 } | 2149 } |
2157 size += hpack_encoding.size(); | 2150 size += hpack_encoding.size(); |
2158 } else { | 2151 } else { |
2159 size += GetSerializedLength(syn_stream.name_value_block()); | 2152 size += GetSerializedLength(syn_stream.name_value_block()); |
2160 } | 2153 } |
2161 | 2154 |
2162 SpdyFrameBuilder builder(size, protocol_version()); | 2155 SpdyFrameBuilder builder(size, protocol_version()); |
2163 if (protocol_version() <= SPDY3) { | 2156 if (protocol_version() <= SPDY3) { |
2164 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); | 2157 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2206 if (protocol_version() > SPDY3) { | 2199 if (protocol_version() > SPDY3) { |
2207 flags |= HEADERS_FLAG_END_HEADERS; | 2200 flags |= HEADERS_FLAG_END_HEADERS; |
2208 } | 2201 } |
2209 | 2202 |
2210 // The size of this frame, including variable-length name-value block. | 2203 // The size of this frame, including variable-length name-value block. |
2211 size_t size = GetSynReplyMinimumSize(); | 2204 size_t size = GetSynReplyMinimumSize(); |
2212 | 2205 |
2213 string hpack_encoding; | 2206 string hpack_encoding; |
2214 if (protocol_version() > SPDY3) { | 2207 if (protocol_version() > SPDY3) { |
2215 if (enable_compression_) { | 2208 if (enable_compression_) { |
2216 hpack_encoder_->EncodeHeaderSet( | 2209 GetHpackEncoder()->EncodeHeaderSet( |
2217 syn_reply.name_value_block(), &hpack_encoding); | 2210 syn_reply.name_value_block(), &hpack_encoding); |
2218 } else { | 2211 } else { |
2219 hpack_encoder_->EncodeHeaderSetWithoutCompression( | 2212 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2220 syn_reply.name_value_block(), &hpack_encoding); | 2213 syn_reply.name_value_block(), &hpack_encoding); |
2221 } | 2214 } |
2222 size += hpack_encoding.size(); | 2215 size += hpack_encoding.size(); |
2223 } else { | 2216 } else { |
2224 size += GetSerializedLength(syn_reply.name_value_block()); | 2217 size += GetSerializedLength(syn_reply.name_value_block()); |
2225 } | 2218 } |
2226 | 2219 |
2227 SpdyFrameBuilder builder(size, protocol_version()); | 2220 SpdyFrameBuilder builder(size, protocol_version()); |
2228 if (protocol_version() <= SPDY3) { | 2221 if (protocol_version() <= SPDY3) { |
2229 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); | 2222 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2426 if (priority > GetLowestPriority()) { | 2419 if (priority > GetLowestPriority()) { |
2427 DLOG(DFATAL) << "Priority out-of-bounds."; | 2420 DLOG(DFATAL) << "Priority out-of-bounds."; |
2428 priority = GetLowestPriority(); | 2421 priority = GetLowestPriority(); |
2429 } | 2422 } |
2430 size += 4; | 2423 size += 4; |
2431 } | 2424 } |
2432 | 2425 |
2433 string hpack_encoding; | 2426 string hpack_encoding; |
2434 if (protocol_version() > SPDY3) { | 2427 if (protocol_version() > SPDY3) { |
2435 if (enable_compression_) { | 2428 if (enable_compression_) { |
2436 hpack_encoder_->EncodeHeaderSet( | 2429 GetHpackEncoder()->EncodeHeaderSet( |
2437 headers.name_value_block(), &hpack_encoding); | 2430 headers.name_value_block(), &hpack_encoding); |
2438 } else { | 2431 } else { |
2439 hpack_encoder_->EncodeHeaderSetWithoutCompression( | 2432 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2440 headers.name_value_block(), &hpack_encoding); | 2433 headers.name_value_block(), &hpack_encoding); |
2441 } | 2434 } |
2442 size += hpack_encoding.size(); | 2435 size += hpack_encoding.size(); |
2443 if (size > GetControlFrameBufferMaxSize()) { | 2436 if (size > GetControlFrameBufferMaxSize()) { |
2444 size += GetNumberRequiredContinuationFrames(size) * | 2437 size += GetNumberRequiredContinuationFrames(size) * |
2445 GetContinuationMinimumSize(); | 2438 GetContinuationMinimumSize(); |
2446 flags &= ~HEADERS_FLAG_END_HEADERS; | 2439 flags &= ~HEADERS_FLAG_END_HEADERS; |
2447 } | 2440 } |
2448 } else { | 2441 } else { |
2449 size += GetSerializedLength(headers.name_value_block()); | 2442 size += GetSerializedLength(headers.name_value_block()); |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2519 DCHECK_LT(SPDY3, protocol_version()); | 2512 DCHECK_LT(SPDY3, protocol_version()); |
2520 uint8 flags = 0; | 2513 uint8 flags = 0; |
2521 // This will get overwritten if we overflow into a CONTINUATION frame. | 2514 // This will get overwritten if we overflow into a CONTINUATION frame. |
2522 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2515 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2523 // The size of this frame, including variable-length name-value block. | 2516 // The size of this frame, including variable-length name-value block. |
2524 size_t size = GetPushPromiseMinimumSize(); | 2517 size_t size = GetPushPromiseMinimumSize(); |
2525 | 2518 |
2526 string hpack_encoding; | 2519 string hpack_encoding; |
2527 if (protocol_version() > SPDY3) { | 2520 if (protocol_version() > SPDY3) { |
2528 if (enable_compression_) { | 2521 if (enable_compression_) { |
2529 hpack_encoder_->EncodeHeaderSet( | 2522 GetHpackEncoder()->EncodeHeaderSet( |
2530 push_promise.name_value_block(), &hpack_encoding); | 2523 push_promise.name_value_block(), &hpack_encoding); |
2531 } else { | 2524 } else { |
2532 hpack_encoder_->EncodeHeaderSetWithoutCompression( | 2525 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2533 push_promise.name_value_block(), &hpack_encoding); | 2526 push_promise.name_value_block(), &hpack_encoding); |
2534 } | 2527 } |
2535 size += hpack_encoding.size(); | 2528 size += hpack_encoding.size(); |
2536 if (size > GetControlFrameBufferMaxSize()) { | 2529 if (size > GetControlFrameBufferMaxSize()) { |
2537 size += GetNumberRequiredContinuationFrames(size) * | 2530 size += GetNumberRequiredContinuationFrames(size) * |
2538 GetContinuationMinimumSize(); | 2531 GetContinuationMinimumSize(); |
2539 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2532 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2540 } | 2533 } |
2541 } else { | 2534 } else { |
2542 size += GetSerializedLength(push_promise.name_value_block()); | 2535 size += GetSerializedLength(push_promise.name_value_block()); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2579 CHECK_LT(SPDY3, protocol_version()); | 2572 CHECK_LT(SPDY3, protocol_version()); |
2580 uint8 flags = 0; | 2573 uint8 flags = 0; |
2581 if (continuation.end_headers()) { | 2574 if (continuation.end_headers()) { |
2582 flags |= HEADERS_FLAG_END_HEADERS; | 2575 flags |= HEADERS_FLAG_END_HEADERS; |
2583 } | 2576 } |
2584 | 2577 |
2585 // The size of this frame, including variable-length name-value block. | 2578 // The size of this frame, including variable-length name-value block. |
2586 size_t size = GetContinuationMinimumSize(); | 2579 size_t size = GetContinuationMinimumSize(); |
2587 string hpack_encoding; | 2580 string hpack_encoding; |
2588 if (enable_compression_) { | 2581 if (enable_compression_) { |
2589 hpack_encoder_->EncodeHeaderSet( | 2582 GetHpackEncoder()->EncodeHeaderSet( |
2590 continuation.name_value_block(), &hpack_encoding); | 2583 continuation.name_value_block(), &hpack_encoding); |
2591 } else { | 2584 } else { |
2592 hpack_encoder_->EncodeHeaderSetWithoutCompression( | 2585 GetHpackEncoder()->EncodeHeaderSetWithoutCompression( |
2593 continuation.name_value_block(), &hpack_encoding); | 2586 continuation.name_value_block(), &hpack_encoding); |
2594 } | 2587 } |
2595 size += hpack_encoding.size(); | 2588 size += hpack_encoding.size(); |
2596 | 2589 |
2597 SpdyFrameBuilder builder(size, protocol_version()); | 2590 SpdyFrameBuilder builder(size, protocol_version()); |
2598 builder.BeginNewFrame(*this, CONTINUATION, flags, | 2591 builder.BeginNewFrame(*this, CONTINUATION, flags, |
2599 continuation.stream_id()); | 2592 continuation.stream_id()); |
2600 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); | 2593 DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); |
2601 | 2594 |
2602 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2595 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2801 | 2794 |
2802 int success = inflateInit(header_decompressor_.get()); | 2795 int success = inflateInit(header_decompressor_.get()); |
2803 if (success != Z_OK) { | 2796 if (success != Z_OK) { |
2804 LOG(WARNING) << "inflateInit failure: " << success; | 2797 LOG(WARNING) << "inflateInit failure: " << success; |
2805 header_decompressor_.reset(NULL); | 2798 header_decompressor_.reset(NULL); |
2806 return NULL; | 2799 return NULL; |
2807 } | 2800 } |
2808 return header_decompressor_.get(); | 2801 return header_decompressor_.get(); |
2809 } | 2802 } |
2810 | 2803 |
| 2804 HpackEncoder* SpdyFramer::GetHpackEncoder() { |
| 2805 DCHECK_LT(SPDY3, spdy_version_); |
| 2806 if (hpack_encoder_.get() == NULL) { |
| 2807 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); |
| 2808 } |
| 2809 return hpack_encoder_.get(); |
| 2810 } |
| 2811 |
| 2812 HpackDecoder* SpdyFramer::GetHpackDecoder() { |
| 2813 DCHECK_LT(SPDY3, spdy_version_); |
| 2814 if (hpack_decoder_.get() == NULL) { |
| 2815 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); |
| 2816 } |
| 2817 return hpack_decoder_.get(); |
| 2818 } |
| 2819 |
2811 // Incrementally decompress the control frame's header block, feeding the | 2820 // Incrementally decompress the control frame's header block, feeding the |
2812 // result to the visitor in chunks. Continue this until the visitor | 2821 // result to the visitor in chunks. Continue this until the visitor |
2813 // indicates that it cannot process any more data, or (more commonly) we | 2822 // indicates that it cannot process any more data, or (more commonly) we |
2814 // run out of data to deliver. | 2823 // run out of data to deliver. |
2815 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | 2824 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( |
2816 SpdyStreamId stream_id, | 2825 SpdyStreamId stream_id, |
2817 const char* data, | 2826 const char* data, |
2818 size_t len) { | 2827 size_t len) { |
2819 // Get a decompressor or set error. | 2828 // Get a decompressor or set error. |
2820 z_stream* decomp = GetHeaderDecompressor(); | 2829 z_stream* decomp = GetHeaderDecompressor(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2987 builder->Seek(compressed_size); | 2996 builder->Seek(compressed_size); |
2988 builder->RewriteLength(*this); | 2997 builder->RewriteLength(*this); |
2989 | 2998 |
2990 pre_compress_bytes.Add(uncompressed_len); | 2999 pre_compress_bytes.Add(uncompressed_len); |
2991 post_compress_bytes.Add(compressed_size); | 3000 post_compress_bytes.Add(compressed_size); |
2992 | 3001 |
2993 compressed_frames.Increment(); | 3002 compressed_frames.Increment(); |
2994 } | 3003 } |
2995 | 3004 |
2996 } // namespace net | 3005 } // namespace net |
OLD | NEW |