| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_headers_block_parser.h" | 5 #include "net/spdy/spdy_headers_block_parser.h" |
| 6 | 6 |
| 7 #include "base/sys_byteorder.h" | 7 #include "base/sys_byteorder.h" |
| 8 | 8 |
| 9 namespace net { | 9 namespace net { |
| 10 | 10 |
| 11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; | 11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; |
| 12 | 12 |
| 13 SpdyHeadersBlockParser::SpdyHeadersBlockParser( | 13 SpdyHeadersBlockParser::SpdyHeadersBlockParser( |
| 14 SpdyMajorVersion spdy_version, | 14 SpdyMajorVersion spdy_version, |
| 15 SpdyHeadersHandlerInterface* handler) : | 15 SpdyHeadersHandlerInterface* handler) : |
| 16 state_(READING_HEADER_BLOCK_LEN), | 16 state_(READING_HEADER_BLOCK_LEN), |
| 17 length_field_size_(LengthFieldSizeForVersion(spdy_version)), | 17 length_field_size_(LengthFieldSizeForVersion(spdy_version)), |
| 18 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)), | 18 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)), |
| 19 total_bytes_received_(0), |
| 19 remaining_key_value_pairs_for_frame_(0), | 20 remaining_key_value_pairs_for_frame_(0), |
| 20 handler_(handler), | 21 handler_(handler), |
| 21 error_(OK) { | 22 error_(OK) { |
| 22 // The handler that we set must not be NULL. | 23 // The handler that we set must not be NULL. |
| 23 DCHECK(handler_ != NULL); | 24 DCHECK(handler_ != NULL); |
| 24 } | 25 } |
| 25 | 26 |
| 26 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} | 27 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} |
| 27 | 28 |
| 28 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData( | 29 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData( |
| 29 SpdyStreamId stream_id, | 30 SpdyStreamId stream_id, |
| 30 const char* headers_data, | 31 const char* headers_data, |
| 31 size_t headers_data_length) { | 32 size_t headers_data_length) { |
| 32 if (error_ == NEED_MORE_DATA) { | 33 if (error_ == NEED_MORE_DATA) { |
| 33 error_ = OK; | 34 error_ = OK; |
| 34 } | 35 } |
| 35 CHECK_EQ(error_, OK); | 36 CHECK_EQ(error_, OK); |
| 36 | 37 |
| 37 // If this is the first call with the current header block, | 38 // If this is the first call with the current header block, |
| 38 // save its stream id. | 39 // save its stream id. |
| 39 if (state_ == READING_HEADER_BLOCK_LEN) { | 40 if (state_ == READING_HEADER_BLOCK_LEN) { |
| 40 stream_id_ = stream_id; | 41 stream_id_ = stream_id; |
| 41 } | 42 } |
| 42 CHECK_EQ(stream_id_, stream_id); | 43 CHECK_EQ(stream_id_, stream_id); |
| 43 | 44 |
| 45 total_bytes_received_ += headers_data_length; |
| 46 |
| 44 SpdyPinnableBufferPiece prefix, key, value; | 47 SpdyPinnableBufferPiece prefix, key, value; |
| 45 // Simultaneously tie lifetimes to the stack, and clear member variables. | 48 // Simultaneously tie lifetimes to the stack, and clear member variables. |
| 46 prefix.Swap(&headers_block_prefix_); | 49 prefix.Swap(&headers_block_prefix_); |
| 47 key.Swap(&key_); | 50 key.Swap(&key_); |
| 48 | 51 |
| 49 // Apply the parsing state machine to the remaining prefix | 52 // Apply the parsing state machine to the remaining prefix |
| 50 // from last invocation, plus newly-available headers data. | 53 // from last invocation, plus newly-available headers data. |
| 51 Reader reader(prefix.buffer(), prefix.length(), | 54 Reader reader(prefix.buffer(), prefix.length(), |
| 52 headers_data, headers_data_length); | 55 headers_data, headers_data_length); |
| 53 while (error_ == OK) { | 56 while (error_ == OK) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 79 } else { | 82 } else { |
| 80 handler_->OnHeader(stream_id, key, value); | 83 handler_->OnHeader(stream_id, key, value); |
| 81 } | 84 } |
| 82 break; | 85 break; |
| 83 case FINISHED_HEADER: | 86 case FINISHED_HEADER: |
| 84 // Prepare for next header or block. | 87 // Prepare for next header or block. |
| 85 if (--remaining_key_value_pairs_for_frame_ > 0) { | 88 if (--remaining_key_value_pairs_for_frame_ > 0) { |
| 86 next_state = READING_KEY_LEN; | 89 next_state = READING_KEY_LEN; |
| 87 } else { | 90 } else { |
| 88 next_state = READING_HEADER_BLOCK_LEN; | 91 next_state = READING_HEADER_BLOCK_LEN; |
| 89 handler_->OnHeaderBlockEnd(stream_id); | 92 handler_->OnHeaderBlockEnd(stream_id, total_bytes_received_); |
| 90 // Expect to have consumed all buffer. | 93 // Expect to have consumed all buffer. |
| 91 if (reader.Available() != 0) { | 94 if (reader.Available() != 0) { |
| 92 error_ = TOO_MUCH_DATA; | 95 error_ = TOO_MUCH_DATA; |
| 93 } | 96 } |
| 94 } | 97 } |
| 95 break; | 98 break; |
| 96 default: | 99 default: |
| 97 CHECK(false) << "Not reached."; | 100 CHECK(false) << "Not reached."; |
| 98 } | 101 } |
| 99 | 102 |
| 100 if (error_ == OK) { | 103 if (error_ == OK) { |
| 101 state_ = next_state; | 104 state_ = next_state; |
| 102 | 105 |
| 103 if (next_state == READING_HEADER_BLOCK_LEN) { | 106 if (next_state == READING_HEADER_BLOCK_LEN) { |
| 104 // We completed reading a full header block. Return to caller. | 107 // We completed reading a full header block. Return to caller. |
| 108 total_bytes_received_ = 0; |
| 105 break; | 109 break; |
| 106 } | 110 } |
| 107 } else if (error_ == NEED_MORE_DATA) { | 111 } else if (error_ == NEED_MORE_DATA) { |
| 108 // We can't continue parsing until more data is available. Make copies of | 112 // We can't continue parsing until more data is available. Make copies of |
| 109 // the key and buffer remainder, in preperation for the next invocation. | 113 // the key and buffer remainder, in preperation for the next invocation. |
| 110 if (state_ > READING_KEY) { | 114 if (state_ > READING_KEY) { |
| 111 key_.Swap(&key); | 115 key_.Swap(&key); |
| 112 key_.Pin(); | 116 key_.Pin(); |
| 113 } | 117 } |
| 114 reader.ReadN(reader.Available(), &headers_block_prefix_); | 118 reader.ReadN(reader.Available(), &headers_block_prefix_); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 SpdyPinnableBufferPiece empty; | 161 SpdyPinnableBufferPiece empty; |
| 158 headers_block_prefix_.Swap(&empty); | 162 headers_block_prefix_.Swap(&empty); |
| 159 } | 163 } |
| 160 { | 164 { |
| 161 SpdyPinnableBufferPiece empty; | 165 SpdyPinnableBufferPiece empty; |
| 162 key_.Swap(&empty); | 166 key_.Swap(&empty); |
| 163 } | 167 } |
| 164 error_ = OK; | 168 error_ = OK; |
| 165 state_ = READING_HEADER_BLOCK_LEN; | 169 state_ = READING_HEADER_BLOCK_LEN; |
| 166 stream_id_ = 0; | 170 stream_id_ = 0; |
| 171 total_bytes_received_ = 0; |
| 167 } | 172 } |
| 168 | 173 |
| 169 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion( | 174 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion( |
| 170 SpdyMajorVersion spdy_version) { | 175 SpdyMajorVersion spdy_version) { |
| 171 if (spdy_version < SPDY3) { | 176 if (spdy_version < SPDY3) { |
| 172 return sizeof(uint16_t); | 177 return sizeof(uint16_t); |
| 173 } | 178 } |
| 174 return sizeof(uint32_t); | 179 return sizeof(uint32_t); |
| 175 } | 180 } |
| 176 | 181 |
| 177 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion( | 182 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion( |
| 178 SpdyMajorVersion spdy_version) { | 183 SpdyMajorVersion spdy_version) { |
| 179 // Account for the length of the header block field. | 184 // Account for the length of the header block field. |
| 180 size_t max_bytes_for_headers = | 185 size_t max_bytes_for_headers = |
| 181 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); | 186 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); |
| 182 | 187 |
| 183 // A minimal size header is twice the length field size (and has a | 188 // A minimal size header is twice the length field size (and has a |
| 184 // zero-lengthed key and a zero-lengthed value). | 189 // zero-lengthed key and a zero-lengthed value). |
| 185 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); | 190 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); |
| 186 } | 191 } |
| 187 | 192 |
| 188 } // namespace net | 193 } // namespace net |
| OLD | NEW |