| 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 namespace { |
| 11 |
| 12 // 0 is invalid according to both the SPDY 3.1 and HTTP/2 specifications. |
| 13 const SpdyStreamId kInvalidStreamId = 0; |
| 14 |
| 15 } // anonymous namespace |
| 10 | 16 |
| 11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; | 17 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024; |
| 12 | 18 |
| 13 SpdyHeadersBlockParser::SpdyHeadersBlockParser( | 19 SpdyHeadersBlockParser::SpdyHeadersBlockParser( |
| 14 SpdyMajorVersion spdy_version, | 20 SpdyMajorVersion spdy_version, |
| 15 SpdyHeadersHandlerInterface* handler) | 21 SpdyHeadersHandlerInterface* handler) |
| 16 : state_(READING_HEADER_BLOCK_LEN), | 22 : state_(READING_HEADER_BLOCK_LEN), |
| 17 length_field_size_(LengthFieldSizeForVersion(spdy_version)), | 23 length_field_size_(LengthFieldSizeForVersion(spdy_version)), |
| 18 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)), | 24 max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)), |
| 19 total_bytes_received_(0), | 25 total_bytes_received_(0), |
| 20 remaining_key_value_pairs_for_frame_(0), | 26 remaining_key_value_pairs_for_frame_(0), |
| 21 handler_(handler), | 27 handler_(handler), |
| 28 stream_id_(kInvalidStreamId), |
| 22 error_(OK), | 29 error_(OK), |
| 23 spdy_version_(spdy_version) { | 30 spdy_version_(spdy_version) { |
| 24 // The handler that we set must not be NULL. | 31 // The handler that we set must not be NULL. |
| 25 DCHECK(handler_ != NULL); | 32 DCHECK(handler_ != NULL); |
| 26 } | 33 } |
| 27 | 34 |
| 28 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} | 35 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} |
| 29 | 36 |
| 30 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData( | 37 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData( |
| 31 SpdyStreamId stream_id, | 38 SpdyStreamId stream_id, |
| 32 const char* headers_data, | 39 const char* headers_data, |
| 33 size_t headers_data_length) { | 40 size_t headers_data_length) { |
| 34 if (error_ == NEED_MORE_DATA) { | 41 if (error_ == NEED_MORE_DATA) { |
| 35 error_ = OK; | 42 error_ = OK; |
| 36 } | 43 } |
| 37 CHECK_EQ(error_, OK); | 44 if (error_ != OK) { |
| 45 LOG(DFATAL) << "Unexpected error: " << error_; |
| 46 return false; |
| 47 } |
| 38 | 48 |
| 39 // If this is the first call with the current header block, | 49 // If this is the first call with the current header block, |
| 40 // save its stream id. | 50 // save its stream id. |
| 41 if (state_ == READING_HEADER_BLOCK_LEN) { | 51 if (state_ == READING_HEADER_BLOCK_LEN && stream_id_ == kInvalidStreamId) { |
| 42 stream_id_ = stream_id; | 52 stream_id_ = stream_id; |
| 43 } | 53 } |
| 44 CHECK_EQ(stream_id_, stream_id); | 54 if (stream_id != stream_id_) { |
| 45 | 55 LOG(DFATAL) << "Unexpected stream id: " << stream_id << " (expected " |
| 56 << stream_id_ << ")"; |
| 57 error_ = UNEXPECTED_STREAM_ID; |
| 58 return false; |
| 59 } |
| 60 if (stream_id_ == kInvalidStreamId) { |
| 61 LOG(DFATAL) << "Expected nonzero stream id, saw: " << stream_id_; |
| 62 error_ = UNEXPECTED_STREAM_ID; |
| 63 return false; |
| 64 } |
| 46 total_bytes_received_ += headers_data_length; | 65 total_bytes_received_ += headers_data_length; |
| 47 | 66 |
| 48 SpdyPinnableBufferPiece prefix, key, value; | 67 SpdyPinnableBufferPiece prefix, key, value; |
| 49 // Simultaneously tie lifetimes to the stack, and clear member variables. | 68 // Simultaneously tie lifetimes to the stack, and clear member variables. |
| 50 prefix.Swap(&headers_block_prefix_); | 69 prefix.Swap(&headers_block_prefix_); |
| 51 key.Swap(&key_); | 70 key.Swap(&key_); |
| 52 | 71 |
| 53 // Apply the parsing state machine to the remaining prefix | 72 // Apply the parsing state machine to the remaining prefix |
| 54 // from last invocation, plus newly-available headers data. | 73 // from last invocation, plus newly-available headers data. |
| 55 Reader reader(prefix.buffer(), prefix.length(), | 74 Reader reader(prefix.buffer(), prefix.length(), |
| (...skipping 18 matching lines...) Expand all Loading... |
| 74 break; | 93 break; |
| 75 case READING_VALUE_LEN: | 94 case READING_VALUE_LEN: |
| 76 next_state = READING_VALUE; | 95 next_state = READING_VALUE; |
| 77 ParseFieldLength(&reader); | 96 ParseFieldLength(&reader); |
| 78 break; | 97 break; |
| 79 case READING_VALUE: | 98 case READING_VALUE: |
| 80 next_state = FINISHED_HEADER; | 99 next_state = FINISHED_HEADER; |
| 81 if (!reader.ReadN(next_field_length_, &value)) { | 100 if (!reader.ReadN(next_field_length_, &value)) { |
| 82 error_ = NEED_MORE_DATA; | 101 error_ = NEED_MORE_DATA; |
| 83 } else { | 102 } else { |
| 84 handler_->OnHeader(stream_id, key, value); | 103 handler_->OnHeader(key, value); |
| 85 } | 104 } |
| 86 break; | 105 break; |
| 87 case FINISHED_HEADER: | 106 case FINISHED_HEADER: |
| 88 // Prepare for next header or block. | 107 // Prepare for next header or block. |
| 89 if (--remaining_key_value_pairs_for_frame_ > 0) { | 108 if (--remaining_key_value_pairs_for_frame_ > 0) { |
| 90 next_state = READING_KEY_LEN; | 109 next_state = READING_KEY_LEN; |
| 91 } else { | 110 } else { |
| 92 next_state = READING_HEADER_BLOCK_LEN; | 111 next_state = READING_HEADER_BLOCK_LEN; |
| 93 handler_->OnHeaderBlockEnd(stream_id, total_bytes_received_); | 112 handler_->OnHeaderBlockEnd(total_bytes_received_); |
| 113 stream_id_ = kInvalidStreamId; |
| 94 // Expect to have consumed all buffer. | 114 // Expect to have consumed all buffer. |
| 95 if (reader.Available() != 0) { | 115 if (reader.Available() != 0) { |
| 96 error_ = TOO_MUCH_DATA; | 116 error_ = TOO_MUCH_DATA; |
| 97 } | 117 } |
| 98 } | 118 } |
| 99 break; | 119 break; |
| 100 default: | |
| 101 CHECK(false) << "Not reached."; | |
| 102 } | 120 } |
| 103 | 121 |
| 104 if (error_ == OK) { | 122 if (error_ == OK) { |
| 105 state_ = next_state; | 123 state_ = next_state; |
| 106 | 124 |
| 107 if (next_state == READING_HEADER_BLOCK_LEN) { | 125 if (next_state == READING_HEADER_BLOCK_LEN) { |
| 108 // We completed reading a full header block. Return to caller. | 126 // We completed reading a full header block. Return to caller. |
| 109 total_bytes_received_ = 0; | 127 total_bytes_received_ = 0; |
| 110 break; | 128 break; |
| 111 } | 129 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 123 return error_ == OK; | 141 return error_ == OK; |
| 124 } | 142 } |
| 125 | 143 |
| 126 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { | 144 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { |
| 127 ParseLength(reader, &remaining_key_value_pairs_for_frame_); | 145 ParseLength(reader, &remaining_key_value_pairs_for_frame_); |
| 128 if (error_ == OK && | 146 if (error_ == OK && |
| 129 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { | 147 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { |
| 130 error_ = HEADER_BLOCK_TOO_LARGE; | 148 error_ = HEADER_BLOCK_TOO_LARGE; |
| 131 } | 149 } |
| 132 if (error_ == OK) { | 150 if (error_ == OK) { |
| 133 handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_); | 151 handler_->OnHeaderBlock(remaining_key_value_pairs_for_frame_); |
| 134 } | 152 } |
| 135 } | 153 } |
| 136 | 154 |
| 137 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { | 155 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { |
| 138 ParseLength(reader, &next_field_length_); | 156 ParseLength(reader, &next_field_length_); |
| 139 if (error_ == OK && | 157 if (error_ == OK && |
| 140 next_field_length_ > kMaximumFieldLength) { | 158 next_field_length_ > kMaximumFieldLength) { |
| 141 error_ = HEADER_FIELD_TOO_LARGE; | 159 error_ = HEADER_FIELD_TOO_LARGE; |
| 142 } | 160 } |
| 143 } | 161 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 170 // Account for the length of the header block field. | 188 // Account for the length of the header block field. |
| 171 size_t max_bytes_for_headers = | 189 size_t max_bytes_for_headers = |
| 172 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); | 190 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); |
| 173 | 191 |
| 174 // A minimal size header is twice the length field size (and has a | 192 // A minimal size header is twice the length field size (and has a |
| 175 // zero-lengthed key and a zero-lengthed value). | 193 // zero-lengthed key and a zero-lengthed value). |
| 176 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); | 194 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); |
| 177 } | 195 } |
| 178 | 196 |
| 179 } // namespace net | 197 } // namespace net |
| OLD | NEW |