• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "net/spdy/spdy_headers_block_parser.h"
6 
7 #include "base/sys_byteorder.h"
8 
9 namespace net {
10 
11 const size_t SpdyHeadersBlockParser::kMaximumFieldLength = 16 * 1024;
12 
SpdyHeadersBlockParser(SpdyMajorVersion spdy_version,SpdyHeadersHandlerInterface * handler)13 SpdyHeadersBlockParser::SpdyHeadersBlockParser(
14     SpdyMajorVersion spdy_version,
15     SpdyHeadersHandlerInterface* handler) :
16     state_(READING_HEADER_BLOCK_LEN),
17     length_field_size_(LengthFieldSizeForVersion(spdy_version)),
18     max_headers_in_block_(MaxNumberOfHeadersForVersion(spdy_version)),
19     total_bytes_received_(0),
20     remaining_key_value_pairs_for_frame_(0),
21     handler_(handler),
22     error_(OK) {
23   // The handler that we set must not be NULL.
24   DCHECK(handler_ != NULL);
25 }
26 
~SpdyHeadersBlockParser()27 SpdyHeadersBlockParser::~SpdyHeadersBlockParser() {}
28 
HandleControlFrameHeadersData(SpdyStreamId stream_id,const char * headers_data,size_t headers_data_length)29 bool SpdyHeadersBlockParser::HandleControlFrameHeadersData(
30     SpdyStreamId stream_id,
31     const char* headers_data,
32     size_t headers_data_length) {
33   if (error_ == NEED_MORE_DATA) {
34     error_ = OK;
35   }
36   CHECK_EQ(error_, OK);
37 
38   // If this is the first call with the current header block,
39   // save its stream id.
40   if (state_ == READING_HEADER_BLOCK_LEN) {
41     stream_id_ = stream_id;
42   }
43   CHECK_EQ(stream_id_, stream_id);
44 
45   total_bytes_received_ += headers_data_length;
46 
47   SpdyPinnableBufferPiece prefix, key, value;
48   // Simultaneously tie lifetimes to the stack, and clear member variables.
49   prefix.Swap(&headers_block_prefix_);
50   key.Swap(&key_);
51 
52   // Apply the parsing state machine to the remaining prefix
53   // from last invocation, plus newly-available headers data.
54   Reader reader(prefix.buffer(), prefix.length(),
55                 headers_data, headers_data_length);
56   while (error_ == OK) {
57     ParserState next_state(FINISHED_HEADER);
58 
59     switch (state_) {
60       case READING_HEADER_BLOCK_LEN:
61         next_state = READING_KEY_LEN;
62         ParseBlockLength(&reader);
63         break;
64       case READING_KEY_LEN:
65         next_state = READING_KEY;
66         ParseFieldLength(&reader);
67         break;
68       case READING_KEY:
69         next_state = READING_VALUE_LEN;
70         if (!reader.ReadN(next_field_length_, &key)) {
71           error_ = NEED_MORE_DATA;
72         }
73         break;
74       case READING_VALUE_LEN:
75         next_state = READING_VALUE;
76         ParseFieldLength(&reader);
77         break;
78       case READING_VALUE:
79         next_state = FINISHED_HEADER;
80         if (!reader.ReadN(next_field_length_, &value)) {
81           error_ = NEED_MORE_DATA;
82         } else {
83           handler_->OnHeader(stream_id, key, value);
84         }
85         break;
86       case FINISHED_HEADER:
87         // Prepare for next header or block.
88         if (--remaining_key_value_pairs_for_frame_ > 0) {
89           next_state = READING_KEY_LEN;
90         } else {
91           next_state = READING_HEADER_BLOCK_LEN;
92           handler_->OnHeaderBlockEnd(stream_id, total_bytes_received_);
93           // Expect to have consumed all buffer.
94           if (reader.Available() != 0) {
95             error_ = TOO_MUCH_DATA;
96           }
97         }
98         break;
99       default:
100         CHECK(false) << "Not reached.";
101     }
102 
103     if (error_ == OK) {
104       state_ = next_state;
105 
106       if (next_state == READING_HEADER_BLOCK_LEN) {
107         // We completed reading a full header block. Return to caller.
108         total_bytes_received_ = 0;
109         break;
110       }
111     } else if (error_ == NEED_MORE_DATA) {
112       // We can't continue parsing until more data is available. Make copies of
113       // the key and buffer remainder, in preperation for the next invocation.
114       if (state_ > READING_KEY) {
115         key_.Swap(&key);
116         key_.Pin();
117       }
118       reader.ReadN(reader.Available(), &headers_block_prefix_);
119       headers_block_prefix_.Pin();
120     }
121   }
122   return error_ == OK;
123 }
124 
ParseBlockLength(Reader * reader)125 void SpdyHeadersBlockParser::ParseBlockLength(Reader* reader) {
126   ParseLength(reader, &remaining_key_value_pairs_for_frame_);
127   if (error_ == OK &&
128     remaining_key_value_pairs_for_frame_ > max_headers_in_block_) {
129     error_ = HEADER_BLOCK_TOO_LARGE;
130   }
131   if (error_ == OK) {
132     handler_->OnHeaderBlock(stream_id_, remaining_key_value_pairs_for_frame_);
133   }
134 }
135 
ParseFieldLength(Reader * reader)136 void SpdyHeadersBlockParser::ParseFieldLength(Reader* reader) {
137   ParseLength(reader, &next_field_length_);
138   if (error_ == OK &&
139       next_field_length_ > kMaximumFieldLength) {
140     error_ = HEADER_FIELD_TOO_LARGE;
141   }
142 }
143 
ParseLength(Reader * reader,uint32_t * parsed_length)144 void SpdyHeadersBlockParser::ParseLength(Reader* reader,
145                                          uint32_t* parsed_length) {
146   char buffer[] = {0, 0, 0, 0};
147   if (!reader->ReadN(length_field_size_, buffer)) {
148     error_ = NEED_MORE_DATA;
149     return;
150   }
151   // Convert from network to host order and return the parsed out integer.
152   if (length_field_size_ == sizeof(uint32_t)) {
153     *parsed_length = ntohl(*reinterpret_cast<const uint32_t *>(buffer));
154   } else {
155     *parsed_length = ntohs(*reinterpret_cast<const uint16_t *>(buffer));
156   }
157 }
158 
Reset()159 void SpdyHeadersBlockParser::Reset() {
160   {
161     SpdyPinnableBufferPiece empty;
162     headers_block_prefix_.Swap(&empty);
163   }
164   {
165     SpdyPinnableBufferPiece empty;
166     key_.Swap(&empty);
167   }
168   error_ = OK;
169   state_ = READING_HEADER_BLOCK_LEN;
170   stream_id_ = 0;
171   total_bytes_received_ = 0;
172 }
173 
LengthFieldSizeForVersion(SpdyMajorVersion spdy_version)174 size_t SpdyHeadersBlockParser::LengthFieldSizeForVersion(
175     SpdyMajorVersion spdy_version) {
176   if (spdy_version < SPDY3) {
177     return sizeof(uint16_t);
178   }
179   return sizeof(uint32_t);
180 }
181 
MaxNumberOfHeadersForVersion(SpdyMajorVersion spdy_version)182 size_t SpdyHeadersBlockParser::MaxNumberOfHeadersForVersion(
183     SpdyMajorVersion spdy_version) {
184   // Account for the length of the header block field.
185   size_t max_bytes_for_headers =
186       kMaximumFieldLength - LengthFieldSizeForVersion(spdy_version);
187 
188   // A minimal size header is twice the length field size (and has a
189   // zero-lengthed key and a zero-lengthed value).
190   return max_bytes_for_headers / (2 * LengthFieldSizeForVersion(spdy_version));
191 }
192 
193 }  // namespace net
194