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)// TODO(rtenhove) clean up frame buffer size calculations so that we aren't 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constantly adding and subtracting header sizes; this is ugly and error- 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// prone. 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/stats_counters.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/valgrind/memcheck.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_builder.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_bitmasks.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/zlib/zlib.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Compute the id of our dictionary so that we know we're using the 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// right one when asked for it. 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uLong CalculateDictionaryId(const char* dictionary, 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t dictionary_size) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uLong initial_value = adler32(0L, Z_NULL, 0); 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return adler32(initial_value, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct DictionaryIds { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryIds() 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : v2_dictionary_id(CalculateDictionaryId(kV2Dictionary, kV2DictionarySize)), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v3_dictionary_id(CalculateDictionaryId(kV3Dictionary, kV3DictionarySize)) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) {} 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uLong v2_dictionary_id; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uLong v3_dictionary_id; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Adler ID for the SPDY header compressor dictionaries. Note that they are 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// initialized lazily to avoid static initializers. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to indicate no flags in a SPDY flags field. 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const uint8 kNoFlags = 0; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SpdyStreamId SpdyFramer::kInvalidStream = -1; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// calculation details. 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 18; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate) \ 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Changing state from: " \ 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << StateToString(state_) \ 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << " to " << StateToString(newstate) << "\n"; \ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate) \ 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 wire) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version < 3) { 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : flags_(flags), id_(id & 0x00ffffff) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(1u << 24, id) << "SPDY setting ID too large."; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 SettingsFlagsAndId::GetWireFormat(int version) const { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version < 3) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wire; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// little-endian and big-endian hosts. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa). 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* wire_array = reinterpret_cast<uint8*>(val); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[0], wire_array[3]); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[1], wire_array[2]); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::SpdyCredential() : slot(0) {} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::~SpdyCredential() {} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)SpdyFramer::SpdyFramer(SpdyMajorVersion version) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : current_frame_buffer_(new char[kControlFrameBufferSize]), 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_compression_(true), 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_(NULL), 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) debug_visitor_(NULL), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_protocol_("SPDY"), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_version_(version), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_(false), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) probable_http_response_(false) { 12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_GE(spdy_version_, SPDY_MIN_VERSION); 12790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK_LE(spdy_version_, SPDY_MAX_VERSION); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Reset(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_compressor_.get()) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deflateEnd(header_compressor_.get()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_decompressor_.get()) { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inflateEnd(header_decompressor_.get()); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = SPDY_RESET; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = SPDY_RESET; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code_ = SPDY_NO_ERROR; 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = 0; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ = 0; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_ = 0; 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) current_frame_type_ = DATA; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_flags_ = 0; 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_length_ = 0; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_ = kInvalidStream; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.Reset(); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const { 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of the data frame header. Future versions of SPDY 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // will likely vary this, so we allow for the flexibility of a function call 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // for this value as opposed to a constant. 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 8; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size, in bytes, of the control frame header. 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const { 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (protocol_version()) { 16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case SPDY2: 16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case SPDY3: 16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case SPDY4: 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 8; 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "Unhandled SPDY version."; 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynStreamMinimumSize() const { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SYN_STREAM frame not including the variable-length 17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) 17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 10; 18090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 18190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // frame prefix + 4 (associated stream ID) + 1 (priority) + 1 (slot) 18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 6; 18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSynReplyMinimumSize() const { 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SYN_REPLY frame not including the variable-length 18990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size = GetControlFrameHeaderSize(); 19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream IDs) 19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size += 4; 19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In SPDY 2, there were 2 unused bytes before payload. 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 2; 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetRstStreamSize() const { 20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Size, in bytes, of a RST_STREAM frame. 20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream id) + 4 (status code) 21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 8; 21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // frame prefix + 4 (status code) 21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSettingsMinimumSize() const { 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a SETTINGS frame not including the IDs and values 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // from the variable-length value block. Calculated as: 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // control frame header + 4 (number of ID/value pairs) 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetPingSize() const { 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of this PING frame. Calculated as: 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // control frame header + 4 (id) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetGoAwaySize() const { 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of this GOAWAY frame. Calculated as: 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // control frame header + 4 (last good stream id) 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size = GetControlFrameHeaderSize() + 4; 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SPDY 3+ GOAWAY frames also contain a status. 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() >= 3) { 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 4; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetHeadersMinimumSize() const { 2457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Size, in bytes, of a HEADERS frame not including the variable-length 24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // name-value block. 24790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size_t size = GetControlFrameHeaderSize(); 24890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 25090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream IDs) 25190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) size += 4; 25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // In SPDY 2, there were 2 unused bytes before payload. 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 2; 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetWindowUpdateSize() const { 26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Size, in bytes, of a WINDOW_UPDATE frame. 26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 26690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // control frame header + 4 (stream id) + 4 (delta) 26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 8; 26890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 26990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Calculated as: 27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // frame prefix + 4 (delta) 27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return GetControlFrameHeaderSize() + 4; 27290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetCredentialMinimumSize() const { 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // and proof. Calculated as: 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // control frame header + 2 (slot) 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return GetControlFrameHeaderSize() + 2; 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t SpdyFramer::GetBlockedSize() const { 283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_LE(4, protocol_version()); 284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Size, in bytes, of a BLOCKED frame. 285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // The BLOCKED frame has no payload beyond the control frame header. 286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return GetControlFrameHeaderSize(); 287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsize_t SpdyFramer::GetPushPromiseMinimumSize() const { 2907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(4, protocol_version()); 2917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Size, in bytes, of a PUSH_PROMISE frame, sans the embedded header block. 2927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Calculated as frame prefix + 4 (promised stream id). 2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return GetControlFrameHeaderSize() + 4; 2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMinimumSize() const { 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetFrameMaximumSize() const { 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return (protocol_version() < 4) ? 0xffffff : 0xffff; 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)size_t SpdyFramer::GetDataFrameMaximumPayload() const { 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return GetFrameMaximumSize() - GetDataFrameMinimumSize(); 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StateToString(int state) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ERROR: 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "ERROR"; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_AUTO_RESET: 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "AUTO_RESET"; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_RESET: 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "RESET"; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_READING_COMMON_HEADER: 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "READING_COMMON_HEADER"; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_PAYLOAD: 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CONTROL_FRAME_PAYLOAD"; 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_IGNORE_REMAINING_PAYLOAD: 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "IGNORE_REMAINING_PAYLOAD"; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_FORWARD_STREAM_FRAME: 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FORWARD_STREAM_FRAME"; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_HEADER_BLOCK: 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CREDENTIAL_FRAME_PAYLOAD: 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_CREDENTIAL_FRAME_PAYLOAD"; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_SETTINGS_FRAME_PAYLOAD: 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_SETTINGS_FRAME_PAYLOAD"; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_STATE"; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::set_error(SpdyError error) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visitor_); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code_ = error; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_ERROR); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnError(this); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::ErrorCodeToString(int error_code) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (error_code) { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_NO_ERROR: 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "NO_ERROR"; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_INVALID_CONTROL_FRAME: 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_CONTROL_FRAME"; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_PAYLOAD_TOO_LARGE: 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CONTROL_PAYLOAD_TOO_LARGE"; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ZLIB_INIT_FAILURE: 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "ZLIB_INIT_FAILURE"; 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_UNSUPPORTED_VERSION: 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNSUPPORTED_VERSION"; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_DECOMPRESS_FAILURE: 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "DECOMPRESS_FAILURE"; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_COMPRESS_FAILURE: 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "COMPRESS_FAILURE"; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_INVALID_DATA_FRAME_FLAGS: 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SPDY_INVALID_DATA_FRAME_FLAGS"; 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SPDY_INVALID_CONTROL_FRAME_FLAGS: 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return "SPDY_INVALID_CONTROL_FRAME_FLAGS"; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_ERROR"; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdyFramer::StatusCodeToString(int status_code) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (status_code) { 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID: 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID"; 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_PROTOCOL_ERROR: 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "PROTOCOL_ERROR"; 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID_STREAM: 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_STREAM"; 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_REFUSED_STREAM: 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "REFUSED_STREAM"; 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_UNSUPPORTED_VERSION: 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNSUPPORTED_VERSION"; 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_CANCEL: 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CANCEL"; 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INTERNAL_ERROR: 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INTERNAL_ERROR"; 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_FLOW_CONTROL_ERROR: 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FLOW_CONTROL_ERROR"; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_STREAM_IN_USE: 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "STREAM_IN_USE"; 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_STREAM_ALREADY_CLOSED: 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "STREAM_ALREADY_CLOSED"; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_INVALID_CREDENTIALS: 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "INVALID_CREDENTIALS"; 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case RST_STREAM_FRAME_TOO_LARGE: 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "FRAME_TOO_LARGE"; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_STATUS"; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case DATA: 400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return "DATA"; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SYN_STREAM"; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SYN_REPLY"; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RST_STREAM: 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "RST_STREAM"; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "SETTINGS"; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case NOOP: 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "NOOP"; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PING: 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "PING"; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GOAWAY: 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "GOAWAY"; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "HEADERS"; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINDOW_UPDATE: 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "WINDOW_UPDATE"; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CREDENTIAL: 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "CREDENTIAL"; 421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case BLOCKED: 422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return "BLOCKED"; 4237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 4247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return "PUSH_PROMISE"; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return "UNKNOWN_CONTROL_TYPE"; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(visitor_); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state_) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_ERROR: 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bottom; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_AUTO_RESET: 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_RESET: 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reset(); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > 0) { 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_READING_COMMON_HEADER); 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_READING_COMMON_HEADER: { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessCommonHeader(data, len); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 4567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Control frames that contain header blocks 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // (SYN_STREAM, SYN_REPLY, HEADERS, PUSH_PROMISE) 4587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // take a different path through the state machine - they 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will go: 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SETTINGS frames take a slightly modified route: 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 2. SPDY_SETTINGS_FRAME_PAYLOAD 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All other control frames will use the alternate route directly to 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SPDY_CONTROL_FRAME_PAYLOAD 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_SETTINGS_FRAME_PAYLOAD: { 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = ProcessSettingsFramePayload(data, len); 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bytes_read = ProcessControlFrameHeaderBlock(data, len); 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CREDENTIAL_FRAME_PAYLOAD: { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessCredentialFramePayload(data, len); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_CONTROL_FRAME_PAYLOAD: { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessControlFramePayload(data, len); 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_IGNORE_REMAINING_PAYLOAD: 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // control frame has too-large payload 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // intentional fallthrough 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SPDY_FORWARD_STREAM_FRAME: { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = ProcessDataFramePayload(data, len); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_read; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_read; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Invalid value for " << display_protocol_ 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " framer state: " << state_; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This ensures that we don't infinite-loop if state_ gets an 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // invalid value somehow, such as due to a SpdyFramer getting deleted 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // from a callback it calls. 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) goto bottom; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (state_ != previous_state_); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bottom: 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(len == 0 || state_ == SPDY_ERROR); 5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ == 0 && 5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ == 0 && 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ == 0) { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "State: " << StateToString(state_); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This should only be called when we're in the SPDY_READING_COMMON_HEADER 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // state. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update current frame buffer as needed. 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t bytes_desired = 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetControlFrameHeaderSize() - current_frame_buffer_length_; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Not enough information to do anything meaningful. 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return original_len - len; 5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Using a scoped_ptr here since we may need to create a new SpdyFrameReader 5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // when processing DATA frames below. 5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrameReader> reader( 5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new SpdyFrameReader(current_frame_buffer_.get(), 5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_)); 5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16 version = 0; 5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_control_frame = false; 5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 561c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint16 control_frame_type_field = DATA; 562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader() will set current_frame_type_ to the 563c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // correct value if this is a valid control frame. 564c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) current_frame_type_ = DATA; 5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 4) { 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool successful_read = reader->ReadUInt16(&version); 5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) is_control_frame = (version & kControlFlagMask) != 0; 5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version &= ~kControlFlagMask; // Only valid for control frames. 5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (is_control_frame) { 572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We check control_frame_type_field's validity in 573c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader(). 574c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successful_read = reader->ReadUInt16(&control_frame_type_field); 5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader->Rewind(); 5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt8(¤t_frame_flags_); 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 length_field = 0; 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt24(&length_field); 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = length_field; 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) version = protocol_version(); 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint16 length_field = 0; 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool successful_read = reader->ReadUInt16(&length_field); 5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_length_ = length_field; 5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint8 control_frame_type_field_uint8 = DATA; 597c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 599c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We check control_frame_type_field's validity in 600c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ProcessControlFrameHeader(). 601c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) control_frame_type_field = control_frame_type_field_uint8; 602c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) is_control_frame = (control_frame_type_field != DATA); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader->ReadUInt8(¤t_frame_flags_); 6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 60790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 60890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(successful_read); 60990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); 6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() 6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : GetDataFrameMinimumSize(), 6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader->GetBytesConsumed()); 6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(current_frame_length_, 6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ + reader->GetBytesConsumed()); 6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is just a sanity check for help debugging early frame errors. 6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ > 1000000u) { 6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The strncmp for 5 is safe because we only hit this point if we 6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have kMinCommonHeader (8) bytes 6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!syn_frame_processed_ && 6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) { 6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_ 6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " request"; 6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) probable_http_response_ = true; 6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ 6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << " session is likely corrupt."; 6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if we're here, then we have the common header all received. 6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!is_control_frame) { 6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_flags_ & ~DATA_FLAG_FIN) { 6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnDataFrameHeader(current_frame_stream_id_, 6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_, 6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_flags_ & DATA_FLAG_FIN); 6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ > 0) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Empty data frame. 6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_flags_ & DATA_FLAG_FIN) { 6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData( 6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, NULL, 0, true); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (version != spdy_version_) { 6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We check version before we check validity: version can never be 6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 'invalid', it can only be unsupported. 655a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unsupported SPDY version " << version 656a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << " (expected " << spdy_version_ << ")"; 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_UNSUPPORTED_VERSION); 6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProcessControlFrameHeader(control_frame_type_field); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_NO_ERROR, error_code_); 667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 669c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (control_frame_type_field < FIRST_CONTROL_TYPE || 670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) control_frame_type_field > LAST_CONTROL_TYPE) { 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field); 676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ == NOOP) { 678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "NOOP control frame found. Ignoring."; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Do some sanity checking on the control frame sizes and flags. 6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSynStreamMinimumSize()) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & 6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSynReplyMinimumSize()) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RST_STREAM: 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ != GetRstStreamSize()) { 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that we have an integral number of 8-byte key/value pairs, 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plus a 4-byte length field. 7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetSettingsMinimumSize() || 7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Invalid length for SETTINGS frame: " 7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_length_; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & 7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 720ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PING: 721ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_length_ != GetPingSize()) { 722ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 723ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else if (current_frame_flags_ != 0) { 724ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 725ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 726ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case GOAWAY: 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ != GetGoAwaySize()) { 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetHeadersMinimumSize()) { 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case WINDOW_UPDATE: 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ != GetWindowUpdateSize()) { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CREDENTIAL: 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ < GetCredentialMinimumSize()) { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (current_frame_flags_ != 0) { 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case BLOCKED: 758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (current_frame_length_ != GetBlockedSize()) { 759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else if (current_frame_flags_ != 0) { 761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 763868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 7647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 7657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (current_frame_length_ < GetPushPromiseMinimumSize()) { 7667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 7677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else if (current_frame_flags_ != 0) { 7687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 7697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 7707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Valid " << display_protocol_ 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " control frame with unhandled type: " 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_type_; 7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This branch should be unreachable because of the frame type bounds 7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // check above. However, we DLOG(FATAL) here in an effort to painfully 7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // club the head of the developer who failed to keep this file in sync 7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // with spdy_protocol.h. 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(FATAL); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ == SPDY_ERROR) { 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_length_ > GetControlFrameBufferMaxSize()) { 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Received control frame with way too big of a payload: " 7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << current_frame_length_; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ == CREDENTIAL) { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine the frame size without variable-length data. 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 frame_size_without_variable_data; 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_ = true; 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSynStreamMinimumSize(); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_ = true; 8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSynReplyMinimumSize(); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS: 8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame_size_without_variable_data = GetSettingsMinimumSize(); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 814ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case HEADERS: 815ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch frame_size_without_variable_data = GetHeadersMinimumSize(); 816ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 8177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch case PUSH_PROMISE: 8187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_size_without_variable_data = GetPushPromiseMinimumSize(); 8197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_size_without_variable_data = -1; 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((frame_size_without_variable_data == -1) && 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_length_ > kControlFrameBufferSize)) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We should already be in an error state. Double-check. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_ERROR, state_); 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state_ != SPDY_ERROR) { 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << display_protocol_ 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " control frame buffer too small for fixed-length frame."; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (frame_size_without_variable_data > 0) { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We have a control frame with a header block. We need to parse the 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // remainder of the control frame's header before we can parse the header 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // block. The start of the header block varies with the control type. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(frame_size_without_variable_data, 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<int32>(current_frame_buffer_length_)); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ = frame_size_without_variable_data - 8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_; 8457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_bytes) { 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_read = std::min(*len, max_bytes); 856868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (bytes_to_read > 0) { 857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_GE(kControlFrameBufferSize, 858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_ + bytes_to_read); 859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, 860868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *data, 861868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bytes_to_read); 862868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_ += bytes_to_read; 863868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *data += bytes_to_read; 864868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) *len -= bytes_to_read; 865868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bytes_to_read; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const int spdy_version, 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeaderBlock* headers) { 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t num_name_value_pairs_size 8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t length_of_name_size = num_name_value_pairs_size; 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t length_of_value_size = num_name_value_pairs_size; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t total_length = num_name_value_pairs_size; 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SpdyHeaderBlock::const_iterator it = headers->begin(); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != headers->end(); 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++it) { 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We add space for the length of the name and the length of the value as 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // well as the length of the name and the length of the value. 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_length += length_of_name_size + it->first.size() + 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_of_value_size + it->second.size(); 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return total_length; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, 8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int spdy_version, 8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeaderBlock* headers) { 8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (spdy_version < 3) { 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->WriteUInt16(headers->size()); // Number of headers. 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame->WriteUInt32(headers->size()); // Number of headers. 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock::const_iterator it; 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = headers->begin(); it != headers->end(); ++it) { 8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (spdy_version < 3) { 8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteString(it->first); 9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteString(it->second); 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteStringPiece32(it->first); 9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frame->WriteStringPiece32(it->second); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Clean up after we no longer need 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to workaround http://crbug.com/139744. 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(USE_SYSTEM_ZLIB) 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These constants are used by zlib to differentiate between normal data and 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. Cookie data is handled specially by zlib when compressing. 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ZDataClass { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZStandardData is compressed normally, save that it will never match 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // against any other class of data in the window. 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZStandardData = Z_CLASS_STANDARD, 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZCookieData is compressed in its own Huffman blocks and only matches in 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // its entirety and only against other kZCookieData blocks. Any matches must 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be preceeded by a kZStandardData byte, or a semicolon to prevent matching 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // prefix matches. 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZCookieData = Z_CLASS_COOKIE, 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kZHuffmanOnlyData is only Huffman compressed - no matches are performed 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // against the window. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needed when switching between classes of data. 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteZ(const base::StringPiece& data, 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZDataClass clas, 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* out) { 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are switching from standard to non-standard data then we need to end 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current Huffman context to avoid it leaking between them. 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (out->clas == kZStandardData && 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) clas != kZStandardData) { 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->avail_in = 0; 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_PARTIAL_FLUSH); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(Z_OK, rv); 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, out->avail_in); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, out->avail_out); 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->avail_in = data.size(); 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->clas = clas; 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (clas == kZStandardData) { 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_NO_FLUSH); 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = deflate(out, Z_PARTIAL_FLUSH); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!data.empty()) { 9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If we didn't provide any data then zlib will return Z_BUF_ERROR. 9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(Z_OK, rv); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0u, out->avail_in); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, out->avail_out); 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WriteLengthZ(size_t n, 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned length, 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ZDataClass clas, 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* out) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[4]; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(length, sizeof(buf)); 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 1; i <= length; i++) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[length - i] = n; 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n >>= 8; 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(base::StringPiece(buf, length), clas, out); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// manner that resists the length of the compressed data from compromising 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cookie data. 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* z) const { 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned length_length = 4; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spdy_version_ < 3) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) length_length = 2; 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(headers->size(), length_length, kZStandardData, z); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, std::string>::const_iterator it; 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (it = headers->begin(); it != headers->end(); ++it) { 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->first.size(), length_length, kZStandardData, z); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->first, kZStandardData, z); 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first == "cookie") { 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We require the cookie values (save for the last) to end with a 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // semicolon and (save for the first) to start with a space. This is 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typically the format that we are given them in but we reserialize them 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be sure. 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<base::StringPiece> cookie_values; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t cookie_length = 0; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece cookie_data(it->second); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (;;) { 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!cookie_data.empty() && 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(1); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cookie_data.empty()) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t i; 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < cookie_data.size(); i++) { 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cookie_data[i] == ';') 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < cookie_data.size()) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_values.push_back(cookie_data.substr(0, i)); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_length += i + 2 /* semicolon and space */; 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(i + 1); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_values.push_back(cookie_data); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_length += cookie_data.size(); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie_data.remove_prefix(i); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(cookie_length, length_length, kZStandardData, z); 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < cookie_values.size(); i++) { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string cookie; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since zlib will only back-reference complete cookies, a cookie that 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is currently last (and so doesn't have a trailing semicolon) won't 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // match if it's later in a non-final position. The same is true of 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the first cookie. 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0 && cookie_values.size() == 1) { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = cookie_values[i].as_string(); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i == 0) { 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = cookie_values[i].as_string() + ";"; 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (i < cookie_values.size() - 1) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = " " + cookie_values[i].as_string() + ";"; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cookie = " " + cookie_values[i].as_string(); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(cookie, kZCookieData, z); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (it->first == "accept" || 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-charset" || 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-encoding" || 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "accept-language" || 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "host" || 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "version" || 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "method" || 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "scheme" || 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":host" || 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":version" || 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":method" || 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == ":scheme" || 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->first == "user-agent") { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->second, kZStandardData, z); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Non-whitelisted headers are Huffman compressed in their own block, but 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't match against the window. 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WriteZ(it->second, kZHuffmanOnlyData, z); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z->avail_in = 0; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = deflate(z, Z_SYNC_FLUSH); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(Z_OK, rv); 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z->clas = kZStandardData; 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(USE_SYSTEM_ZLIB) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len) { 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_control_header_ > 0) { 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ -= bytes_read; 10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= bytes_read; 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remaining_control_header_ == 0) { 10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_buffer_length_); 10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (current_frame_type_) { 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_STREAM: 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 109590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool successful_read = true; 109690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 109790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 109890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(successful_read); 109990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId associated_to_stream_id = kInvalidStream; 11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt31(&associated_to_stream_id); 11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyPriority priority = 0; 11102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt8(&priority); 11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority = priority >> 6; 11142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 11152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority = priority >> 5; 11162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 slot = 0; 11192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 11202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SPDY 2 had an unused byte here. Seek past it. 11212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader.Seek(1); 11222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 11232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt8(&slot); 11242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 11252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 11272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(reader.IsDoneReading()); 11287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 11297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 11307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_stream_id_, 11317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_type_, 11327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_length_); 11337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnSynStream( 11352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 11362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) associated_to_stream_id, 11372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) priority, 11382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) slot, 11392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 11402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case SETTINGS: 1145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch visitor_->OnSettings(current_frame_flags_ & 1146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS); 1147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); 11487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch break; 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SYN_REPLY: 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case HEADERS: 11512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SYN_REPLY and HEADERS are the same, save for the visitor call. 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 115390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) bool successful_read = true; 115490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 115590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 115690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) DCHECK(successful_read); 115790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 1158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 11622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 11632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SPDY 2 had two unused bytes here. Seek past them. 11642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reader.Seek(2); 11652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(reader.IsDoneReading()); 11677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 11687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 11697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_stream_id_, 11707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_type_, 11717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_length_); 11727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 11732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ == SYN_REPLY) { 11742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnSynReply( 11752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 11762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 11772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 11782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnHeaders( 11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, 11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 11812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PUSH_PROMISE: 1186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch { 1187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_LE(4, protocol_version()); 1188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (current_frame_stream_id_ == 0) { 1189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyStreamId promised_stream_id = kInvalidStream; 1193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool successful_read = reader.ReadUInt31(&promised_stream_id); 1194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (promised_stream_id == 0) { 1197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch set_error(SPDY_INVALID_CONTROL_FRAME); 1198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1200ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (debug_visitor_) { 1201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch debug_visitor_->OnReceiveCompressedFrame( 1202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_stream_id_, 1203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_type_, 1204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_length_); 1205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch visitor_->OnPushPromise(current_frame_stream_id_, promised_stream_id); 1207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(false); 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Does not buffer the control payload. Instead, either passes directly to the 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// visitor or decompresses and then passes directly to the visitor, via 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDeliverControlFrameHeaderData() or 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IncrementallyDecompressControlFrameHeaderData() respectively. 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_len) { 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_successfully = true; 12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_type_ != SYN_STREAM && 12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_type_ != SYN_REPLY && 1228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_type_ != HEADERS && 1229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch current_frame_type_ != PUSH_PROMISE) { 12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; 12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t process_bytes = std::min(data_len, remaining_data_length_); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (process_bytes > 0) { 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_compression_) { 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = IncrementallyDecompressControlFrameHeaderData( 12362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, process_bytes); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = IncrementallyDeliverControlFrameHeaderData( 12392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, process_bytes); 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= process_bytes; 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle the case that there is no futher data in this frame. 12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ == 0 && processed_successfully) { 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The complete header block has been delivered. We send a zero-length 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnControlFrameHeaderData() to indicate this. 12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this is a FIN, tell the caller. 12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (current_frame_flags_ & CONTROL_FLAG_FIN) { 12532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle error. 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processed_successfully) { 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return data_len; 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return amount processed. 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return process_bytes; 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t data_len) { 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); 12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(SETTINGS, current_frame_type_); 12722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t processed_bytes = 0; 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Loop over our incoming data. 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (unprocessed_bytes > 0) { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process up to one setting at a time. 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t processing = std::min( 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unprocessed_bytes, 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we have a complete setting in our input. 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (processing == 8) { 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Parse the setting directly out of the input without buffering. 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ProcessSetting(data + processed_bytes)) { 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Continue updating settings_scratch_.setting_buf. 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data + processed_bytes, 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processing); 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.setting_buf_len += processing; 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we have a complete setting buffered. 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (settings_scratch_.setting_buf_len == 8) { 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ProcessSetting(settings_scratch_.setting_buf)) { 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_INVALID_CONTROL_FRAME); 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset settings_scratch_.setting_buf for our next setting. 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.setting_buf_len = 0; 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Iterate. 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unprocessed_bytes -= processing; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_bytes += processing; 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check if we're done handling this SETTINGS frame. 13132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= processed_bytes; 13142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ == 0) { 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_bytes; 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ProcessSetting(const char* data) { 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extract fields. 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndId id_and_flags = 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 flags = id_and_flags.flags(); 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate id. 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (id_and_flags.id()) { 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_UPLOAD_BANDWIDTH: 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_DOWNLOAD_BANDWIDTH: 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_ROUND_TRIP_TIME: 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_MAX_CONCURRENT_STREAMS: 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_CURRENT_CWND: 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_DOWNLOAD_RETRANS_RATE: 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SETTINGS_INITIAL_WINDOW_SIZE: 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Valid values. 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id(); 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id()); 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Detect duplciates. 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) { 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " in " << display_protocol_ << " SETTINGS frame " 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "(last settikng id was " 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << settings_scratch_.last_setting_id << ")."; 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_scratch_.last_setting_id = id; 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validate flags. 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((flags & ~(kFlagsMask)) != 0) { 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << flags; 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Validation succeeded. Pass on to visitor. 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnSetting(id, flags, value); 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 1372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) size_t bytes_read = 1373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_); 1374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) remaining_data_length_ -= bytes_read; 1375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (remaining_data_length_ == 0) { 1376868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyFrameReader reader(current_frame_buffer_.get(), 1377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) current_frame_buffer_length_); 1378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) reader.Seek(GetControlFrameHeaderSize()); // Skip frame header. 1379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Use frame-specific handlers. 1381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) switch (current_frame_type_) { 1382868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case RST_STREAM: { 1383868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool successful_read = true; 1384868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (spdy_version_ < 4) { 1385868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1388868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyRstStreamStatus status = RST_STREAM_INVALID; 1389868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uint32 status_raw = status; 1390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) successful_read = reader.ReadUInt32(&status_raw); 1391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(successful_read); 1392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (status_raw > RST_STREAM_INVALID && 1393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status_raw < RST_STREAM_NUM_STATUS_CODES) { 1394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status = static_cast<SpdyRstStreamStatus>(status_raw); 1395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } else { 1396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(hkhalil): Probably best to OnError here, depending on 1397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // our interpretation of the spec. Keeping with existing liberal 1398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // behavior for now. 1399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1400868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(reader.IsDoneReading()); 1401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) visitor_->OnRstStream(current_frame_stream_id_, status); 1402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 1404ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case PING: { 1405ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyPingId id = 0; 1406ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool successful_read = reader.ReadUInt32(&id); 1407ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1408ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1409ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch visitor_->OnPing(id); 1410ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1411ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case GOAWAY: { 1413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(successful_read); 1415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyGoAwayStatus status = GOAWAY_OK; 1416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (spdy_version_ >= 3) { 1417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) uint32 status_raw = GOAWAY_OK; 14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) successful_read = reader.ReadUInt32(&status_raw); 14192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(successful_read); 1420868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (status_raw >= GOAWAY_OK && 1421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) { 1422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) status = static_cast<SpdyGoAwayStatus>(status_raw); 14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(hkhalil): Probably best to OnError here, depending on 14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // our interpretation of the spec. Keeping with existing liberal 14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // behavior for now. 14272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(reader.IsDoneReading()); 1430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) visitor_->OnGoAway(current_frame_stream_id_, status); 1431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1432868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 1433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case WINDOW_UPDATE: { 1434ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32 delta_window_size = 0; 1435ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool successful_read = true; 1436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (spdy_version_ < 4) { 1437ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1438ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch successful_read = reader.ReadUInt32(&delta_window_size); 1441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(successful_read); 1442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(reader.IsDoneReading()); 1443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch visitor_->OnWindowUpdate(current_frame_stream_id_, 1444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delta_window_size); 1445ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1446ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 1447868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case BLOCKED: { 1448868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_LE(4, protocol_version()); 1449868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(reader.IsDoneReading()); 1450868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) visitor_->OnBlocked(current_frame_stream_id_); 1451868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1452868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) break; 1453868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) default: 1454868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Unreachable. 1455868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(FATAL) << "Unhandled control frame " << current_frame_type_; 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1457868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) { 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > 0) { 1465ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Clamp to the actual remaining payload. 1466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (len > remaining_data_length_) { 1467ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch len = remaining_data_length_; 1468ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_succesfully = visitor_->OnCredentialFrameData(data, len); 14702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= len; 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processed_succesfully) { 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CREDENTIAL_FRAME_CORRUPT); 14732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (remaining_data_length_ == 0) { 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_->OnCredentialFrameData(NULL, 0); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return len; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t original_len = len; 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ > 0) { 14852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t amount_to_forward = std::min(remaining_data_length_, len); 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only inform the visitor if there is data. 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (amount_to_forward) { 14892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData( 14902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_frame_stream_id_, data, amount_to_forward, false); 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += amount_to_forward; 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= amount_to_forward; 14952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) remaining_data_length_ -= amount_to_forward; 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the FIN flag is set, and there is no more data in this data 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frame, inform the visitor of EOF via a 0-length data frame. 14992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) { 15002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (remaining_data_length_ == 0) { 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHANGE_STATE(SPDY_AUTO_RESET); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return original_len - len; 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t header_length, 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock* block) const { 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyFrameReader reader(header_data, header_length); 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read number of headers. 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 num_headers; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spdy_version_ < 3) { 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 temp; 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reader.ReadUInt16(&temp)) { 1520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read number of headers."; 15212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_headers = temp; 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!reader.ReadUInt32(&num_headers)) { 1526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read number of headers."; 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read each header. 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (uint32 index = 0; index < num_headers; ++index) { 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece temp; 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read header name. 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : !reader.ReadStringPiece32(&temp)) { 1538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read header name (" << index + 1 << " of " 1539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 15402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string name = temp.as_string(); 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Read header value. 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : !reader.ReadStringPiece32(&temp)) { 1547a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Unable to read header value (" << index + 1 << " of " 1548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 15492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value = temp.as_string(); 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure no duplicates. 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (block->find(name) != block->end()) { 1555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DVLOG(1) << "Duplicate header '" << name << "' (" << index + 1 << " of " 1556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << num_headers << ")."; 15572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Store header. 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*block)[name] = value; 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return reader.GetBytesConsumed(); 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* static */ 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::ParseCredentialData(const char* data, size_t len, 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyCredential* credential) { 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(credential); 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyFrameReader parser(data, len); 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece temp; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parser.ReadUInt16(&credential->slot)) { 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parser.ReadStringPiece32(&temp)) { 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credential->proof = temp.as_string(); 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!parser.IsDoneReading()) { 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!parser.ReadStringPiece32(&temp)) { 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) credential->certs.push_back(temp.as_string()); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdyFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, 1592ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const char* data, 1593ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32 len, SpdyDataFlags flags) const { 1594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(0, flags & (!DATA_FLAG_FIN)); 1595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyDataIR data_ir(stream_id, base::StringPiece(data, len)); 1597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch data_ir.set_fin(flags & DATA_FLAG_FIN); 1598ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return SerializeData(data_ir); 1599ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1600ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1601ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const { 1602ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const size_t kSize = GetDataFrameMinimumSize() + data.data().length(); 1603ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1604ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyDataFlags flags = DATA_FLAG_NONE; 1605ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (data.fin()) { 1606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags = DATA_FLAG_FIN; 1607ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1608ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1609ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyFrameBuilder builder(kSize); 1610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder.WriteBytes(data.data().data(), data.data().length()); 1612ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(kSize, builder.length()); 1613ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return builder.take(); 1614ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1615ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1616ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochSpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader( 1617ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const SpdyDataIR& data) const { 1618ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const size_t kSize = GetDataFrameMinimumSize(); 1619ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1620ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyDataFlags flags = DATA_FLAG_NONE; 1621ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (data.fin()) { 1622ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch flags = DATA_FLAG_FIN; 1623ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1624ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1625ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch SpdyFrameBuilder builder(kSize); 1626ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1627ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (protocol_version() < 4) { 1628ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder.OverwriteLength(*this, data.data().length()); 1629ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 1630ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch builder.OverwriteLength(*this, data.data().length() + kSize); 1631ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(kSize, builder.length()); 1633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return builder.take(); 1634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 1635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 16362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSynStream( 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId associated_stream_id, 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyPriority priority, 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8 credential_slot, 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyControlFlags flags, 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock* headers) { 16432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL); 16442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySynStreamIR syn_stream(stream_id); 16462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_stream.set_associated_to_stream_id(associated_stream_id); 16472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_stream.set_priority(priority); 16482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_stream.set_slot(credential_slot); 16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); 16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(hkhalil): Avoid copy here. 16522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(syn_stream.GetMutableNameValueBlock()) = *headers; 16532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SerializeSynStream(syn_stream); 16552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynStream( 16582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySynStreamIR& syn_stream) { 16592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 16602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_stream.fin()) { 16612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 16622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_stream.unidirectional()) { 16642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_UNIDIRECTIONAL; 16652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t size = GetSynStreamMinimumSize() 16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) + GetSerializedLength(syn_stream.name_value_block()); 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(size); 167290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 167390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); 167490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(syn_stream.stream_id()); 167590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 167690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, 167790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SYN_STREAM, 167890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags, 167990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syn_stream.stream_id()); 168090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 16812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(syn_stream.associated_to_stream_id()); 16822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 priority = syn_stream.priority(); 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (priority > GetLowestPriority()) { 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(DFATAL) << "Priority out-of-bounds."; 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) priority = GetLowestPriority(); 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); 16882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt8(syn_stream.slot()); 16892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); 16902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SerializeNameValueBlock(&builder, syn_stream); 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 16937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const size_t payload_len = GetSerializedLength( 16947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) protocol_version(), &(syn_stream.name_value_block())); 16957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(syn_stream.stream_id(), 16967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SYN_STREAM, 16977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 16987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 16997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 17007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSynReply( 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyControlFlags flags, 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock* headers) { 17082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySynReplyIR syn_reply(stream_id); 17112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) syn_reply.set_fin(flags & CONTROL_FLAG_FIN); 17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(hkhalil): Avoid copy here. 17132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(syn_reply.GetMutableNameValueBlock()) = *headers; 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SerializeSynReply(syn_reply); 17162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSynReply( 17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySynReplyIR& syn_reply) { 17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 17212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (syn_reply.fin()) { 17222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 17262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size = GetSynReplyMinimumSize() 17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) + GetSerializedLength(syn_reply.name_value_block()); 17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(size); 173090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 173190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); 173290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(syn_reply.stream_id()); 173390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 173490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, 173590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) SYN_REPLY, 173690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags, 173790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) syn_reply.stream_id()); 173890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 17402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt16(0); // Unused. 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); 17432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SerializeNameValueBlock(&builder, syn_reply); 17442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 17467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const size_t payload_len = GetSerializedLength( 17477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) protocol_version(), &(syn_reply.name_value_block())); 17487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(syn_reply.stream_id(), 17497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) SYN_REPLY, 17507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 17517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 17527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 17537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateRstStream( 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyRstStreamStatus status) const { 17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyRstStreamIR rst_stream(stream_id, status); 17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeRstStream(rst_stream); 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeRstStream( 17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyRstStreamIR& rst_stream) const { 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(GetRstStreamSize()); 176790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 176890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, RST_STREAM, 0); 176990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(rst_stream.stream_id()); 177090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 177190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, 177290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) RST_STREAM, 177390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 0, 177490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) rst_stream.stream_id()); 177590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 17762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(rst_stream.status()); 17772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetRstStreamSize(), builder.length()); 17782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateSettings( 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SettingsMap& values) const { 17832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdySettingsIR settings; 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SettingsMap::const_iterator it = values.begin(); 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != values.end(); 17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 17872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) settings.AddSetting(it->first, 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, 17902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it->second.second); 17912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 17922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeSettings(settings); 17932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeSettings( 17962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySettingsIR& settings) const { 17972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 17982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (settings.clear_settings()) { 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdySettingsIR::ValueMap* values = &(settings.values()); 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Size, in bytes, of this SETTINGS frame. 18042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t size = GetSettingsMinimumSize() + (values->size() * 8); 18052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(size); 180790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 180890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, SETTINGS, flags); 180990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 181090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, SETTINGS, flags, 0); 181190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(values->size()); 18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); 18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != values->end(); 18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 setting_flags = 0; 18182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second.persist_value) { 18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; 18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (it->second.persisted) { 18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) setting_flags |= SETTINGS_FLAG_PERSISTED; 18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SettingsFlagsAndId flags_and_id(setting_flags, it->first); 18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); 18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteBytes(&id_and_flags_wire, 4); 18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(it->second.value); 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(size, builder.length()); 18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1833868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)SpdyFrame* SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked) const { 1834868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK_LE(4, protocol_version()); 1835868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) SpdyFrameBuilder builder(GetBlockedSize()); 1836868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) builder.WriteFramePrefix(*this, BLOCKED, kNoFlags, blocked.stream_id()); 1837868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return builder.take(); 1838868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 1839868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { 18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyPingIR ping(unique_id); 18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializePing(ping); 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { 18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(GetPingSize()); 184790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 184890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, PING, kNoFlags); 184990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 185090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, PING, 0, 0); 185190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(ping.id()); 18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetPingSize(), builder.length()); 18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateGoAway( 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId last_accepted_stream_id, 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyGoAwayStatus status) const { 18602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyGoAwayIR goaway(last_accepted_stream_id, status); 18612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeGoAway(goaway); 18622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeGoAway( 18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyGoAwayIR& goaway) const { 18662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(GetGoAwaySize()); 186790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 186890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, GOAWAY, kNoFlags); 186990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 187090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, GOAWAY, 0, 0); 187190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(goaway.last_good_stream_id()); 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (protocol_version() >= 3) { 18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(goaway.status()); 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetGoAwaySize(), builder.length()); 18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateHeaders( 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyControlFlags flags, 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeaderBlock* header_block) { 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Basically the same as CreateSynReply(). 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyHeadersIR headers(stream_id); 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) headers.set_fin(flags & CONTROL_FLAG_FIN); 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(hkhalil): Avoid copy here. 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *(headers.GetMutableNameValueBlock()) = *header_block; 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SerializeHeaders(headers); 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeHeaders( 18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyHeadersIR& headers) { 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) uint8 flags = 0; 18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (headers.fin()) { 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) flags |= CONTROL_FLAG_FIN; 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The size of this frame, including variable-length name-value block. 19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size = GetHeadersMinimumSize() 19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) + GetSerializedLength(headers.name_value_block()); 19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(size); 190790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 190890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, HEADERS, flags); 190990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(headers.stream_id()); 191090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 191190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, 191290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) HEADERS, 191390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) flags, 191490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) headers.stream_id()); 191590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 19172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt16(0); // Unused. 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); 19202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SerializeNameValueBlock(&builder, headers); 19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (debug_visitor_) { 19247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const size_t payload_len = GetSerializedLength( 19257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) protocol_version(), &(headers.name_value_block())); 19267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) debug_visitor_->OnSendCompressedFrame(headers.stream_id(), 19277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) HEADERS, 19287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) payload_len, 19297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) builder.length()); 19307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 19317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateWindowUpdate( 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId stream_id, 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 delta_window_size) const { 19382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyWindowUpdateIR window_update(stream_id, delta_window_size); 19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeWindowUpdate(window_update); 19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( 19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyWindowUpdateIR& window_update) const { 19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(GetWindowUpdateSize()); 194590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 194690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); 194790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteUInt32(window_update.stream_id()); 194890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 194990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, 195090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) WINDOW_UPDATE, 195190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) kNoFlags, 195290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) window_update.stream_id()); 195390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt32(window_update.delta()); 19552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetWindowUpdateSize(), builder.length()); 19562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 19572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TODO(hkhalil): Gut with SpdyCredential removal. 19602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdyFrame* SpdyFramer::CreateCredentialFrame( 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyCredential& credential) const { 19622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyCredentialIR credential_ir(credential.slot); 19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credential_ir.set_proof(credential.proof); 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert != credential.certs.end(); 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++cert) { 19672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credential_ir.AddCertificate(*cert); 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeCredential(credential_ir); 19702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SpdySerializedFrame* SpdyFramer::SerializeCredential( 19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyCredentialIR& credential) const { 19742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t size = GetCredentialMinimumSize(); 19752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 4 + credential.proof().length(); // Room for proof. 19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (SpdyCredentialIR::CertificateList::const_iterator it = 19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credential.certificates()->begin(); 19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != credential.certificates()->end(); 19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += 4 + it->length(); // Room for certificate. 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder builder(size); 198490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (spdy_version_ < 4) { 198590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteControlFrameHeader(*this, CREDENTIAL, kNoFlags); 198690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } else { 198790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) builder.WriteFramePrefix(*this, CREDENTIAL, kNoFlags, 0); 198890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteUInt16(credential.slot()); 19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(GetCredentialMinimumSize(), builder.length()); 19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteStringPiece32(credential.proof()); 19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (SpdyCredentialIR::CertificateList::const_iterator it = 19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) credential.certificates()->begin(); 19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) it != credential.certificates()->end(); 19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder.WriteStringPiece32(*it); 19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(size, builder.length()); 19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return builder.take(); 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20027dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::CreatePushPromise( 20037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyStreamId stream_id, 20047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyStreamId promised_stream_id, 20057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SpdyHeaderBlock* header_block) { 20067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyPushPromiseIR push_promise(stream_id, promised_stream_id); 20077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // TODO(hkhalil): Avoid copy here. 20087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch *(push_promise.GetMutableNameValueBlock()) = *header_block; 20097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return SerializePushPromise(push_promise); 20117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 20127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20137dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochSpdyFrame* SpdyFramer::SerializePushPromise( 20147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SpdyPushPromiseIR& push_promise) { 20157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_LE(4, protocol_version()); 20167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // The size of this frame, including variable-length name-value block. 20177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch size_t size = GetPushPromiseMinimumSize() 20187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch + GetSerializedLength(push_promise.name_value_block()); 20197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SpdyFrameBuilder builder(size); 20217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch builder.WriteFramePrefix(*this, PUSH_PROMISE, kNoFlags, 20227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch push_promise.stream_id()); 20237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch builder.WriteUInt32(push_promise.promised_stream_id()); 20247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); 20257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch SerializeNameValueBlock(&builder, push_promise); 20277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (debug_visitor_) { 20297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const size_t payload_len = GetSerializedLength( 20307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch protocol_version(), &(push_promise.name_value_block())); 20317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch debug_visitor_->OnSendCompressedFrame(push_promise.stream_id(), 20327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch PUSH_PROMISE, payload_len, builder.length()); 20337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 20347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 20357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return builder.take(); 20367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 20377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 2038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace { 2039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass FrameSerializationVisitor : public SpdyFrameVisitor { 2041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public: 2042eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch explicit FrameSerializationVisitor(SpdyFramer* framer) : framer_(framer) {} 2043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual ~FrameSerializationVisitor() {} 2044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2045eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdySerializedFrame* ReleaseSerializedFrame() { return frame_.release(); } 2046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2047ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch virtual void VisitData(const SpdyDataIR& data) OVERRIDE { 2048ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch frame_.reset(framer_->SerializeData(data)); 2049ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 2050eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSynStream(const SpdySynStreamIR& syn_stream) OVERRIDE { 2051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSynStream(syn_stream)); 2052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSynReply(const SpdySynReplyIR& syn_reply) OVERRIDE { 2054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSynReply(syn_reply)); 2055eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2056eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitRstStream(const SpdyRstStreamIR& rst_stream) OVERRIDE { 2057eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeRstStream(rst_stream)); 2058eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2059eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitSettings(const SpdySettingsIR& settings) OVERRIDE { 2060eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeSettings(settings)); 2061eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2062eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitPing(const SpdyPingIR& ping) OVERRIDE { 2063eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializePing(ping)); 2064eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2065eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitGoAway(const SpdyGoAwayIR& goaway) OVERRIDE { 2066eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeGoAway(goaway)); 2067eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2068eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitHeaders(const SpdyHeadersIR& headers) OVERRIDE { 2069eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeHeaders(headers)); 2070eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2071eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitWindowUpdate( 2072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const SpdyWindowUpdateIR& window_update) OVERRIDE { 2073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeWindowUpdate(window_update)); 2074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitCredential(const SpdyCredentialIR& credential) OVERRIDE { 2076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeCredential(credential)); 2077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 2078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch virtual void VisitBlocked(const SpdyBlockedIR& blocked) OVERRIDE { 2079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame_.reset(framer_->SerializeBlocked(blocked)); 2080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch } 20817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch virtual void VisitPushPromise( 20827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch const SpdyPushPromiseIR& push_promise) OVERRIDE { 20837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch frame_.reset(framer_->SerializePushPromise(push_promise)); 20847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 2085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private: 2087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch SpdyFramer* framer_; 2088eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch scoped_ptr<SpdySerializedFrame> frame_; 2089eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}; 2090eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2091eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} // namespace 2092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 2093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochSpdySerializedFrame* SpdyFramer::SerializeFrame(const SpdyFrameIR& frame) { 2094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch FrameSerializationVisitor visitor(this); 2095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch frame.Visit(&visitor); 2096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return visitor.ReleaseSerializedFrame(); 2097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 2098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 20992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { 21002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t uncompressed_length = 21012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetSerializedLength(protocol_version(), &headers); 21022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enable_compression_) { 21032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return uncompressed_length; 21042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 21052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) z_stream* compressor = GetHeaderCompressor(); 21062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since we'll be performing lots of flushes when compressing the data, 21072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // zlib's lower bounds may be insufficient. 21082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 2 * deflateBound(compressor, uncompressed_length); 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following compression setting are based on Brian Olson's analysis. See 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for more details. 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// System zlib is not expected to have workaround for http://crbug.com/139744, 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so disable compression in that case. 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(phajdan.jr): Remove the special case when it's no longer necessary. 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 0; 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // !defined(USE_SYSTEM_ZLIB) 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorLevel = 9; 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // !defined(USE_SYSTEM_ZLIB) 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorWindowSizeInBits = 11; 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kCompressorMemLevel = 1; 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderCompressor() { 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_compressor_.get()) 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_compressor_.get(); // Already initialized. 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_compressor_.reset(new z_stream); 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(header_compressor_.get(), 0, sizeof(z_stream)); 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int success = deflateInit2(header_compressor_.get(), 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorLevel, 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Z_DEFLATED, 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorWindowSizeInBits, 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCompressorMemLevel, 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Z_DEFAULT_STRATEGY); 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success == Z_OK) { 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kV3Dictionary; 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kV3DictionarySize; 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) success = deflateSetDictionary(header_compressor_.get(), 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success != Z_OK) { 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "deflateSetDictionary failure: " << success; 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_compressor_.reset(NULL); 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_compressor_.get(); 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)z_stream* SpdyFramer::GetHeaderDecompressor() { 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_decompressor_.get()) 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_decompressor_.get(); // Already initialized. 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_decompressor_.reset(new z_stream); 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memset(header_decompressor_.get(), 0, sizeof(z_stream)); 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int success = inflateInit(header_decompressor_.get()); 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (success != Z_OK) { 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "inflateInit failure: " << success; 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_decompressor_.reset(NULL); 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return header_decompressor_.get(); 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Incrementally decompress the control frame's header block, feeding the 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// result to the visitor in chunks. Continue this until the visitor 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// indicates that it cannot process any more data, or (more commonly) we 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// run out of data to deliver. 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 21762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len) { 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a decompressor or set error. 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_stream* decomp = GetHeaderDecompressor(); 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decomp == NULL) { 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_successfully = true; 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer[kHeaderDataChunkMaxSize]; 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->avail_in = len; 2192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If we get a SYN_STREAM/SYN_REPLY/HEADERS frame with stream ID zero, we 2193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // signal an error back in ProcessControlFrameBeforeHeaderBlock. So if we've 2194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // reached this method successfully, stream_id should be nonzero. 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0u, stream_id); 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (decomp->avail_in > 0 && processed_successfully) { 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->next_out = reinterpret_cast<Bytef*>(buffer); 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decomp->avail_out = arraysize(buffer); 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = inflate(decomp, Z_SYNC_FLUSH); 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == Z_NEED_DICT) { 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kV3Dictionary; 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : kV3DictionarySize; 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryIds& ids = g_dictionary_ids.Get(); 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ids.v3_dictionary_id; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to try again with the right dictionary. 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decomp->adler == dictionary_id) { 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = inflateSetDictionary(decomp, 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const Bytef*>(dictionary), 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_size); 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == Z_OK) 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = inflate(decomp, Z_SYNC_FLUSH); 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inflate will generate a Z_BUF_ERROR if it runs out of input 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without producing any output. The input is consumed and 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buffered internally by zlib so we can detect this condition by 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // checking if avail_in is 0 after the call to inflate. 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((rv == Z_OK) || input_exhausted) { 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (decompressed_len > 0) { 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = visitor_->OnControlFrameHeaderData( 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, buffer, decompressed_len); 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processed_successfully) { 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assume that the problem was the header block was too large for the 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visitor. 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DLOG(WARNING) << "inflate failure: " << rv << " " << len; 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_DECOMPRESS_FAILURE); 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processed_successfully = false; 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processed_successfully; 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 22452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyStreamId stream_id, const char* data, size_t len) { 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool read_successfully = true; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (read_successfully && len > 0) { 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_to_deliver); 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += bytes_to_deliver; 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= bytes_to_deliver; 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!read_successfully) { 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assume that the problem was the header block was too large for the 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // visitor. 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return read_successfully; 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlockWithoutCompression( 22632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder* builder, 2264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const SpdyNameValueBlock& name_value_block) const { 22652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize number of headers. 22662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 2267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) builder->WriteUInt16(name_value_block.size()); 22682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 2269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) builder->WriteUInt32(name_value_block.size()); 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Serialize each header. 2273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (SpdyHeaderBlock::const_iterator it = name_value_block.begin(); 2274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it != name_value_block.end(); 22752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++it) { 22762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (protocol_version() < 3) { 22772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteString(it->first); 22782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteString(it->second); 22792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 22802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteStringPiece32(it->first); 22812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->WriteStringPiece32(it->second); 22822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SpdyFramer::SerializeNameValueBlock( 22872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder* builder, 22882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const SpdyFrameWithNameValueBlockIR& frame) { 22892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!enable_compression_) { 2290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return SerializeNameValueBlockWithoutCompression(builder, 2291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame.name_value_block()); 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First build an uncompressed version to be fed into the compressor. 22952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t uncompressed_len = GetSerializedLength( 22962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protocol_version(), &(frame.name_value_block())); 22972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrameBuilder uncompressed_builder(uncompressed_len); 2298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SerializeNameValueBlockWithoutCompression(&uncompressed_builder, 2299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) frame.name_value_block()); 23002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); 23012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) z_stream* compressor = GetHeaderCompressor(); 23032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!compressor) { 23042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(DFATAL) << "Could not obtain compressor."; 23052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter compressed_frames("spdy.CompressedFrames"); 23092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 23102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 23112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create an output frame. 23132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Since we'll be performing lots of flushes when compressing the data, 23142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // zlib's lower bounds may be insufficient. 23152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 23162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(akalin): Avoid the duplicate calculation with 23172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // GetSerializedLength(const SpdyHeaderBlock&). 23182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int compressed_max_size = 23192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2 * deflateBound(compressor, uncompressed_len); 23202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(phajdan.jr): Clean up after we no longer need 23222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to workaround http://crbug.com/139744. 23232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 23242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); 23252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->avail_in = uncompressed_len; 23262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(USE_SYSTEM_ZLIB) 23272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->next_out = reinterpret_cast<Bytef*>( 23282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->GetWritableBuffer(compressed_max_size)); 23292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressor->avail_out = compressed_max_size; 23302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(phajdan.jr): Clean up after we no longer need 23322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to workaround http://crbug.com/139744. 23332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_SYSTEM_ZLIB) 23342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv = deflate(compressor, Z_SYNC_FLUSH); 23352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv != Z_OK) { // How can we know that it compressed everything? 23362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This shouldn't happen, right? 23372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(WARNING) << "deflate failure: " << rv; 23382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(akalin): Upstream this return. 23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 23412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 23422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WriteHeaderBlockToZ(&frame.name_value_block(), compressor); 23432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // defined(USE_SYSTEM_ZLIB) 23442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int compressed_size = compressed_max_size - compressor->avail_out; 23462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->Seek(compressed_size); 23472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) builder->RewriteLength(*this); 23482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pre_compress_bytes.Add(uncompressed_len); 23502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) post_compress_bytes.Add(compressed_size); 23512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 23522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) compressed_frames.Increment(); 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 2356