| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/spdy/hpack/hpack_decoder3.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "net/http2/decoder/decode_buffer.h" |
| 9 #include "net/http2/decoder/decode_status.h" |
| 10 |
| 11 using base::StringPiece; |
| 12 |
| 13 namespace net { |
| 14 namespace { |
| 15 const size_t kMaxDecodeBufferSizeBytes = 32 * 1024; // 32 KB |
| 16 } // namespace |
| 17 |
| 18 HpackDecoder3::HpackDecoder3() |
| 19 : hpack_decoder_(&listener_adapter_, kMaxDecodeBufferSizeBytes), |
| 20 max_decode_buffer_size_bytes_(kMaxDecodeBufferSizeBytes), |
| 21 header_block_started_(false) {} |
| 22 |
| 23 HpackDecoder3::~HpackDecoder3() {} |
| 24 |
| 25 void HpackDecoder3::ApplyHeaderTableSizeSetting(size_t size_setting) { |
| 26 DVLOG(2) << "HpackDecoder3::ApplyHeaderTableSizeSetting"; |
| 27 hpack_decoder_.ApplyHeaderTableSizeSetting(size_setting); |
| 28 } |
| 29 |
| 30 void HpackDecoder3::HandleControlFrameHeadersStart( |
| 31 SpdyHeadersHandlerInterface* handler) { |
| 32 DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersStart"; |
| 33 DCHECK(!header_block_started_); |
| 34 listener_adapter_.set_handler(handler); |
| 35 } |
| 36 |
| 37 bool HpackDecoder3::HandleControlFrameHeadersData(const char* headers_data, |
| 38 size_t headers_data_length) { |
| 39 DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersData: len=" |
| 40 << headers_data_length; |
| 41 if (!header_block_started_) { |
| 42 // Initialize the decoding process here rather than in |
| 43 // HandleControlFrameHeadersStart because that method is not always called. |
| 44 total_hpack_bytes_ = 0; |
| 45 header_block_started_ = true; |
| 46 if (!hpack_decoder_.StartDecodingBlock()) { |
| 47 header_block_started_ = false; |
| 48 return false; |
| 49 } |
| 50 } |
| 51 |
| 52 // Sometimes we get a call with headers_data==nullptr and |
| 53 // headers_data_length==0, in which case we need to avoid creating |
| 54 // a DecodeBuffer, which would otherwise complain. |
| 55 if (headers_data_length > 0) { |
| 56 DCHECK_NE(headers_data, nullptr); |
| 57 if (headers_data_length > max_decode_buffer_size_bytes_) { |
| 58 DVLOG(1) << "max_decode_buffer_size_bytes_ < headers_data_length: " |
| 59 << max_decode_buffer_size_bytes_ << " < " << headers_data_length; |
| 60 return false; |
| 61 } |
| 62 total_hpack_bytes_ += headers_data_length; |
| 63 DecodeBuffer db(headers_data, headers_data_length); |
| 64 bool ok = hpack_decoder_.DecodeFragment(&db); |
| 65 DCHECK(!ok || db.Empty()) << "Remaining=" << db.Remaining(); |
| 66 return ok; |
| 67 } |
| 68 return true; |
| 69 } |
| 70 |
| 71 // TODO(jamessynge): Determine if compressed_len is needed; it is used to |
| 72 // produce UUMA stat Net.SpdyHpackDecompressionPercentage, but only for |
| 73 // SPDY3, not HTTP2. |
| 74 bool HpackDecoder3::HandleControlFrameHeadersComplete(size_t* compressed_len) { |
| 75 DVLOG(2) << "HpackDecoder3::HandleControlFrameHeadersComplete"; |
| 76 if (compressed_len != nullptr) { |
| 77 *compressed_len = total_hpack_bytes_; |
| 78 } |
| 79 if (!hpack_decoder_.EndDecodingBlock()) { |
| 80 DVLOG(3) << "EndDecodingBlock returned false"; |
| 81 return false; |
| 82 } |
| 83 header_block_started_ = false; |
| 84 return true; |
| 85 } |
| 86 |
| 87 const SpdyHeaderBlock& HpackDecoder3::decoded_block() const { |
| 88 return listener_adapter_.decoded_block(); |
| 89 } |
| 90 |
| 91 void HpackDecoder3::SetHeaderTableDebugVisitor( |
| 92 std::unique_ptr<HpackHeaderTable::DebugVisitorInterface> visitor) { |
| 93 DVLOG(2) << "HpackDecoder3::SetHeaderTableDebugVisitor"; |
| 94 // Dropping on the floor for now. Not sure yet if needed at all. |
| 95 } |
| 96 |
| 97 void HpackDecoder3::set_max_decode_buffer_size_bytes( |
| 98 size_t max_decode_buffer_size_bytes) { |
| 99 DVLOG(2) << "HpackDecoder3::set_max_decode_buffer_size_bytes"; |
| 100 max_decode_buffer_size_bytes_ = max_decode_buffer_size_bytes; |
| 101 hpack_decoder_.set_max_string_size_bytes(max_decode_buffer_size_bytes); |
| 102 } |
| 103 |
| 104 HpackDecoder3::ListenerAdapter::ListenerAdapter() : handler_(nullptr) {} |
| 105 HpackDecoder3::ListenerAdapter::~ListenerAdapter() {} |
| 106 |
| 107 void HpackDecoder3::ListenerAdapter::set_handler( |
| 108 SpdyHeadersHandlerInterface* handler) { |
| 109 handler_ = handler; |
| 110 } |
| 111 |
| 112 void HpackDecoder3::ListenerAdapter::OnHeaderListStart() { |
| 113 DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeaderListStart"; |
| 114 total_uncompressed_bytes_ = 0; |
| 115 decoded_block_.clear(); |
| 116 if (handler_ != nullptr) { |
| 117 handler_->OnHeaderBlockStart(); |
| 118 } |
| 119 } |
| 120 |
| 121 void HpackDecoder3::ListenerAdapter::OnHeader(HpackEntryType entry_type, |
| 122 const HpackString& name, |
| 123 const HpackString& value) { |
| 124 DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeader:\n name: " << name |
| 125 << "\n value: " << value; |
| 126 total_uncompressed_bytes_ += name.size() + value.size(); |
| 127 if (handler_ == nullptr) { |
| 128 DVLOG(3) << "Adding to decoded_block"; |
| 129 decoded_block_.AppendValueOrAddHeader(name, value); |
| 130 } else { |
| 131 DVLOG(3) << "Passing to handler"; |
| 132 handler_->OnHeader(name, value); |
| 133 } |
| 134 } |
| 135 |
| 136 void HpackDecoder3::ListenerAdapter::OnHeaderListEnd() { |
| 137 DVLOG(2) << "HpackDecoder3::ListenerAdapter::OnHeaderListEnd"; |
| 138 // We don't clear the SpdyHeaderBlock here to allow access to it until the |
| 139 // next HPACK block is decoded. |
| 140 if (handler_ != nullptr) { |
| 141 handler_->OnHeaderBlockEnd(total_uncompressed_bytes_); |
| 142 handler_ = nullptr; |
| 143 } |
| 144 } |
| 145 |
| 146 void HpackDecoder3::ListenerAdapter::OnHeaderErrorDetected( |
| 147 StringPiece error_message) { |
| 148 VLOG(1) << error_message; |
| 149 } |
| 150 |
| 151 } // namespace net |
| OLD | NEW |