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 <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cctype> |
10 #include <ios> | 11 #include <ios> |
11 #include <iterator> | 12 #include <iterator> |
12 #include <list> | 13 #include <list> |
13 #include <memory> | 14 #include <memory> |
14 #include <new> | 15 #include <new> |
15 #include <string> | 16 #include <string> |
16 #include <vector> | 17 #include <vector> |
17 | 18 |
18 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/memory/ptr_util.h" | 21 #include "base/memory/ptr_util.h" |
21 #include "base/metrics/histogram_macros.h" | 22 #include "base/metrics/histogram_macros.h" |
| 23 #include "base/strings/string_util.h" |
22 #include "net/quic/core/quic_flags.h" | 24 #include "net/quic/core/quic_flags.h" |
23 #include "net/spdy/hpack/hpack_constants.h" | 25 #include "net/spdy/hpack/hpack_constants.h" |
24 #include "net/spdy/spdy_bitmasks.h" | 26 #include "net/spdy/spdy_bitmasks.h" |
25 #include "net/spdy/spdy_bug_tracker.h" | 27 #include "net/spdy/spdy_bug_tracker.h" |
26 #include "net/spdy/spdy_flags.h" | 28 #include "net/spdy/spdy_flags.h" |
27 #include "net/spdy/spdy_frame_builder.h" | 29 #include "net/spdy/spdy_frame_builder.h" |
28 #include "net/spdy/spdy_frame_reader.h" | 30 #include "net/spdy/spdy_frame_reader.h" |
29 #include "net/spdy/spdy_framer_decoder_adapter.h" | 31 #include "net/spdy/spdy_framer_decoder_adapter.h" |
30 #include "net/spdy/spdy_headers_block_parser.h" | 32 #include "net/spdy/spdy_headers_block_parser.h" |
31 #include "third_party/zlib/zlib.h" | 33 #include "third_party/zlib/zlib.h" |
(...skipping 1365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 // manner that resists the length of the compressed data from compromising | 1399 // manner that resists the length of the compressed data from compromising |
1398 // cookie data. | 1400 // cookie data. |
1399 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, | 1401 void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, |
1400 z_stream* z) const { | 1402 z_stream* z) const { |
1401 const size_t length_length = 4; | 1403 const size_t length_length = 4; |
1402 WriteLengthZ(headers->size(), length_length, kZStandardData, z); | 1404 WriteLengthZ(headers->size(), length_length, kZStandardData, z); |
1403 | 1405 |
1404 SpdyHeaderBlock::const_iterator it; | 1406 SpdyHeaderBlock::const_iterator it; |
1405 for (it = headers->begin(); it != headers->end(); ++it) { | 1407 for (it = headers->begin(); it != headers->end(); ++it) { |
1406 WriteLengthZ(it->first.size(), length_length, kZStandardData, z); | 1408 WriteLengthZ(it->first.size(), length_length, kZStandardData, z); |
1407 WriteZ(it->first, kZStandardData, z); | |
1408 | 1409 |
1409 if (it->first == "cookie") { | 1410 std::string lowercase_key = base::ToLowerASCII(it->first); |
| 1411 WriteZ(lowercase_key, kZStandardData, z); |
| 1412 |
| 1413 if (lowercase_key == "cookie") { |
1410 // We require the cookie values (save for the last) to end with a | 1414 // We require the cookie values (save for the last) to end with a |
1411 // semicolon and (save for the first) to start with a space. This is | 1415 // semicolon and (save for the first) to start with a space. This is |
1412 // typically the format that we are given them in but we reserialize them | 1416 // typically the format that we are given them in but we reserialize them |
1413 // to be sure. | 1417 // to be sure. |
1414 | 1418 |
1415 std::vector<base::StringPiece> cookie_values; | 1419 std::vector<base::StringPiece> cookie_values; |
1416 size_t cookie_length = 0; | 1420 size_t cookie_length = 0; |
1417 base::StringPiece cookie_data(it->second); | 1421 base::StringPiece cookie_data(it->second); |
1418 | 1422 |
1419 for (;;) { | 1423 for (;;) { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 cookie = cookie_values[i].as_string(); | 1461 cookie = cookie_values[i].as_string(); |
1458 } else if (i == 0) { | 1462 } else if (i == 0) { |
1459 cookie = cookie_values[i].as_string() + ";"; | 1463 cookie = cookie_values[i].as_string() + ";"; |
1460 } else if (i < cookie_values.size() - 1) { | 1464 } else if (i < cookie_values.size() - 1) { |
1461 cookie = " " + cookie_values[i].as_string() + ";"; | 1465 cookie = " " + cookie_values[i].as_string() + ";"; |
1462 } else { | 1466 } else { |
1463 cookie = " " + cookie_values[i].as_string(); | 1467 cookie = " " + cookie_values[i].as_string(); |
1464 } | 1468 } |
1465 WriteZ(cookie, kZCookieData, z); | 1469 WriteZ(cookie, kZCookieData, z); |
1466 } | 1470 } |
1467 } else if (it->first == "accept" || | 1471 } else if (lowercase_key == "accept" || |
1468 it->first == "accept-charset" || | 1472 lowercase_key == "accept-charset" || |
1469 it->first == "accept-encoding" || | 1473 lowercase_key == "accept-encoding" || |
1470 it->first == "accept-language" || | 1474 lowercase_key == "accept-language" || |
1471 it->first == "host" || | 1475 lowercase_key == "host" || |
1472 it->first == "version" || | 1476 lowercase_key == "version" || |
1473 it->first == "method" || | 1477 lowercase_key == "method" || |
1474 it->first == "scheme" || | 1478 lowercase_key == "scheme" || |
1475 it->first == ":host" || | 1479 lowercase_key == ":host" || |
1476 it->first == ":version" || | 1480 lowercase_key == ":version" || |
1477 it->first == ":method" || | 1481 lowercase_key == ":method" || |
1478 it->first == ":scheme" || | 1482 lowercase_key == ":scheme" || |
1479 it->first == "user-agent") { | 1483 lowercase_key == "user-agent") { |
1480 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); | 1484 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); |
1481 WriteZ(it->second, kZStandardData, z); | 1485 WriteZ(it->second, kZStandardData, z); |
1482 } else { | 1486 } else { |
1483 // Non-whitelisted headers are Huffman compressed in their own block, but | 1487 // Non-whitelisted headers are Huffman compressed in their own block, but |
1484 // don't match against the window. | 1488 // don't match against the window. |
1485 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); | 1489 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); |
1486 WriteZ(it->second, kZHuffmanOnlyData, z); | 1490 WriteZ(it->second, kZHuffmanOnlyData, z); |
1487 } | 1491 } |
1488 } | 1492 } |
1489 | 1493 |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1689 break; | 1693 break; |
1690 default: | 1694 default: |
1691 #ifndef NDEBUG | 1695 #ifndef NDEBUG |
1692 LOG(FATAL) << "Invalid control frame type: " << current_frame_type_; | 1696 LOG(FATAL) << "Invalid control frame type: " << current_frame_type_; |
1693 #else | 1697 #else |
1694 set_error(SPDY_INVALID_CONTROL_FRAME); | 1698 set_error(SPDY_INVALID_CONTROL_FRAME); |
1695 return original_len - len; | 1699 return original_len - len; |
1696 #endif | 1700 #endif |
1697 } | 1701 } |
1698 | 1702 |
1699 if (use_new_methods_ && current_frame_type_ != CONTINUATION) { | 1703 if (current_frame_type_ != CONTINUATION) { |
1700 header_handler_ = visitor_->OnHeaderFrameStart(current_frame_stream_id_); | 1704 header_handler_ = visitor_->OnHeaderFrameStart(current_frame_stream_id_); |
1701 if (header_handler_ == nullptr) { | 1705 if (header_handler_ == nullptr) { |
1702 SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr"; | 1706 SPDY_BUG << "visitor_->OnHeaderFrameStart returned nullptr"; |
1703 set_error(SPDY_INTERNAL_FRAMER_ERROR); | 1707 set_error(SPDY_INTERNAL_FRAMER_ERROR); |
1704 return original_len - len; | 1708 return original_len - len; |
1705 } | 1709 } |
1706 if (protocol_version() == SPDY3) { | 1710 if (protocol_version() == SPDY3) { |
1707 header_parser_.reset( | 1711 header_parser_.reset( |
1708 new SpdyHeadersBlockParser(protocol_version(), header_handler_)); | 1712 new SpdyHeadersBlockParser(protocol_version(), header_handler_)); |
1709 } else { | 1713 } else { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1759 remaining_data_length_ -= process_bytes; | 1763 remaining_data_length_ -= process_bytes; |
1760 | 1764 |
1761 // Handle the case that there is no futher data in this frame. | 1765 // Handle the case that there is no futher data in this frame. |
1762 if (remaining_data_length_ == remaining_padding_payload_length_ && | 1766 if (remaining_data_length_ == remaining_padding_payload_length_ && |
1763 processed_successfully) { | 1767 processed_successfully) { |
1764 if (expect_continuation_ == 0) { | 1768 if (expect_continuation_ == 0) { |
1765 if (is_hpack_header_block) { | 1769 if (is_hpack_header_block) { |
1766 size_t compressed_len = 0; | 1770 size_t compressed_len = 0; |
1767 if (GetHpackDecoder()->HandleControlFrameHeadersComplete( | 1771 if (GetHpackDecoder()->HandleControlFrameHeadersComplete( |
1768 &compressed_len)) { | 1772 &compressed_len)) { |
1769 if (use_new_methods_) { | 1773 visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true); |
1770 visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true); | 1774 if (state_ == SPDY_ERROR) { |
1771 if (state_ == SPDY_ERROR) { | 1775 return data_len; |
1772 return data_len; | |
1773 } | |
1774 } else { | |
1775 // TODO(jgraettinger): To be removed with migration to | |
1776 // SpdyHeadersHandlerInterface. Serializes the HPACK block as a | |
1777 // SPDY3 block, delivered via reentrant call to | |
1778 // ProcessControlFrameHeaderBlock(). | |
1779 DeliverHpackBlockAsSpdy3Block(compressed_len); | |
1780 return process_bytes; | |
1781 } | 1776 } |
1782 } else { | 1777 } else { |
1783 set_error(SPDY_DECOMPRESS_FAILURE); | 1778 set_error(SPDY_DECOMPRESS_FAILURE); |
1784 processed_successfully = false; | 1779 processed_successfully = false; |
1785 } | 1780 } |
1786 } else { | 1781 } else { |
1787 if (use_new_methods_) { | 1782 visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true); |
1788 visitor_->OnHeaderFrameEnd(current_frame_stream_id_, true); | 1783 if (state_ == SPDY_ERROR) { |
1789 if (state_ == SPDY_ERROR) { | 1784 return data_len; |
1790 return data_len; | |
1791 } | |
1792 } else { | |
1793 // The complete header block has been delivered. We send a zero-length | |
1794 // OnControlFrameHeaderData() to indicated this. | |
1795 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, nullptr, | |
1796 0); | |
1797 } | 1785 } |
1798 } | 1786 } |
1799 } | 1787 } |
1800 if (processed_successfully) { | 1788 if (processed_successfully) { |
1801 CHANGE_STATE(SPDY_CONSUME_PADDING); | 1789 CHANGE_STATE(SPDY_CONSUME_PADDING); |
1802 } | 1790 } |
1803 } | 1791 } |
1804 | 1792 |
1805 // Handle error. | 1793 // Handle error. |
1806 if (!processed_successfully) { | 1794 if (!processed_successfully) { |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2353 // Read each header. | 2341 // Read each header. |
2354 for (uint32_t index = 0; index < num_headers; ++index) { | 2342 for (uint32_t index = 0; index < num_headers; ++index) { |
2355 base::StringPiece temp; | 2343 base::StringPiece temp; |
2356 | 2344 |
2357 // Read header name. | 2345 // Read header name. |
2358 if (!reader.ReadStringPiece32(&temp)) { | 2346 if (!reader.ReadStringPiece32(&temp)) { |
2359 DVLOG(1) << "Unable to read header name (" << index + 1 << " of " | 2347 DVLOG(1) << "Unable to read header name (" << index + 1 << " of " |
2360 << num_headers << ")."; | 2348 << num_headers << ")."; |
2361 return false; | 2349 return false; |
2362 } | 2350 } |
| 2351 const char* begin = temp.data(); |
| 2352 const char* end = begin; |
| 2353 std::advance(end, temp.size()); |
| 2354 if (protocol_version_ == HTTP2 && std::any_of(begin, end, isupper)) { |
| 2355 DVLOG(1) << "Malformed header: Header name " << temp |
| 2356 << " contains upper-case characters."; |
| 2357 return false; |
| 2358 } |
2363 std::string name = temp.as_string(); | 2359 std::string name = temp.as_string(); |
2364 | 2360 |
2365 // Read header value. | 2361 // Read header value. |
2366 if (!reader.ReadStringPiece32(&temp)) { | 2362 if (!reader.ReadStringPiece32(&temp)) { |
2367 DVLOG(1) << "Unable to read header value (" << index + 1 << " of " | 2363 DVLOG(1) << "Unable to read header value (" << index + 1 << " of " |
2368 << num_headers << ")."; | 2364 << num_headers << ")."; |
2369 return false; | 2365 return false; |
2370 } | 2366 } |
2371 std::string value = temp.as_string(); | 2367 std::string value = temp.as_string(); |
2372 | 2368 |
(...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3294 } | 3290 } |
3295 | 3291 |
3296 // Inflate will generate a Z_BUF_ERROR if it runs out of input | 3292 // Inflate will generate a Z_BUF_ERROR if it runs out of input |
3297 // without producing any output. The input is consumed and | 3293 // without producing any output. The input is consumed and |
3298 // buffered internally by zlib so we can detect this condition by | 3294 // buffered internally by zlib so we can detect this condition by |
3299 // checking if avail_in is 0 after the call to inflate. | 3295 // checking if avail_in is 0 after the call to inflate. |
3300 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); | 3296 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); |
3301 if ((rv == Z_OK) || input_exhausted) { | 3297 if ((rv == Z_OK) || input_exhausted) { |
3302 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; | 3298 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; |
3303 if (decompressed_len > 0) { | 3299 if (decompressed_len > 0) { |
3304 if (use_new_methods_) { | 3300 processed_successfully = header_parser_->HandleControlFrameHeadersData( |
3305 processed_successfully = | 3301 stream_id, buffer, decompressed_len); |
3306 header_parser_->HandleControlFrameHeadersData(stream_id, buffer, | 3302 if (header_parser_->get_error() == |
3307 decompressed_len); | 3303 SpdyHeadersBlockParser::NEED_MORE_DATA) { |
3308 if (header_parser_->get_error() == | 3304 processed_successfully = true; |
3309 SpdyHeadersBlockParser::NEED_MORE_DATA) { | |
3310 processed_successfully = true; | |
3311 } | |
3312 } else { | |
3313 processed_successfully = visitor_->OnControlFrameHeaderData( | |
3314 stream_id, buffer, decompressed_len); | |
3315 } | 3305 } |
3316 } | 3306 } |
3317 if (!processed_successfully) { | 3307 if (!processed_successfully) { |
3318 // Assume that the problem was the header block was too large for the | 3308 // Assume that the problem was the header block was too large for the |
3319 // visitor. | 3309 // visitor. |
3320 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 3310 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
3321 } | 3311 } |
3322 } else { | 3312 } else { |
3323 DLOG(WARNING) << "inflate failure: " << rv << " " << len; | 3313 DLOG(WARNING) << "inflate failure: " << rv << " " << len; |
3324 set_error(SPDY_DECOMPRESS_FAILURE); | 3314 set_error(SPDY_DECOMPRESS_FAILURE); |
3325 processed_successfully = false; | 3315 processed_successfully = false; |
3326 } | 3316 } |
3327 } | 3317 } |
3328 return processed_successfully; | 3318 return processed_successfully; |
3329 } | 3319 } |
3330 | 3320 |
3331 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( | 3321 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( |
3332 SpdyStreamId stream_id, const char* data, size_t len) { | 3322 SpdyStreamId stream_id, const char* data, size_t len) { |
3333 bool read_successfully = true; | 3323 bool read_successfully = true; |
3334 while (read_successfully && len > 0) { | 3324 while (read_successfully && len > 0) { |
3335 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); | 3325 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); |
3336 if (use_new_methods_) { | 3326 read_successfully = header_parser_->HandleControlFrameHeadersData( |
3337 read_successfully = header_parser_->HandleControlFrameHeadersData( | 3327 stream_id, data, bytes_to_deliver); |
3338 stream_id, data, bytes_to_deliver); | 3328 if (header_parser_->get_error() == SpdyHeadersBlockParser::NEED_MORE_DATA) { |
3339 if (header_parser_->get_error() == | 3329 read_successfully = true; |
3340 SpdyHeadersBlockParser::NEED_MORE_DATA) { | |
3341 read_successfully = true; | |
3342 } | |
3343 } else { | |
3344 read_successfully = | |
3345 visitor_->OnControlFrameHeaderData(stream_id, data, bytes_to_deliver); | |
3346 } | 3330 } |
3347 data += bytes_to_deliver; | 3331 data += bytes_to_deliver; |
3348 len -= bytes_to_deliver; | 3332 len -= bytes_to_deliver; |
3349 if (!read_successfully) { | 3333 if (!read_successfully) { |
3350 // Assume that the problem was the header block was too large for the | 3334 // Assume that the problem was the header block was too large for the |
3351 // visitor. | 3335 // visitor. |
3352 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 3336 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
3353 } | 3337 } |
3354 } | 3338 } |
3355 return read_successfully; | 3339 return read_successfully; |
(...skipping 30 matching lines...) Expand all Loading... |
3386 } | 3370 } |
3387 | 3371 |
3388 void SpdyFramer::SerializeHeaderBlockWithoutCompression( | 3372 void SpdyFramer::SerializeHeaderBlockWithoutCompression( |
3389 SpdyFrameBuilder* builder, | 3373 SpdyFrameBuilder* builder, |
3390 const SpdyHeaderBlock& header_block) const { | 3374 const SpdyHeaderBlock& header_block) const { |
3391 // Serialize number of headers. | 3375 // Serialize number of headers. |
3392 builder->WriteUInt32(header_block.size()); | 3376 builder->WriteUInt32(header_block.size()); |
3393 | 3377 |
3394 // Serialize each header. | 3378 // Serialize each header. |
3395 for (const auto& header : header_block) { | 3379 for (const auto& header : header_block) { |
3396 builder->WriteStringPiece32(header.first); | 3380 builder->WriteStringPiece32(base::ToLowerASCII(header.first)); |
3397 builder->WriteStringPiece32(header.second); | 3381 builder->WriteStringPiece32(header.second); |
3398 } | 3382 } |
3399 } | 3383 } |
3400 | 3384 |
3401 void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder, | 3385 void SpdyFramer::SerializeHeaderBlock(SpdyFrameBuilder* builder, |
3402 const SpdyFrameWithHeaderBlockIR& frame) { | 3386 const SpdyFrameWithHeaderBlockIR& frame) { |
3403 if (!enable_compression_) { | 3387 if (!enable_compression_) { |
3404 return SerializeHeaderBlockWithoutCompression(builder, | 3388 return SerializeHeaderBlockWithoutCompression(builder, |
3405 frame.header_block()); | 3389 frame.header_block()); |
3406 } | 3390 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3450 #else | 3434 #else |
3451 WriteHeaderBlockToZ(&frame.header_block(), compressor); | 3435 WriteHeaderBlockToZ(&frame.header_block(), compressor); |
3452 #endif // defined(USE_SYSTEM_ZLIB) | 3436 #endif // defined(USE_SYSTEM_ZLIB) |
3453 | 3437 |
3454 int compressed_size = compressed_max_size - compressor->avail_out; | 3438 int compressed_size = compressed_max_size - compressor->avail_out; |
3455 builder->Seek(compressed_size); | 3439 builder->Seek(compressed_size); |
3456 builder->RewriteLength(*this); | 3440 builder->RewriteLength(*this); |
3457 } | 3441 } |
3458 | 3442 |
3459 } // namespace net | 3443 } // namespace net |
OLD | NEW |