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

Unified Diff: net/spdy/spdy_framer.cc

Issue 22074002: DO NOT COMMIT: Implement HPACK (draft 03) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Update for httpbis-draft-06 / hpack-draft-03 Created 7 years, 2 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_framer.cc
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index f48a46c307c813676e169d281ea311be581c1c13..c99c2f83895a96ebd021295d97c783edb4ec682b 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -8,6 +8,8 @@
#include "net/spdy/spdy_framer.h"
+#include <cstring>
+
#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/stats_counters.h"
@@ -129,11 +131,11 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version)
}
SpdyFramer::~SpdyFramer() {
- if (header_compressor_.get()) {
- deflateEnd(header_compressor_.get());
+ if (spdy_header_compressor_.get()) {
+ deflateEnd(spdy_header_compressor_.get());
}
- if (header_decompressor_.get()) {
- inflateEnd(header_decompressor_.get());
+ if (spdy_header_decompressor_.get()) {
+ inflateEnd(spdy_header_decompressor_.get());
}
}
@@ -1286,7 +1288,8 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
}
size_t process_bytes = std::min(data_len, remaining_data_length_);
- if (process_bytes > 0) {
+ if ((spdy_version_ < SPDY4 && process_bytes > 0) ||
+ ((spdy_version_ >= SPDY4))) {
if (enable_compression_) {
processed_successfully = IncrementallyDecompressControlFrameHeaderData(
current_frame_stream_id_, data, process_bytes);
@@ -1299,7 +1302,11 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
}
// Handle the case that there is no futher data in this frame.
- if (remaining_data_length_ == 0 && processed_successfully) {
+ if ((spdy_version_ < SPDY4 &&
+ (remaining_data_length_ == 0 && processed_successfully)) ||
+ (spdy_version_ >= SPDY4 &&
+ ((current_frame_flags_ & HEADERS_FLAG_END_HEADERS) != 0) &&
+ processed_successfully)) {
// The complete header block has been delivered. We send a zero-length
// OnControlFrameHeaderData() to indicate this.
visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
@@ -2191,7 +2198,11 @@ size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) {
if (!enable_compression_) {
return uncompressed_length;
}
- z_stream* compressor = GetHeaderCompressor();
+ if (spdy_version_ >= SPDY4) {
+ // TODO(akalin): Handle >= SPDY4 case properly.
+ return uncompressed_length;
+ }
+ z_stream* compressor = GetSpdyHeaderCompressor();
// Since we'll be performing lots of flushes when compressing the data,
// zlib's lower bounds may be insufficient.
return 2 * deflateBound(compressor, uncompressed_length);
@@ -2211,14 +2222,14 @@ static const int kCompressorLevel = 9;
static const int kCompressorWindowSizeInBits = 11;
static const int kCompressorMemLevel = 1;
-z_stream* SpdyFramer::GetHeaderCompressor() {
- if (header_compressor_.get())
- return header_compressor_.get(); // Already initialized.
+z_stream* SpdyFramer::GetSpdyHeaderCompressor() {
+ if (spdy_header_compressor_.get())
+ return spdy_header_compressor_.get(); // Already initialized.
- header_compressor_.reset(new z_stream);
- memset(header_compressor_.get(), 0, sizeof(z_stream));
+ spdy_header_compressor_.reset(new z_stream);
+ memset(spdy_header_compressor_.get(), 0, sizeof(z_stream));
- int success = deflateInit2(header_compressor_.get(),
+ int success = deflateInit2(spdy_header_compressor_.get(),
kCompressorLevel,
Z_DEFLATED,
kCompressorWindowSizeInBits,
@@ -2229,32 +2240,44 @@ z_stream* SpdyFramer::GetHeaderCompressor() {
: kV3Dictionary;
const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize
: kV3DictionarySize;
- success = deflateSetDictionary(header_compressor_.get(),
+ success = deflateSetDictionary(spdy_header_compressor_.get(),
reinterpret_cast<const Bytef*>(dictionary),
dictionary_size);
}
if (success != Z_OK) {
LOG(WARNING) << "deflateSetDictionary failure: " << success;
- header_compressor_.reset(NULL);
+ spdy_header_compressor_.reset(NULL);
return NULL;
}
- return header_compressor_.get();
+ return spdy_header_compressor_.get();
}
-z_stream* SpdyFramer::GetHeaderDecompressor() {
- if (header_decompressor_.get())
- return header_decompressor_.get(); // Already initialized.
+z_stream* SpdyFramer::GetSpdyHeaderDecompressor() {
+ if (spdy_header_decompressor_.get())
+ return spdy_header_decompressor_.get(); // Already initialized.
- header_decompressor_.reset(new z_stream);
- memset(header_decompressor_.get(), 0, sizeof(z_stream));
+ spdy_header_decompressor_.reset(new z_stream);
+ memset(spdy_header_decompressor_.get(), 0, sizeof(z_stream));
- int success = inflateInit(header_decompressor_.get());
+ int success = inflateInit(spdy_header_decompressor_.get());
if (success != Z_OK) {
LOG(WARNING) << "inflateInit failure: " << success;
- header_decompressor_.reset(NULL);
+ spdy_header_decompressor_.reset(NULL);
return NULL;
}
- return header_decompressor_.get();
+ return spdy_header_decompressor_.get();
+}
+
+Http2Compressor* SpdyFramer::GetHttp2HeaderCompressor() {
+ if (!http2_header_compressor_)
+ http2_header_compressor_.reset(new Http2Compressor());
+ return http2_header_compressor_.get();
+}
+
+Http2Decompressor* SpdyFramer::GetHttp2HeaderDecompressor() {
+ if (!http2_header_decompressor_)
+ http2_header_decompressor_.reset(new Http2Decompressor());
+ return http2_header_decompressor_.get();
}
// Incrementally decompress the control frame's header block, feeding the
@@ -2265,8 +2288,26 @@ bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData(
SpdyStreamId stream_id,
const char* data,
size_t len) {
+ if (spdy_version_ >= SPDY4) {
+ SpdyNameValueBlock name_value_block;
+ if (!GetHttp2HeaderDecompressor()->DecodeNameValueBlock(
+ data, len, &name_value_block)) {
+ set_error(SPDY_DECOMPRESS_FAILURE);
+ return false;
+ }
+ const size_t uncompressed_length =
+ GetSerializedLength(spdy_version_, &name_value_block);
+ SpdyFrameBuilder builder(uncompressed_length);
+ SerializeNameValueBlockWithoutCompression(&builder, name_value_block);
+ scoped_ptr<SpdyFrame> frame(builder.take());
+ if (!visitor_->OnControlFrameHeaderData(
+ stream_id, frame->data(), frame->size()))
+ return false;
+ return true;
+ }
+
// Get a decompressor or set error.
- z_stream* decomp = GetHeaderDecompressor();
+ z_stream* decomp = GetSpdyHeaderDecompressor();
if (decomp == NULL) {
LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers.";
set_error(SPDY_DECOMPRESS_FAILURE);
@@ -2380,58 +2421,70 @@ void SpdyFramer::SerializeNameValueBlock(
frame.name_value_block());
}
+ base::StatsCounter compressed_frames("spdy.CompressedFrames");
+ base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
+ base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
+
// First build an uncompressed version to be fed into the compressor.
const size_t uncompressed_len = GetSerializedLength(
protocol_version(), &(frame.name_value_block()));
- SpdyFrameBuilder uncompressed_builder(uncompressed_len);
- SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
- frame.name_value_block());
- scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
-
- z_stream* compressor = GetHeaderCompressor();
- if (!compressor) {
- LOG(DFATAL) << "Could not obtain compressor.";
- return;
- }
+ int compressed_size = 0;
- base::StatsCounter compressed_frames("spdy.CompressedFrames");
- base::StatsCounter pre_compress_bytes("spdy.PreCompressSize");
- base::StatsCounter post_compress_bytes("spdy.PostCompressSize");
+ if (spdy_version_ >= SPDY4) {
+ Http2Compressor* compressor = GetHttp2HeaderCompressor();
+ const std::string& compressed =
+ compressor->EncodeNameValueBlock(frame.name_value_block());
+ char* out = builder->GetWritableBuffer(compressed.size());
+ std::memcpy(out, compressed.data(), compressed.size());
+ compressed_size = compressed.size();
+ } else {
+ SpdyFrameBuilder uncompressed_builder(uncompressed_len);
+ SerializeNameValueBlockWithoutCompression(&uncompressed_builder,
+ frame.name_value_block());
+ scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take());
+
+ z_stream* compressor = GetSpdyHeaderCompressor();
+ if (!compressor) {
+ LOG(DFATAL) << "Could not obtain compressor.";
+ return;
+ }
- // Create an output frame.
- // Since we'll be performing lots of flushes when compressing the data,
- // zlib's lower bounds may be insufficient.
- //
- // TODO(akalin): Avoid the duplicate calculation with
- // GetSerializedLength(const SpdyHeaderBlock&).
- const int compressed_max_size =
- 2 * deflateBound(compressor, uncompressed_len);
-
- // TODO(phajdan.jr): Clean up after we no longer need
- // to workaround http://crbug.com/139744.
+ // Create an output frame.
+ // Since we'll be performing lots of flushes when compressing the data,
+ // zlib's lower bounds may be insufficient.
+ //
+ // TODO(akalin): Avoid the duplicate calculation with
+ // GetSerializedLength(const SpdyHeaderBlock&).
+ const int compressed_max_size =
+ 2 * deflateBound(compressor, uncompressed_len);
+
+ // TODO(phajdan.jr): Clean up after we no longer need
+ // to workaround http://crbug.com/139744.
#if defined(USE_SYSTEM_ZLIB)
- compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
- compressor->avail_in = uncompressed_len;
+ compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data());
+ compressor->avail_in = uncompressed_len;
#endif // defined(USE_SYSTEM_ZLIB)
- compressor->next_out = reinterpret_cast<Bytef*>(
- builder->GetWritableBuffer(compressed_max_size));
- compressor->avail_out = compressed_max_size;
+ compressor->next_out = reinterpret_cast<Bytef*>(
+ builder->GetWritableBuffer(compressed_max_size));
+ compressor->avail_out = compressed_max_size;
- // TODO(phajdan.jr): Clean up after we no longer need
- // to workaround http://crbug.com/139744.
+ // TODO(phajdan.jr): Clean up after we no longer need
+ // to workaround http://crbug.com/139744.
#if defined(USE_SYSTEM_ZLIB)
- int rv = deflate(compressor, Z_SYNC_FLUSH);
- if (rv != Z_OK) { // How can we know that it compressed everything?
- // This shouldn't happen, right?
- LOG(WARNING) << "deflate failure: " << rv;
- // TODO(akalin): Upstream this return.
- return;
- }
+ int rv = deflate(compressor, Z_SYNC_FLUSH);
+ if (rv != Z_OK) { // How can we know that it compressed everything?
+ // This shouldn't happen, right?
+ LOG(WARNING) << "deflate failure: " << rv;
+ // TODO(akalin): Upstream this return.
+ return;
+ }
#else
- WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
+ WriteHeaderBlockToZ(&frame.name_value_block(), compressor);
#endif // defined(USE_SYSTEM_ZLIB)
- int compressed_size = compressed_max_size - compressor->avail_out;
+ compressed_size = compressed_max_size - compressor->avail_out;
+ }
+
builder->Seek(compressed_size);
builder->RewriteLength(*this);
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698