Index: net/spdy/spdy_framer.cc |
=================================================================== |
--- net/spdy/spdy_framer.cc (revision 80449) |
+++ net/spdy/spdy_framer.cc (working copy) |
@@ -20,6 +20,10 @@ |
#include "third_party/zlib/zlib.h" |
#endif |
+namespace net { |
+ |
Mike Belshe
2011/04/06 18:32:53
delete lines 22-25.
|
+} // namespace net |
+ |
namespace { |
// The following compression setting are based on Brian Olson's analysis. See |
@@ -29,7 +33,9 @@ |
const int kCompressorWindowSizeInBits = 11; |
const int kCompressorMemLevel = 1; |
-uLong dictionary_id = 0; |
+// TODO(jtl): Need to decide how to handle this. The array dimension must be as |
+// large as the maximum SCTP stream ID we will ever use. |
+uLong dictionary_ids[100] = {0}; |
} // namespace |
@@ -93,12 +99,7 @@ |
} |
SpdyFramer::~SpdyFramer() { |
- if (header_compressor_.get()) { |
- deflateEnd(header_compressor_.get()); |
- } |
- if (header_decompressor_.get()) { |
- inflateEnd(header_decompressor_.get()); |
- } |
+ CleanupHeaderCompressorsAndDecompressors(); |
CleanupStreamCompressorsAndDecompressors(); |
delete [] current_frame_buffer_; |
} |
@@ -800,54 +801,87 @@ |
return original_len - len; |
} |
-z_stream* SpdyFramer::GetHeaderCompressor() { |
- if (header_compressor_.get()) |
- return header_compressor_.get(); // Already initialized. |
+uint16 SpdyFramer::GetDictionaryIndex(const SpdyControlFrame& control_frame) { |
+ uint32 stream_id = 0; |
+ // TODO(jtl): Need to reconcile this with IsCompressible() which only returns |
+ // true for SYN_STREAM and SYN_REPLY control frames. |
+ switch (control_frame.type()) { |
+ case SYN_STREAM: |
+ stream_id = reinterpret_cast<const SpdySynStreamControlFrame&> |
+ (control_frame).stream_id(); |
+ break; |
+ case SYN_REPLY: |
+ stream_id = reinterpret_cast<const SpdySynReplyControlFrame&> |
+ (control_frame).stream_id(); |
+ break; |
+ case RST_STREAM: |
+ stream_id = reinterpret_cast<const SpdyRstStreamControlFrame&> |
+ (control_frame).stream_id(); |
+ break; |
+ case HEADERS: |
+ stream_id = reinterpret_cast<const SpdyHeadersControlFrame&> |
+ (control_frame).stream_id(); |
+ break; |
+ case WINDOW_UPDATE: |
+ stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame&> |
+ (control_frame).stream_id(); |
+ break; |
+ default: |
+ break; |
+ } |
- header_compressor_.reset(new z_stream); |
- memset(header_compressor_.get(), 0, sizeof(z_stream)); |
+ return stream_id ? MapSpdyToSctp(stream_id) : 0; |
+} |
- int success = deflateInit2(header_compressor_.get(), |
+z_stream* SpdyFramer::GetHeaderCompressor(int index) { |
+ CompressorMap::iterator it = header_compressors_.find(index); |
+ if (it != header_compressors_.end()) |
+ return it->second; // Already initialized. |
+ |
+ scoped_ptr<z_stream> compressor(new z_stream); |
+ memset(compressor.get(), 0, sizeof(z_stream)); |
+ |
+ int success = deflateInit2(compressor.get(), |
kCompressorLevel, |
Z_DEFLATED, |
kCompressorWindowSizeInBits, |
kCompressorMemLevel, |
Z_DEFAULT_STRATEGY); |
if (success == Z_OK) |
- success = deflateSetDictionary(header_compressor_.get(), |
+ success = deflateSetDictionary(compressor.get(), |
reinterpret_cast<const Bytef*>(kDictionary), |
kDictionarySize); |
if (success != Z_OK) { |
LOG(WARNING) << "deflateSetDictionary failure: " << success; |
- header_compressor_.reset(NULL); |
+ compressor.reset(NULL); |
return NULL; |
} |
- return header_compressor_.get(); |
+ return header_compressors_[index] = compressor.release(); |
} |
-z_stream* SpdyFramer::GetHeaderDecompressor() { |
- if (header_decompressor_.get()) |
- return header_decompressor_.get(); // Already initialized. |
+z_stream* SpdyFramer::GetHeaderDecompressor(int index) { |
+ CompressorMap::iterator it = header_decompressors_.find(index); |
+ if (it != header_decompressors_.end()) |
+ return it->second; // Already initialized. |
- header_decompressor_.reset(new z_stream); |
- memset(header_decompressor_.get(), 0, sizeof(z_stream)); |
+ scoped_ptr<z_stream> decompressor(new z_stream); |
+ memset(decompressor.get(), 0, sizeof(z_stream)); |
// Compute the id of our dictionary so that we know we're using the |
// right one when asked for it. |
- if (dictionary_id == 0) { |
- dictionary_id = adler32(0L, Z_NULL, 0); |
- dictionary_id = adler32(dictionary_id, |
+ if (dictionary_ids[index] == 0) { |
+ dictionary_ids[index] = adler32(0L, Z_NULL, 0); |
+ dictionary_ids[index] = adler32(dictionary_ids[index], |
reinterpret_cast<const Bytef*>(kDictionary), |
kDictionarySize); |
} |
- int success = inflateInit(header_decompressor_.get()); |
+ int success = inflateInit(decompressor.get()); |
if (success != Z_OK) { |
LOG(WARNING) << "inflateInit failure: " << success; |
- header_decompressor_.reset(NULL); |
return NULL; |
} |
- return header_decompressor_.get(); |
+ return header_decompressors_[index] = decompressor.release(); |
} |
z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) { |
@@ -889,7 +923,11 @@ |
SpdyControlFrame* SpdyFramer::CompressControlFrame( |
const SpdyControlFrame& frame) { |
- z_stream* compressor = GetHeaderCompressor(); |
+ uint16 dictionary_index = 0; |
+ if (using_sctp() && !using_sctp_control_stream()) |
+ dictionary_index = GetDictionaryIndex(frame); |
+ z_stream* compressor = GetHeaderCompressor(dictionary_index); |
+ |
if (!compressor) |
return NULL; |
return reinterpret_cast<SpdyControlFrame*>( |
@@ -906,7 +944,11 @@ |
SpdyControlFrame* SpdyFramer::DecompressControlFrame( |
const SpdyControlFrame& frame) { |
- z_stream* decompressor = GetHeaderDecompressor(); |
+ uint16 dictionary_index = 0; |
+ if (using_sctp() && !using_sctp_control_stream()) |
+ dictionary_index = GetDictionaryIndex(frame); |
+ z_stream* decompressor = GetHeaderDecompressor(dictionary_index); |
+ |
if (!decompressor) |
return NULL; |
return reinterpret_cast<SpdyControlFrame*>( |
@@ -1026,7 +1068,13 @@ |
int rv = inflate(decompressor, Z_SYNC_FLUSH); |
if (rv == Z_NEED_DICT) { |
// Need to try again with the right dictionary. |
- if (decompressor->adler == dictionary_id) { |
+ uint16 dictionary_index = 0; |
+ if (using_sctp() && !using_sctp_control_stream() && |
+ frame.is_control_frame()) { |
+ dictionary_index = GetDictionaryIndex( |
+ reinterpret_cast<const SpdyControlFrame&>(frame)); |
+ } |
+ if (decompressor->adler == dictionary_ids[dictionary_index]) { |
rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary, |
kDictionarySize); |
if (rv == Z_OK) |
@@ -1103,6 +1151,28 @@ |
stream_decompressors_.clear(); |
} |
+void SpdyFramer::CleanupHeaderCompressorsAndDecompressors() { |
+ CompressorMap::iterator it; |
+ |
+ it = header_compressors_.begin(); |
+ while (it != header_compressors_.end()) { |
+ z_stream* compressor = it->second; |
+ deflateEnd(compressor); |
+ delete compressor; |
+ ++it; |
+ } |
+ header_compressors_.clear(); |
+ |
+ it = header_decompressors_.begin(); |
+ while (it != header_decompressors_.end()) { |
+ z_stream* decompressor = it->second; |
+ inflateEnd(decompressor); |
+ delete decompressor; |
+ ++it; |
+ } |
+ header_decompressors_.clear(); |
+} |
+ |
size_t SpdyFramer::BytesSafeToRead() const { |
switch (state_) { |
case SPDY_ERROR: |