OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include "net/spdy/spdy_framer.h" | 5 #include "net/spdy/spdy_framer.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/metrics/stats_counters.h" | 9 #include "base/metrics/stats_counters.h" |
10 #include "base/third_party/valgrind/memcheck.h" | 10 #include "base/third_party/valgrind/memcheck.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 const uLong v3_dictionary_id; | 40 const uLong v3_dictionary_id; |
41 }; | 41 }; |
42 | 42 |
43 // Adler ID for the SPDY header compressor dictionaries. Note that they are | 43 // Adler ID for the SPDY header compressor dictionaries. Note that they are |
44 // initialized lazily to avoid static initializers. | 44 // initialized lazily to avoid static initializers. |
45 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; | 45 base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; |
46 | 46 |
47 // Used to indicate no flags in a SPDY flags field. | 47 // Used to indicate no flags in a SPDY flags field. |
48 const uint8 kNoFlags = 0; | 48 const uint8 kNoFlags = 0; |
49 | 49 |
| 50 // Wire sizes of priority payloads. |
| 51 const size_t kPriorityDependencyPayloadSize = 4; |
| 52 const size_t kPriorityWeightPayloadSize = 1; |
| 53 |
50 } // namespace | 54 } // namespace |
51 | 55 |
52 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | 56 const SpdyStreamId SpdyFramer::kInvalidStream = -1; |
53 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 57 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
54 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for | 58 // largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for |
55 // calculation details. | 59 // calculation details. |
56 const size_t SpdyFramer::kControlFrameBufferSize = 18; | 60 const size_t SpdyFramer::kControlFrameBufferSize = 18; |
57 | 61 |
58 #ifdef DEBUG_SPDY_STATE_CHANGES | 62 #ifdef DEBUG_SPDY_STATE_CHANGES |
59 #define CHANGE_STATE(newstate) \ | 63 #define CHANGE_STATE(newstate) \ |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 | 180 |
177 size_t SpdyFramer::GetSynStreamMinimumSize() const { | 181 size_t SpdyFramer::GetSynStreamMinimumSize() const { |
178 // Size, in bytes, of a SYN_STREAM frame not including the variable-length | 182 // Size, in bytes, of a SYN_STREAM frame not including the variable-length |
179 // name-value block. | 183 // name-value block. |
180 if (protocol_version() <= SPDY3) { | 184 if (protocol_version() <= SPDY3) { |
181 // Calculated as: | 185 // Calculated as: |
182 // control frame header + 2 * 4 (stream IDs) + 1 (priority) | 186 // control frame header + 2 * 4 (stream IDs) + 1 (priority) |
183 // + 1 (unused, was credential slot) | 187 // + 1 (unused, was credential slot) |
184 return GetControlFrameHeaderSize() + 10; | 188 return GetControlFrameHeaderSize() + 10; |
185 } else { | 189 } else { |
186 // Calculated as: | 190 return GetControlFrameHeaderSize() + |
187 // frame prefix + 4 (priority) | 191 kPriorityDependencyPayloadSize + |
188 return GetControlFrameHeaderSize() + 4; | 192 kPriorityWeightPayloadSize; |
189 } | 193 } |
190 } | 194 } |
191 | 195 |
192 size_t SpdyFramer::GetSynReplyMinimumSize() const { | 196 size_t SpdyFramer::GetSynReplyMinimumSize() const { |
193 // Size, in bytes, of a SYN_REPLY frame not including the variable-length | 197 // Size, in bytes, of a SYN_REPLY frame not including the variable-length |
194 // name-value block. | 198 // name-value block. |
195 size_t size = GetControlFrameHeaderSize(); | 199 size_t size = GetControlFrameHeaderSize(); |
196 if (protocol_version() <= SPDY3) { | 200 if (protocol_version() <= SPDY3) { |
197 // Calculated as: | 201 // Calculated as: |
198 // control frame header + 4 (stream IDs) | 202 // control frame header + 4 (stream IDs) |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 // (optional) Origin fields, all of which can vary in length. | 320 // (optional) Origin fields, all of which can vary in length. |
317 // Note that this gives a lower bound on the frame size rather than a true | 321 // Note that this gives a lower bound on the frame size rather than a true |
318 // minimum; the actual frame should always be larger than this. | 322 // minimum; the actual frame should always be larger than this. |
319 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte) | 323 // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte) |
320 // + 1 (pid_len) + 1 (host_len). | 324 // + 1 (pid_len) + 1 (host_len). |
321 return GetControlFrameHeaderSize() + 9; | 325 return GetControlFrameHeaderSize() + 9; |
322 } | 326 } |
323 | 327 |
324 size_t SpdyFramer::GetPrioritySize() const { | 328 size_t SpdyFramer::GetPrioritySize() const { |
325 // Size, in bytes, of a PRIORITY frame. | 329 // Size, in bytes, of a PRIORITY frame. |
326 // Calculated as frame prefix + 4 (stream dependency) + 1 (weight) | 330 return GetControlFrameHeaderSize() + |
327 return GetControlFrameHeaderSize() + 5; | 331 kPriorityDependencyPayloadSize + |
| 332 kPriorityWeightPayloadSize; |
328 } | 333 } |
329 | 334 |
330 size_t SpdyFramer::GetFrameMinimumSize() const { | 335 size_t SpdyFramer::GetFrameMinimumSize() const { |
331 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); | 336 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); |
332 } | 337 } |
333 | 338 |
334 size_t SpdyFramer::GetFrameMaximumSize() const { | 339 size_t SpdyFramer::GetFrameMaximumSize() const { |
335 return SpdyConstants::GetFrameMaximumSize(protocol_version()); | 340 return SpdyConstants::GetFrameMaximumSize(protocol_version()); |
336 } | 341 } |
337 | 342 |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 syn_frame_processed_ = true; | 1045 syn_frame_processed_ = true; |
1041 frame_size_without_variable_data = GetSynReplyMinimumSize(); | 1046 frame_size_without_variable_data = GetSynReplyMinimumSize(); |
1042 break; | 1047 break; |
1043 case SETTINGS: | 1048 case SETTINGS: |
1044 frame_size_without_variable_data = GetSettingsMinimumSize(); | 1049 frame_size_without_variable_data = GetSettingsMinimumSize(); |
1045 break; | 1050 break; |
1046 case HEADERS: | 1051 case HEADERS: |
1047 frame_size_without_variable_data = GetHeadersMinimumSize(); | 1052 frame_size_without_variable_data = GetHeadersMinimumSize(); |
1048 if (protocol_version() > SPDY3 && | 1053 if (protocol_version() > SPDY3 && |
1049 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { | 1054 current_frame_flags_ & HEADERS_FLAG_PRIORITY) { |
1050 frame_size_without_variable_data += 4; // priority | 1055 frame_size_without_variable_data += |
| 1056 kPriorityDependencyPayloadSize + |
| 1057 kPriorityWeightPayloadSize; |
1051 } | 1058 } |
1052 break; | 1059 break; |
1053 case PUSH_PROMISE: | 1060 case PUSH_PROMISE: |
1054 frame_size_without_variable_data = GetPushPromiseMinimumSize(); | 1061 frame_size_without_variable_data = GetPushPromiseMinimumSize(); |
1055 break; | 1062 break; |
1056 case CONTINUATION: | 1063 case CONTINUATION: |
1057 frame_size_without_variable_data = GetContinuationMinimumSize(); | 1064 frame_size_without_variable_data = GetContinuationMinimumSize(); |
1058 break; | 1065 break; |
1059 default: | 1066 default: |
1060 frame_size_without_variable_data = -1; | 1067 frame_size_without_variable_data = -1; |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1407 if (protocol_version() > SPDY3 && | 1414 if (protocol_version() > SPDY3 && |
1408 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && | 1415 !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && |
1409 current_frame_type_ == HEADERS) { | 1416 current_frame_type_ == HEADERS) { |
1410 expect_continuation_ = current_frame_stream_id_; | 1417 expect_continuation_ = current_frame_stream_id_; |
1411 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; | 1418 end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; |
1412 } | 1419 } |
1413 const bool has_priority = | 1420 const bool has_priority = |
1414 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; | 1421 (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; |
1415 uint32 priority = 0; | 1422 uint32 priority = 0; |
1416 if (protocol_version() > SPDY3 && has_priority) { | 1423 if (protocol_version() > SPDY3 && has_priority) { |
1417 successful_read = reader.ReadUInt31(&priority); | 1424 // TODO(jgraettinger): Process dependency rather than ignoring it. |
1418 DCHECK(successful_read); | 1425 reader.Seek(kPriorityDependencyPayloadSize); |
| 1426 uint8 weight = 0; |
| 1427 successful_read = reader.ReadUInt8(&weight); |
| 1428 if (successful_read) { |
| 1429 priority = MapWeightToPriority(weight); |
| 1430 } |
1419 } | 1431 } |
1420 DCHECK(reader.IsDoneReading()); | 1432 DCHECK(reader.IsDoneReading()); |
1421 if (debug_visitor_) { | 1433 if (debug_visitor_) { |
1422 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM. | 1434 // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM. |
1423 SpdyFrameType reported_type = current_frame_type_; | 1435 SpdyFrameType reported_type = current_frame_type_; |
1424 if (protocol_version() > SPDY3 && has_priority) { | 1436 if (protocol_version() > SPDY3 && has_priority) { |
1425 reported_type = SYN_STREAM; | 1437 reported_type = SYN_STREAM; |
1426 } | 1438 } |
1427 debug_visitor_->OnReceiveCompressedFrame( | 1439 debug_visitor_->OnReceiveCompressedFrame( |
1428 current_frame_stream_id_, | 1440 current_frame_stream_id_, |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2369 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); | 2381 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); |
2370 builder.WriteUInt32(syn_stream.stream_id()); | 2382 builder.WriteUInt32(syn_stream.stream_id()); |
2371 builder.WriteUInt32(syn_stream.associated_to_stream_id()); | 2383 builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
2372 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); | 2384 builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); |
2373 builder.WriteUInt8(0); // Unused byte where credential slot used to be. | 2385 builder.WriteUInt8(0); // Unused byte where credential slot used to be. |
2374 } else { | 2386 } else { |
2375 builder.BeginNewFrame(*this, | 2387 builder.BeginNewFrame(*this, |
2376 HEADERS, | 2388 HEADERS, |
2377 flags, | 2389 flags, |
2378 syn_stream.stream_id()); | 2390 syn_stream.stream_id()); |
2379 builder.WriteUInt32(priority); | 2391 // TODO(jgraettinger): Plumb priorities and stream dependencies. |
| 2392 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. |
| 2393 builder.WriteUInt8(MapPriorityToWeight(priority)); |
2380 } | 2394 } |
2381 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); | 2395 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); |
2382 if (protocol_version() > SPDY3) { | 2396 if (protocol_version() > SPDY3) { |
2383 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); | 2397 builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); |
2384 } else { | 2398 } else { |
2385 SerializeNameValueBlock(&builder, syn_stream); | 2399 SerializeNameValueBlock(&builder, syn_stream); |
2386 } | 2400 } |
2387 | 2401 |
2388 if (debug_visitor_) { | 2402 if (debug_visitor_) { |
2389 const size_t payload_len = protocol_version() > SPDY3 ? | 2403 const size_t payload_len = protocol_version() > SPDY3 ? |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2657 SpdyFrameBuilder builder(size, protocol_version()); | 2671 SpdyFrameBuilder builder(size, protocol_version()); |
2658 if (protocol_version() <= SPDY3) { | 2672 if (protocol_version() <= SPDY3) { |
2659 builder.WriteControlFrameHeader(*this, HEADERS, flags); | 2673 builder.WriteControlFrameHeader(*this, HEADERS, flags); |
2660 builder.WriteUInt32(headers.stream_id()); | 2674 builder.WriteUInt32(headers.stream_id()); |
2661 } else { | 2675 } else { |
2662 builder.BeginNewFrame(*this, | 2676 builder.BeginNewFrame(*this, |
2663 HEADERS, | 2677 HEADERS, |
2664 flags, | 2678 flags, |
2665 headers.stream_id()); | 2679 headers.stream_id()); |
2666 if (headers.has_priority()) { | 2680 if (headers.has_priority()) { |
2667 builder.WriteUInt32(priority); | 2681 // TODO(jgraettinger): Plumb priorities and stream dependencies. |
| 2682 builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. |
| 2683 builder.WriteUInt8(MapPriorityToWeight(priority)); |
2668 } | 2684 } |
2669 } | 2685 } |
2670 if (protocol_version() <= SPDY2) { | 2686 if (protocol_version() <= SPDY2) { |
2671 builder.WriteUInt16(0); // Unused. | 2687 builder.WriteUInt16(0); // Unused. |
2672 } | 2688 } |
2673 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | 2689 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
2674 | 2690 |
2675 if (protocol_version() > SPDY3) { | 2691 if (protocol_version() > SPDY3) { |
2676 WritePayloadWithContinuation(&builder, | 2692 WritePayloadWithContinuation(&builder, |
2677 hpack_encoding, | 2693 hpack_encoding, |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3048 } | 3064 } |
3049 | 3065 |
3050 HpackDecoder* SpdyFramer::GetHpackDecoder() { | 3066 HpackDecoder* SpdyFramer::GetHpackDecoder() { |
3051 DCHECK_LT(SPDY3, spdy_version_); | 3067 DCHECK_LT(SPDY3, spdy_version_); |
3052 if (hpack_decoder_.get() == NULL) { | 3068 if (hpack_decoder_.get() == NULL) { |
3053 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); | 3069 hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); |
3054 } | 3070 } |
3055 return hpack_decoder_.get(); | 3071 return hpack_decoder_.get(); |
3056 } | 3072 } |
3057 | 3073 |
| 3074 uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) { |
| 3075 const float kSteps = 255.9f / 7.f; |
| 3076 return static_cast<uint8>(kSteps * (7.f - priority)); |
| 3077 } |
| 3078 |
| 3079 SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) { |
| 3080 const float kSteps = 255.9f / 7.f; |
| 3081 return static_cast<SpdyPriority>(7.f - weight / kSteps); |
| 3082 } |
| 3083 |
3058 // Incrementally decompress the control frame's header block, feeding the | 3084 // Incrementally decompress the control frame's header block, feeding the |
3059 // result to the visitor in chunks. Continue this until the visitor | 3085 // result to the visitor in chunks. Continue this until the visitor |
3060 // indicates that it cannot process any more data, or (more commonly) we | 3086 // indicates that it cannot process any more data, or (more commonly) we |
3061 // run out of data to deliver. | 3087 // run out of data to deliver. |
3062 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | 3088 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( |
3063 SpdyStreamId stream_id, | 3089 SpdyStreamId stream_id, |
3064 const char* data, | 3090 const char* data, |
3065 size_t len) { | 3091 size_t len) { |
3066 // Get a decompressor or set error. | 3092 // Get a decompressor or set error. |
3067 z_stream* decomp = GetHeaderDecompressor(); | 3093 z_stream* decomp = GetHeaderDecompressor(); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3234 builder->Seek(compressed_size); | 3260 builder->Seek(compressed_size); |
3235 builder->RewriteLength(*this); | 3261 builder->RewriteLength(*this); |
3236 | 3262 |
3237 pre_compress_bytes.Add(uncompressed_len); | 3263 pre_compress_bytes.Add(uncompressed_len); |
3238 post_compress_bytes.Add(compressed_size); | 3264 post_compress_bytes.Add(compressed_size); |
3239 | 3265 |
3240 compressed_frames.Increment(); | 3266 compressed_frames.Increment(); |
3241 } | 3267 } |
3242 | 3268 |
3243 } // namespace net | 3269 } // namespace net |
OLD | NEW |