OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |