15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/valgrind/memcheck.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_bitmasks.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/zlib.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using base::StringPiece; 1723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)using std::string; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compute the id of our dictionary so that we know we're using the 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right one when asked for it. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong CalculateDictionaryId(const char* dictionary, 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t dictionary_size) { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uLong initial_value = adler32(0L, Z_NULL, 0); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return adler32(initial_value, 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Check to see if the name and value of a cookie are both empty. 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool IsCookieEmpty(const base::StringPiece& cookie) { 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (cookie.size() == 0) { 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t pos = cookie.find('='); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (pos == base::StringPiece::npos) { 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Ignore leading whitespaces of cookie value. 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t value_start = pos + 1; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (; value_start < cookie.size(); value_start++) { 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!(cookie[value_start] == ' ' || cookie[value_start] == '\t')) { 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break; 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (pos == 0) && ((cookie.size() - value_start) == 0); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DictionaryIds { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryIds() 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)), 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uLong v2_dictionary_id; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uLong v3_dictionary_id; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adler ID for the SPDY header compressor dictionaries. Note that they are 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized lazily to avoid static initializers. 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to indicate no flags in a SPDY flags field. 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8 kNoFlags = 0; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Wire sizes of priority payloads. 70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kPriorityDependencyPayloadSize = 4; 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const size_t kPriorityWeightPayloadSize = 1; 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// calculation details. 8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 19; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate) \ 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Changing state from: " \ 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << StateToString(state_) \ 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << " to " << StateToString(newstate) << "\n"; \ 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate) \ 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSettingsFlagsAndId SettingsFlagsAndId::FromWireFormat( 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyMajorVersion version, uint32 wire) { 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (version < SPDY3) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : flags_(flags), id_(id & 0x00ffffff) { 1134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch LOG_IF(DFATAL, id > (1u << 24)) << "SPDY setting ID too large: " << id; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuuint32 SettingsFlagsAndId::GetWireFormat(SpdyMajorVersion version) 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); 1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (version < SPDY3) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wire; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// little-endian and big-endian hosts. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa). 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* wire_array = reinterpret_cast<uint8*>(val); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[0], wire_array[3]); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[1], wire_array[2]); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); } 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyAltSvcScratch::~SpdyAltSvcScratch() {} 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data, 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t len) { 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool SpdyFramerVisitorInterface::OnRstStreamFrameData( 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const char* rst_stream_data, 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t len) { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SpdyFramer::SpdyFramer(SpdyMajorVersion version) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : current_frame_buffer_(new char[kControlFrameBufferSize]), 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_compression_(true), 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_(NULL), 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) debug_visitor_(NULL), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_protocol_("SPDY"), 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_version_(version), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_(false), 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) probable_http_response_(false), 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_(0), 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) end_stream_when_done_(false) { 16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); 16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_compressor_.get()) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deflateEnd(header_compressor_.get()); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_decompressor_.get()) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inflateEnd(header_decompressor_.get()); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = SPDY_RESET; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = SPDY_RESET; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code_ = SPDY_NO_ERROR; 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = 0; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ = 0; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_ = 0; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) current_frame_type_ = DATA; 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_flags_ = 0; 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_length_ = 0; 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_ = kInvalidStream; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.Reset(); 187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.Reset(); 1884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch remaining_padding_payload_length_ = 0; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const { 19203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return SpdyConstants::GetDataFrameMinimumSize(protocol_version()); 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size, in bytes, of the control frame header. 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const { 1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return SpdyConstants::GetControlFrameHeaderSize(protocol_version()); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynStreamMinimumSize() const { 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SYN_STREAM frame not including the variable-length 20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 2034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // control frame header + 2 * 4 (stream IDs) + 1 (priority) 2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // + 1 (unused, was credential slot) 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 10; 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetControlFrameHeaderSize() + 210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityDependencyPayloadSize + 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityWeightPayloadSize; 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynReplyMinimumSize() const { 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SYN_REPLY frame not including the variable-length 21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size = GetControlFrameHeaderSize(); 2194ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream IDs) 22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size += 4; 22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In SPDY 2, there were 2 unused bytes before payload. 2264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() < SPDY3) { 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 2; 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::GetRstStreamMinimumSize() const { 23490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Size, in bytes, of a RST_STREAM frame. 2354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 23790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream id) + 4 (status code) 23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 8; 23990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 24090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 24190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // frame prefix + 4 (status code) 24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 24390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSettingsMinimumSize() const { 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SETTINGS frame not including the IDs and values 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from the variable-length value block. Calculated as: 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // control frame header + 4 (number of ID/value pairs) 2504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 251a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetControlFrameHeaderSize() + 4; 252a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 253a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetControlFrameHeaderSize(); 254a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetPingSize() const { 2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Size, in bytes, of this PING frame. 2594ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Calculated as: 2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // control frame header + 4 (id) 2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetControlFrameHeaderSize() + 4; 2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Calculated as: 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // control frame header + 8 (id) 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return GetControlFrameHeaderSize() + 8; 2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::GetGoAwayMinimumSize() const { 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of this GOAWAY frame. Calculated as: 2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 1. Control frame header size 2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t size = GetControlFrameHeaderSize(); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 2. Last good stream id (4 bytes) 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size += 4; 2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // 3. SPDY 3+ GOAWAY frames also contain a status (4 bytes) 2795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (protocol_version() >= SPDY3) { 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 4; 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetHeadersMinimumSize() const { 2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Size, in bytes, of a HEADERS frame not including the variable-length 28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size = GetControlFrameHeaderSize(); 2904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream IDs) 29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size += 4; 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In SPDY 2, there were 2 unused bytes before payload. 2974ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 2; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetWindowUpdateSize() const { 30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Size, in bytes, of a WINDOW_UPDATE frame. 3064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream id) + 4 (delta) 30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 8; 31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 31190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // frame prefix + 4 (delta) 31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t SpdyFramer::GetBlockedSize() const { 3185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_LT(SPDY3, protocol_version()); 319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Size, in bytes, of a BLOCKED frame. 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The BLOCKED frame has no payload beyond the control frame header. 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return GetControlFrameHeaderSize(); 322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t SpdyFramer::GetPushPromiseMinimumSize() const { 3255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_LT(SPDY3, protocol_version()); 3267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block. 3277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Calculated as frame prefix + 4 (promised stream id). 3287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return GetControlFrameHeaderSize() + 4; 3297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 3307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetContinuationMinimumSize() const { 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Size, in bytes, of a CONTINUATION frame not including the variable-length 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // headers fragments. 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetControlFrameHeaderSize(); 335a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 337cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetAltSvcMinimumSize() const { 338cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and 339cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // (optional) Origin fields, all of which can vary in length. 340cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Note that this gives a lower bound on the frame size rather than a true 341cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // minimum; the actual frame should always be larger than this. 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte) 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // + 1 (pid_len) + 1 (host_len). 344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetControlFrameHeaderSize() + 9; 345cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::GetPrioritySize() const { 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Size, in bytes, of a PRIORITY frame. 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return GetControlFrameHeaderSize() + 350cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityDependencyPayloadSize + 351cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityWeightPayloadSize; 352cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMinimumSize() const { 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMaximumSize() const { 3595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return SpdyConstants::GetFrameMaximumSize(protocol_version()); 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMaximumPayload() const { 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetFrameMaximumSize() - GetDataFrameMinimumSize(); 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetPrefixLength(SpdyFrameType type) const { 3675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return SpdyConstants::GetPrefixLength(type, protocol_version()); 3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 3695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StateToString(int state) { 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ERROR: 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "ERROR"; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_AUTO_RESET: 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "AUTO_RESET"; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_RESET: 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "RESET"; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_READING_COMMON_HEADER: 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "READING_COMMON_HEADER"; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_PAYLOAD: 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CONTROL_FRAME_PAYLOAD"; 3824ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch case SPDY_READ_PADDING_LENGTH: 3834ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return "SPDY_READ_PADDING_LENGTH"; 3844ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch case SPDY_CONSUME_PADDING: 3854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return "SPDY_CONSUME_PADDING"; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_IGNORE_REMAINING_PAYLOAD: 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "IGNORE_REMAINING_PAYLOAD"; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_FORWARD_STREAM_FRAME: 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FORWARD_STREAM_FRAME"; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_HEADER_BLOCK: 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SPDY_GOAWAY_FRAME_PAYLOAD: 3955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "SPDY_GOAWAY_FRAME_PAYLOAD"; 3965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SPDY_RST_STREAM_FRAME_PAYLOAD: 3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return "SPDY_RST_STREAM_FRAME_PAYLOAD"; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_SETTINGS_FRAME_PAYLOAD: 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_SETTINGS_FRAME_PAYLOAD"; 400cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case SPDY_ALTSVC_FRAME_PAYLOAD: 401cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return "SPDY_ALTSVC_FRAME_PAYLOAD"; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_STATE"; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::set_error(SpdyError error) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visitor_); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code_ = error; 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // These values will usually get reset once we come to the end 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // of a header block, but if we run into an error that 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // might not happen, so reset them here. 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_ = 0; 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) end_stream_when_done_ = false; 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_ERROR); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnError(this); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::ErrorCodeToString(int error_code) { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error_code) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_NO_ERROR: 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "NO_ERROR"; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_INVALID_CONTROL_FRAME: 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_CONTROL_FRAME"; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_PAYLOAD_TOO_LARGE: 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CONTROL_PAYLOAD_TOO_LARGE"; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ZLIB_INIT_FAILURE: 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "ZLIB_INIT_FAILURE"; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_UNSUPPORTED_VERSION: 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNSUPPORTED_VERSION"; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_DECOMPRESS_FAILURE: 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "DECOMPRESS_FAILURE"; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_COMPRESS_FAILURE: 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "COMPRESS_FAILURE"; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_INVALID_DATA_FRAME_FLAGS: 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_INVALID_DATA_FRAME_FLAGS"; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SPDY_INVALID_CONTROL_FRAME_FLAGS: 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "SPDY_INVALID_CONTROL_FRAME_FLAGS"; 439a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case SPDY_UNEXPECTED_FRAME: 440a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return "UNEXPECTED_FRAME"; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_ERROR"; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StatusCodeToString(int status_code) { 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status_code) { 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID: 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID"; 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_PROTOCOL_ERROR: 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "PROTOCOL_ERROR"; 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID_STREAM: 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_STREAM"; 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_REFUSED_STREAM: 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "REFUSED_STREAM"; 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_UNSUPPORTED_VERSION: 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNSUPPORTED_VERSION"; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_CANCEL: 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CANCEL"; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INTERNAL_ERROR: 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INTERNAL_ERROR"; 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_FLOW_CONTROL_ERROR: 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FLOW_CONTROL_ERROR"; 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_STREAM_IN_USE: 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "STREAM_IN_USE"; 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_STREAM_ALREADY_CLOSED: 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "STREAM_ALREADY_CLOSED"; 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID_CREDENTIALS: 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_CREDENTIALS"; 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_FRAME_TOO_LARGE: 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FRAME_TOO_LARGE"; 4715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case RST_STREAM_CONNECT_ERROR: 4725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return "CONNECT_ERROR"; 4735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case RST_STREAM_ENHANCE_YOUR_CALM: 4745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return "ENHANCE_YOUR_CALM"; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_STATUS"; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DATA: 482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return "DATA"; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SYN_STREAM"; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SYN_REPLY"; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RST_STREAM: 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "RST_STREAM"; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SETTINGS"; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PING: 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "PING"; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GOAWAY: 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "GOAWAY"; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "HEADERS"; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINDOW_UPDATE: 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "WINDOW_UPDATE"; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CREDENTIAL: 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CREDENTIAL"; 5017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 5027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return "PUSH_PROMISE"; 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case CONTINUATION: 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return "CONTINUATION"; 505cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PRIORITY: 506cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return "PRIORITY"; 50703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case ALTSVC: 50803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return "ALTSVC"; 50903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) case BLOCKED: 51003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return "BLOCKED"; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_CONTROL_TYPE"; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visitor_); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state_) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ERROR: 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bottom; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_AUTO_RESET: 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_RESET: 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reset(); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > 0) { 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_READING_COMMON_HEADER); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_READING_COMMON_HEADER: { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessCommonHeader(data, len); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 5427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Control frames that contain header blocks 543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE, CONTINUATION) 5447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // take a different path through the state machine - they 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will go: 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SETTINGS frames take a slightly modified route: 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. SPDY_SETTINGS_FRAME_PAYLOAD 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All other control frames will use the alternate route directly to 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SPDY_CONTROL_FRAME_PAYLOAD 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_SETTINGS_FRAME_PAYLOAD: { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = ProcessSettingsFramePayload(data, len); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 56923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) int bytes_read = ProcessControlFrameHeaderBlock( 5704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch data, len, protocol_version() > SPDY3); 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SPDY_RST_STREAM_FRAME_PAYLOAD: { 5775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t bytes_read = ProcessRstStreamFramePayload(data, len); 5785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) len -= bytes_read; 5795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) data += bytes_read; 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) break; 5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 5825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 5835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SPDY_GOAWAY_FRAME_PAYLOAD: { 5845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t bytes_read = ProcessGoAwayFramePayload(data, len); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 590cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case SPDY_ALTSVC_FRAME_PAYLOAD: { 591cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t bytes_read = ProcessAltSvcFramePayload(data, len); 592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len -= bytes_read; 593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data += bytes_read; 594cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_PAYLOAD: { 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessControlFramePayload(data, len); 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch case SPDY_READ_PADDING_LENGTH: { 6054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t bytes_read = ProcessFramePaddingLength(data, len); 6064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch len -= bytes_read; 6074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch data += bytes_read; 6084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch break; 6094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 6104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 6114ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch case SPDY_CONSUME_PADDING: { 6124ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t bytes_read = ProcessFramePadding(data, len); 6134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch len -= bytes_read; 6144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch data += bytes_read; 6154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch break; 6164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 6174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 6185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu case SPDY_IGNORE_REMAINING_PAYLOAD: { 6195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t bytes_read = ProcessIgnoredControlFramePayload(/*data,*/ len); 6205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu len -= bytes_read; 6215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu data += bytes_read; 6225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu break; 6235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 6245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_FORWARD_STREAM_FRAME: { 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessDataFramePayload(data, len); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Invalid value for " << display_protocol_ 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " framer state: " << state_; 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This ensures that we don't infinite-loop if state_ gets an 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalid value somehow, such as due to a SpdyFramer getting deleted 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from a callback it calls. 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bottom; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (state_ != previous_state_); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom: 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(len == 0 || state_ == SPDY_ERROR); 6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ == 0 && 6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ == 0 && 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ == 0) { 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "State: " << StateToString(state_); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should only be called when we're in the SPDY_READING_COMMON_HEADER 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // state. 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update current frame buffer as needed. 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bytes_desired = 6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetControlFrameHeaderSize() - current_frame_buffer_length_; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Not enough information to do anything meaningful. 6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return original_len - len; 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Using a scoped_ptr here since we may need to create a new SpdyFrameReader 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when processing DATA frames below. 6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrameReader> reader( 6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SpdyFrameReader(current_frame_buffer_.get(), 6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_)); 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16 version = 0; 6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_control_frame = false; 6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 681116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint16 control_frame_type_field = 682116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SpdyConstants::DataFrameType(protocol_version()); 683c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader() will set current_frame_type_ to the 684c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // correct value if this is a valid control frame. 685c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) current_frame_type_ = DATA; 6864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool successful_read = reader->ReadUInt16(&version); 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_control_frame = (version & kControlFlagMask) != 0; 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version &= ~kControlFlagMask; // Only valid for control frames. 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_control_frame) { 6925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // We check version before we check validity: version can never be 6935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // 'invalid', it can only be unsupported. 6945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (version < SpdyConstants::SerializeMajorVersion(SPDY_MIN_VERSION) || 6955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu version > SpdyConstants::SerializeMajorVersion(SPDY_MAX_VERSION) || 6965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyConstants::ParseMajorVersion(version) != protocol_version()) { 6975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Version does not match the version the framer was initialized with. 6985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DVLOG(1) << "Unsupported SPDY version " 6995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << version 7005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << " (expected " << protocol_version() << ")"; 7015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu set_error(SPDY_UNSUPPORTED_VERSION); 7025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return 0; 7035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 7045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Convert version from wire format to SpdyMajorVersion. 7055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu version = SpdyConstants::ParseMajorVersion(version); 7065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 707c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We check control_frame_type_field's validity in 708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader(). 709c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successful_read = reader->ReadUInt16(&control_frame_type_field); 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader->Rewind(); 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt8(¤t_frame_flags_); 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 length_field = 0; 7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt24(&length_field); 7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = length_field; 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version = protocol_version(); 72603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) uint32 length_field = 0; 72703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool successful_read = reader->ReadUInt24(&length_field); 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint8 control_frame_type_field_uint8 = 731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SpdyConstants::DataFrameType(protocol_version()); 732c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 734c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We check control_frame_type_field's validity in 735c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader(). 736c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) control_frame_type_field = control_frame_type_field_uint8; 737116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch is_control_frame = (protocol_version() > SPDY3) ? 73803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) control_frame_type_field != 73903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SpdyConstants::SerializeFrameType(protocol_version(), DATA) : 74003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) control_frame_type_field != 0; 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (is_control_frame) { 7434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_length_ = length_field + GetControlFrameHeaderSize(); 7444ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else { 7454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_length_ = length_field + GetDataFrameMinimumSize(); 7464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 7474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt8(¤t_frame_flags_); 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 75290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(successful_read); 75390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); 755a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 756a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Before we accept a DATA frame, we need to make sure we're not in the 757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // middle of processing a header block. 7584ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const bool is_continuation_frame = (control_frame_type_field == 7594ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch SpdyConstants::SerializeFrameType(protocol_version(), CONTINUATION)); 7604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if ((expect_continuation_ != 0) != is_continuation_frame) { 7614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (expect_continuation_ != 0) { 7624ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DLOG(ERROR) << "The framer was expecting to receive a CONTINUATION " 7634ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch << "frame, but instead received frame type " 7644ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch << control_frame_type_field; 7654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else { 7664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DLOG(ERROR) << "The framer received an unexpected CONTINUATION frame."; 7674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 768a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_UNEXPECTED_FRAME); 769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return original_len - len; 770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : GetDataFrameMinimumSize(), 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader->GetBytesConsumed()); 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(current_frame_length_, 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ + reader->GetBytesConsumed()); 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is just a sanity check for help debugging early frame errors. 7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ > 1000000u) { 7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The strncmp for 5 is safe because we only hit this point if we 7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have kMinCommonHeader (8) bytes 7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!syn_frame_processed_ && 7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) { 7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_ 7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " request"; 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) probable_http_response_ = true; 7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ 7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " session is likely corrupt."; 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if we're here, then we have the common header all received. 7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_control_frame) { 7954ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 79623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Catch bogus tests sending oversized DATA frames. 79723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK_GE(GetFrameMaximumSize(), current_frame_length_) 79823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) << "DATA frame too large for SPDY >= 4."; 79923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 80023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 8014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch uint8 valid_data_flags = 0; 8024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 803116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch valid_data_flags = 804116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DATA_FLAG_FIN | DATA_FLAG_END_SEGMENT | DATA_FLAG_PADDED; 8054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else { 8064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch valid_data_flags = DATA_FLAG_FIN; 8074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 8084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 8094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (current_frame_flags_ & ~valid_data_flags) { 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnDataFrameHeader(current_frame_stream_id_, 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_, 8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_flags_ & DATA_FLAG_FIN); 8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ > 0) { 8164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHANGE_STATE(SPDY_READ_PADDING_LENGTH); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty data frame. 8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_flags_ & DATA_FLAG_FIN) { 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData( 8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, NULL, 0, true); 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProcessControlFrameHeader(control_frame_type_field); 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_NO_ERROR, error_code_); 835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(mlavan): Either remove credential frames from the code entirely, 838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // or add them to parsing + serialization methods for SPDY3. 8394ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch // Early detection of deprecated frames that we ignore. 8404ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 8414ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (control_frame_type_field == CREDENTIAL) { 8424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_type_ = CREDENTIAL; 8434ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(SPDY3, protocol_version()); 8444ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DVLOG(1) << "CREDENTIAL control frame found. Ignoring."; 8454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 8464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return; 8474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (!SpdyConstants::IsValidFrameType(protocol_version(), 8514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch control_frame_type_field)) { 85203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (protocol_version() <= SPDY3) { 85303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DLOG(WARNING) << "Invalid control frame type " << control_frame_type_field 85403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << " (protocol version: " << protocol_version() << ")"; 85503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 85603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 85703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 85803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // In HTTP2 we ignore unknown frame types for extensibility, as long as 85903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the rest of the control frame header is valid. 86003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // We rely on the visitor to check validity of current_frame_stream_id_. 86103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool valid_stream = visitor_->OnUnknownFrame(current_frame_stream_id_, 86203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) control_frame_type_field); 86303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (valid_stream) { 86403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DVLOG(1) << "Ignoring unknown frame type."; 86503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 86603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 86703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Report an invalid frame error and close the stream if the 86803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // stream_id is not valid. 86903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DLOG(WARNING) << "Unknown control frame type " 87003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << control_frame_type_field 87103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << " received on invalid stream " 87203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) << current_frame_stream_id_; 87303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 87403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 87503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; 87603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 8775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8794ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_type_ = SpdyConstants::ParseFrameType(protocol_version(), 8804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch control_frame_type_field); 8814ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do some sanity checking on the control frame sizes and flags. 8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSynStreamMinimumSize()) { 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & 8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSynReplyMinimumSize()) { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RST_STREAM: 9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For SPDY versions < 4, the header has a fixed length. 9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For SPDY version 4 and up, the RST_STREAM frame may include optional 9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // opaque data, so we only have a lower limit on the frame size. 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((current_frame_length_ != GetRstStreamMinimumSize() && 9044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch protocol_version() <= SPDY3) || 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (current_frame_length_ < GetRstStreamMinimumSize() && 9064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch protocol_version() > SPDY3)) { 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 913a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that we have an integral number of 8-byte key/value pairs, 915a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // plus a 4-byte length field in SPDY3 and below. 9164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t values_prefix_size = (protocol_version() <= SPDY3 ? 4 : 0); 917a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Size of each key/value pair in bytes. 918116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t setting_size = SpdyConstants::GetSettingSize(protocol_version()); 9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSettingsMinimumSize() || 920a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (current_frame_length_ - GetControlFrameHeaderSize()) 921a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) % setting_size != values_prefix_size) { 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Invalid length for SETTINGS frame: " 9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_length_; 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() <= SPDY3 && 926a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_flags_ & 9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() > SPDY3 && 930a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_flags_ & ~SETTINGS_FLAG_ACK) { 931a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() > SPDY3 && 933a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_flags_ & SETTINGS_FLAG_ACK && 934a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_length_ > GetSettingsMinimumSize()) { 935a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 938a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 939ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PING: 940ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_length_ != GetPingSize()) { 941ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 9424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if ((protocol_version() <= SPDY3 && current_frame_flags_ != 0) || 943a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (current_frame_flags_ & ~PING_FLAG_ACK)) { 944ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 945ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 946ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GOAWAY: 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For SPDY version < 4, there are only mandatory fields and the header 9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // has a fixed length. For SPDY version >= 4, optional opaque data may 9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // be appended to the GOAWAY frame, thus there is only a minimal length 9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // restriction. 9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if ((current_frame_length_ != GetGoAwayMinimumSize() && 9544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch protocol_version() <= SPDY3) || 9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (current_frame_length_ < GetGoAwayMinimumSize() && 9564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch protocol_version() > SPDY3)) { 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t min_size = GetHeadersMinimumSize(); 9664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && 9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (current_frame_flags_ & HEADERS_FLAG_PRIORITY)) { 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) min_size += 4; 9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_frame_length_ < min_size) { 97103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // TODO(mlavan): check here for HEADERS with no payload? 97203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // (not allowed in SPDY4) 9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() <= SPDY3 && 9755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_flags_ & ~CONTROL_FLAG_FIN) { 9765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 977cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (protocol_version() > SPDY3 && 978cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_flags_ & 979cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY | 980cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT | 981116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HEADERS_FLAG_PADDED)) { 9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINDOW_UPDATE: 9872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ != GetWindowUpdateSize()) { 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 993868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case BLOCKED: 994cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_length_ != GetBlockedSize() || 995cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protocol_version() <= SPDY3) { 996868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 997868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (current_frame_flags_ != 0) { 998868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 999868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1000868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 10017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 10027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (current_frame_length_ < GetPushPromiseMinimumSize()) { 10037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 10044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) { 1005a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 1006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (protocol_version() > SPDY3 && 1007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_flags_ & 1008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE | 1009116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch HEADERS_FLAG_PADDED)) { 1010a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 1011a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1012a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 1013a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case CONTINUATION: 10145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (current_frame_length_ < GetContinuationMinimumSize() || 10155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protocol_version() <= SPDY3) { 1016a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 1017116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) { 1018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 1019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 1021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case ALTSVC: 1022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_length_ <= GetAltSvcMinimumSize()) { 1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 1024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (current_frame_flags_ != 0) { 1025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 1026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 1028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PRIORITY: 1029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_length_ != GetPrioritySize() || 1030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) protocol_version() <= SPDY3) { 1031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 1032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (current_frame_flags_ != 0) { 10337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 10347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 10357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Valid " << display_protocol_ 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " control frame with unhandled type: " 10392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_type_; 10402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This branch should be unreachable because of the frame type bounds 10412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // check above. However, we DLOG(FATAL) here in an effort to painfully 10422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // club the head of the developer who failed to keep this file in sync 10432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // with spdy_protocol.h. 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(FATAL); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == SPDY_ERROR) { 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ > GetControlFrameBufferMaxSize()) { 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Received control frame with way too big of a payload: " 10552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_length_; 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_frame_type_ == GOAWAY) { 10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHANGE_STATE(SPDY_GOAWAY_FRAME_PAYLOAD); 10625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 10645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_frame_type_ == RST_STREAM) { 10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHANGE_STATE(SPDY_RST_STREAM_FRAME_PAYLOAD); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_type_ == ALTSVC) { 1071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD); 1072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 1073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the frame size without variable-length data. 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 frame_size_without_variable_data; 10762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_ = true; 10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSynStreamMinimumSize(); 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_ = true; 10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSynReplyMinimumSize(); 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSettingsMinimumSize(); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1088ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case HEADERS: 1089ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch frame_size_without_variable_data = GetHeadersMinimumSize(); 10904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && 10914ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_flags_ & HEADERS_FLAG_PRIORITY) { 1092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame_size_without_variable_data += 1093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityDependencyPayloadSize + 1094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) kPriorityWeightPayloadSize; 10955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1096ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 10977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 10987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_size_without_variable_data = GetPushPromiseMinimumSize(); 10997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 1100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case CONTINUATION: 1101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame_size_without_variable_data = GetContinuationMinimumSize(); 1102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_size_without_variable_data = -1; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((frame_size_without_variable_data == -1) && 11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_length_ > kControlFrameBufferSize)) { 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should already be in an error state. Double-check. 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_ERROR, state_); 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ != SPDY_ERROR) { 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << display_protocol_ 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " control frame buffer too small for fixed-length frame."; 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_size_without_variable_data > 0) { 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a control frame with a header block. We need to parse the 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remainder of the control frame's header before we can parse the header 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block. The start of the header block varies with the control type. 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(frame_size_without_variable_data, 11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<int32>(current_frame_buffer_length_)); 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ = frame_size_without_variable_data - 11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_; 11287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_bytes) { 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_read = std::min(*len, max_bytes); 1139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (bytes_to_read > 0) { 1140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_GE(kControlFrameBufferSize, 1141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_ + bytes_to_read); 1142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, 1143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *data, 1144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bytes_to_read); 1145868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_ += bytes_to_read; 1146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *data += bytes_to_read; 1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *len -= bytes_to_read; 1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_to_read; 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetSerializedLength( 11535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const SpdyMajorVersion spdy_version, 11545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const SpdyHeaderBlock* headers) { 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t num_name_value_pairs_size 11565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu = (spdy_version < SPDY3) ? sizeof(uint16) : sizeof(uint32); 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t length_of_name_size = num_name_value_pairs_size; 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t length_of_value_size = num_name_value_pairs_size; 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 116023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t total_length = num_name_value_pairs_size; 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SpdyHeaderBlock::const_iterator it = headers->begin(); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != headers->end(); 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We add space for the length of the name and the length of the value as 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // well as the length of the name and the length of the value. 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_length += length_of_name_size + it->first.size() + 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_of_value_size + it->second.size(); 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return total_length; 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, 11735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const SpdyMajorVersion spdy_version, 11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeaderBlock* headers) { 11755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (spdy_version < SPDY3) { 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->WriteUInt16(headers->size()); // Number of headers. 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->WriteUInt32(headers->size()); // Number of headers. 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock::const_iterator it; 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = headers->begin(); it != headers->end(); ++it) { 11825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (spdy_version < SPDY3) { 11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteString(it->first); 11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteString(it->second); 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteStringPiece32(it->first); 11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteStringPiece32(it->second); 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Clean up after we no longer need 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to workaround http://crbug.com/139744. 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_SYSTEM_ZLIB) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These constants are used by zlib to differentiate between normal data and 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. Cookie data is handled specially by zlib when compressing. 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ZDataClass { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZStandardData is compressed normally, save that it will never match 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // against any other class of data in the window. 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZStandardData = Z_CLASS_STANDARD, 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZCookieData is compressed in its own Huffman blocks and only matches in 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // its entirety and only against other kZCookieData blocks. Any matches must 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be preceeded by a kZStandardData byte, or a semicolon to prevent matching 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prefix matches. 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZCookieData = Z_CLASS_COOKIE, 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZHuffmanOnlyData is only Huffman compressed - no matches are performed 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // against the window. 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needed when switching between classes of data. 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteZ(const base::StringPiece& data, 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZDataClass clas, 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* out) { 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv; 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are switching from standard to non-standard data then we need to end 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current Huffman context to avoid it leaking between them. 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (out->clas == kZStandardData && 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clas != kZStandardData) { 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->avail_in = 0; 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_PARTIAL_FLUSH); 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(Z_OK, rv); 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, out->avail_in); 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, out->avail_out); 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->avail_in = data.size(); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->clas = clas; 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clas == kZStandardData) { 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_NO_FLUSH); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_PARTIAL_FLUSH); 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data.empty()) { 12402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we didn't provide any data then zlib will return Z_BUF_ERROR. 12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(Z_OK, rv); 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, out->avail_in); 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, out->avail_out); 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteLengthZ(size_t n, 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned length, 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZDataClass clas, 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* out) { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[4]; 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(length, sizeof(buf)); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 1; i <= length; i++) { 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[length - i] = n; 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n >>= 8; 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(base::StringPiece(buf, length), clas, out); 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manner that resists the length of the compressed data from compromising 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* z) const { 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned length_length = 4; 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spdy_version_ < 3) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_length = 2; 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(headers->size(), length_length, kZStandardData, z); 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, std::string>::const_iterator it; 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = headers->begin(); it != headers->end(); ++it) { 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->first.size(), length_length, kZStandardData, z); 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->first, kZStandardData, z); 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first == "cookie") { 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We require the cookie values (save for the last) to end with a 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // semicolon and (save for the first) to start with a space. This is 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typically the format that we are given them in but we reserialize them 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be sure. 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<base::StringPiece> cookie_values; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t cookie_length = 0; 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece cookie_data(it->second); 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!cookie_data.empty() && 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(1); 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cookie_data.empty()) 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i; 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < cookie_data.size(); i++) { 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cookie_data[i] == ';') 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < cookie_data.size()) { 13015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!IsCookieEmpty(cookie_data.substr(0, i))) { 13025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cookie_values.push_back(cookie_data.substr(0, i)); 13035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cookie_length += i + 2 /* semicolon and space */; 13045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(i + 1); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!IsCookieEmpty(cookie_data)) { 13085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cookie_values.push_back(cookie_data); 13095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cookie_length += cookie_data.size(); 13105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } else if (cookie_length > 2) { 13115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cookie_length -= 2 /* compensate for previously added length */; 13125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(i); 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(cookie_length, length_length, kZStandardData, z); 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < cookie_values.size(); i++) { 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cookie; 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since zlib will only back-reference complete cookies, a cookie that 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is currently last (and so doesn't have a trailing semicolon) won't 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // match if it's later in a non-final position. The same is true of 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the first cookie. 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0 && cookie_values.size() == 1) { 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = cookie_values[i].as_string(); 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i == 0) { 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = cookie_values[i].as_string() + ";"; 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i < cookie_values.size() - 1) { 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = " " + cookie_values[i].as_string() + ";"; 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = " " + cookie_values[i].as_string(); 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(cookie, kZCookieData, z); 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (it->first == "accept" || 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-charset" || 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-encoding" || 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-language" || 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "host" || 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "version" || 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "method" || 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "scheme" || 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":host" || 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":version" || 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":method" || 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":scheme" || 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "user-agent") { 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->second, kZStandardData, z); 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-whitelisted headers are Huffman compressed in their own block, but 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't match against the window. 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->second, kZHuffmanOnlyData, z); 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z->avail_in = 0; 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = deflate(z, Z_SYNC_FLUSH); 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(Z_OK, rv); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z->clas = kZStandardData; 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(USE_SYSTEM_ZLIB) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len) { 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t original_len = len; 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_control_header_ > 0) { 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_); 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ -= bytes_read; 13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= bytes_read; 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_control_header_ == 0) { 13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_); 13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_GE(SPDY3, protocol_version()); 138790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool successful_read = true; 13884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 13894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK(successful_read); 1390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1391ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1393ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId associated_to_stream_id = kInvalidStream; 13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt31(&associated_to_stream_id); 13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyPriority priority = 0; 14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt8(&priority); 14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 14024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority = priority >> 6; 14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority = priority >> 5; 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Seek past unused byte; used to be credential slot in SPDY 3. 14095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reader.Seek(1); 14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(reader.IsDoneReading()); 14127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 14137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 14147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_stream_id_, 14157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_type_, 14167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_length_); 14177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnSynStream( 14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 14202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) associated_to_stream_id, 14212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority, 14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1427ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case SETTINGS: 14284ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && 14294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_flags_ & SETTINGS_FLAG_ACK) { 1430a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnSettingsAck(); 1431a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 1432a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 1433a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnSettings(current_frame_flags_ & 1434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS); 1435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); 1436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 14377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 14402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SYN_REPLY and HEADERS are the same, save for the visitor call. 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 14424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(HEADERS, current_frame_type_); 14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 144590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool successful_read = true; 14464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 144790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 144890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(successful_read); 144990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1450ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1453ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 14544ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 14552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SPDY 2 had two unused bytes here. Seek past them. 14562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader.Seek(2); 14572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14584ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && 1459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !(current_frame_flags_ & HEADERS_FLAG_END_HEADERS) && 1460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_type_ == HEADERS) { 1461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_ = current_frame_stream_id_; 1462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) end_stream_when_done_ = current_frame_flags_ & CONTROL_FLAG_FIN; 1463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 14645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const bool has_priority = 14655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (current_frame_flags_ & HEADERS_FLAG_PRIORITY) != 0; 14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 priority = 0; 14674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && has_priority) { 1468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(jgraettinger): Process dependency rather than ignoring it. 1469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reader.Seek(kPriorityDependencyPayloadSize); 1470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) uint8 weight = 0; 1471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) successful_read = reader.ReadUInt8(&weight); 1472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (successful_read) { 1473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) priority = MapWeightToPriority(weight); 1474cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 14755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(reader.IsDoneReading()); 14777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 14785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // SPDY 4 reports HEADERS with PRIORITY as SYN_STREAM. 14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyFrameType reported_type = current_frame_type_; 14804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && has_priority) { 14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reported_type = SYN_STREAM; 14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 14837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 14847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_stream_id_, 14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reported_type, 14867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_length_); 14877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 14882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ == SYN_REPLY) { 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnSynReply( 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 14912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 14924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else if (protocol_version() > SPDY3 && 14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_flags_ & HEADERS_FLAG_PRIORITY) { 14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // SPDY 4+ is missing SYN_STREAM. Simulate it so that API changes 14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // can be made independent of wire changes. 14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visitor_->OnSynStream( 14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_stream_id_, 14985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, // associated_to_stream_id 14995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) priority, 15005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_flags_ & CONTROL_FLAG_FIN, 15015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false); // unidirectional 15022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 15032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnHeaders( 15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 1505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 1506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_ == 0); 15072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1509cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHANGE_STATE(SPDY_READ_PADDING_LENGTH); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1511ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PUSH_PROMISE: 1512ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 15134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_LT(SPDY3, protocol_version()); 1514ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1515ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1516ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1517ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1518ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyStreamId promised_stream_id = kInvalidStream; 1519ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool successful_read = reader.ReadUInt31(&promised_stream_id); 1520ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1521ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1522ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (promised_stream_id == 0) { 1523ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1524ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1525ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!(current_frame_flags_ & PUSH_PROMISE_FLAG_END_PUSH_PROMISE)) { 1527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_ = current_frame_stream_id_; 1528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1529ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (debug_visitor_) { 1530ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 1531ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_stream_id_, 1532ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_type_, 1533ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_length_); 1534ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnPushPromise(current_frame_stream_id_, 1536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) promised_stream_id, 1537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (current_frame_flags_ & 1538a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0); 1539a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHANGE_STATE(SPDY_READ_PADDING_LENGTH); 1541a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 1542a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case CONTINUATION: 1543a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 1544a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Check to make sure the stream id of the current frame is 1545a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // the same as that of the preceding frame. 1546a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If we're at this point we should already know that 1547a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // expect_continuation_ != 0, so this doubles as a check 1548a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // that current_frame_stream_id != 0. 1549a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (current_frame_stream_id_ != expect_continuation_) { 1550a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 1551a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 1552a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (current_frame_flags_ & HEADERS_FLAG_END_HEADERS) { 1554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expect_continuation_ = 0; 1555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (debug_visitor_) { 1557a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) debug_visitor_->OnReceiveCompressedFrame( 1558a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_stream_id_, 1559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_type_, 1560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_length_); 1561a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1562a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnContinuation(current_frame_stream_id_, 1563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (current_frame_flags_ & 1564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) HEADERS_FLAG_END_HEADERS) != 0); 1565ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1566116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(false); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not buffer the control payload. Instead, either passes directly to the 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// visitor or decompresses and then passes directly to the visitor, via 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDeliverControlFrameHeaderData() or 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDecompressControlFrameHeaderData() respectively. 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 158023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t data_len, 158123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) bool is_hpack_header_block) { 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_successfully = true; 15852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ != SYN_STREAM && 15862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_type_ != SYN_REPLY && 1587ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_type_ != HEADERS && 1588a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_type_ != PUSH_PROMISE && 1589a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_frame_type_ != CONTINUATION) { 15902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; 15912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t process_bytes = std::min( 1593cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data_len, remaining_data_length_ - remaining_padding_payload_length_); 159423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (is_hpack_header_block) { 1595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!GetHpackDecoder()->HandleControlFrameHeadersData( 1596cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_stream_id_, data, process_bytes)) { 159723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // TODO(jgraettinger): Finer-grained HPACK error codes. 159823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 159923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) processed_successfully = false; 160023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 160123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else if (process_bytes > 0) { 16024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (enable_compression_ && protocol_version() <= SPDY3) { 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = IncrementallyDecompressControlFrameHeaderData( 16042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, process_bytes); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = IncrementallyDeliverControlFrameHeaderData( 16072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, process_bytes); 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 161023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) remaining_data_length_ -= process_bytes; 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle the case that there is no futher data in this frame. 1613cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (remaining_data_length_ == remaining_padding_payload_length_ && 1614cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processed_successfully) { 1615a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (expect_continuation_ == 0) { 161623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (is_hpack_header_block) { 1617cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!GetHpackDecoder()->HandleControlFrameHeadersComplete( 1618cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_stream_id_)) { 161923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 162023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) processed_successfully = false; 162123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 162223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // TODO(jgraettinger): To be removed with migration to 162323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // SpdyHeadersHandlerInterface. Serializes the HPACK block as a SPDY3 162423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // block, delivered via reentrant call to 162523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // ProcessControlFrameHeaderBlock(). 162623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DeliverHpackBlockAsSpdy3Block(); 162723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return process_bytes; 162823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 162923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 163023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // The complete header block has been delivered. We send a zero-length 163123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // OnControlFrameHeaderData() to indicate this. 163223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); 163323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (processed_successfully) { 1636cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHANGE_STATE(SPDY_CONSUME_PADDING); 1637cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle error. 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processed_successfully) { 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_len; 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return amount processed. 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return process_bytes; 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_len) { 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); 16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(SETTINGS, current_frame_type_); 16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t processed_bytes = 0; 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1656116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t setting_size = SpdyConstants::GetSettingSize(protocol_version()); 1657a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loop over our incoming data. 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unprocessed_bytes > 0) { 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process up to one setting at a time. 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t processing = std::min( 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unprocessed_bytes, 1663a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static_cast<size_t>(setting_size - settings_scratch_.setting_buf_len)); 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we have a complete setting in our input. 1666a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (processing == setting_size) { 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the setting directly out of the input without buffering. 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ProcessSetting(data + processed_bytes)) { 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Continue updating settings_scratch_.setting_buf. 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data + processed_bytes, 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processing); 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.setting_buf_len += processing; 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we have a complete setting buffered. 1680a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (settings_scratch_.setting_buf_len == setting_size) { 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ProcessSetting(settings_scratch_.setting_buf)) { 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset settings_scratch_.setting_buf for our next setting. 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.setting_buf_len = 0; 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate. 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unprocessed_bytes -= processing; 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_bytes += processing; 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we're done handling this SETTINGS frame. 16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= processed_bytes; 16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ == 0) { 1698a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnSettingsEnd(); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)void SpdyFramer::DeliverHpackBlockAsSpdy3Block() { 17064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_LT(SPDY3, protocol_version()); 1707cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); 170823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1709cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block(); 171023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) if (block.empty()) { 171123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) // Special-case this to make tests happy. 171223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ProcessControlFrameHeaderBlock(NULL, 0, false); 171323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return; 171423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 171523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SpdyFrameBuilder builder( 17165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GetSerializedLength(protocol_version(), &block), 17175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SPDY3); 171823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 171923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SerializeNameValueBlockWithoutCompression(&builder, block); 172023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) scoped_ptr<SpdyFrame> frame(builder.take()); 172123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 1722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Preserve padding length, and reset it after the re-entrant call. 1723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t remaining_padding = remaining_padding_payload_length_; 1724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) remaining_padding_payload_length_ = 0; 172623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) remaining_data_length_ = frame->size(); 1727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 172823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false); 1729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) remaining_padding_payload_length_ = remaining_padding; 1731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) remaining_data_length_ = remaining_padding; 173223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)} 173323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ProcessSetting(const char* data) { 17354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch int id_field; 1736a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpdySettingsIds id; 1737a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 flags = 0; 1738a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32 value; 1739a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract fields. 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. 17424ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 1743a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); 1744a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SettingsFlagsAndId id_and_flags = 17454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch SettingsFlagsAndId::FromWireFormat(protocol_version(), id_and_flags_wire); 17464ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch id_field = id_and_flags.id(); 1747a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags = id_and_flags.flags(); 1748a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); 1749a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 1750116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch id_field = ntohs(*(reinterpret_cast<const uint16*>(data))); 1751116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch value = ntohl(*(reinterpret_cast<const uint32*>(data + 2))); 1752a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate id. 17554ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (!SpdyConstants::IsValidSettingId(protocol_version(), id_field)) { 17564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DLOG(WARNING) << "Unknown SETTINGS ID: " << id_field; 175703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (protocol_version() <= SPDY3) { 175803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 175903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } else { 176003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // In HTTP2 we ignore unknown settings for extensibility. 176103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return true; 176203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17644ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch id = SpdyConstants::ParseSettingId(protocol_version(), id_field); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 1767a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Detect duplicates. 17684ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (id <= settings_scratch_.last_setting_id) { 1769a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id 1770a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " in " << display_protocol_ << " SETTINGS frame " 1771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "(last setting id was " 1772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << settings_scratch_.last_setting_id << ")."; 1773a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) settings_scratch_.last_setting_id = id; 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Validate flags. 1778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; 1779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if ((flags & ~(kFlagsMask)) != 0) { 1780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " 1781a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << flags; 1782a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 1783a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validation succeeded. Pass on to visitor. 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnSetting(id, flags, value); 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 17935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 17945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) remaining_data_length_); 1795868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) remaining_data_length_ -= bytes_read; 1796868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (remaining_data_length_ == 0) { 1797868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 1798868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_); 1799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Skip frame header. 1800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Use frame-specific handlers. 1802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (current_frame_type_) { 1803ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PING: { 1804ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyPingId id = 0; 18054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch bool is_ack = protocol_version() > SPDY3 && 18064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch (current_frame_flags_ & PING_FLAG_ACK); 18075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool successful_read = true; 18084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 18095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 id32 = 0; 18105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) successful_read = reader.ReadUInt32(&id32); 18115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) id = id32; 18125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) successful_read = reader.ReadUInt64(&id); 18145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1817a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) visitor_->OnPing(id, is_ack); 1818ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1819ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1820ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WINDOW_UPDATE: { 1821ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32 delta_window_size = 0; 1822ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool successful_read = true; 18234ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 1824ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1825ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1826ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1827ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch successful_read = reader.ReadUInt32(&delta_window_size); 1828ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1829ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1830ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch visitor_->OnWindowUpdate(current_frame_stream_id_, 1831ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delta_window_size); 1832ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1833ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case BLOCKED: { 18354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_LT(SPDY3, protocol_version()); 1836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(reader.IsDoneReading()); 1837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) visitor_->OnBlocked(current_frame_stream_id_); 1838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 1840cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case PRIORITY: { 1841cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(SPDY3, protocol_version()); 1842116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint32 parent_stream_id; 1843116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint8 weight; 1844116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool exclusive; 1845116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool successful_read = true; 1846116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch successful_read = reader.ReadUInt32(&parent_stream_id); 1847116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(successful_read); 1848116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Exclusivity is indicated by a single bit flag. 1849116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch exclusive = (parent_stream_id >> 31) != 0; 1850116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Zero out the highest-order bit to get the parent stream id. 1851116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch parent_stream_id &= 0x7fffffff; 1852116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch successful_read = reader.ReadUInt8(&weight); 1853116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(successful_read); 1854cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(reader.IsDoneReading()); 1855116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch visitor_->OnPriority( 1856116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_frame_stream_id_, parent_stream_id, weight, exclusive); 1857cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 1858cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 1859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 1860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Unreachable. 1861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(FATAL) << "Unhandled control frame " << current_frame_type_; 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::ProcessGoAwayFramePayload(const char* data, size_t len) { 18705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len == 0) { 18715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 18725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 18735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Clamp to the actual remaining payload. 18745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len > remaining_data_length_) { 18755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) len = remaining_data_length_; 18765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 18775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t original_len = len; 18785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 18795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check if we had already read enough bytes to parse the GOAWAY header. 18805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t header_size = GetGoAwayMinimumSize(); 18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t unread_header_bytes = header_size - current_frame_buffer_length_; 18825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool already_parsed_header = (unread_header_bytes == 0); 18835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!already_parsed_header) { 18845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Buffer the new GOAWAY header bytes we got. 18855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes); 18865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 18875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do we have enough to parse the constant size GOAWAY header? 18885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_frame_buffer_length_ == header_size) { 18895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Parse out the last good stream id. 18905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 18915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_buffer_length_); 18925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 18935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 18945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(successful_read); 18955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 18965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In SPDYv3 and up, frames also specify a status code - parse it out. 18975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyGoAwayStatus status = GOAWAY_OK; 18984ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() >= SPDY3) { 18995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 status_raw = GOAWAY_OK; 19005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) successful_read = reader.ReadUInt32(&status_raw); 19015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(successful_read); 19025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (SpdyConstants::IsValidGoAwayStatus(protocol_version(), 19035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status_raw)) { 19045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status = SpdyConstants::ParseGoAwayStatus(protocol_version(), 19055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status_raw); 19065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 19075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (protocol_version() > SPDY3) { 190803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Treat unrecognized status codes as INTERNAL_ERROR as 190903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // recommended by the HTTP/2 spec. 191003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) status = GOAWAY_INTERNAL_ERROR; 19115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 19125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Finished parsing the GOAWAY header, call frame handler. 19155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visitor_->OnGoAway(current_frame_stream_id_, status); 1916ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 19175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Handle remaining data as opaque. 19205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool processed_successfully = true; 19215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len > 0) { 19225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) processed_successfully = visitor_->OnGoAwayFrameData(data, len); 19235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) remaining_data_length_ -= original_len; 19255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!processed_successfully) { 19265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_error(SPDY_GOAWAY_FRAME_CORRUPT); 19275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (remaining_data_length_ == 0) { 19285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Signal that there is not more opaque data. 19295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visitor_->OnGoAwayFrameData(NULL, 0); 19305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 19315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return original_len; 19335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 19345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) { 19365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len == 0) { 19375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 0; 19385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Clamp to the actual remaining payload. 19405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len > remaining_data_length_) { 19415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) len = remaining_data_length_; 19425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t original_len = len; 19445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Check if we had already read enough bytes to parse the fixed-length portion 19465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // of the RST_STREAM frame. 19475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const size_t header_size = GetRstStreamMinimumSize(); 19485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) size_t unread_header_bytes = header_size - current_frame_buffer_length_; 19495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool already_parsed_header = (unread_header_bytes == 0); 19505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!already_parsed_header) { 19515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Buffer the new RST_STREAM header bytes we got. 19525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, unread_header_bytes); 19535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Do we have enough to parse the constant size RST_STREAM header? 19555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (current_frame_buffer_length_ == header_size) { 19565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Parse out the last good stream id. 19575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 19585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) current_frame_buffer_length_); 19595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 19604ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 19615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 19625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(successful_read); 19635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SpdyRstStreamStatus status = RST_STREAM_INVALID; 19665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint32 status_raw = status; 19675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool successful_read = reader.ReadUInt32(&status_raw); 19685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK(successful_read); 19695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (SpdyConstants::IsValidRstStreamStatus(protocol_version(), 19705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu status_raw)) { 19715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = static_cast<SpdyRstStreamStatus>(status_raw); 19725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 19735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (protocol_version() > SPDY3) { 197403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Treat unrecognized status codes as INTERNAL_ERROR as 197503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // recommended by the HTTP/2 spec. 197603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) status = RST_STREAM_INTERNAL_ERROR; 19775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 19785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Finished parsing the RST_STREAM header, call frame handler. 19805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visitor_->OnRstStream(current_frame_stream_id_, status); 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Handle remaining data as opaque. 19855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool processed_successfully = true; 19865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (len > 0) { 19875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) processed_successfully = visitor_->OnRstStreamFrameData(data, len); 19885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) remaining_data_length_ -= original_len; 19905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!processed_successfully) { 19915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_error(SPDY_RST_STREAM_FRAME_CORRUPT); 19925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (remaining_data_length_ == 0) { 19935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Signal that there is not more opaque data. 19945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) visitor_->OnRstStreamFrameData(NULL, 0); 19955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 19965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return original_len; 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2000cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) { 2001cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (len == 0) { 2002cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 2003cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2004cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2005cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Clamp to the actual remaining payload. 2006cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len = std::min(len, remaining_data_length_); 2007cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2008cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t processed_bytes = 0; 2009cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t processing = 0; 2010cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t bytes_remaining; 2011cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) char* buffer; 2012cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t* buffer_len; 2013cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2014cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) while (len > 0) { 2015cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (altsvc_scratch_.pid_len == 0) { 2016cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The size of the frame up to the PID_LEN field. 2017cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t fixed_len_portion = GetAltSvcMinimumSize() - 1; 2018cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_remaining = fixed_len_portion - current_frame_buffer_length_; 2019cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processing = std::min(len, bytes_remaining); 2020cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Buffer the new ALTSVC bytes we got. 2021cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, processing); 2022cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Do we have enough to parse the length of the protocol id? 2024cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_buffer_length_ == fixed_len_portion) { 2025cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Parse out the max age, port, and pid_len. 2026cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 2027cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_buffer_length_); 2028cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 2029cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age); 2030cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reader.ReadUInt16(&altsvc_scratch_.port); 2031cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reader.Seek(1); // Reserved byte. 2032cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) successful_read = successful_read && 2033cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) reader.ReadUInt8(&altsvc_scratch_.pid_len); 2034cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(successful_read); 2035cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Sanity check length value. 2036cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >= 2037cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) current_frame_length_) { 2038cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 2039cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 2040cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2041cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.protocol_id.reset( 2042cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new char[size_t(altsvc_scratch_.pid_len)]); 2043cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2044cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processed_bytes += processing; 2045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 2046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) { 2047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Buffer protocol id field as in comes in. 2048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer = altsvc_scratch_.protocol_id.get(); 2049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_len = &altsvc_scratch_.pid_buf_len; 2050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len; 2051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (altsvc_scratch_.host_len == 0) { 2052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Parse out the host length. 2053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processing = 1; 2054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data); 2055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Sanity check length value. 2056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len + 2057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.host_len > current_frame_length_) { 2058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 2059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 2060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]); 2062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Once we have host length, we can also determine the origin length 2063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // by process of elimination. 2064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.origin_len = current_frame_length_ - 2065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetAltSvcMinimumSize() - 2066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.pid_len - 2067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.host_len; 2068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (altsvc_scratch_.origin_len > 0) { 2069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]); 2070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2071cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data += processing; 2072cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processed_bytes += processing; 2073cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len -= processing; 2074cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 2075cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) { 2076cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Buffer host field as it comes in. 2077cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(mlavan): check formatting for host and origin 2078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer = altsvc_scratch_.host.get(); 2079cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_len = &altsvc_scratch_.host_buf_len; 2080cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len; 2081cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 2082cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Buffer (optional) origin field as it comes in. 2083cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (altsvc_scratch_.origin_len <= 0) { 2084cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 2085cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 2086cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2087cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer = altsvc_scratch_.origin.get(); 2088cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) buffer_len = &altsvc_scratch_.origin_buf_len; 2089cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bytes_remaining = remaining_data_length_ - 2090cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processed_bytes - 2091cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.origin_buf_len; 2092cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (len > bytes_remaining) { 2093cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This is our last field; there shouldn't be any more bytes. 2094cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 2095cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 0; 2096cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2097cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2098cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2099cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Copy data bytes into the appropriate field. 2100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processing = std::min(len, bytes_remaining); 2101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) memcpy(buffer + *buffer_len, 2102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data, 2103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processing); 2104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) *buffer_len += processing; 2105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) data += processing; 2106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) processed_bytes += processing; 2107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) len -= processing; 2108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) remaining_data_length_ -= processed_bytes; 2111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (remaining_data_length_ == 0) { 2112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) visitor_->OnAltSvc(current_frame_stream_id_, 2113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.max_age, 2114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.port, 2115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StringPiece(altsvc_scratch_.protocol_id.get(), 2116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.pid_len), 2117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StringPiece(altsvc_scratch_.host.get(), 2118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.host_len), 2119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) StringPiece(altsvc_scratch_.origin.get(), 2120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc_scratch_.origin_len)); 2121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 2122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return processed_bytes; 2125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 2126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// TODO(raullenchai): ProcessFramePaddingLength should be able to deal with 2128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// HEADERS_FLAG_PADDED and PUSH_PROMISE_FLAG_PADDED as well (see b/15777051). 21294ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) { 21304ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_); 2131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(remaining_padding_payload_length_, 0u); 21324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 2134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_frame_flags_ & DATA_FLAG_PADDED) { 2135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (len != 0) { 2136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (remaining_data_length_ < 1) { 2137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 2138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 0; 2139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch remaining_padding_payload_length_ = *reinterpret_cast<const uint8*>(data); 2142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++data; 2143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch --len; 2144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch --remaining_data_length_; 2145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 2146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // We don't have the data available for parsing the pad length field. Keep 2147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // waiting. 21484ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return 0; 21494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 21504ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (remaining_padding_payload_length_ > remaining_data_length_) { 2153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 2154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return 0; 21554ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 2156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (current_frame_type_ == DATA) { 2157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 2158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 2159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(current_frame_type_ == HEADERS || 2160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_frame_type_ == PUSH_PROMISE || 2161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_frame_type_ == SYN_STREAM || 2162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch current_frame_type_ == SYN_REPLY) 2163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch << current_frame_type_; 2164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 21654ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 21664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return original_len - len; 21674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch} 21684ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 21694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) { 21704ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(SPDY_CONSUME_PADDING, state_); 21714ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 21724ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t original_len = len; 21734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (remaining_padding_payload_length_ > 0) { 21744ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_); 21754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t amount_to_discard = std::min(remaining_padding_payload_length_, len); 2176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (current_frame_type_ == DATA && amount_to_discard > 0) { 2177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // The visitor needs to know about padding so it can send window updates. 2178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Communicate the padding to the visitor through a NULL data pointer, 2179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // with a nonzero size. 21804ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch visitor_->OnStreamFrameData( 21814ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch current_frame_stream_id_, NULL, amount_to_discard, false); 21824ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 21834ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch data += amount_to_discard; 21844ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch len -= amount_to_discard; 21854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch remaining_padding_payload_length_ -= amount_to_discard; 21864ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch remaining_data_length_ -= amount_to_discard; 21875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 21884ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 21895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (remaining_data_length_ == 0) { 2190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If the FIN flag is set, or this ends a header block which set FIN, 21915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // inform the visitor of EOF via a 0-length data frame. 2192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (expect_continuation_ == 0 && 2193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 || 2194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) end_stream_when_done_)) { 2195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) end_stream_when_done_ = false; 21964ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 21974ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 21984ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHANGE_STATE(SPDY_AUTO_RESET); 21994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 22004ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return original_len - len; 22014ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch} 22024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 22034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdochsize_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 22044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t original_len = len; 22054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (remaining_data_length_ - remaining_padding_payload_length_ > 0) { 22064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch size_t amount_to_forward = std::min( 22074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch remaining_data_length_ - remaining_padding_payload_length_, len); 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only inform the visitor if there is data. 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (amount_to_forward) { 22112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData( 22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, amount_to_forward, false); 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += amount_to_forward; 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= amount_to_forward; 22172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= amount_to_forward; 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22204ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (remaining_data_length_ == remaining_padding_payload_length_) { 22214ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHANGE_STATE(SPDY_CONSUME_PADDING); 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::ProcessIgnoredControlFramePayload(/*const char* data,*/ 22275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t len) { 22285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t original_len = len; 22295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (remaining_data_length_ > 0) { 22305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t amount_to_ignore = std::min(remaining_data_length_, len); 22315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu len -= amount_to_ignore; 22325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu remaining_data_length_ -= amount_to_ignore; 22335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 22345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 22355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (remaining_data_length_ == 0) { 22365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CHANGE_STATE(SPDY_AUTO_RESET); 22375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 22385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return original_len - len; 22395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 22405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 22412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t header_length, 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock* block) const { 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyFrameReader reader(header_data, header_length); 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read number of headers. 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 num_headers; 22484ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 temp; 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reader.ReadUInt16(&temp)) { 2251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read number of headers."; 22522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_headers = temp; 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reader.ReadUInt32(&num_headers)) { 2257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read number of headers."; 22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read each header. 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 index = 0; index < num_headers; ++index) { 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece temp; 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read header name. 22674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp) 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : !reader.ReadStringPiece32(&temp)) { 2269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read header name (" << index + 1 << " of " 2270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 22712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name = temp.as_string(); 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read header value. 22764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if ((protocol_version() <= SPDY2) ? !reader.ReadStringPiece16(&temp) 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : !reader.ReadStringPiece32(&temp)) { 2278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read header value (" << index + 1 << " of " 2279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 22802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = temp.as_string(); 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure no duplicates. 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (block->find(name) != block->end()) { 2286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of " 2287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store header. 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*block)[name] = value; 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reader.GetBytesConsumed(); 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdySerializedFrame* SpdyFramer::SerializeData( 22985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const SpdyDataIR& data_ir) const { 22994ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch uint8 flags = DATA_FLAG_NONE; 23005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (data_ir.fin()) { 2301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags = DATA_FLAG_FIN; 2302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 23054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch int num_padding_fields = 0; 2306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (data_ir.padded()) { 2307116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch flags |= DATA_FLAG_PADDED; 23084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch ++num_padding_fields; 23094ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 23104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch 23114ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const size_t size_with_padding = num_padding_fields + 23125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu data_ir.data().length() + data_ir.padding_payload_len() + 23134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch GetDataFrameMinimumSize(); 23145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size_with_padding, protocol_version()); 23155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 2316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (data_ir.padded()) { 23175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); 23184ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 23195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); 23205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (data_ir.padding_payload_len() > 0) { 23215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu string padding = string(data_ir.padding_payload_len(), '0'); 23224ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch builder.WriteBytes(padding.data(), padding.length()); 23234ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 23244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(size_with_padding, builder.length()); 23254ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return builder.take(); 23264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } else { 23275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const size_t size = GetDataFrameMinimumSize() + data_ir.data().length(); 23285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 23295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 23305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteBytes(data_ir.data().data(), data_ir.data().length()); 23314ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_EQ(size, builder.length()); 23324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch return builder.take(); 23334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 2334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 2335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdySerializedFrame* SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( 23375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const SpdyDataIR& data_ir) const { 23384ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch uint8 flags = DATA_FLAG_NONE; 23395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (data_ir.fin()) { 2340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags = DATA_FLAG_FIN; 2341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 23425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 23435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t frame_size = GetDataFrameMinimumSize(); 23445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t num_padding_fields = 0; 23454ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 2346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (data_ir.padded()) { 2347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch flags |= DATA_FLAG_PADDED; 23485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ++num_padding_fields; 23494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 23505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu frame_size += num_padding_fields; 23514ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch } 2352ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(frame_size, protocol_version()); 23545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteDataFrameHeader(*this, data_ir.stream_id(), flags); 23555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (protocol_version() > SPDY3) { 2356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (data_ir.padded()) { 23575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); 23585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 23595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.OverwriteLength(*this, num_padding_fields + 23605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu data_ir.data().length() + data_ir.padding_payload_len()); 23615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 23625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.OverwriteLength(*this, data_ir.data().length()); 23635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 23645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_EQ(frame_size, builder.length()); 2365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return builder.take(); 2366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 2367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 23682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynStream( 23692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySynStreamIR& syn_stream) { 2370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_GE(SPDY3, protocol_version()); 23712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 23722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_stream.fin()) { 23732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 23742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 23752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_stream.unidirectional()) { 23765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(hkhalil): invalid for HTTP2. 23772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_UNIDIRECTIONAL; 23782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 23795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 23805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Sanitize priority. 23815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint8 priority = syn_stream.priority(); 23825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (priority > GetLowestPriority()) { 23835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DLOG(DFATAL) << "Priority out-of-bounds."; 23845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) priority = GetLowestPriority(); 23855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 23862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 2388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t size = GetSynStreamMinimumSize() + 2389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetSerializedLength(syn_stream.name_value_block()); 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 2392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); 2393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt32(syn_stream.stream_id()); 2394116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt32(syn_stream.associated_to_stream_id()); 2395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt8(priority << ((protocol_version() <= SPDY2) ? 6 : 5)); 2396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt8(0); // Unused byte where credential slot used to be. 23972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); 2398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SerializeNameValueBlock(&builder, syn_stream); 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 2401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t payload_len = 240223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetSerializedLength(protocol_version(), 240323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &(syn_stream.name_value_block())); 24047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), 24057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SYN_STREAM, 24067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 24077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 24087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 24097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 24102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynReply( 24142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySynReplyIR& syn_reply) { 2415116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_GE(SPDY3, protocol_version()); 24162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 24172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_reply.fin()) { 24182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 2422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t size = GetSynReplyMinimumSize() + 2423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetSerializedLength(syn_reply.name_value_block()); 24242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 24264ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 242790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); 242890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(syn_reply.stream_id()); 242990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 24305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, 24315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HEADERS, 24325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags, 24335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu syn_reply.stream_id()); 243490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 24354ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() < SPDY3) { 24362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt16(0); // Unused. 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); 2439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SerializeNameValueBlock(&builder, syn_reply); 24402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 2442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t payload_len = GetSerializedLength( 2443116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch protocol_version(), &(syn_reply.name_value_block())); 24447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(), 24457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SYN_REPLY, 24467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 24477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 24487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 24497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeRstStream( 24542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyRstStreamIR& rst_stream) const { 24555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // TODO(jgraettinger): For now, Chromium will support parsing RST_STREAM 24565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // payloads, but will not emit them. SPDY4 is used for draft HTTP/2, 24575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // which doesn't currently include RST_STREAM payloads. GFE flags have been 24585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // commented but left in place to simplify future patching. 24595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Compute the output buffer size, taking opaque data into account. 24605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint16 expected_length = GetRstStreamMinimumSize(); 24614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 24625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_length += rst_stream.description().size(); 24635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 24645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(expected_length, protocol_version()); 24655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 24665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Serialize the RST_STREAM frame. 24674ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 246890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, RST_STREAM, 0); 246990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(rst_stream.stream_id()); 247090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 24715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); 247290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 24735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 24742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(rst_stream.status()); 24752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In SPDY4 and up, RST_STREAM frames may also specify opaque data. 24774ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && rst_stream.description().size() > 0) { 24785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder.WriteBytes(rst_stream.description().data(), 24795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rst_stream.description().size()); 24802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 24825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(expected_length, builder.length()); 24835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return builder.take(); 24842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 24852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 24862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSettings( 24872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySettingsIR& settings) const { 24882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 2489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 24904ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 2491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (settings.clear_settings()) { 2492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 2493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 2495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (settings.is_ack()) { 2496a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags |= SETTINGS_FLAG_ACK; 2497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 24982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 24992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySettingsIR::ValueMap* values = &(settings.values()); 25002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2501116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t setting_size = SpdyConstants::GetSettingSize(protocol_version()); 25022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of this SETTINGS frame. 2503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const size_t size = GetSettingsMinimumSize() + 2504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (values->size() * setting_size); 25055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 25064ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 250790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, SETTINGS, flags); 250890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 25095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, SETTINGS, flags, 0); 251090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If this is an ACK, payload should be empty. 25134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3 && settings.is_ack()) { 2514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return builder.take(); 2515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2516a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 25174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 2518a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) builder.WriteUInt32(values->size()); 2519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 25202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); 25212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); 25222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != values->end(); 25232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 25244ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 2525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 setting_flags = 0; 2526a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it->second.persist_value) { 2527a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; 2528a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2529a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (it->second.persisted) { 2530a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) setting_flags |= SETTINGS_FLAG_PERSISTED; 2531a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 25324ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch SettingsFlagsAndId flags_and_id( 25334ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch setting_flags, 25344ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch SpdyConstants::SerializeSettingId(protocol_version(), it->first)); 2535a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); 2536a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) builder.WriteBytes(&id_and_flags_wire, 4); 2537a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 2538116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt16(SpdyConstants::SerializeSettingId(protocol_version(), 2539116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->first)); 25402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(it->second.value); 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(size, builder.length()); 25442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { 25485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(GetPingSize(), protocol_version()); 25494ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 255090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, PING, kNoFlags); 25515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder.WriteUInt32(static_cast<uint32>(ping.id())); 255290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 2553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 flags = 0; 2554a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (ping.is_ack()) { 2555a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags |= PING_FLAG_ACK; 2556a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 25575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, PING, flags, 0); 25585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder.WriteUInt64(ping.id()); 255990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 25602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetPingSize(), builder.length()); 25612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 25622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 25632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 25642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeGoAway( 25652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyGoAwayIR& goaway) const { 25665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 25675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Compute the output buffer size, take opaque data into account. 25685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint16 expected_length = GetGoAwayMinimumSize(); 25694ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 25705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) expected_length += goaway.description().size(); 25715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 25725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(expected_length, protocol_version()); 25735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 25745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Serialize the GOAWAY frame. 25754ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 257690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); 257790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 25785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, GOAWAY, 0, 0); 257990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 25805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 25815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // GOAWAY frames specify the last good stream id for all SPDY versions. 25822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(goaway.last_good_stream_id()); 25835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 25845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In SPDY3 and up, GOAWAY frames also specify the error status code. 25854ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() >= SPDY3) { 2586f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // TODO(jgraettinger): Merge back to server-side. 2587f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) builder.WriteUInt32(SpdyConstants::SerializeGoAwayStatus(protocol_version(), 2588f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) goaway.status())); 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // In SPDY4 and up, GOAWAY frames may also specify opaque data. 25924ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if ((protocol_version() > SPDY3) && (goaway.description().size() > 0)) { 25935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) builder.WriteBytes(goaway.description().data(), 25945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) goaway.description().size()); 25955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DCHECK_EQ(expected_length, builder.length()); 25985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return builder.take(); 25992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 26002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeHeaders( 26022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeadersIR& headers) { 26032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 26042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (headers.fin()) { 26052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 2608cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This will get overwritten if we overflow into a CONTINUATION frame. 2609cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) flags |= HEADERS_FLAG_END_HEADERS; 2610a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (headers.has_priority()) { 2611a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags |= HEADERS_FLAG_PRIORITY; 2612a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2613a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 261623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t size = GetHeadersMinimumSize(); 2617a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2618a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint32 priority = headers.priority(); 2619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (headers.has_priority()) { 2620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (priority > GetLowestPriority()) { 2621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DLOG(DFATAL) << "Priority out-of-bounds."; 2622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) priority = GetLowestPriority(); 2623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2624116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size += 5; 2625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 26262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) string hpack_encoding; 26284ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 26295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (enable_compression_) { 2630cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetHpackEncoder()->EncodeHeaderSet( 26315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu headers.name_value_block(), &hpack_encoding); 26325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 2633cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetHpackEncoder()->EncodeHeaderSetWithoutCompression( 26345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu headers.name_value_block(), &hpack_encoding); 26355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 263623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size += hpack_encoding.size(); 2637116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (size > GetHeaderFragmentMaxSize()) { 26385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size += GetNumberRequiredContinuationFrames(size) * 26395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GetContinuationMinimumSize(); 26405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags &= ~HEADERS_FLAG_END_HEADERS; 26415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 264223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 264323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size += GetSerializedLength(headers.name_value_block()); 264423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 264523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 26465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 26474ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 264890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, HEADERS, flags); 264990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(headers.stream_id()); 265090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 26515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, 26525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HEADERS, 26535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags, 26545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu headers.stream_id()); 265590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 26564ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 26572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt16(0); // Unused. 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); 26602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26614ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() > SPDY3) { 2662116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (headers.has_priority()) { 2663116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // TODO(jgraettinger): Plumb priorities and stream dependencies. 2664116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt32(0); // Non-exclusive bit and root stream ID. 2665116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt8(MapPriorityToWeight(priority)); 2666116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 26675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WritePayloadWithContinuation(&builder, 26685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu hpack_encoding, 26695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu headers.stream_id(), 26705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu HEADERS); 267123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 267223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) SerializeNameValueBlock(&builder, headers); 267323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 26742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 26757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 2676116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // SPDY4 uses HPACK for header compression. However, continue to 2677116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // use GetSerializedLength() for an apples-to-apples comparision of 2678116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // compression performance between HPACK and SPDY w/ deflate. 2679116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t payload_len = 268023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetSerializedLength(protocol_version(), 268123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &(headers.name_value_block())); 26827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(headers.stream_id(), 26837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HEADERS, 26847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 26857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 26867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 26877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 26882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( 26922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyWindowUpdateIR& window_update) const { 26935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(GetWindowUpdateSize(), protocol_version()); 26944ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY3) { 269590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); 269690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(window_update.stream_id()); 269790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 26985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, 26995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu WINDOW_UPDATE, 27005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kNoFlags, 27015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu window_update.stream_id()); 270290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 27032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(window_update.delta()); 27042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetWindowUpdateSize(), builder.length()); 27052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 27062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 27072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 27085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuSpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { 27095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_LT(SPDY3, protocol_version()); 27105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(GetBlockedSize(), protocol_version()); 27115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); 27125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return builder.take(); 27135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 27145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 27157dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::SerializePushPromise( 27167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SpdyPushPromiseIR& push_promise) { 27174ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch DCHECK_LT(SPDY3, protocol_version()); 2718a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 flags = 0; 2719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // This will get overwritten if we overflow into a CONTINUATION frame. 2720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 27217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The size of this frame, including variable-length name-value block. 272223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t size = GetPushPromiseMinimumSize(); 272323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 272423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) string hpack_encoding; 2725116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (enable_compression_) { 2726116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetHpackEncoder()->EncodeHeaderSet( 2727116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch push_promise.name_value_block(), &hpack_encoding); 272823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 2729116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetHpackEncoder()->EncodeHeaderSetWithoutCompression( 2730116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch push_promise.name_value_block(), &hpack_encoding); 2731116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2732116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size += hpack_encoding.size(); 2733116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (size > GetHeaderFragmentMaxSize()) { 2734116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size += GetNumberRequiredContinuationFrames(size) * 2735116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch GetContinuationMinimumSize(); 2736116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 273723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } 27387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 27395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 27405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, 27415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PUSH_PROMISE, 27425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags, 27435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu push_promise.stream_id()); 27447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch builder.WriteUInt32(push_promise.promised_stream_id()); 27457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); 27467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2747116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch WritePayloadWithContinuation(&builder, 2748116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch hpack_encoding, 2749116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch push_promise.stream_id(), 2750116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PUSH_PROMISE); 27517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 27527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 2753116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // SPDY4 uses HPACK for header compression. However, continue to 2754116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // use GetSerializedLength() for an apples-to-apples comparision of 2755116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // compression performance between HPACK and SPDY w/ deflate. 2756116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t payload_len = 275723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetSerializedLength(protocol_version(), 275823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) &(push_promise.name_value_block())); 27597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), 2760116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch PUSH_PROMISE, 2761116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch payload_len, 2762116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.length()); 27637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 27647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 27657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return builder.take(); 27667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 27677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 276823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// TODO(jgraettinger): This implementation is incorrect. The continuation 276923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// frame continues a previously-begun HPACK encoding; it doesn't begin a 277023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// new one. Figure out whether it makes sense to keep SerializeContinuation(). 2771a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeContinuation( 2772a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const SpdyContinuationIR& continuation) { 27734ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHECK_LT(SPDY3, protocol_version()); 2774a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) uint8 flags = 0; 2775a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (continuation.end_headers()) { 2776a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) flags |= HEADERS_FLAG_END_HEADERS; 2777a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2778a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2779a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // The size of this frame, including variable-length name-value block. 278023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size_t size = GetContinuationMinimumSize(); 278123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) string hpack_encoding; 27825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (enable_compression_) { 2783cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetHpackEncoder()->EncodeHeaderSet( 27845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu continuation.name_value_block(), &hpack_encoding); 27855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 2786cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) GetHpackEncoder()->EncodeHeaderSetWithoutCompression( 27875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu continuation.name_value_block(), &hpack_encoding); 27885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 278923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) size += hpack_encoding.size(); 2790a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 27915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder builder(size, protocol_version()); 27925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder.BeginNewFrame(*this, CONTINUATION, flags, 2793a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continuation.stream_id()); 2794a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK_EQ(GetContinuationMinimumSize(), builder.length()); 2795a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 279623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) builder.WriteBytes(&hpack_encoding[0], hpack_encoding.size()); 2797a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return builder.take(); 2798a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 2799a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2800cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) { 2801cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(SPDY3, protocol_version()); 2802cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size_t size = GetAltSvcMinimumSize(); 2803cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size += altsvc.protocol_id().length(); 2804cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size += altsvc.host().length(); 2805cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) size += altsvc.origin().length(); 2806cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2807cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) SpdyFrameBuilder builder(size, protocol_version()); 2808cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id()); 2809cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2810cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteUInt32(altsvc.max_age()); 2811cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteUInt16(altsvc.port()); 2812cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteUInt8(0); // Reserved. 2813cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteUInt8(altsvc.protocol_id().length()); 2814cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteBytes(altsvc.protocol_id().data(), 2815cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) altsvc.protocol_id().length()); 2816cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteUInt8(altsvc.host().length()); 2817cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteBytes(altsvc.host().data(), altsvc.host().length()); 2818cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length()); 2819cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); 2820cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return builder.take(); 2821cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 2822cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2823116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSpdyFrame* SpdyFramer::SerializePriority(const SpdyPriorityIR& priority) { 2824116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_LT(SPDY3, protocol_version()); 2825116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t size = GetPrioritySize(); 2826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch SpdyFrameBuilder builder(size, protocol_version()); 2828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); 2829116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2830116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Make sure the highest-order bit in the parent stream id is zeroed out. 2831116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint32 parent_stream_id = priority.parent_stream_id() & 0x7fffffff; 2832116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint32 exclusive = priority.exclusive() ? 0x80000000 : 0; 2833116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Set the one-bit exclusivity flag. 2834116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint32 flag_and_parent_id = parent_stream_id | exclusive; 2835116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt32(flag_and_parent_id); 2836116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch builder.WriteUInt8(priority.weight()); 2837116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK_EQ(GetPrioritySize(), builder.length()); 2838116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return builder.take(); 2839116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 2840116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2841eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 2842eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2843eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FrameSerializationVisitor : public SpdyFrameVisitor { 2844eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 2845eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {} 2846eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~FrameSerializationVisitor() {} 2847eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2848eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); } 2849eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2850ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch virtual void VisitData(const SpdyDataIR& data) OVERRIDE { 2851ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch frame_.reset(framer_->SerializeData(data)); 2852ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2853eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE { 2854eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSynStream(syn_stream)); 2855eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2856eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE { 2857eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSynReply(syn_reply)); 2858eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2859eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE { 2860eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeRstStream(rst_stream)); 2861eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2862eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE { 2863eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSettings(settings)); 2864eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2865eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE { 2866eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializePing(ping)); 2867eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2868eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE { 2869eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeGoAway(goaway)); 2870eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2871eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE { 2872eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeHeaders(headers)); 2873eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2874eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitWindowUpdate( 2875eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SpdyWindowUpdateIR& window_update) OVERRIDE { 2876eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeWindowUpdate(window_update)); 2877eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2878eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE { 2879eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeBlocked(blocked)); 2880eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 28817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch virtual void VisitPushPromise( 28827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SpdyPushPromiseIR& push_promise) OVERRIDE { 28837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_.reset(framer_->SerializePushPromise(push_promise)); 28847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2885a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) virtual void VisitContinuation( 2886a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const SpdyContinuationIR& continuation) OVERRIDE { 2887a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) frame_.reset(framer_->SerializeContinuation(continuation)); 2888a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 2889cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE { 2890cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) frame_.reset(framer_->SerializeAltSvc(altsvc)); 2891cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2892116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void VisitPriority(const SpdyPriorityIR& priority) OVERRIDE { 2893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch frame_.reset(framer_->SerializePriority(priority)); 2894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 2895eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2896eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 2897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyFramer* framer_; 2898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdySerializedFrame> frame_; 2899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 2900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 2902eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2903eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) { 2904eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FrameSerializationVisitor visitor(this); 2905eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame.Visit(&visitor); 2906eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return visitor.ReleaseSerializedFrame(); 2907eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 290923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { 29104ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHECK_GE(SPDY3, protocol_version()); 29112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t uncompressed_length = 291223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) GetSerializedLength(protocol_version(), &headers); 29132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enable_compression_) { 29142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return uncompressed_length; 29152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 29162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) z_stream* compressor = GetHeaderCompressor(); 29172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since we'll be performing lots of flushes when compressing the data, 29182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // zlib's lower bounds may be insufficient. 29192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2 * deflateBound(compressor, uncompressed_length); 29205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 29215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liusize_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { 2923116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); 29245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_GT(protocol_version(), SPDY3); 29255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_GT(size, kMaxControlFrameSize); 29265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t overflow = size - kMaxControlFrameSize; 29275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return overflow / (kMaxControlFrameSize - GetContinuationMinimumSize()) + 1; 29285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 29295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, 29315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const string& hpack_encoding, 29325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyStreamId stream_id, 29335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameType type) { 2934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const size_t kMaxControlFrameSize = GetHeaderFragmentMaxSize(); 29355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // In addition to the prefix, fixed_field_size includes the size of 29375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // any fields that come before the variable-length name/value block. 29385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t fixed_field_size = 0; 29395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint8 end_flag = 0; 29405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu uint8 flags = 0; 29415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (type == HEADERS) { 29425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu fixed_field_size = GetHeadersMinimumSize(); 29435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu end_flag = HEADERS_FLAG_END_HEADERS; 29445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else if (type == PUSH_PROMISE) { 29455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu fixed_field_size = GetPushPromiseMinimumSize(); 29465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; 29475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } else { 29485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " 29495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu << FrameTypeToString(type); 29505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 29515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write as much of the payload as possible into the initial frame. 29535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t bytes_remaining = hpack_encoding.size() - 29545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::min(hpack_encoding.size(), 29555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kMaxControlFrameSize - fixed_field_size); 29565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder->WriteBytes(&hpack_encoding[0], 29575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu hpack_encoding.size() - bytes_remaining); 29585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (bytes_remaining > 0) { 29605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder->OverwriteLength(*this, 29615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kMaxControlFrameSize - GetControlFrameHeaderSize()); 29625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 29635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Tack on CONTINUATION frames for the overflow. 29655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu while (bytes_remaining > 0) { 29665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t bytes_to_write = std::min(bytes_remaining, 29675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu kMaxControlFrameSize - 29685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu GetContinuationMinimumSize()); 29695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write CONTINUATION frame prefix. 29705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (bytes_remaining == bytes_to_write) { 29715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags |= end_flag; 29725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 29735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder->BeginNewFrame(*this, 29745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CONTINUATION, 29755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu flags, 29765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu stream_id); 29775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Write payload fragment. 29785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu builder->WriteBytes(&hpack_encoding[hpack_encoding.size() - 29795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bytes_remaining], 29805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bytes_to_write); 29815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu bytes_remaining -= bytes_to_write; 29825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 29835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 29845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following compression setting are based on Brian Olson's analysis. See 29865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 29875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for more details. 29885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 29895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// System zlib is not expected to have workaround for http://crbug.com/139744, 29905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so disable compression in that case. 29915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Remove the special case when it's no longer necessary. 29925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 0; 29935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // !defined(USE_SYSTEM_ZLIB) 29945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 9; 29955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(USE_SYSTEM_ZLIB) 29965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorWindowSizeInBits = 11; 29975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorMemLevel = 1; 29985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderCompressor() { 30005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_compressor_.get()) 30015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_compressor_.get(); // Already initialized. 30025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_compressor_.reset(new z_stream); 30045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(header_compressor_.get(), 0, sizeof(z_stream)); 30055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int success = deflateInit2(header_compressor_.get(), 30075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorLevel, 30085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Z_DEFLATED, 30095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorWindowSizeInBits, 30105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorMemLevel, 30115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Z_DEFAULT_STRATEGY); 30125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success == Z_OK) { 30134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const char* dictionary = (protocol_version() <= SPDY2) ? 30144ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch kV2Dictionary : kV3Dictionary; 30154ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const int dictionary_size = (protocol_version() <= SPDY2) ? 30164ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch kV2DictionarySize : kV3DictionarySize; 30175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = deflateSetDictionary(header_compressor_.get(), 30185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 30195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 30205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success != Z_OK) { 30225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "deflateSetDictionary failure: " << success; 30235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_compressor_.reset(NULL); 30245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 30255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_compressor_.get(); 30275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderDecompressor() { 30305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_decompressor_.get()) 30315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_decompressor_.get(); // Already initialized. 30325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_decompressor_.reset(new z_stream); 30345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(header_decompressor_.get(), 0, sizeof(z_stream)); 30355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int success = inflateInit(header_decompressor_.get()); 30375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success != Z_OK) { 30385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "inflateInit failure: " << success; 30395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_decompressor_.reset(NULL); 30405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 30415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_decompressor_.get(); 30435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 30445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HpackEncoder* SpdyFramer::GetHpackEncoder() { 3046cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(SPDY3, spdy_version_); 3047cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (hpack_encoder_.get() == NULL) { 3048cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); 3049cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3050cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return hpack_encoder_.get(); 3051cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 3052cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3053cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)HpackDecoder* SpdyFramer::GetHpackDecoder() { 3054cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_LT(SPDY3, spdy_version_); 3055cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (hpack_decoder_.get() == NULL) { 3056cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable())); 3057cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3058cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return hpack_decoder_.get(); 3059cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 3060cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3061cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)uint8 SpdyFramer::MapPriorityToWeight(SpdyPriority priority) { 3062cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float kSteps = 255.9f / 7.f; 3063cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<uint8>(kSteps * (7.f - priority)); 3064cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 3065cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3066cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)SpdyPriority SpdyFramer::MapWeightToPriority(uint8 weight) { 3067cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float kSteps = 255.9f / 7.f; 3068cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return static_cast<SpdyPriority>(7.f - weight / kSteps); 3069cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 3070cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 30715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Incrementally decompress the control frame's header block, feeding the 30725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// result to the visitor in chunks. Continue this until the visitor 30735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicates that it cannot process any more data, or (more commonly) we 30745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run out of data to deliver. 30755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 30762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, 30775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 30785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len) { 30795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a decompressor or set error. 30805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* decomp = GetHeaderDecompressor(); 30815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decomp == NULL) { 30825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 30835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 30845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 30855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 30865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_successfully = true; 30885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kHeaderDataChunkMaxSize]; 30895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 30915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->avail_in = len; 3092ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we 3093ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've 3094ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // reached this method successfully, stream_id should be nonzero. 30955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, stream_id); 30965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (decomp->avail_in > 0 && processed_successfully) { 30975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->next_out = reinterpret_cast<Bytef*>(buffer); 30985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->avail_out = arraysize(buffer); 30995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = inflate(decomp, Z_SYNC_FLUSH); 31015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == Z_NEED_DICT) { 31024ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const char* dictionary = (protocol_version() <= SPDY2) ? kV2Dictionary 31034ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch : kV3Dictionary; 31044ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const int dictionary_size = (protocol_version() <= SPDY2) ? 31054ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch kV2DictionarySize : kV3DictionarySize; 31065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryIds& ids = g_dictionary_ids.Get(); 31074ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch const uLong dictionary_id = (protocol_version() <= SPDY2) ? 31084ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch ids.v2_dictionary_id : ids.v3_dictionary_id; 31095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to try again with the right dictionary. 31105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decomp->adler == dictionary_id) { 31115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = inflateSetDictionary(decomp, 31125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 31135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 31145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == Z_OK) 31155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = inflate(decomp, Z_SYNC_FLUSH); 31165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inflate will generate a Z_BUF_ERROR if it runs out of input 31205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without producing any output. The input is consumed and 31215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffered internally by zlib so we can detect this condition by 31225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checking if avail_in is 0 after the call to inflate. 31235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); 31245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((rv == Z_OK) || input_exhausted) { 31255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 31265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decompressed_len > 0) { 31275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = visitor_->OnControlFrameHeaderData( 31285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, buffer, decompressed_len); 31295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processed_successfully) { 31315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assume that the problem was the header block was too large for the 31325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visitor. 31335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 31345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 31365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "inflate failure: " << rv << " " << len; 31375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 31385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = false; 31395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_successfully; 31425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 31452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, const char* data, size_t len) { 31465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool read_successfully = true; 31475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (read_successfully && len > 0) { 31485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 31495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 31505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_deliver); 31515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_to_deliver; 31525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_to_deliver; 31535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_successfully) { 31545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assume that the problem was the header block was too large for the 31555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visitor. 31565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 31575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return read_successfully; 31605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlockWithoutCompression( 31632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder* builder, 316423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const SpdyNameValueBlock& name_value_block) const { 31652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize number of headers. 31664ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 316723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) builder->WriteUInt16(name_value_block.size()); 316823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) } else { 316923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) builder->WriteUInt32(name_value_block.size()); 31705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize each header. 3173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (SpdyHeaderBlock::const_iterator it = name_value_block.begin(); 3174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it != name_value_block.end(); 31752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 31764ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch if (protocol_version() <= SPDY2) { 31772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteString(it->first); 31782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteString(it->second); 31792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 31802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteStringPiece32(it->first); 31812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteStringPiece32(it->second); 31822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 31832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 31845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 31855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlock( 31872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder* builder, 318823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const SpdyFrameWithNameValueBlockIR& frame) { 31894ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch CHECK_GE(SPDY3, protocol_version()); 31902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enable_compression_) { 3191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return SerializeNameValueBlockWithoutCompression(builder, 319223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) frame.name_value_block()); 31935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 31945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First build an uncompressed version to be fed into the compressor. 31962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t uncompressed_len = GetSerializedLength( 319723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) protocol_version(), &(frame.name_value_block())); 31985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu SpdyFrameBuilder uncompressed_builder(uncompressed_len, protocol_version()); 3199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SerializeNameValueBlockWithoutCompression(&uncompressed_builder, 320023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) frame.name_value_block()); 32012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); 32022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) z_stream* compressor = GetHeaderCompressor(); 32042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!compressor) { 32052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "Could not obtain compressor."; 32062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 32075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 32085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter compressed_frames("spdy.CompressedFrames"); 32102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 32112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 32122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create an output frame. 32142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since we'll be performing lots of flushes when compressing the data, 32152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // zlib's lower bounds may be insufficient. 32162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 32172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(akalin): Avoid the duplicate calculation with 32182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // GetSerializedLength(const SpdyHeaderBlock&). 32192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int compressed_max_size = 32202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2 * deflateBound(compressor, uncompressed_len); 32212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(phajdan.jr): Clean up after we no longer need 32232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to workaround http://crbug.com/139744. 32242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 32252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); 32262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->avail_in = uncompressed_len; 32272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(USE_SYSTEM_ZLIB) 32282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->next_out = reinterpret_cast<Bytef*>( 32292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->GetWritableBuffer(compressed_max_size)); 32302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->avail_out = compressed_max_size; 32312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(phajdan.jr): Clean up after we no longer need 32332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to workaround http://crbug.com/139744. 32342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 32352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = deflate(compressor, Z_SYNC_FLUSH); 32362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != Z_OK) { // How can we know that it compressed everything? 32372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This shouldn't happen, right? 32382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "deflate failure: " << rv; 32392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(akalin): Upstream this return. 32402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 32412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 32422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 32432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WriteHeaderBlockToZ(&frame.name_value_block(), compressor); 32442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(USE_SYSTEM_ZLIB) 32452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int compressed_size = compressed_max_size - compressor->avail_out; 32472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->Seek(compressed_size); 32482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->RewriteLength(*this); 32492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pre_compress_bytes.Add(uncompressed_len); 32512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_compress_bytes.Add(compressed_size); 32522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 32532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressed_frames.Increment(); 32545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 32555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 3257