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

Side by Side Diff: net/spdy/spdy_framer.cc

Issue 6800009: Attn: Mike Belshe Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 9 years, 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't
6 // constantly adding and subtracting header sizes; this is ugly and error- 6 // constantly adding and subtracting header sizes; this is ugly and error-
7 // prone. 7 // prone.
8 8
9 #include "net/spdy/spdy_framer.h" 9 #include "net/spdy/spdy_framer.h"
10 10
11 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/metrics/stats_counters.h" 12 #include "base/metrics/stats_counters.h"
13 #include "base/third_party/valgrind/memcheck.h" 13 #include "base/third_party/valgrind/memcheck.h"
14 #include "net/spdy/spdy_frame_builder.h" 14 #include "net/spdy/spdy_frame_builder.h"
15 #include "net/spdy/spdy_bitmasks.h" 15 #include "net/spdy/spdy_bitmasks.h"
16 16
17 #if defined(USE_SYSTEM_ZLIB) 17 #if defined(USE_SYSTEM_ZLIB)
18 #include <zlib.h> 18 #include <zlib.h>
19 #else 19 #else
20 #include "third_party/zlib/zlib.h" 20 #include "third_party/zlib/zlib.h"
21 #endif 21 #endif
22 22
23 namespace net {
24
Mike Belshe 2011/04/06 18:32:53 delete lines 22-25.
25 } // namespace net
26
23 namespace { 27 namespace {
24 28
25 // The following compression setting are based on Brian Olson's analysis. See 29 // The following compression setting are based on Brian Olson's analysis. See
26 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 30 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2
27 // for more details. 31 // for more details.
28 const int kCompressorLevel = 9; 32 const int kCompressorLevel = 9;
29 const int kCompressorWindowSizeInBits = 11; 33 const int kCompressorWindowSizeInBits = 11;
30 const int kCompressorMemLevel = 1; 34 const int kCompressorMemLevel = 1;
31 35
32 uLong dictionary_id = 0; 36 // TODO(jtl): Need to decide how to handle this. The array dimension must be as
37 // large as the maximum SCTP stream ID we will ever use.
38 uLong dictionary_ids[100] = {0};
33 39
34 } // namespace 40 } // namespace
35 41
36 namespace spdy { 42 namespace spdy {
37 43
38 // This is just a hacked dictionary to use for shrinking HTTP-like headers. 44 // This is just a hacked dictionary to use for shrinking HTTP-like headers.
39 // TODO(mbelshe): Use a scientific methodology for computing the dictionary. 45 // TODO(mbelshe): Use a scientific methodology for computing the dictionary.
40 const char SpdyFramer::kDictionary[] = 46 const char SpdyFramer::kDictionary[] =
41 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" 47 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-"
42 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" 48 "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi"
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 remaining_payload_(0), 92 remaining_payload_(0),
87 remaining_control_payload_(0), 93 remaining_control_payload_(0),
88 current_frame_buffer_(NULL), 94 current_frame_buffer_(NULL),
89 current_frame_len_(0), 95 current_frame_len_(0),
90 current_frame_capacity_(0), 96 current_frame_capacity_(0),
91 enable_compression_(compression_default_), 97 enable_compression_(compression_default_),
92 visitor_(NULL) { 98 visitor_(NULL) {
93 } 99 }
94 100
95 SpdyFramer::~SpdyFramer() { 101 SpdyFramer::~SpdyFramer() {
96 if (header_compressor_.get()) { 102 CleanupHeaderCompressorsAndDecompressors();
97 deflateEnd(header_compressor_.get());
98 }
99 if (header_decompressor_.get()) {
100 inflateEnd(header_decompressor_.get());
101 }
102 CleanupStreamCompressorsAndDecompressors(); 103 CleanupStreamCompressorsAndDecompressors();
103 delete [] current_frame_buffer_; 104 delete [] current_frame_buffer_;
104 } 105 }
105 106
106 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 107 size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
107 DCHECK(visitor_); 108 DCHECK(visitor_);
108 DCHECK(data); 109 DCHECK(data);
109 110
110 size_t original_len = len; 111 size_t original_len = len;
111 while (len != 0) { 112 while (len != 0) {
(...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 current_data_frame.flags() & DATA_FLAG_FIN) { 794 current_data_frame.flags() & DATA_FLAG_FIN) {
794 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0); 795 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0);
795 CleanupDecompressorForStream(current_data_frame.stream_id()); 796 CleanupDecompressorForStream(current_data_frame.stream_id());
796 } 797 }
797 } else { 798 } else {
798 CHANGE_STATE(SPDY_AUTO_RESET); 799 CHANGE_STATE(SPDY_AUTO_RESET);
799 } 800 }
800 return original_len - len; 801 return original_len - len;
801 } 802 }
802 803
803 z_stream* SpdyFramer::GetHeaderCompressor() { 804 uint16 SpdyFramer::GetDictionaryIndex(const SpdyControlFrame& control_frame) {
804 if (header_compressor_.get()) 805 uint32 stream_id = 0;
805 return header_compressor_.get(); // Already initialized. 806 // TODO(jtl): Need to reconcile this with IsCompressible() which only returns
807 // true for SYN_STREAM and SYN_REPLY control frames.
808 switch (control_frame.type()) {
809 case SYN_STREAM:
810 stream_id = reinterpret_cast<const SpdySynStreamControlFrame&>
811 (control_frame).stream_id();
812 break;
813 case SYN_REPLY:
814 stream_id = reinterpret_cast<const SpdySynReplyControlFrame&>
815 (control_frame).stream_id();
816 break;
817 case RST_STREAM:
818 stream_id = reinterpret_cast<const SpdyRstStreamControlFrame&>
819 (control_frame).stream_id();
820 break;
821 case HEADERS:
822 stream_id = reinterpret_cast<const SpdyHeadersControlFrame&>
823 (control_frame).stream_id();
824 break;
825 case WINDOW_UPDATE:
826 stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame&>
827 (control_frame).stream_id();
828 break;
829 default:
830 break;
831 }
806 832
807 header_compressor_.reset(new z_stream); 833 return stream_id ? MapSpdyToSctp(stream_id) : 0;
808 memset(header_compressor_.get(), 0, sizeof(z_stream)); 834 }
809 835
810 int success = deflateInit2(header_compressor_.get(), 836 z_stream* SpdyFramer::GetHeaderCompressor(int index) {
837 CompressorMap::iterator it = header_compressors_.find(index);
838 if (it != header_compressors_.end())
839 return it->second; // Already initialized.
840
841 scoped_ptr<z_stream> compressor(new z_stream);
842 memset(compressor.get(), 0, sizeof(z_stream));
843
844 int success = deflateInit2(compressor.get(),
811 kCompressorLevel, 845 kCompressorLevel,
812 Z_DEFLATED, 846 Z_DEFLATED,
813 kCompressorWindowSizeInBits, 847 kCompressorWindowSizeInBits,
814 kCompressorMemLevel, 848 kCompressorMemLevel,
815 Z_DEFAULT_STRATEGY); 849 Z_DEFAULT_STRATEGY);
816 if (success == Z_OK) 850 if (success == Z_OK)
817 success = deflateSetDictionary(header_compressor_.get(), 851 success = deflateSetDictionary(compressor.get(),
818 reinterpret_cast<const Bytef*>(kDictionary), 852 reinterpret_cast<const Bytef*>(kDictionary),
819 kDictionarySize); 853 kDictionarySize);
820 if (success != Z_OK) { 854 if (success != Z_OK) {
821 LOG(WARNING) << "deflateSetDictionary failure: " << success; 855 LOG(WARNING) << "deflateSetDictionary failure: " << success;
822 header_compressor_.reset(NULL); 856 compressor.reset(NULL);
823 return NULL; 857 return NULL;
824 } 858 }
825 return header_compressor_.get(); 859 return header_compressors_[index] = compressor.release();
826 } 860 }
827 861
828 z_stream* SpdyFramer::GetHeaderDecompressor() { 862 z_stream* SpdyFramer::GetHeaderDecompressor(int index) {
829 if (header_decompressor_.get()) 863 CompressorMap::iterator it = header_decompressors_.find(index);
830 return header_decompressor_.get(); // Already initialized. 864 if (it != header_decompressors_.end())
865 return it->second; // Already initialized.
831 866
832 header_decompressor_.reset(new z_stream); 867 scoped_ptr<z_stream> decompressor(new z_stream);
833 memset(header_decompressor_.get(), 0, sizeof(z_stream)); 868 memset(decompressor.get(), 0, sizeof(z_stream));
834 869
835 // Compute the id of our dictionary so that we know we're using the 870 // Compute the id of our dictionary so that we know we're using the
836 // right one when asked for it. 871 // right one when asked for it.
837 if (dictionary_id == 0) { 872 if (dictionary_ids[index] == 0) {
838 dictionary_id = adler32(0L, Z_NULL, 0); 873 dictionary_ids[index] = adler32(0L, Z_NULL, 0);
839 dictionary_id = adler32(dictionary_id, 874 dictionary_ids[index] = adler32(dictionary_ids[index],
840 reinterpret_cast<const Bytef*>(kDictionary), 875 reinterpret_cast<const Bytef*>(kDictionary),
841 kDictionarySize); 876 kDictionarySize);
842 } 877 }
843 878
844 int success = inflateInit(header_decompressor_.get()); 879 int success = inflateInit(decompressor.get());
845 if (success != Z_OK) { 880 if (success != Z_OK) {
846 LOG(WARNING) << "inflateInit failure: " << success; 881 LOG(WARNING) << "inflateInit failure: " << success;
847 header_decompressor_.reset(NULL);
848 return NULL; 882 return NULL;
849 } 883 }
850 return header_decompressor_.get(); 884 return header_decompressors_[index] = decompressor.release();
851 } 885 }
852 886
853 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) { 887 z_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) {
854 CompressorMap::iterator it = stream_compressors_.find(stream_id); 888 CompressorMap::iterator it = stream_compressors_.find(stream_id);
855 if (it != stream_compressors_.end()) 889 if (it != stream_compressors_.end())
856 return it->second; // Already initialized. 890 return it->second; // Already initialized.
857 891
858 scoped_ptr<z_stream> compressor(new z_stream); 892 scoped_ptr<z_stream> compressor(new z_stream);
859 memset(compressor.get(), 0, sizeof(z_stream)); 893 memset(compressor.get(), 0, sizeof(z_stream));
860 894
(...skipping 21 matching lines...) Expand all
882 int success = inflateInit(decompressor.get()); 916 int success = inflateInit(decompressor.get());
883 if (success != Z_OK) { 917 if (success != Z_OK) {
884 LOG(WARNING) << "inflateInit failure: " << success; 918 LOG(WARNING) << "inflateInit failure: " << success;
885 return NULL; 919 return NULL;
886 } 920 }
887 return stream_decompressors_[stream_id] = decompressor.release(); 921 return stream_decompressors_[stream_id] = decompressor.release();
888 } 922 }
889 923
890 SpdyControlFrame* SpdyFramer::CompressControlFrame( 924 SpdyControlFrame* SpdyFramer::CompressControlFrame(
891 const SpdyControlFrame& frame) { 925 const SpdyControlFrame& frame) {
892 z_stream* compressor = GetHeaderCompressor(); 926 uint16 dictionary_index = 0;
927 if (using_sctp() && !using_sctp_control_stream())
928 dictionary_index = GetDictionaryIndex(frame);
929 z_stream* compressor = GetHeaderCompressor(dictionary_index);
930
893 if (!compressor) 931 if (!compressor)
894 return NULL; 932 return NULL;
895 return reinterpret_cast<SpdyControlFrame*>( 933 return reinterpret_cast<SpdyControlFrame*>(
896 CompressFrameWithZStream(frame, compressor)); 934 CompressFrameWithZStream(frame, compressor));
897 } 935 }
898 936
899 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) { 937 SpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) {
900 z_stream* compressor = GetStreamCompressor(frame.stream_id()); 938 z_stream* compressor = GetStreamCompressor(frame.stream_id());
901 if (!compressor) 939 if (!compressor)
902 return NULL; 940 return NULL;
903 return reinterpret_cast<SpdyDataFrame*>( 941 return reinterpret_cast<SpdyDataFrame*>(
904 CompressFrameWithZStream(frame, compressor)); 942 CompressFrameWithZStream(frame, compressor));
905 } 943 }
906 944
907 SpdyControlFrame* SpdyFramer::DecompressControlFrame( 945 SpdyControlFrame* SpdyFramer::DecompressControlFrame(
908 const SpdyControlFrame& frame) { 946 const SpdyControlFrame& frame) {
909 z_stream* decompressor = GetHeaderDecompressor(); 947 uint16 dictionary_index = 0;
948 if (using_sctp() && !using_sctp_control_stream())
949 dictionary_index = GetDictionaryIndex(frame);
950 z_stream* decompressor = GetHeaderDecompressor(dictionary_index);
951
910 if (!decompressor) 952 if (!decompressor)
911 return NULL; 953 return NULL;
912 return reinterpret_cast<SpdyControlFrame*>( 954 return reinterpret_cast<SpdyControlFrame*>(
913 DecompressFrameWithZStream(frame, decompressor)); 955 DecompressFrameWithZStream(frame, decompressor));
914 } 956 }
915 957
916 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { 958 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) {
917 z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); 959 z_stream* decompressor = GetStreamDecompressor(frame.stream_id());
918 if (!decompressor) 960 if (!decompressor)
919 return NULL; 961 return NULL;
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 1061
1020 decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); 1062 decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload));
1021 decompressor->avail_in = payload_length; 1063 decompressor->avail_in = payload_length;
1022 decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + 1064 decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) +
1023 header_length; 1065 header_length;
1024 decompressor->avail_out = decompressed_max_size; 1066 decompressor->avail_out = decompressed_max_size;
1025 1067
1026 int rv = inflate(decompressor, Z_SYNC_FLUSH); 1068 int rv = inflate(decompressor, Z_SYNC_FLUSH);
1027 if (rv == Z_NEED_DICT) { 1069 if (rv == Z_NEED_DICT) {
1028 // Need to try again with the right dictionary. 1070 // Need to try again with the right dictionary.
1029 if (decompressor->adler == dictionary_id) { 1071 uint16 dictionary_index = 0;
1072 if (using_sctp() && !using_sctp_control_stream() &&
1073 frame.is_control_frame()) {
1074 dictionary_index = GetDictionaryIndex(
1075 reinterpret_cast<const SpdyControlFrame&>(frame));
1076 }
1077 if (decompressor->adler == dictionary_ids[dictionary_index]) {
1030 rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary, 1078 rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary,
1031 kDictionarySize); 1079 kDictionarySize);
1032 if (rv == Z_OK) 1080 if (rv == Z_OK)
1033 rv = inflate(decompressor, Z_SYNC_FLUSH); 1081 rv = inflate(decompressor, Z_SYNC_FLUSH);
1034 } 1082 }
1035 } 1083 }
1036 if (rv != Z_OK) { // How can we know that it decompressed everything? 1084 if (rv != Z_OK) { // How can we know that it decompressed everything?
1037 LOG(WARNING) << "inflate failure: " << rv; 1085 LOG(WARNING) << "inflate failure: " << rv;
1038 return NULL; 1086 return NULL;
1039 } 1087 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 it = stream_decompressors_.begin(); 1144 it = stream_decompressors_.begin();
1097 while (it != stream_decompressors_.end()) { 1145 while (it != stream_decompressors_.end()) {
1098 z_stream* decompressor = it->second; 1146 z_stream* decompressor = it->second;
1099 inflateEnd(decompressor); 1147 inflateEnd(decompressor);
1100 delete decompressor; 1148 delete decompressor;
1101 ++it; 1149 ++it;
1102 } 1150 }
1103 stream_decompressors_.clear(); 1151 stream_decompressors_.clear();
1104 } 1152 }
1105 1153
1154 void SpdyFramer::CleanupHeaderCompressorsAndDecompressors() {
1155 CompressorMap::iterator it;
1156
1157 it = header_compressors_.begin();
1158 while (it != header_compressors_.end()) {
1159 z_stream* compressor = it->second;
1160 deflateEnd(compressor);
1161 delete compressor;
1162 ++it;
1163 }
1164 header_compressors_.clear();
1165
1166 it = header_decompressors_.begin();
1167 while (it != header_decompressors_.end()) {
1168 z_stream* decompressor = it->second;
1169 inflateEnd(decompressor);
1170 delete decompressor;
1171 ++it;
1172 }
1173 header_decompressors_.clear();
1174 }
1175
1106 size_t SpdyFramer::BytesSafeToRead() const { 1176 size_t SpdyFramer::BytesSafeToRead() const {
1107 switch (state_) { 1177 switch (state_) {
1108 case SPDY_ERROR: 1178 case SPDY_ERROR:
1109 case SPDY_DONE: 1179 case SPDY_DONE:
1110 case SPDY_AUTO_RESET: 1180 case SPDY_AUTO_RESET:
1111 case SPDY_RESET: 1181 case SPDY_RESET:
1112 return 0; 1182 return 0;
1113 case SPDY_READING_COMMON_HEADER: 1183 case SPDY_READING_COMMON_HEADER:
1114 DCHECK_LT(current_frame_len_, SpdyFrame::size()); 1184 DCHECK_LT(current_frame_len_, SpdyFrame::size());
1115 return SpdyFrame::size() - current_frame_len_; 1185 return SpdyFrame::size() - current_frame_len_;
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
1189 } else { 1259 } else {
1190 frame_size = SpdyFrame::size(); 1260 frame_size = SpdyFrame::size();
1191 *header_length = frame_size; 1261 *header_length = frame_size;
1192 *payload_length = frame.length(); 1262 *payload_length = frame.length();
1193 *payload = frame.data() + SpdyFrame::size(); 1263 *payload = frame.data() + SpdyFrame::size();
1194 } 1264 }
1195 return true; 1265 return true;
1196 } 1266 }
1197 1267
1198 } // namespace spdy 1268 } // namespace spdy
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698