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 remaining_key_value_pairs_for_frame_(0), | 19 remaining_key_value_pairs_for_frame_(0), |
20 handler_(handler), | 20 handler_(handler), |
21 error_(OK) { | 21 error_(OK) { |
22 // The handler that we set must not be NULL. | 22 // The handler that we set must not be NULL. |
23 DCHECK(handler_ != NULL); | 23 DCHECK(handler_ != NULL); |
24 } | 24 } |
25 | 25 |
26 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {} | 26 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() { |
| 27 } |
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 |
44 SpdyPinnableBufferPiece prefix, key, value; | 45 SpdyPinnableBufferPiece prefix, key, value; |
45 // Simultaneously tie lifetimes to the stack, and clear member variables. | 46 // Simultaneously tie lifetimes to the stack, and clear member variables. |
46 prefix.Swap(&headers_block_prefix_); | 47 prefix.Swap(&headers_block_prefix_); |
47 key.Swap(&key_); | 48 key.Swap(&key_); |
48 | 49 |
49 // Apply the parsing state machine to the remaining prefix | 50 // Apply the parsing state machine to the remaining prefix |
50 // from last invocation, plus newly-available headers data. | 51 // from last invocation, plus newly-available headers data. |
51 Reader reader(prefix.buffer(), prefix.length(), | 52 Reader reader( |
52 headers_data, headers_data_length); | 53 prefix.buffer(), prefix.length(), headers_data, headers_data_length); |
53 while (error_ == OK) { | 54 while (error_ == OK) { |
54 ParserState next_state(FINISHED_HEADER); | 55 ParserState next_state(FINISHED_HEADER); |
55 | 56 |
56 switch (state_) { | 57 switch (state_) { |
57 case READING_HEADER_BLOCK_LEN: | 58 case READING_HEADER_BLOCK_LEN: |
58 next_state = READING_KEY_LEN; | 59 next_state = READING_KEY_LEN; |
59 ParseBlockLength(&reader); | 60 ParseBlockLength(&reader); |
60 break; | 61 break; |
61 case READING_KEY_LEN: | 62 case READING_KEY_LEN: |
62 next_state = READING_KEY; | 63 next_state = READING_KEY; |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 reader.ReadN(reader.Available(), &headers_block_prefix_); | 115 reader.ReadN(reader.Available(), &headers_block_prefix_); |
115 headers_block_prefix_.Pin(); | 116 headers_block_prefix_.Pin(); |
116 } | 117 } |
117 } | 118 } |
118 return error_ == OK; | 119 return error_ == OK; |
119 } | 120 } |
120 | 121 |
121 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { | 122 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) { |
122 ParseLength(reader, &remaining_key_value_pairs_for_frame_); | 123 ParseLength(reader, &remaining_key_value_pairs_for_frame_); |
123 if (error_ == OK && | 124 if (error_ == OK && |
124 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { | 125 remaining_key_value_pairs_for_frame_ > max_headers_in_block_) { |
125 error_ = HEADER_BLOCK_TOO_LARGE; | 126 error_ = HEADER_BLOCK_TOO_LARGE; |
126 } | 127 } |
127 if (error_ == OK) { | 128 if (error_ == OK) { |
128 handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_); | 129 handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_); |
129 } | 130 } |
130 } | 131 } |
131 | 132 |
132 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { | 133 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) { |
133 ParseLength(reader, &next_field_length_); | 134 ParseLength(reader, &next_field_length_); |
134 if (error_ == OK && | 135 if (error_ == OK && next_field_length_ > kMaximumFieldLength) { |
135 next_field_length_ > kMaximumFieldLength) { | |
136 error_ = HEADER_FIELD_TOO_LARGE; | 136 error_ = HEADER_FIELD_TOO_LARGE; |
137 } | 137 } |
138 } | 138 } |
139 | 139 |
140 void SpdyHeadersBlockParser::ParseLength(Reader* reader, | 140 void SpdyHeadersBlockParser::ParseLength(Reader* reader, |
141 uint32_t* parsed_length) { | 141 uint32_t* parsed_length) { |
142 char buffer[] = {0, 0, 0, 0}; | 142 char buffer[] = {0, 0, 0, 0}; |
143 if (!reader->ReadN(length_field_size_, buffer)) { | 143 if (!reader->ReadN(length_field_size_, buffer)) { |
144 error_ = NEED_MORE_DATA; | 144 error_ = NEED_MORE_DATA; |
145 return; | 145 return; |
146 } | 146 } |
147 // Convert from network to host order and return the parsed out integer. | 147 // Convert from network to host order and return the parsed out integer. |
148 if (length_field_size_ == sizeof(uint32_t)) { | 148 if (length_field_size_ == sizeof(uint32_t)) { |
149 *parsed_length = ntohl(*reinterpret_cast<const uint32_t *>(buffer)); | 149 *parsed_length = ntohl(*reinterpret_cast<const uint32_t*>(buffer)); |
150 } else { | 150 } else { |
151 *parsed_length = ntohs(*reinterpret_cast<const uint16_t *>(buffer)); | 151 *parsed_length = ntohs(*reinterpret_cast<const uint16_t*>(buffer)); |
152 } | 152 } |
153 } | 153 } |
154 | 154 |
155 void SpdyHeadersBlockParser::Reset() { | 155 void SpdyHeadersBlockParser::Reset() { |
156 { | 156 { |
157 SpdyPinnableBufferPiece empty; | 157 SpdyPinnableBufferPiece empty; |
158 headers_block_prefix_.Swap(&empty); | 158 headers_block_prefix_.Swap(&empty); |
159 } | 159 } |
160 { | 160 { |
161 SpdyPinnableBufferPiece empty; | 161 SpdyPinnableBufferPiece empty; |
(...skipping 17 matching lines...) Expand all Loading... |
179 // Account for the length of the header block field. | 179 // Account for the length of the header block field. |
180 size_t max_bytes_for_headers = | 180 size_t max_bytes_for_headers = |
181 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); | 181 kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version); |
182 | 182 |
183 // A minimal size header is twice the length field size (and has a | 183 // A minimal size header is twice the length field size (and has a |
184 // zero-lengthed key and a zero-lengthed value). | 184 // zero-lengthed key and a zero-lengthed value). |
185 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); | 185 return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version)); |
186 } | 186 } |
187 | 187 |
188 } // namespace net | 188 } // namespace net |
OLD | NEW |