OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't |
6 // constantly adding and subtracting header sizes; this is ugly and error- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
7 // prone. | 7 // prone. |
8 | 8 |
9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... | |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 // The following compression setting are based on Brian Olson's analysis. See | 25 // The following compression setting are based on Brian Olson's analysis. See |
26 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 | 26 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79 2 |
27 // for more details. | 27 // for more details. |
28 const int kCompressorLevel = 9; | 28 const int kCompressorLevel = 9; |
29 const int kCompressorWindowSizeInBits = 11; | 29 const int kCompressorWindowSizeInBits = 11; |
30 const int kCompressorMemLevel = 1; | 30 const int kCompressorMemLevel = 1; |
31 | 31 |
32 // Adler ID for the SPDY header compressor dictionary. | |
32 uLong dictionary_id = 0; | 33 uLong dictionary_id = 0; |
33 | 34 |
34 } // namespace | 35 } // namespace |
35 | 36 |
36 namespace spdy { | 37 namespace spdy { |
37 | 38 |
38 // This is just a hacked dictionary to use for shrinking HTTP-like headers. | 39 // This is just a hacked dictionary to use for shrinking HTTP-like headers. |
39 // TODO(mbelshe): Use a scientific methodology for computing the dictionary. | 40 // TODO(mbelshe): Use a scientific methodology for computing the dictionary. |
40 const char SpdyFramer::kDictionary[] = | 41 const char SpdyFramer::kDictionary[] = |
41 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" | 42 "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" |
(...skipping 17 matching lines...) Expand all Loading... | |
59 | 60 |
60 // The initial size of the control frame buffer; this is used internally | 61 // The initial size of the control frame buffer; this is used internally |
61 // as we parse through control frames. (It is exposed here for unit test | 62 // as we parse through control frames. (It is exposed here for unit test |
62 // purposes.) | 63 // purposes.) |
63 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024; | 64 size_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024; |
64 | 65 |
65 // The maximum size of the control frame buffer that we support. | 66 // The maximum size of the control frame buffer that we support. |
66 // TODO(mbelshe): We should make this stream-based so there are no limits. | 67 // TODO(mbelshe): We should make this stream-based so there are no limits. |
67 size_t SpdyFramer::kControlFrameBufferMaxSize = 16 * 1024; | 68 size_t SpdyFramer::kControlFrameBufferMaxSize = 16 * 1024; |
68 | 69 |
70 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | |
71 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | |
72 | |
69 #ifdef DEBUG_SPDY_STATE_CHANGES | 73 #ifdef DEBUG_SPDY_STATE_CHANGES |
70 #define CHANGE_STATE(newstate) \ | 74 #define CHANGE_STATE(newstate) \ |
71 { \ | 75 { \ |
72 do { \ | 76 do { \ |
73 LOG(INFO) << "Changing state from: " \ | 77 LOG(INFO) << "Changing state from: " \ |
74 << StateToString(state_) \ | 78 << StateToString(state_) \ |
75 << " to " << StateToString(newstate) << "\n"; \ | 79 << " to " << StateToString(newstate) << "\n"; \ |
76 state_ = newstate; \ | 80 state_ = newstate; \ |
77 } while (false); \ | 81 } while (false); \ |
78 } | 82 } |
79 #else | 83 #else |
80 #define CHANGE_STATE(newstate) (state_ = newstate) | 84 #define CHANGE_STATE(newstate) (state_ = newstate) |
81 #endif | 85 #endif |
82 | 86 |
87 int DecompressHeaderBlockInZStream(z_stream* decompressor) { | |
88 int rv = inflate(decompressor, Z_SYNC_FLUSH); | |
89 if (rv == Z_NEED_DICT) { | |
90 // Need to try again with the right dictionary. | |
91 if (decompressor->adler == dictionary_id) { | |
92 rv = inflateSetDictionary(decompressor, | |
93 (const Bytef*)SpdyFramer::kDictionary, | |
94 SpdyFramer::kDictionarySize); | |
95 if (rv == Z_OK) | |
96 rv = inflate(decompressor, Z_SYNC_FLUSH); | |
97 } | |
98 } | |
99 return rv; | |
100 } | |
101 | |
102 // Retrieve serialized length of SpdyHeaderBlock. | |
103 size_t GetSerializedLength(const SpdyHeaderBlock* headers) { | |
104 size_t total_length = SpdyControlFrame::kNumNameValuePairsSize; | |
105 SpdyHeaderBlock::const_iterator it; | |
106 for (it = headers->begin(); it != headers->end(); ++it) { | |
107 // We add space for the length of the name and the length of the value as | |
108 // well as the length of the name and the length of the value. | |
109 total_length += SpdyControlFrame::kLengthOfNameSize + | |
110 it->first.size() + | |
111 SpdyControlFrame::kLengthOfValueSize + | |
112 it->second.size(); | |
113 } | |
114 return total_length; | |
115 } | |
116 | |
117 // Serializes a SpdyHeaderBlock. | |
118 void WriteHeaderBlock(SpdyFrameBuilder* frame, const SpdyHeaderBlock* headers) { | |
119 frame->WriteUInt16(headers->size()); // Number of headers. | |
120 SpdyHeaderBlock::const_iterator it; | |
121 for (it = headers->begin(); it != headers->end(); ++it) { | |
122 bool wrote_header; | |
123 wrote_header = frame->WriteString(it->first); | |
124 wrote_header &= frame->WriteString(it->second); | |
125 DCHECK(wrote_header); | |
126 } | |
127 } | |
128 | |
129 // Creates a FlagsAndLength. | |
130 FlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) { | |
131 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); | |
132 FlagsAndLength flags_length; | |
133 flags_length.length_ = htonl(static_cast<uint32>(length)); | |
134 DCHECK_EQ(0, flags & ~kControlFlagsMask); | |
135 flags_length.flags_[0] = flags; | |
136 return flags_length; | |
137 } | |
138 | |
83 SpdyFramer::SpdyFramer() | 139 SpdyFramer::SpdyFramer() |
84 : state_(SPDY_RESET), | 140 : state_(SPDY_RESET), |
85 error_code_(SPDY_NO_ERROR), | 141 error_code_(SPDY_NO_ERROR), |
86 remaining_payload_(0), | 142 remaining_data_(0), |
87 remaining_control_payload_(0), | 143 remaining_control_payload_(0), |
144 remaining_control_header_(0), | |
88 current_frame_buffer_(NULL), | 145 current_frame_buffer_(NULL), |
89 current_frame_len_(0), | 146 current_frame_len_(0), |
90 current_frame_capacity_(0), | 147 current_frame_capacity_(0), |
148 validate_control_frame_sizes_(true), | |
91 enable_compression_(compression_default_), | 149 enable_compression_(compression_default_), |
92 visitor_(NULL) { | 150 visitor_(NULL) { |
93 } | 151 } |
94 | 152 |
95 SpdyFramer::~SpdyFramer() { | 153 SpdyFramer::~SpdyFramer() { |
96 if (header_compressor_.get()) { | 154 if (header_compressor_.get()) { |
97 deflateEnd(header_compressor_.get()); | 155 deflateEnd(header_compressor_.get()); |
98 } | 156 } |
99 if (header_decompressor_.get()) { | 157 if (header_decompressor_.get()) { |
100 inflateEnd(header_decompressor_.get()); | 158 inflateEnd(header_decompressor_.get()); |
101 } | 159 } |
102 CleanupStreamCompressorsAndDecompressors(); | 160 CleanupStreamCompressorsAndDecompressors(); |
103 delete [] current_frame_buffer_; | 161 delete [] current_frame_buffer_; |
104 } | 162 } |
105 | 163 |
164 const char* SpdyFramer::StatusCodeToString(int status_code) { | |
165 switch (status_code) { | |
166 case INVALID: | |
167 return "INVALID"; | |
168 case PROTOCOL_ERROR: | |
169 return "PROTOCOL_ERROR"; | |
170 case INVALID_STREAM: | |
171 return "INVALID_STREAM"; | |
172 case REFUSED_STREAM: | |
173 return "REFUSED_STREAM"; | |
174 case UNSUPPORTED_VERSION: | |
175 return "UNSUPPORTED_VERSION"; | |
176 case CANCEL: | |
177 return "CANCEL"; | |
178 case INTERNAL_ERROR: | |
179 return "INTERNAL_ERROR"; | |
180 case FLOW_CONTROL_ERROR: | |
181 return "FLOW_CONTROL_ERROR"; | |
182 } | |
183 return "UNKNOWN_STATUS"; | |
184 } | |
185 | |
186 const char* SpdyFramer::ControlTypeToString(SpdyControlType type) { | |
187 switch (type) { | |
188 case SYN_STREAM: | |
189 return "SYN_STREAM"; | |
190 case SYN_REPLY: | |
191 return "SYN_REPLY"; | |
192 case RST_STREAM: | |
193 return "RST_STREAM"; | |
194 case SETTINGS: | |
195 return "SETTINGS"; | |
196 case NOOP: | |
197 return "NOOP"; | |
198 case PING: | |
199 return "PING"; | |
200 case GOAWAY: | |
201 return "GOAWAY"; | |
202 case HEADERS: | |
203 return "HEADERS"; | |
204 case WINDOW_UPDATE: | |
205 return "WINDOW_UPDATE"; | |
206 case NUM_CONTROL_FRAME_TYPES: | |
207 break; | |
208 } | |
209 return "UNKNOWN_CONTROL_TYPE"; | |
210 } | |
211 | |
106 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { | 212 size_t SpdyFramer::ProcessInput(const char* data, size_t len) { |
107 DCHECK(visitor_); | 213 DCHECK(visitor_); |
108 DCHECK(data); | 214 DCHECK(data); |
109 | 215 |
110 size_t original_len = len; | 216 size_t original_len = len; |
111 while (len != 0) { | 217 while (len != 0) { |
112 switch (state_) { | 218 switch (state_) { |
113 case SPDY_ERROR: | 219 case SPDY_ERROR: |
114 case SPDY_DONE: | 220 case SPDY_DONE: |
115 goto bottom; | 221 goto bottom; |
116 | 222 |
117 case SPDY_AUTO_RESET: | 223 case SPDY_AUTO_RESET: |
118 case SPDY_RESET: | 224 case SPDY_RESET: |
119 Reset(); | 225 Reset(); |
120 CHANGE_STATE(SPDY_READING_COMMON_HEADER); | 226 CHANGE_STATE(SPDY_READING_COMMON_HEADER); |
121 continue; | 227 continue; |
122 | 228 |
123 case SPDY_READING_COMMON_HEADER: { | 229 case SPDY_READING_COMMON_HEADER: { |
124 size_t bytes_read = ProcessCommonHeader(data, len); | 230 size_t bytes_read = ProcessCommonHeader(data, len); |
125 len -= bytes_read; | 231 len -= bytes_read; |
126 data += bytes_read; | 232 data += bytes_read; |
127 continue; | 233 continue; |
128 } | 234 } |
129 | 235 |
130 // Arguably, this case is not necessary, as no bytes are consumed here. | 236 // Arguably, this case is not necessary, as no bytes are consumed here. |
131 // I felt it was a nice partitioning, however (which probably indicates | 237 // I felt it was a nice partitioning, however (which probably indicates |
132 // that it should be refactored into its own function!) | 238 // that it should be refactored into its own function!) |
239 // TODO(hkhalil): Remove -- while loop above prevents proper handling of | |
240 // zero-length control frames. | |
133 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: | 241 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: |
134 ProcessControlFrameHeader(); | 242 ProcessControlFrameHeader(); |
135 continue; | 243 continue; |
136 | 244 |
245 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { | |
246 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, | |
247 // HEADERS) take a different path through the state machine - they | |
248 // will go: | |
249 // 1. SPDY_INTERPRET_CONTROL_FRAME_COMMON HEADER | |
250 // 2. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK | |
251 // 3. SPDY_CONTROL_FRAME_HEADER_BLOCK | |
252 // | |
253 // All other control frames will use the alternate route: | |
254 // 1. SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER | |
255 // 2. SPDY_CONTROL_FRAME_PAYLOAD | |
256 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); | |
257 len -= bytes_read; | |
258 data += bytes_read; | |
259 continue; | |
260 } | |
261 | |
262 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { | |
263 int bytes_read = ProcessControlFrameHeaderBlock(data, len); | |
264 len -= bytes_read; | |
265 data += bytes_read; | |
266 continue; | |
267 } | |
268 | |
137 case SPDY_CONTROL_FRAME_PAYLOAD: { | 269 case SPDY_CONTROL_FRAME_PAYLOAD: { |
138 size_t bytes_read = ProcessControlFramePayload(data, len); | 270 size_t bytes_read = ProcessControlFramePayload(data, len); |
139 len -= bytes_read; | 271 len -= bytes_read; |
140 data += bytes_read; | 272 data += bytes_read; |
141 } | 273 } |
142 // intentional fallthrough | 274 // intentional fallthrough |
143 case SPDY_IGNORE_REMAINING_PAYLOAD: | 275 case SPDY_IGNORE_REMAINING_PAYLOAD: |
144 // control frame has too-large payload | 276 // control frame has too-large payload |
145 // intentional fallthrough | 277 // intentional fallthrough |
146 case SPDY_FORWARD_STREAM_FRAME: { | 278 case SPDY_FORWARD_STREAM_FRAME: { |
147 size_t bytes_read = ProcessDataFramePayload(data, len); | 279 size_t bytes_read = ProcessDataFramePayload(data, len); |
148 len -= bytes_read; | 280 len -= bytes_read; |
149 data += bytes_read; | 281 data += bytes_read; |
150 continue; | 282 continue; |
151 } | 283 } |
152 default: | 284 default: |
153 break; | 285 break; |
154 } | 286 } |
155 } | 287 } |
156 bottom: | 288 bottom: |
157 return original_len - len; | 289 return original_len - len; |
158 } | 290 } |
159 | 291 |
160 void SpdyFramer::Reset() { | 292 void SpdyFramer::Reset() { |
161 state_ = SPDY_RESET; | 293 state_ = SPDY_RESET; |
162 error_code_ = SPDY_NO_ERROR; | 294 error_code_ = SPDY_NO_ERROR; |
163 remaining_payload_ = 0; | 295 remaining_data_ = 0; |
164 remaining_control_payload_ = 0; | 296 remaining_control_payload_ = 0; |
297 remaining_control_header_ = 0; | |
165 current_frame_len_ = 0; | 298 current_frame_len_ = 0; |
166 if (current_frame_capacity_ != kControlFrameBufferInitialSize) { | 299 if (current_frame_capacity_ != kControlFrameBufferInitialSize) { |
167 delete [] current_frame_buffer_; | 300 delete [] current_frame_buffer_; |
168 current_frame_buffer_ = 0; | 301 current_frame_buffer_ = 0; |
169 current_frame_capacity_ = 0; | 302 current_frame_capacity_ = 0; |
170 ExpandControlFrameBuffer(kControlFrameBufferInitialSize); | 303 ExpandControlFrameBuffer(kControlFrameBufferInitialSize); |
171 } | 304 } |
172 } | 305 } |
173 | 306 |
174 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, | 307 bool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
229 } else { | 362 } else { |
230 return false; | 363 return false; |
231 } | 364 } |
232 } | 365 } |
233 return index == num_headers && | 366 return index == num_headers && |
234 iter == header_data + header_length; | 367 iter == header_data + header_length; |
235 } | 368 } |
236 return false; | 369 return false; |
237 } | 370 } |
238 | 371 |
372 size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, | |
373 size_t max_bytes) { | |
374 size_t bytes_to_read = std::min(*len, max_bytes); | |
375 DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read); | |
376 memcpy(¤t_frame_buffer_[current_frame_len_], *data, bytes_to_read); | |
377 current_frame_len_ += bytes_to_read; | |
378 *data += bytes_to_read; | |
379 *len -= bytes_to_read; | |
380 return bytes_to_read; | |
381 } | |
382 | |
383 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, | |
384 size_t len) { | |
385 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); | |
386 DCHECK_GT(remaining_control_header_, 0u); | |
387 size_t original_len = len; | |
388 | |
389 if (remaining_control_header_) { | |
390 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | |
391 remaining_control_header_); | |
392 remaining_control_header_ -= bytes_read; | |
393 if (remaining_control_header_ == 0) { | |
394 SpdyControlFrame control_frame(current_frame_buffer_, false); | |
395 DCHECK(control_frame.type() == SYN_STREAM || | |
396 control_frame.type() == SYN_REPLY || | |
397 control_frame.type() == HEADERS); | |
398 visitor_->OnControl(&control_frame); | |
399 | |
400 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); | |
401 } | |
402 } | |
403 return original_len - len; | |
404 } | |
405 | |
406 // Does not buffer the control payload. Instead, either passes directly to the | |
407 // visitor or decompresses and then passes directly to the visitor, via | |
408 // IncrementallyDeliverControlFrameHeaderData() or | |
409 // IncrementallyDecompressControlFrameHeaderData() respectively. | |
410 size_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data, | |
411 size_t data_len) { | |
412 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | |
413 SpdyControlFrame control_frame(current_frame_buffer_, false); | |
414 bool processed_successfully = true; | |
415 DCHECK(control_frame.type() == SYN_STREAM || | |
416 control_frame.type() == SYN_REPLY || | |
417 control_frame.type() == HEADERS); | |
418 size_t process_bytes = std::min(data_len, remaining_control_payload_); | |
419 DCHECK_GT(process_bytes, 0u); | |
420 | |
421 if (enable_compression_) { | |
422 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | |
423 &control_frame, data, process_bytes); | |
424 } else { | |
425 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | |
426 &control_frame, data, process_bytes); | |
427 } | |
428 remaining_control_payload_ -= process_bytes; | |
429 | |
430 // Handle the case that there is no futher data in this frame. | |
431 if (remaining_control_payload_ == 0 && processed_successfully) { | |
432 // The complete header block has been delivered. We send a zero-length | |
433 // OnControlFrameHeaderData() to indicate this. | |
434 visitor_->OnControlFrameHeaderData( | |
435 GetControlFrameStreamId(&control_frame), NULL, 0); | |
436 | |
437 // If this is a FIN, tell the caller. | |
438 if (control_frame.flags() & CONTROL_FLAG_FIN) { | |
439 visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame), | |
440 NULL, 0); | |
441 } | |
442 | |
443 CHANGE_STATE(SPDY_RESET); | |
444 } | |
445 | |
446 // Handle error. | |
447 if (!processed_successfully) { | |
448 return data_len; | |
449 } | |
450 | |
451 // Return amount processed. | |
452 return process_bytes; | |
453 } | |
454 | |
455 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | |
456 size_t data_len) { | |
457 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | |
458 size_t original_data_len = data_len; | |
459 SpdyControlFrame control_frame(current_frame_buffer_, false); | |
460 bool read_successfully = true; | |
461 DCHECK(control_frame.type() == SYN_STREAM || | |
462 control_frame.type() == SYN_REPLY || | |
463 control_frame.type() == HEADERS); | |
464 | |
465 if (enable_compression_) { | |
466 // Note that the header block is held in the frame's payload, and is not | |
467 // part of the frame's headers. | |
468 if (remaining_control_payload_ > 0) { | |
469 size_t bytes_read = UpdateCurrentFrameBuffer( | |
470 &data, | |
471 &data_len, | |
472 remaining_control_payload_); | |
473 remaining_control_payload_ -= bytes_read; | |
474 if (remaining_control_payload_ == 0) { | |
475 read_successfully = IncrementallyDecompressControlFrameHeaderData( | |
476 &control_frame); | |
477 } | |
478 } | |
479 } else { | |
480 size_t bytes_to_send = std::min(data_len, remaining_control_payload_); | |
481 DCHECK_GT(bytes_to_send, 0u); | |
482 read_successfully = IncrementallyDeliverControlFrameHeaderData( | |
483 &control_frame, data, bytes_to_send); | |
484 data_len -= bytes_to_send; | |
485 remaining_control_payload_ -= bytes_to_send; | |
486 } | |
487 if (remaining_control_payload_ == 0 && read_successfully) { | |
488 // The complete header block has been delivered. | |
489 visitor_->OnControlFrameHeaderData(GetControlFrameStreamId(&control_frame), | |
490 NULL, 0); | |
491 | |
492 // If this is a FIN, tell the caller. | |
493 if (control_frame.flags() & CONTROL_FLAG_FIN) { | |
494 visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame), | |
495 NULL, 0); | |
496 } | |
497 | |
498 CHANGE_STATE(SPDY_RESET); | |
499 } | |
500 if (!read_successfully) { | |
501 return original_data_len; | |
502 } | |
503 return original_data_len - data_len; | |
504 } | |
505 | |
506 /* static */ | |
507 bool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, | |
508 size_t header_length, | |
509 SpdyHeaderBlock* block) { | |
510 SpdyFrameBuilder builder(header_data, header_length); | |
511 void* iter = NULL; | |
512 uint16 num_headers; | |
513 if (builder.ReadUInt16(&iter, &num_headers)) { | |
514 for (int index = 0; index < num_headers; ++index) { | |
515 std::string name; | |
516 std::string value; | |
517 if (!builder.ReadString(&iter, &name)) | |
518 return false; | |
519 if (!builder.ReadString(&iter, &value)) | |
520 return false; | |
521 if (block->find(name) == block->end()) { | |
522 (*block)[name] = value; | |
523 } else { | |
524 return false; | |
525 } | |
526 } | |
527 return true; | |
528 } | |
529 return false; | |
530 } | |
531 | |
239 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( | 532 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
240 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, | 533 SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, |
241 SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) { | 534 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { |
242 SpdyFrameBuilder frame; | 535 SpdyFrameBuilder frame; |
243 | 536 |
244 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); | 537 DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); |
245 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 538 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
246 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); | 539 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); |
247 | 540 |
248 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 541 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
249 frame.WriteUInt16(SYN_STREAM); | 542 frame.WriteUInt16(SYN_STREAM); |
250 frame.WriteUInt32(0); // Placeholder for the length and flags | 543 frame.WriteUInt32(0); // Placeholder for the length and flags |
251 frame.WriteUInt32(stream_id); | 544 frame.WriteUInt32(stream_id); |
252 frame.WriteUInt32(associated_stream_id); | 545 frame.WriteUInt32(associated_stream_id); |
253 frame.WriteUInt16(ntohs(priority) << 6); // Priority. | 546 frame.WriteUInt16(ntohs(priority) << 6); // Priority. |
254 | 547 |
255 frame.WriteUInt16(headers->size()); // Number of headers. | 548 frame.WriteUInt16(headers->size()); // Number of headers. |
256 SpdyHeaderBlock::iterator it; | 549 SpdyHeaderBlock::const_iterator it; |
257 for (it = headers->begin(); it != headers->end(); ++it) { | 550 for (it = headers->begin(); it != headers->end(); ++it) { |
258 bool wrote_header; | 551 bool wrote_header; |
259 wrote_header = frame.WriteString(it->first); | 552 wrote_header = frame.WriteString(it->first); |
260 wrote_header &= frame.WriteString(it->second); | 553 wrote_header &= frame.WriteString(it->second); |
261 DCHECK(wrote_header); | 554 DCHECK(wrote_header); |
262 } | 555 } |
263 | 556 |
264 // Write the length and flags. | 557 // Write the length and flags. |
265 size_t length = frame.length() - SpdyFrame::size(); | 558 size_t length = frame.length() - SpdyFrame::size(); |
266 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); | 559 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); |
267 FlagsAndLength flags_length; | 560 FlagsAndLength flags_length; |
268 flags_length.length_ = htonl(static_cast<uint32>(length)); | 561 flags_length.length_ = htonl(static_cast<uint32>(length)); |
269 DCHECK_EQ(0, flags & ~kControlFlagsMask); | 562 DCHECK_EQ(0, flags & ~kControlFlagsMask); |
270 flags_length.flags_[0] = flags; | 563 flags_length.flags_[0] = flags; |
271 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); | 564 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); |
272 | 565 |
273 scoped_ptr<SpdyFrame> syn_frame(frame.take()); | 566 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
567 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); | |
274 if (compressed) { | 568 if (compressed) { |
275 return reinterpret_cast<SpdySynStreamControlFrame*>( | 569 return reinterpret_cast<SpdySynStreamControlFrame*>( |
276 CompressFrame(*syn_frame.get())); | 570 CompressControlFrame(*syn_frame.get())); |
277 } | 571 } |
278 return reinterpret_cast<SpdySynStreamControlFrame*>(syn_frame.release()); | 572 return syn_frame.release(); |
279 } | 573 } |
280 | 574 |
281 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id, | 575 SpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id, |
282 SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) { | 576 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { |
283 DCHECK_GT(stream_id, 0u); | 577 DCHECK_GT(stream_id, 0u); |
284 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 578 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
285 | 579 |
286 SpdyFrameBuilder frame; | 580 SpdyFrameBuilder frame; |
287 | 581 |
288 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 582 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
289 frame.WriteUInt16(SYN_REPLY); | 583 frame.WriteUInt16(SYN_REPLY); |
290 frame.WriteUInt32(0); // Placeholder for the length and flags. | 584 frame.WriteUInt32(0); // Placeholder for the length and flags. |
291 frame.WriteUInt32(stream_id); | 585 frame.WriteUInt32(stream_id); |
292 frame.WriteUInt16(0); // Unused | 586 frame.WriteUInt16(0); // Unused |
293 | 587 |
294 frame.WriteUInt16(headers->size()); // Number of headers. | 588 frame.WriteUInt16(headers->size()); // Number of headers. |
295 SpdyHeaderBlock::iterator it; | 589 SpdyHeaderBlock::const_iterator it; |
296 for (it = headers->begin(); it != headers->end(); ++it) { | 590 for (it = headers->begin(); it != headers->end(); ++it) { |
297 bool wrote_header; | 591 bool wrote_header; |
298 wrote_header = frame.WriteString(it->first); | 592 wrote_header = frame.WriteString(it->first); |
299 wrote_header &= frame.WriteString(it->second); | 593 wrote_header &= frame.WriteString(it->second); |
300 DCHECK(wrote_header); | 594 DCHECK(wrote_header); |
301 } | 595 } |
302 | 596 |
303 // Write the length and flags. | 597 // Write the length and flags. |
304 size_t length = frame.length() - SpdyFrame::size(); | 598 size_t length = frame.length() - SpdyFrame::size(); |
305 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); | 599 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); |
306 FlagsAndLength flags_length; | 600 FlagsAndLength flags_length; |
307 flags_length.length_ = htonl(static_cast<uint32>(length)); | 601 flags_length.length_ = htonl(static_cast<uint32>(length)); |
308 DCHECK_EQ(0, flags & ~kControlFlagsMask); | 602 DCHECK_EQ(0, flags & ~kControlFlagsMask); |
309 flags_length.flags_[0] = flags; | 603 flags_length.flags_[0] = flags; |
310 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); | 604 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); |
311 | 605 |
312 scoped_ptr<SpdyFrame> reply_frame(frame.take()); | 606 scoped_ptr<SpdySynReplyControlFrame> reply_frame( |
607 reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); | |
313 if (compressed) { | 608 if (compressed) { |
314 return reinterpret_cast<SpdySynReplyControlFrame*>( | 609 return reinterpret_cast<SpdySynReplyControlFrame*>( |
315 CompressFrame(*reply_frame.get())); | 610 CompressControlFrame(*reply_frame.get())); |
316 } | 611 } |
317 return reinterpret_cast<SpdySynReplyControlFrame*>(reply_frame.release()); | 612 return reply_frame.release(); |
318 } | 613 } |
319 | 614 |
320 /* static */ | 615 /* static */ |
321 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id, | 616 SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id, |
322 SpdyStatusCodes status) { | 617 SpdyStatusCodes status) { |
323 DCHECK_GT(stream_id, 0u); | 618 DCHECK_GT(stream_id, 0u); |
324 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 619 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
325 DCHECK_NE(status, INVALID); | 620 DCHECK_NE(status, INVALID); |
326 DCHECK_LT(status, NUM_STATUS_CODES); | 621 DCHECK_LT(status, NUM_STATUS_CODES); |
327 | 622 |
(...skipping 19 matching lines...) Expand all Loading... | |
347 SpdySettings::const_iterator it = values.begin(); | 642 SpdySettings::const_iterator it = values.begin(); |
348 while (it != values.end()) { | 643 while (it != values.end()) { |
349 frame.WriteUInt32(it->first.id_); | 644 frame.WriteUInt32(it->first.id_); |
350 frame.WriteUInt32(it->second); | 645 frame.WriteUInt32(it->second); |
351 ++it; | 646 ++it; |
352 } | 647 } |
353 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); | 648 return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); |
354 } | 649 } |
355 | 650 |
356 /* static */ | 651 /* static */ |
357 SpdyControlFrame* SpdyFramer::CreateNopFrame() { | 652 SpdyNoOpControlFrame* SpdyFramer::CreateNopFrame() { |
358 SpdyFrameBuilder frame; | 653 SpdyFrameBuilder frame; |
359 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 654 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
360 frame.WriteUInt16(NOOP); | 655 frame.WriteUInt16(NOOP); |
361 frame.WriteUInt32(0); | 656 frame.WriteUInt32(0); |
362 return reinterpret_cast<SpdyControlFrame*>(frame.take()); | 657 return reinterpret_cast<SpdyNoOpControlFrame*>(frame.take()); |
658 } | |
659 | |
660 /* static */ | |
661 SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) { | |
662 SpdyFrameBuilder frame; | |
663 frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion); | |
664 frame.WriteUInt16(PING); | |
665 size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::size(); | |
666 frame.WriteUInt32(ping_size); | |
667 frame.WriteUInt32(unique_id); | |
668 return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); | |
363 } | 669 } |
364 | 670 |
365 /* static */ | 671 /* static */ |
366 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( | 672 SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
367 SpdyStreamId last_accepted_stream_id) { | 673 SpdyStreamId last_accepted_stream_id) { |
368 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); | 674 DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); |
369 | 675 |
370 SpdyFrameBuilder frame; | 676 SpdyFrameBuilder frame; |
371 frame.WriteUInt16(kControlFlagMask | spdy_version_); | 677 frame.WriteUInt16(kControlFlagMask | spdy_version_); |
372 frame.WriteUInt16(GOAWAY); | 678 frame.WriteUInt16(GOAWAY); |
373 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size(); | 679 size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size(); |
374 frame.WriteUInt32(go_away_size); | 680 frame.WriteUInt32(go_away_size); |
375 frame.WriteUInt32(last_accepted_stream_id); | 681 frame.WriteUInt32(last_accepted_stream_id); |
376 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); | 682 return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); |
377 } | 683 } |
378 | 684 |
379 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id, | 685 SpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id, |
380 SpdyControlFlags flags, bool compressed, SpdyHeaderBlock* headers) { | 686 SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { |
381 // Basically the same as CreateSynReply(). | 687 // Basically the same as CreateSynReply(). |
382 DCHECK_GT(stream_id, 0u); | 688 DCHECK_GT(stream_id, 0u); |
383 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 689 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
384 | 690 |
385 SpdyFrameBuilder frame; | 691 SpdyFrameBuilder frame; |
386 frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion); | 692 frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion); |
387 frame.WriteUInt16(HEADERS); | 693 frame.WriteUInt16(HEADERS); |
388 frame.WriteUInt32(0); // Placeholder for the length and flags. | 694 frame.WriteUInt32(0); // Placeholder for the length and flags. |
389 frame.WriteUInt32(stream_id); | 695 frame.WriteUInt32(stream_id); |
390 frame.WriteUInt16(0); // Unused | 696 frame.WriteUInt16(0); // Unused |
391 | 697 |
392 frame.WriteUInt16(headers->size()); // Number of headers. | 698 frame.WriteUInt16(headers->size()); // Number of headers. |
393 SpdyHeaderBlock::iterator it; | 699 SpdyHeaderBlock::const_iterator it; |
394 for (it = headers->begin(); it != headers->end(); ++it) { | 700 for (it = headers->begin(); it != headers->end(); ++it) { |
395 bool wrote_header; | 701 bool wrote_header; |
396 wrote_header = frame.WriteString(it->first); | 702 wrote_header = frame.WriteString(it->first); |
397 wrote_header &= frame.WriteString(it->second); | 703 wrote_header &= frame.WriteString(it->second); |
398 DCHECK(wrote_header); | 704 DCHECK(wrote_header); |
399 } | 705 } |
400 | 706 |
401 // Write the length and flags. | 707 // Write the length and flags. |
402 size_t length = frame.length() - SpdyFrame::size(); | 708 size_t length = frame.length() - SpdyFrame::size(); |
403 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); | 709 DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); |
404 FlagsAndLength flags_length; | 710 FlagsAndLength flags_length; |
405 flags_length.length_ = htonl(static_cast<uint32>(length)); | 711 flags_length.length_ = htonl(static_cast<uint32>(length)); |
406 DCHECK_EQ(0, flags & ~kControlFlagsMask); | 712 DCHECK_EQ(0, flags & ~kControlFlagsMask); |
407 flags_length.flags_[0] = flags; | 713 flags_length.flags_[0] = flags; |
408 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); | 714 frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); |
409 | 715 |
410 scoped_ptr<SpdyFrame> headers_frame(frame.take()); | 716 scoped_ptr<SpdyHeadersControlFrame> headers_frame( |
717 reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); | |
411 if (compressed) { | 718 if (compressed) { |
412 return reinterpret_cast<SpdyHeadersControlFrame*>( | 719 return reinterpret_cast<SpdyHeadersControlFrame*>( |
413 CompressFrame(*headers_frame.get())); | 720 CompressControlFrame(*headers_frame.get())); |
414 } | 721 } |
415 return reinterpret_cast<SpdyHeadersControlFrame*>(headers_frame.release()); | 722 return headers_frame.release(); |
416 } | 723 } |
417 | 724 |
418 /* static */ | 725 /* static */ |
419 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( | 726 SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( |
420 SpdyStreamId stream_id, | 727 SpdyStreamId stream_id, |
421 uint32 delta_window_size) { | 728 uint32 delta_window_size) { |
422 DCHECK_GT(stream_id, 0u); | 729 DCHECK_GT(stream_id, 0u); |
423 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 730 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
424 DCHECK_GT(delta_window_size, 0u); | 731 DCHECK_GT(delta_window_size, 0u); |
425 DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize); | 732 DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
468 FlagsAndLength flags_length; | 775 FlagsAndLength flags_length; |
469 flags_length.length_ = htonl(len); | 776 flags_length.length_ = htonl(len); |
470 DCHECK_EQ(0, flags & ~kDataFlagsMask); | 777 DCHECK_EQ(0, flags & ~kDataFlagsMask); |
471 flags_length.flags_[0] = flags; | 778 flags_length.flags_[0] = flags; |
472 frame.WriteBytes(&flags_length, sizeof(flags_length)); | 779 frame.WriteBytes(&flags_length, sizeof(flags_length)); |
473 | 780 |
474 frame.WriteBytes(data, len); | 781 frame.WriteBytes(data, len); |
475 scoped_ptr<SpdyFrame> data_frame(frame.take()); | 782 scoped_ptr<SpdyFrame> data_frame(frame.take()); |
476 SpdyDataFrame* rv; | 783 SpdyDataFrame* rv; |
477 if (flags & DATA_FLAG_COMPRESSED) { | 784 if (flags & DATA_FLAG_COMPRESSED) { |
785 // LOG(DFATAL) << "DATA_FLAG_COMPRESSED invalid for SPDY."; | |
willchan no longer on Chromium
2011/09/25 22:18:24
Did you add this? I'm surprised to see this.
ramant (doing other things)
2011/09/26 00:27:55
I didn't. It came from server code. Deleted the co
| |
478 rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get())); | 786 rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get())); |
479 } else { | 787 } else { |
480 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); | 788 rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); |
481 } | 789 } |
482 | 790 |
483 if (flags & DATA_FLAG_FIN) { | 791 if (flags & DATA_FLAG_FIN) { |
484 CleanupCompressorForStream(stream_id); | 792 CleanupCompressorForStream(stream_id); |
485 } | 793 } |
486 | 794 |
487 return rv; | 795 return rv; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 case SPDY_READING_COMMON_HEADER: | 849 case SPDY_READING_COMMON_HEADER: |
542 return "READING_COMMON_HEADER"; | 850 return "READING_COMMON_HEADER"; |
543 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: | 851 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: |
544 return "INTERPRET_CONTROL_FRAME_COMMON_HEADER"; | 852 return "INTERPRET_CONTROL_FRAME_COMMON_HEADER"; |
545 case SPDY_CONTROL_FRAME_PAYLOAD: | 853 case SPDY_CONTROL_FRAME_PAYLOAD: |
546 return "CONTROL_FRAME_PAYLOAD"; | 854 return "CONTROL_FRAME_PAYLOAD"; |
547 case SPDY_IGNORE_REMAINING_PAYLOAD: | 855 case SPDY_IGNORE_REMAINING_PAYLOAD: |
548 return "IGNORE_REMAINING_PAYLOAD"; | 856 return "IGNORE_REMAINING_PAYLOAD"; |
549 case SPDY_FORWARD_STREAM_FRAME: | 857 case SPDY_FORWARD_STREAM_FRAME: |
550 return "FORWARD_STREAM_FRAME"; | 858 return "FORWARD_STREAM_FRAME"; |
859 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: | |
860 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; | |
861 case SPDY_CONTROL_FRAME_HEADER_BLOCK: | |
862 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; | |
551 } | 863 } |
552 return "UNKNOWN_STATE"; | 864 return "UNKNOWN_STATE"; |
553 } | 865 } |
554 | 866 |
555 const char* SpdyFramer::ErrorCodeToString(int error_code) { | 867 const char* SpdyFramer::ErrorCodeToString(int error_code) { |
556 switch (error_code) { | 868 switch (error_code) { |
557 case SPDY_NO_ERROR: | 869 case SPDY_NO_ERROR: |
558 return "NO_ERROR"; | 870 return "NO_ERROR"; |
559 case SPDY_INVALID_CONTROL_FRAME: | 871 case SPDY_INVALID_CONTROL_FRAME: |
560 return "INVALID_CONTROL_FRAME"; | 872 return "INVALID_CONTROL_FRAME"; |
(...skipping 23 matching lines...) Expand all Loading... | |
584 // This should only be called when we're in the SPDY_READING_COMMON_HEADER | 896 // This should only be called when we're in the SPDY_READING_COMMON_HEADER |
585 // state. | 897 // state. |
586 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); | 898 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); |
587 | 899 |
588 size_t original_len = len; | 900 size_t original_len = len; |
589 SpdyFrame current_frame(current_frame_buffer_, false); | 901 SpdyFrame current_frame(current_frame_buffer_, false); |
590 | 902 |
591 do { | 903 do { |
592 if (current_frame_len_ < SpdyFrame::size()) { | 904 if (current_frame_len_ < SpdyFrame::size()) { |
593 size_t bytes_desired = SpdyFrame::size() - current_frame_len_; | 905 size_t bytes_desired = SpdyFrame::size() - current_frame_len_; |
594 size_t bytes_to_append = std::min(bytes_desired, len); | 906 UpdateCurrentFrameBuffer(&data, &len, bytes_desired); |
595 char* header_buffer = current_frame_buffer_; | |
596 memcpy(&header_buffer[current_frame_len_], data, bytes_to_append); | |
597 current_frame_len_ += bytes_to_append; | |
598 data += bytes_to_append; | |
599 len -= bytes_to_append; | |
600 // Check for an empty data frame. | 907 // Check for an empty data frame. |
601 if (current_frame_len_ == SpdyFrame::size() && | 908 if (current_frame_len_ == SpdyFrame::size() && |
602 !current_frame.is_control_frame() && | 909 !current_frame.is_control_frame() && |
603 current_frame.length() == 0) { | 910 current_frame.length() == 0) { |
604 if (current_frame.flags() & CONTROL_FLAG_FIN) { | 911 if (current_frame.flags() & CONTROL_FLAG_FIN) { |
605 SpdyDataFrame data_frame(current_frame_buffer_, false); | 912 SpdyDataFrame data_frame(current_frame_buffer_, false); |
606 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); | 913 visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); |
607 } | 914 } |
608 CHANGE_STATE(SPDY_AUTO_RESET); | 915 CHANGE_STATE(SPDY_AUTO_RESET); |
609 } | 916 } |
610 break; | 917 break; |
611 } | 918 } |
612 remaining_payload_ = current_frame.length(); | 919 remaining_data_ = current_frame.length(); |
613 | 920 |
614 // This is just a sanity check for help debugging early frame errors. | 921 // This is just a sanity check for help debugging early frame errors. |
615 if (remaining_payload_ > 1000000u) { | 922 if (remaining_data_ > 1000000u) { |
616 LOG(WARNING) << | 923 LOG(WARNING) << |
617 "Unexpectedly large frame. Spdy session is likely corrupt."; | 924 "Unexpectedly large frame. Spdy session is likely corrupt."; |
618 } | 925 } |
619 | 926 |
620 // if we're here, then we have the common header all received. | 927 // if we're here, then we have the common header all received. |
621 if (!current_frame.is_control_frame()) | 928 if (!current_frame.is_control_frame()) |
622 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); | 929 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); |
623 else | 930 else |
624 CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER); | 931 CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER); |
625 } while (false); | 932 } while (false); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
663 case RST_STREAM: | 970 case RST_STREAM: |
664 if (current_control_frame.length() != | 971 if (current_control_frame.length() != |
665 SpdyRstStreamControlFrame::size() - SpdyFrame::size()) | 972 SpdyRstStreamControlFrame::size() - SpdyFrame::size()) |
666 set_error(SPDY_INVALID_CONTROL_FRAME); | 973 set_error(SPDY_INVALID_CONTROL_FRAME); |
667 break; | 974 break; |
668 case SETTINGS: | 975 case SETTINGS: |
669 if (current_control_frame.length() < | 976 if (current_control_frame.length() < |
670 SpdySettingsControlFrame::size() - SpdyControlFrame::size()) | 977 SpdySettingsControlFrame::size() - SpdyControlFrame::size()) |
671 set_error(SPDY_INVALID_CONTROL_FRAME); | 978 set_error(SPDY_INVALID_CONTROL_FRAME); |
672 break; | 979 break; |
980 // TODO(hkhalil): Remove NOOP. | |
673 case NOOP: | 981 case NOOP: |
674 // NOOP. Swallow it. | 982 // NOOP. Swallow it. |
983 DLOG(INFO) << "Attempted frame size validation for NOOP. Resetting."; | |
675 CHANGE_STATE(SPDY_AUTO_RESET); | 984 CHANGE_STATE(SPDY_AUTO_RESET); |
676 return; | 985 return; |
677 case GOAWAY: | 986 case GOAWAY: |
678 if (current_control_frame.length() != | 987 if (current_control_frame.length() != |
679 SpdyGoAwayControlFrame::size() - SpdyFrame::size()) | 988 SpdyGoAwayControlFrame::size() - SpdyFrame::size()) |
680 set_error(SPDY_INVALID_CONTROL_FRAME); | 989 set_error(SPDY_INVALID_CONTROL_FRAME); |
681 break; | 990 break; |
682 case HEADERS: | 991 case HEADERS: |
683 if (current_control_frame.length() < | 992 if (current_control_frame.length() < |
684 SpdyHeadersControlFrame::size() - SpdyControlFrame::size()) | 993 SpdyHeadersControlFrame::size() - SpdyControlFrame::size()) |
685 set_error(SPDY_INVALID_CONTROL_FRAME); | 994 set_error(SPDY_INVALID_CONTROL_FRAME); |
686 break; | 995 break; |
687 case WINDOW_UPDATE: | 996 case WINDOW_UPDATE: |
688 if (current_control_frame.length() != | 997 if (current_control_frame.length() != |
689 SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size()) | 998 SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size()) |
690 set_error(SPDY_INVALID_CONTROL_FRAME); | 999 set_error(SPDY_INVALID_CONTROL_FRAME); |
691 break; | 1000 break; |
1001 case PING: | |
1002 if (current_control_frame.length() != | |
1003 SpdyPingControlFrame::size() - SpdyControlFrame::size()) | |
1004 set_error(SPDY_INVALID_CONTROL_FRAME); | |
1005 break; | |
692 default: | 1006 default: |
693 LOG(WARNING) << "Valid spdy control frame with unknown type: " | 1007 LOG(WARNING) << "Valid spdy control frame with unhandled type: " |
694 << current_control_frame.type(); | 1008 << current_control_frame.type(); |
695 DCHECK(false); | 1009 DCHECK(false); |
696 set_error(SPDY_INVALID_CONTROL_FRAME); | 1010 set_error(SPDY_INVALID_CONTROL_FRAME); |
697 break; | 1011 break; |
698 } | 1012 } |
699 | 1013 |
700 remaining_control_payload_ = current_control_frame.length(); | 1014 remaining_control_payload_ = current_control_frame.length(); |
701 if (remaining_control_payload_ > kControlFrameBufferMaxSize) { | 1015 if (remaining_control_payload_ > kControlFrameBufferMaxSize) { |
702 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 1016 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
703 return; | 1017 return; |
704 } | 1018 } |
705 | 1019 |
706 ExpandControlFrameBuffer(remaining_control_payload_); | 1020 ExpandControlFrameBuffer(remaining_control_payload_); |
707 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); | 1021 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); |
708 } | 1022 } |
709 | 1023 |
710 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { | 1024 size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { |
711 size_t original_len = len; | 1025 size_t original_len = len; |
712 do { | 1026 do { |
713 if (remaining_control_payload_) { | 1027 if (remaining_control_payload_) { |
714 size_t amount_to_consume = std::min(remaining_control_payload_, len); | 1028 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
715 memcpy(¤t_frame_buffer_[current_frame_len_], data, | 1029 remaining_control_payload_); |
716 amount_to_consume); | 1030 remaining_control_payload_ -= bytes_read; |
717 current_frame_len_ += amount_to_consume; | 1031 remaining_data_ -= bytes_read; |
718 data += amount_to_consume; | |
719 len -= amount_to_consume; | |
720 remaining_control_payload_ -= amount_to_consume; | |
721 remaining_payload_ -= amount_to_consume; | |
722 if (remaining_control_payload_) | 1032 if (remaining_control_payload_) |
723 break; | 1033 break; |
724 } | 1034 } |
725 SpdyControlFrame control_frame(current_frame_buffer_, false); | 1035 SpdyControlFrame control_frame(current_frame_buffer_, false); |
726 visitor_->OnControl(&control_frame); | 1036 visitor_->OnControl(&control_frame); |
727 | 1037 |
728 // If this is a FIN, tell the caller. | 1038 // If this is a FIN, tell the caller. |
729 if (control_frame.type() == SYN_REPLY && | 1039 if (control_frame.type() == SYN_REPLY && |
730 control_frame.flags() & CONTROL_FLAG_FIN) { | 1040 control_frame.flags() & CONTROL_FLAG_FIN) { |
731 visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>( | 1041 visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>( |
732 &control_frame)->stream_id(), | 1042 &control_frame)->stream_id(), |
733 NULL, 0); | 1043 NULL, 0); |
734 } | 1044 } |
735 | 1045 |
736 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); | 1046 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); |
737 } while (false); | 1047 } while (false); |
738 return original_len - len; | 1048 return original_len - len; |
739 } | 1049 } |
740 | 1050 |
741 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { | 1051 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { |
742 size_t original_len = len; | 1052 size_t original_len = len; |
743 | 1053 |
744 SpdyDataFrame current_data_frame(current_frame_buffer_, false); | 1054 SpdyDataFrame current_data_frame(current_frame_buffer_, false); |
745 if (remaining_payload_) { | 1055 if (remaining_data_) { |
746 size_t amount_to_forward = std::min(remaining_payload_, len); | 1056 size_t amount_to_forward = std::min(remaining_data_, len); |
747 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { | 1057 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { |
748 if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) { | 1058 if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) { |
749 z_stream* decompressor = | 1059 z_stream* decompressor = |
750 GetStreamDecompressor(current_data_frame.stream_id()); | 1060 GetStreamDecompressor(current_data_frame.stream_id()); |
751 if (!decompressor) | 1061 if (!decompressor) |
752 return 0; | 1062 return 0; |
753 | 1063 |
754 size_t decompressed_max_size = amount_to_forward * 100; | 1064 size_t decompressed_max_size = amount_to_forward * 100; |
755 scoped_array<char> decompressed(new char[decompressed_max_size]); | 1065 scoped_array<char> decompressed(new char[decompressed_max_size]); |
756 decompressor->next_in = reinterpret_cast<Bytef*>( | 1066 decompressor->next_in = reinterpret_cast<Bytef*>( |
(...skipping 21 matching lines...) Expand all Loading... | |
778 } else { | 1088 } else { |
779 // The data frame was not compressed. | 1089 // The data frame was not compressed. |
780 // Only inform the visitor if there is data. | 1090 // Only inform the visitor if there is data. |
781 if (amount_to_forward) | 1091 if (amount_to_forward) |
782 visitor_->OnStreamFrameData(current_data_frame.stream_id(), | 1092 visitor_->OnStreamFrameData(current_data_frame.stream_id(), |
783 data, amount_to_forward); | 1093 data, amount_to_forward); |
784 } | 1094 } |
785 } | 1095 } |
786 data += amount_to_forward; | 1096 data += amount_to_forward; |
787 len -= amount_to_forward; | 1097 len -= amount_to_forward; |
788 remaining_payload_ -= amount_to_forward; | 1098 remaining_data_ -= amount_to_forward; |
789 | 1099 |
790 // If the FIN flag is set, and there is no more data in this data | 1100 // If the FIN flag is set, and there is no more data in this data |
791 // frame, inform the visitor of EOF via a 0-length data frame. | 1101 // frame, inform the visitor of EOF via a 0-length data frame. |
792 if (!remaining_payload_ && | 1102 if (!remaining_data_ && |
793 current_data_frame.flags() & DATA_FLAG_FIN) { | 1103 current_data_frame.flags() & DATA_FLAG_FIN) { |
794 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0); | 1104 visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0); |
795 CleanupDecompressorForStream(current_data_frame.stream_id()); | 1105 CleanupDecompressorForStream(current_data_frame.stream_id()); |
796 } | 1106 } |
797 } else { | 1107 } else { |
798 CHANGE_STATE(SPDY_AUTO_RESET); | 1108 CHANGE_STATE(SPDY_AUTO_RESET); |
799 } | 1109 } |
800 return original_len - len; | 1110 return original_len - len; |
801 } | 1111 } |
802 | 1112 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
906 | 1216 |
907 SpdyControlFrame* SpdyFramer::DecompressControlFrame( | 1217 SpdyControlFrame* SpdyFramer::DecompressControlFrame( |
908 const SpdyControlFrame& frame) { | 1218 const SpdyControlFrame& frame) { |
909 z_stream* decompressor = GetHeaderDecompressor(); | 1219 z_stream* decompressor = GetHeaderDecompressor(); |
910 if (!decompressor) | 1220 if (!decompressor) |
911 return NULL; | 1221 return NULL; |
912 return reinterpret_cast<SpdyControlFrame*>( | 1222 return reinterpret_cast<SpdyControlFrame*>( |
913 DecompressFrameWithZStream(frame, decompressor)); | 1223 DecompressFrameWithZStream(frame, decompressor)); |
914 } | 1224 } |
915 | 1225 |
1226 // Incrementally decompress the control frame's header block, feeding the | |
1227 // result to the visitor in chunks. Continue this until the visitor | |
1228 // indicates that it cannot process any more data, or (more commonly) we | |
1229 // run out of data to deliver. | |
1230 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | |
1231 const SpdyControlFrame* control_frame) { | |
1232 z_stream* decomp = GetHeaderDecompressor(); | |
1233 int payload_length; | |
1234 int header_length; | |
1235 const char* payload; | |
1236 bool read_successfully = true; | |
1237 bool more = true; | |
1238 char buffer[kHeaderDataChunkMaxSize]; | |
1239 | |
1240 if (!GetFrameBoundaries( | |
1241 *control_frame, &payload_length, &header_length, &payload)) { | |
1242 DLOG(ERROR) << "Control frame of type " | |
1243 << SpdyFramer::ControlTypeToString(control_frame->type()) | |
1244 <<" doesn't have headers"; | |
1245 return false; | |
1246 } | |
1247 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); | |
1248 decomp->avail_in = payload_length; | |
1249 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | |
1250 DCHECK_LT(0u, stream_id); | |
1251 while (more && read_successfully) { | |
1252 decomp->next_out = reinterpret_cast<Bytef*>(buffer); | |
1253 decomp->avail_out = arraysize(buffer); | |
1254 int rv = DecompressHeaderBlockInZStream(decomp); | |
1255 if (rv != Z_OK) { | |
1256 set_error(SPDY_DECOMPRESS_FAILURE); | |
1257 DLOG(WARNING) << "inflate failure: " << rv; | |
1258 more = read_successfully = false; | |
1259 } else { | |
1260 DCHECK_GT(arraysize(buffer), decomp->avail_out); | |
1261 size_t len = arraysize(buffer) - decomp->avail_out; | |
1262 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, buffer, | |
1263 len); | |
1264 if (!read_successfully) { | |
1265 // Assume that the problem was the header block was too large for the | |
1266 // visitor. | |
1267 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | |
1268 } | |
1269 more = decomp->avail_in > 0; | |
1270 } | |
1271 } | |
1272 return read_successfully; | |
1273 } | |
1274 | |
1275 // Incrementally decompress the control frame's header block, feeding the | |
1276 // result to the visitor in chunks. Continue this until the visitor | |
1277 // indicates that it cannot process any more data, or (more commonly) we | |
1278 // run out of data to deliver. | |
1279 bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( | |
1280 const SpdyControlFrame* control_frame, | |
1281 const char* data, | |
1282 size_t len) { | |
1283 // Get a decompressor or set error. | |
1284 z_stream* decomp = GetHeaderDecompressor(); | |
1285 if (decomp == NULL) { | |
1286 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; | |
1287 set_error(SPDY_DECOMPRESS_FAILURE); | |
1288 return false; | |
1289 } | |
1290 | |
1291 bool processed_successfully = true; | |
1292 char buffer[kHeaderDataChunkMaxSize]; | |
1293 | |
1294 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); | |
1295 decomp->avail_in = len; | |
1296 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | |
1297 DCHECK_LT(0u, stream_id); | |
1298 while (decomp->avail_in > 0 && processed_successfully) { | |
1299 decomp->next_out = reinterpret_cast<Bytef*>(buffer); | |
1300 decomp->avail_out = arraysize(buffer); | |
1301 int rv = DecompressHeaderBlockInZStream(decomp); | |
1302 if (rv != Z_OK) { | |
1303 set_error(SPDY_DECOMPRESS_FAILURE); | |
1304 DLOG(WARNING) << "inflate failure: " << rv; | |
1305 processed_successfully = false; | |
1306 } else { | |
1307 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; | |
1308 if (decompressed_len > 0) { | |
1309 processed_successfully = visitor_->OnControlFrameHeaderData( | |
1310 stream_id, buffer, decompressed_len); | |
1311 } | |
1312 if (!processed_successfully) { | |
1313 // Assume that the problem was the header block was too large for the | |
1314 // visitor. | |
1315 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | |
1316 } | |
1317 } | |
1318 } | |
1319 return processed_successfully; | |
1320 } | |
1321 | |
1322 bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( | |
1323 const SpdyControlFrame* control_frame, const char* data, size_t len) { | |
1324 bool read_successfully = true; | |
1325 const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); | |
1326 DCHECK_LT(0u, stream_id); | |
1327 while (read_successfully && len > 0) { | |
1328 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); | |
1329 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, | |
1330 bytes_to_deliver); | |
1331 data += bytes_to_deliver; | |
1332 len -= bytes_to_deliver; | |
1333 if (!read_successfully) { | |
1334 // Assume that the problem was the header block was too large for the | |
1335 // visitor. | |
1336 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | |
1337 } | |
1338 } | |
1339 return read_successfully; | |
1340 } | |
1341 | |
1342 size_t SpdyFramer::GetMinimumControlFrameSize(SpdyControlType type) { | |
1343 switch (type) { | |
1344 case SYN_STREAM: | |
1345 return SpdySynStreamControlFrame::size(); | |
1346 case SYN_REPLY: | |
1347 return SpdySynReplyControlFrame::size(); | |
1348 case RST_STREAM: | |
1349 return SpdyRstStreamControlFrame::size(); | |
1350 case SETTINGS: | |
1351 return SpdySettingsControlFrame::size(); | |
1352 case NOOP: | |
1353 return SpdyNoOpControlFrame::size(); | |
1354 case PING: | |
1355 return SpdyPingControlFrame::size(); | |
1356 case GOAWAY: | |
1357 return SpdyGoAwayControlFrame::size(); | |
1358 case HEADERS: | |
1359 return SpdyHeadersControlFrame::size(); | |
1360 case WINDOW_UPDATE: | |
1361 return SpdyWindowUpdateControlFrame::size(); | |
1362 case NUM_CONTROL_FRAME_TYPES: | |
1363 break; | |
1364 } | |
1365 LOG(ERROR) << "Unknown SPDY control frame type " << type; | |
1366 return 0x7FFFFFFF; // Max signed 32bit int | |
1367 } | |
1368 | |
1369 /* static */ | |
1370 SpdyStreamId SpdyFramer::GetControlFrameStreamId( | |
1371 const SpdyControlFrame* control_frame) { | |
1372 SpdyStreamId stream_id = kInvalidStream; | |
1373 if (control_frame != NULL) { | |
1374 switch (control_frame->type()) { | |
1375 case SYN_STREAM: | |
1376 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( | |
1377 control_frame)->stream_id(); | |
1378 break; | |
1379 case SYN_REPLY: | |
1380 stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>( | |
1381 control_frame)->stream_id(); | |
1382 break; | |
1383 case HEADERS: | |
1384 stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>( | |
1385 control_frame)->stream_id(); | |
1386 break; | |
1387 case RST_STREAM: | |
1388 stream_id = reinterpret_cast<const SpdyRstStreamControlFrame*>( | |
1389 control_frame)->stream_id(); | |
1390 break; | |
1391 case WINDOW_UPDATE: | |
1392 stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame*>( | |
1393 control_frame)->stream_id(); | |
1394 break; | |
1395 // All of the following types are not part of a particular stream. | |
1396 // They all fall through to the invalid control frame type case. | |
1397 // (The default case isn't used so that the compile will break if a new | |
1398 // control frame type is added but not included here.) | |
1399 case SETTINGS: | |
1400 case NOOP: | |
1401 case PING: | |
1402 case GOAWAY: | |
1403 case NUM_CONTROL_FRAME_TYPES: // makes compiler happy | |
1404 break; | |
1405 } | |
1406 } | |
1407 return stream_id; | |
1408 } | |
1409 | |
1410 void SpdyFramer::set_validate_control_frame_sizes(bool value) { | |
1411 validate_control_frame_sizes_ = value; | |
1412 } | |
1413 | |
916 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { | 1414 SpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { |
917 z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); | 1415 z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); |
918 if (!decompressor) | 1416 if (!decompressor) |
919 return NULL; | 1417 return NULL; |
920 return reinterpret_cast<SpdyDataFrame*>( | 1418 return reinterpret_cast<SpdyDataFrame*>( |
921 DecompressFrameWithZStream(frame, decompressor)); | 1419 DecompressFrameWithZStream(frame, decompressor)); |
922 } | 1420 } |
923 | 1421 |
924 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame, | 1422 SpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame, |
925 z_stream* compressor) { | 1423 z_stream* compressor) { |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1108 case SPDY_ERROR: | 1606 case SPDY_ERROR: |
1109 case SPDY_DONE: | 1607 case SPDY_DONE: |
1110 case SPDY_AUTO_RESET: | 1608 case SPDY_AUTO_RESET: |
1111 case SPDY_RESET: | 1609 case SPDY_RESET: |
1112 return 0; | 1610 return 0; |
1113 case SPDY_READING_COMMON_HEADER: | 1611 case SPDY_READING_COMMON_HEADER: |
1114 DCHECK_LT(current_frame_len_, SpdyFrame::size()); | 1612 DCHECK_LT(current_frame_len_, SpdyFrame::size()); |
1115 return SpdyFrame::size() - current_frame_len_; | 1613 return SpdyFrame::size() - current_frame_len_; |
1116 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: | 1614 case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: |
1117 return 0; | 1615 return 0; |
1616 // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK | |
1617 // and SPDY_CONTROL_FRAME_HEADER_BLOCK. | |
1618 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: | |
1619 case SPDY_CONTROL_FRAME_HEADER_BLOCK: | |
1620 return 0; | |
1118 case SPDY_CONTROL_FRAME_PAYLOAD: | 1621 case SPDY_CONTROL_FRAME_PAYLOAD: |
1119 case SPDY_IGNORE_REMAINING_PAYLOAD: | 1622 case SPDY_IGNORE_REMAINING_PAYLOAD: |
1120 case SPDY_FORWARD_STREAM_FRAME: | 1623 case SPDY_FORWARD_STREAM_FRAME: |
1121 return remaining_payload_; | 1624 return remaining_data_; |
1122 } | 1625 } |
1123 // We should never get to here. | 1626 // We should never get to here. |
1124 return 0; | 1627 return 0; |
1125 } | 1628 } |
1126 | 1629 |
1127 void SpdyFramer::set_error(SpdyError error) { | 1630 void SpdyFramer::set_error(SpdyError error) { |
1128 DCHECK(visitor_); | 1631 DCHECK(visitor_); |
1129 error_code_ = error; | 1632 error_code_ = error; |
1130 CHANGE_STATE(SPDY_ERROR); | 1633 CHANGE_STATE(SPDY_ERROR); |
1131 visitor_->OnError(this); | 1634 visitor_->OnError(this); |
1132 } | 1635 } |
1133 | 1636 |
1134 void SpdyFramer::ExpandControlFrameBuffer(size_t size) { | 1637 void SpdyFramer::ExpandControlFrameBuffer(size_t size) { |
1135 size_t alloc_size = size + SpdyFrame::size(); | 1638 size_t alloc_size = size + SpdyFrame::size(); |
1136 DCHECK_LT(alloc_size, kControlFrameBufferMaxSize); | 1639 DCHECK_LE(alloc_size, kControlFrameBufferMaxSize); |
1137 if (alloc_size <= current_frame_capacity_) | 1640 if (alloc_size <= current_frame_capacity_) |
1138 return; | 1641 return; |
1139 char* new_buffer = new char[alloc_size]; | 1642 char* new_buffer = new char[alloc_size]; |
1140 memcpy(new_buffer, current_frame_buffer_, current_frame_len_); | 1643 memcpy(new_buffer, current_frame_buffer_, current_frame_len_); |
1141 delete [] current_frame_buffer_; | 1644 delete [] current_frame_buffer_; |
1142 current_frame_capacity_ = alloc_size; | 1645 current_frame_capacity_ = alloc_size; |
1143 current_frame_buffer_ = new_buffer; | 1646 current_frame_buffer_ = new_buffer; |
1144 } | 1647 } |
1145 | 1648 |
1146 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame, | 1649 bool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1189 } else { | 1692 } else { |
1190 frame_size = SpdyFrame::size(); | 1693 frame_size = SpdyFrame::size(); |
1191 *header_length = frame_size; | 1694 *header_length = frame_size; |
1192 *payload_length = frame.length(); | 1695 *payload_length = frame.length(); |
1193 *payload = frame.data() + SpdyFrame::size(); | 1696 *payload = frame.data() + SpdyFrame::size(); |
1194 } | 1697 } |
1195 return true; | 1698 return true; |
1196 } | 1699 } |
1197 | 1700 |
1198 } // namespace spdy | 1701 } // namespace spdy |
OLD | NEW |