spdy_framer.cc revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
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" 157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "net/spdy/spdy_frame_builder.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_frame_reader.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// initialized lazily to avoid static initializers. 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to indicate no flags in a SPDY flags field. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 kNoFlags = 0; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int SpdyFramer::kMinSpdyVersion = kSpdyVersion2; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int SpdyFramer::kMaxSpdyVersion = kSpdyVersion4; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const SpdyStreamId SpdyFramer::kInvalidStream = -1; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The size of the control frame buffer. Must be >= the minimum size of the 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// calculation details. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t SpdyFramer::kControlFrameBufferSize = 18; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef DEBUG_SPDY_STATE_CHANGES 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define CHANGE_STATE(newstate) \ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(INFO) << "Changing state from: " \ 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << StateToString(state_) \ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " to " << StateToString(newstate) << "\n"; \ 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CHANGE_STATE(newstate) \ 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { \ 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(state_ != SPDY_ERROR); \ 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(previous_state_, state_); \ 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = state_; \ 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = newstate; \ 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (false) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 wire) { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version < 3) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : flags_(flags), id_(id & 0x00ffffff) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(1u << 24, id) << "SPDY setting ID too large."; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 SettingsFlagsAndId::GetWireFormat(int version) const { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version < 3) { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConvertFlagsAndIdForSpdy2(&wire); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return wire; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPDY 2 had a bug in it with respect to byte ordering of id/flags field. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is used to preserve buggy behavior and works on both 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// little-endian and big-endian hosts. 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method is also bidirectional (can be used to translate SPDY 2 to SPDY 3 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as vice versa). 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8* wire_array = reinterpret_cast<uint8*>(val); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[0], wire_array[3]); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::swap(wire_array[1], wire_array[2]); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::SpdyCredential() : slot(0) {} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyCredential::~SpdyCredential() {} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::SpdyFramer(int version) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : current_frame_buffer_(new char[kControlFrameBufferSize]), 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_compression_(true), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visitor_(NULL), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) debug_visitor_(NULL), 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) display_protocol_("SPDY"), 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) spdy_version_(version), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syn_frame_processed_(false), 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) probable_http_response_(false) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(kMaxSpdyVersion, version); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(kMinSpdyVersion, version); 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Reset(); 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdyFramer::~SpdyFramer() { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_compressor_.get()) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deflateEnd(header_compressor_.get()); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_decompressor_.get()) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inflateEnd(header_decompressor_.get()); 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdyFramer::Reset() { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state_ = SPDY_RESET; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) previous_state_ = SPDY_RESET; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code_ = SPDY_NO_ERROR; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_data_length_ = 0; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_control_header_ = 0; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_buffer_length_ = 0; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_type_ = DATA; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_flags_ = 0; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) current_frame_length_ = 0; 1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch current_frame_stream_id_ = kInvalidStream; 1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch settings_scratch_.Reset(); 1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::GetDataFrameMinimumSize() const { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Size, in bytes, of the data frame header. Future versions of SPDY 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will likely vary this, so we allow for the flexibility of a function call 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for this value as opposed to a constant. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 8; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size, in bytes, of the control frame header. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdyFramer::GetControlFrameHeaderSize() const { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (protocol_version()) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 3: 168 return 8; 169 case 4: 170 return 4; 171 } 172 LOG(DFATAL) << "Unhandled SPDY version."; 173 return 0; 174} 175 176size_t SpdyFramer::GetSynStreamMinimumSize() const { 177 // Size, in bytes, of a SYN_STREAM frame not including the variable-length 178 // name-value block. Calculated as: 179 // control frame header + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) 180 return GetControlFrameHeaderSize() + 10; 181} 182 183size_t SpdyFramer::GetSynReplyMinimumSize() const { 184 // Size, in bytes, of a SYN_REPLY frame not including the variable-length 185 // name-value block. Calculated as: 186 // control frame header + 4 (stream ID) 187 size_t size = GetControlFrameHeaderSize() + 4; 188 189 // In SPDY 2, there were 2 unused bytes before payload. 190 if (protocol_version() < 3) { 191 size += 2; 192 } 193 194 return size; 195} 196 197size_t SpdyFramer::GetRstStreamSize() const { 198 // Size, in bytes, of a RST_STREAM frame. Calculated as: 199 // control frame header + 4 (stream id) + 4 (status code) 200 return GetControlFrameHeaderSize() + 8; 201} 202 203size_t SpdyFramer::GetSettingsMinimumSize() const { 204 // Size, in bytes, of a SETTINGS frame not including the IDs and values 205 // from the variable-length value block. Calculated as: 206 // control frame header + 4 (number of ID/value pairs) 207 return GetControlFrameHeaderSize() + 4; 208} 209 210size_t SpdyFramer::GetPingSize() const { 211 // Size, in bytes, of this PING frame. Calculated as: 212 // control frame header + 4 (id) 213 return GetControlFrameHeaderSize() + 4; 214} 215 216size_t SpdyFramer::GetGoAwaySize() const { 217 // Size, in bytes, of this GOAWAY frame. Calculated as: 218 // control frame header + 4 (last good stream id) 219 size_t size = GetControlFrameHeaderSize() + 4; 220 221 // SPDY 3+ GOAWAY frames also contain a status. 222 if (protocol_version() >= 3) { 223 size += 4; 224 } 225 226 return size; 227} 228 229size_t SpdyFramer::GetHeadersMinimumSize() const { 230 // Size, in bytes, of a HEADERS frame not including the variable-length 231 // name-value block. Calculated as: 232 // control frame header + 4 (stream ID) 233 size_t size = GetControlFrameHeaderSize() + 4; 234 235 // In SPDY 2, there were 2 unused bytes before payload. 236 if (protocol_version() < 3) { 237 size += 2; 238 } 239 240 return size; 241} 242 243size_t SpdyFramer::GetWindowUpdateSize() const { 244 // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: 245 // control frame header + 4 (stream id) + 4 (delta) 246 return GetControlFrameHeaderSize() + 8; 247} 248 249size_t SpdyFramer::GetCredentialMinimumSize() const { 250 // Size, in bytes, of a CREDENTIAL frame sans variable-length certificate list 251 // and proof. Calculated as: 252 // control frame header + 2 (slot) 253 return GetControlFrameHeaderSize() + 2; 254} 255 256size_t SpdyFramer::GetFrameMinimumSize() const { 257 return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize()); 258} 259 260size_t SpdyFramer::GetFrameMaximumSize() const { 261 return (protocol_version() < 4) ? 0xffffff : 0xffff; 262} 263 264size_t SpdyFramer::GetDataFrameMaximumPayload() const { 265 return GetFrameMaximumSize() - GetDataFrameMinimumSize(); 266} 267 268const char* SpdyFramer::StateToString(int state) { 269 switch (state) { 270 case SPDY_ERROR: 271 return "ERROR"; 272 case SPDY_AUTO_RESET: 273 return "AUTO_RESET"; 274 case SPDY_RESET: 275 return "RESET"; 276 case SPDY_READING_COMMON_HEADER: 277 return "READING_COMMON_HEADER"; 278 case SPDY_CONTROL_FRAME_PAYLOAD: 279 return "CONTROL_FRAME_PAYLOAD"; 280 case SPDY_IGNORE_REMAINING_PAYLOAD: 281 return "IGNORE_REMAINING_PAYLOAD"; 282 case SPDY_FORWARD_STREAM_FRAME: 283 return "FORWARD_STREAM_FRAME"; 284 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 285 return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 286 case SPDY_CONTROL_FRAME_HEADER_BLOCK: 287 return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 288 case SPDY_CREDENTIAL_FRAME_PAYLOAD: 289 return "SPDY_CREDENTIAL_FRAME_PAYLOAD"; 290 case SPDY_SETTINGS_FRAME_PAYLOAD: 291 return "SPDY_SETTINGS_FRAME_PAYLOAD"; 292 } 293 return "UNKNOWN_STATE"; 294} 295 296void SpdyFramer::set_error(SpdyError error) { 297 DCHECK(visitor_); 298 error_code_ = error; 299 CHANGE_STATE(SPDY_ERROR); 300 visitor_->OnError(this); 301} 302 303const char* SpdyFramer::ErrorCodeToString(int error_code) { 304 switch (error_code) { 305 case SPDY_NO_ERROR: 306 return "NO_ERROR"; 307 case SPDY_INVALID_CONTROL_FRAME: 308 return "INVALID_CONTROL_FRAME"; 309 case SPDY_CONTROL_PAYLOAD_TOO_LARGE: 310 return "CONTROL_PAYLOAD_TOO_LARGE"; 311 case SPDY_ZLIB_INIT_FAILURE: 312 return "ZLIB_INIT_FAILURE"; 313 case SPDY_UNSUPPORTED_VERSION: 314 return "UNSUPPORTED_VERSION"; 315 case SPDY_DECOMPRESS_FAILURE: 316 return "DECOMPRESS_FAILURE"; 317 case SPDY_COMPRESS_FAILURE: 318 return "COMPRESS_FAILURE"; 319 case SPDY_INVALID_DATA_FRAME_FLAGS: 320 return "SPDY_INVALID_DATA_FRAME_FLAGS"; 321 case SPDY_INVALID_CONTROL_FRAME_FLAGS: 322 return "SPDY_INVALID_CONTROL_FRAME_FLAGS"; 323 } 324 return "UNKNOWN_ERROR"; 325} 326 327const char* SpdyFramer::StatusCodeToString(int status_code) { 328 switch (status_code) { 329 case RST_STREAM_INVALID: 330 return "INVALID"; 331 case RST_STREAM_PROTOCOL_ERROR: 332 return "PROTOCOL_ERROR"; 333 case RST_STREAM_INVALID_STREAM: 334 return "INVALID_STREAM"; 335 case RST_STREAM_REFUSED_STREAM: 336 return "REFUSED_STREAM"; 337 case RST_STREAM_UNSUPPORTED_VERSION: 338 return "UNSUPPORTED_VERSION"; 339 case RST_STREAM_CANCEL: 340 return "CANCEL"; 341 case RST_STREAM_INTERNAL_ERROR: 342 return "INTERNAL_ERROR"; 343 case RST_STREAM_FLOW_CONTROL_ERROR: 344 return "FLOW_CONTROL_ERROR"; 345 case RST_STREAM_STREAM_IN_USE: 346 return "STREAM_IN_USE"; 347 case RST_STREAM_STREAM_ALREADY_CLOSED: 348 return "STREAM_ALREADY_CLOSED"; 349 case RST_STREAM_INVALID_CREDENTIALS: 350 return "INVALID_CREDENTIALS"; 351 case RST_STREAM_FRAME_TOO_LARGE: 352 return "FRAME_TOO_LARGE"; 353 } 354 return "UNKNOWN_STATUS"; 355} 356 357const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) { 358 switch (type) { 359 case DATA: 360 return "DATA"; 361 case SYN_STREAM: 362 return "SYN_STREAM"; 363 case SYN_REPLY: 364 return "SYN_REPLY"; 365 case RST_STREAM: 366 return "RST_STREAM"; 367 case SETTINGS: 368 return "SETTINGS"; 369 case NOOP: 370 return "NOOP"; 371 case PING: 372 return "PING"; 373 case GOAWAY: 374 return "GOAWAY"; 375 case HEADERS: 376 return "HEADERS"; 377 case WINDOW_UPDATE: 378 return "WINDOW_UPDATE"; 379 case CREDENTIAL: 380 return "CREDENTIAL"; 381 } 382 return "UNKNOWN_CONTROL_TYPE"; 383} 384 385size_t SpdyFramer::ProcessInput(const char* data, size_t len) { 386 DCHECK(visitor_); 387 DCHECK(data); 388 389 size_t original_len = len; 390 do { 391 previous_state_ = state_; 392 switch (state_) { 393 case SPDY_ERROR: 394 goto bottom; 395 396 case SPDY_AUTO_RESET: 397 case SPDY_RESET: 398 Reset(); 399 if (len > 0) { 400 CHANGE_STATE(SPDY_READING_COMMON_HEADER); 401 } 402 break; 403 404 case SPDY_READING_COMMON_HEADER: { 405 size_t bytes_read = ProcessCommonHeader(data, len); 406 len -= bytes_read; 407 data += bytes_read; 408 break; 409 } 410 411 case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 412 // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, 413 // HEADERS) take a different path through the state machine - they 414 // will go: 415 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 416 // 2. SPDY_CONTROL_FRAME_HEADER_BLOCK 417 // 418 // SETTINGS frames take a slightly modified route: 419 // 1. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 420 // 2. SPDY_SETTINGS_FRAME_PAYLOAD 421 // 422 // All other control frames will use the alternate route directly to 423 // SPDY_CONTROL_FRAME_PAYLOAD 424 int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 425 len -= bytes_read; 426 data += bytes_read; 427 break; 428 } 429 430 case SPDY_SETTINGS_FRAME_PAYLOAD: { 431 int bytes_read = ProcessSettingsFramePayload(data, len); 432 len -= bytes_read; 433 data += bytes_read; 434 break; 435 } 436 437 case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 438 int bytes_read = ProcessControlFrameHeaderBlock(data, len); 439 len -= bytes_read; 440 data += bytes_read; 441 break; 442 } 443 444 case SPDY_CREDENTIAL_FRAME_PAYLOAD: { 445 size_t bytes_read = ProcessCredentialFramePayload(data, len); 446 len -= bytes_read; 447 data += bytes_read; 448 break; 449 } 450 451 case SPDY_CONTROL_FRAME_PAYLOAD: { 452 size_t bytes_read = ProcessControlFramePayload(data, len); 453 len -= bytes_read; 454 data += bytes_read; 455 break; 456 } 457 458 case SPDY_IGNORE_REMAINING_PAYLOAD: 459 // control frame has too-large payload 460 // intentional fallthrough 461 case SPDY_FORWARD_STREAM_FRAME: { 462 size_t bytes_read = ProcessDataFramePayload(data, len); 463 len -= bytes_read; 464 data += bytes_read; 465 break; 466 } 467 default: 468 LOG(DFATAL) << "Invalid value for " << display_protocol_ 469 << " framer state: " << state_; 470 // This ensures that we don't infinite-loop if state_ gets an 471 // invalid value somehow, such as due to a SpdyFramer getting deleted 472 // from a callback it calls. 473 goto bottom; 474 } 475 } while (state_ != previous_state_); 476 bottom: 477 DCHECK(len == 0 || state_ == SPDY_ERROR); 478 if (current_frame_buffer_length_ == 0 && 479 remaining_data_length_ == 0 && 480 remaining_control_header_ == 0) { 481 DCHECK(state_ == SPDY_RESET || state_ == SPDY_ERROR) 482 << "State: " << StateToString(state_); 483 } 484 485 return original_len - len; 486} 487 488size_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 489 // This should only be called when we're in the SPDY_READING_COMMON_HEADER 490 // state. 491 DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 492 493 size_t original_len = len; 494 495 // Update current frame buffer as needed. 496 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 497 size_t bytes_desired = 498 GetControlFrameHeaderSize() - current_frame_buffer_length_; 499 UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 500 } 501 502 if (current_frame_buffer_length_ < GetControlFrameHeaderSize()) { 503 // Not enough information to do anything meaningful. 504 return original_len - len; 505 } 506 507 // Using a scoped_ptr here since we may need to create a new SpdyFrameReader 508 // when processing DATA frames below. 509 scoped_ptr<SpdyFrameReader> reader( 510 new SpdyFrameReader(current_frame_buffer_.get(), 511 current_frame_buffer_length_)); 512 513 uint16 version = 0; 514 bool is_control_frame = false; 515 516 uint16 control_frame_type_field = DATA; 517 // ProcessControlFrameHeader() will set current_frame_type_ to the 518 // correct value if this is a valid control frame. 519 current_frame_type_ = DATA; 520 if (protocol_version() < 4) { 521 bool successful_read = reader->ReadUInt16(&version); 522 DCHECK(successful_read); 523 is_control_frame = (version & kControlFlagMask) != 0; 524 version &= ~kControlFlagMask; // Only valid for control frames. 525 526 if (is_control_frame) { 527 // We check control_frame_type_field's validity in 528 // ProcessControlFrameHeader(). 529 successful_read = reader->ReadUInt16(&control_frame_type_field); 530 } else { 531 reader->Rewind(); 532 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 533 } 534 DCHECK(successful_read); 535 536 successful_read = reader->ReadUInt8(¤t_frame_flags_); 537 DCHECK(successful_read); 538 539 uint32 length_field = 0; 540 successful_read = reader->ReadUInt24(&length_field); 541 DCHECK(successful_read); 542 remaining_data_length_ = length_field; 543 current_frame_length_ = remaining_data_length_ + reader->GetBytesConsumed(); 544 } else { 545 // TODO(hkhalil): Avoid re-reading fields as possible for DATA frames? 546 version = protocol_version(); 547 uint16 length_field = 0; 548 bool successful_read = reader->ReadUInt16(&length_field); 549 DCHECK(successful_read); 550 current_frame_length_ = length_field; 551 552 uint8 control_frame_type_field_uint8 = DATA; 553 successful_read = reader->ReadUInt8(&control_frame_type_field_uint8); 554 DCHECK(successful_read); 555 // We check control_frame_type_field's validity in 556 // ProcessControlFrameHeader(). 557 control_frame_type_field = control_frame_type_field_uint8; 558 is_control_frame = (control_frame_type_field != DATA); 559 560 successful_read = reader->ReadUInt8(¤t_frame_flags_); 561 DCHECK(successful_read); 562 563 if (!is_control_frame) { 564 // We may not have the entirety of the DATA frame header. 565 if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) { 566 size_t bytes_desired = 567 GetDataFrameMinimumSize() - current_frame_buffer_length_; 568 UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 569 if (current_frame_buffer_length_ < GetDataFrameMinimumSize()) { 570 return original_len - len; 571 } 572 } 573 // Construct a new SpdyFrameReader aware of the new frame length. 574 reader.reset(new SpdyFrameReader(current_frame_buffer_.get(), 575 current_frame_buffer_length_)); 576 reader->Seek(GetControlFrameHeaderSize()); 577 successful_read = reader->ReadUInt31(¤t_frame_stream_id_); 578 DCHECK(successful_read); 579 } 580 remaining_data_length_ = current_frame_length_ - reader->GetBytesConsumed(); 581 } 582 DCHECK_EQ(is_control_frame ? GetControlFrameHeaderSize() 583 : GetDataFrameMinimumSize(), 584 reader->GetBytesConsumed()); 585 DCHECK_EQ(current_frame_length_, 586 remaining_data_length_ + reader->GetBytesConsumed()); 587 588 // This is just a sanity check for help debugging early frame errors. 589 if (remaining_data_length_ > 1000000u) { 590 // The strncmp for 5 is safe because we only hit this point if we 591 // have kMinCommonHeader (8) bytes 592 if (!syn_frame_processed_ && 593 strncmp(current_frame_buffer_.get(), "HTTP/", 5) == 0) { 594 LOG(WARNING) << "Unexpected HTTP response to " << display_protocol_ 595 << " request"; 596 probable_http_response_ = true; 597 } else { 598 LOG(WARNING) << "Unexpectedly large frame. " << display_protocol_ 599 << " session is likely corrupt."; 600 } 601 } 602 603 // if we're here, then we have the common header all received. 604 if (!is_control_frame) { 605 if (current_frame_flags_ & ~DATA_FLAG_FIN) { 606 set_error(SPDY_INVALID_DATA_FRAME_FLAGS); 607 } else { 608 visitor_->OnDataFrameHeader(current_frame_stream_id_, 609 remaining_data_length_, 610 current_frame_flags_ & DATA_FLAG_FIN); 611 if (remaining_data_length_ > 0) { 612 CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 613 } else { 614 // Empty data frame. 615 if (current_frame_flags_ & DATA_FLAG_FIN) { 616 visitor_->OnStreamFrameData( 617 current_frame_stream_id_, NULL, 0, true); 618 } 619 CHANGE_STATE(SPDY_AUTO_RESET); 620 } 621 } 622 } else if (version != spdy_version_) { 623 // We check version before we check validity: version can never be 624 // 'invalid', it can only be unsupported. 625 DLOG(INFO) << "Unsupported SPDY version " << version 626 << " (expected " << spdy_version_ << ")"; 627 set_error(SPDY_UNSUPPORTED_VERSION); 628 } else { 629 ProcessControlFrameHeader(control_frame_type_field); 630 } 631 632 return original_len - len; 633} 634 635void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) { 636 DCHECK_EQ(SPDY_NO_ERROR, error_code_); 637 DCHECK_LE(GetControlFrameHeaderSize(), current_frame_buffer_length_); 638 639 if (control_frame_type_field < FIRST_CONTROL_TYPE || 640 control_frame_type_field > LAST_CONTROL_TYPE) { 641 set_error(SPDY_INVALID_CONTROL_FRAME); 642 return; 643 } 644 645 current_frame_type_ = static_cast<SpdyFrameType>(control_frame_type_field); 646 647 if (current_frame_type_ == NOOP) { 648 DLOG(INFO) << "NOOP control frame found. Ignoring."; 649 CHANGE_STATE(SPDY_AUTO_RESET); 650 return; 651 } 652 653 // Do some sanity checking on the control frame sizes and flags. 654 switch (current_frame_type_) { 655 case SYN_STREAM: 656 if (current_frame_length_ < GetSynStreamMinimumSize()) { 657 set_error(SPDY_INVALID_CONTROL_FRAME); 658 } else if (current_frame_flags_ & 659 ~(CONTROL_FLAG_FIN | CONTROL_FLAG_UNIDIRECTIONAL)) { 660 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 661 } 662 break; 663 case SYN_REPLY: 664 if (current_frame_length_ < GetSynReplyMinimumSize()) { 665 set_error(SPDY_INVALID_CONTROL_FRAME); 666 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 667 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 668 } 669 break; 670 case RST_STREAM: 671 if (current_frame_length_ != GetRstStreamSize()) { 672 set_error(SPDY_INVALID_CONTROL_FRAME); 673 } else if (current_frame_flags_ != 0) { 674 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 675 } 676 break; 677 case SETTINGS: 678 // Make sure that we have an integral number of 8-byte key/value pairs, 679 // plus a 4-byte length field. 680 if (current_frame_length_ < GetSettingsMinimumSize() || 681 (current_frame_length_ - GetControlFrameHeaderSize()) % 8 != 4) { 682 DLOG(WARNING) << "Invalid length for SETTINGS frame: " 683 << current_frame_length_; 684 set_error(SPDY_INVALID_CONTROL_FRAME); 685 } else if (current_frame_flags_ & 686 ~SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS) { 687 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 688 } 689 break; 690 case GOAWAY: 691 { 692 if (current_frame_length_ != GetGoAwaySize()) { 693 set_error(SPDY_INVALID_CONTROL_FRAME); 694 } else if (current_frame_flags_ != 0) { 695 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 696 } 697 break; 698 } 699 case HEADERS: 700 if (current_frame_length_ < GetHeadersMinimumSize()) { 701 set_error(SPDY_INVALID_CONTROL_FRAME); 702 } else if (current_frame_flags_ & ~CONTROL_FLAG_FIN) { 703 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 704 } 705 break; 706 case WINDOW_UPDATE: 707 if (current_frame_length_ != GetWindowUpdateSize()) { 708 set_error(SPDY_INVALID_CONTROL_FRAME); 709 } else if (current_frame_flags_ != 0) { 710 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 711 } 712 break; 713 case PING: 714 if (current_frame_length_ != GetPingSize()) { 715 set_error(SPDY_INVALID_CONTROL_FRAME); 716 } else if (current_frame_flags_ != 0) { 717 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 718 } 719 break; 720 case CREDENTIAL: 721 if (current_frame_length_ < GetCredentialMinimumSize()) { 722 set_error(SPDY_INVALID_CONTROL_FRAME); 723 } else if (current_frame_flags_ != 0) { 724 set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS); 725 } 726 break; 727 default: 728 LOG(WARNING) << "Valid " << display_protocol_ 729 << " control frame with unhandled type: " 730 << current_frame_type_; 731 // This branch should be unreachable because of the frame type bounds 732 // check above. However, we DLOG(FATAL) here in an effort to painfully 733 // club the head of the developer who failed to keep this file in sync 734 // with spdy_protocol.h. 735 DLOG(FATAL); 736 set_error(SPDY_INVALID_CONTROL_FRAME); 737 break; 738 } 739 740 if (state_ == SPDY_ERROR) { 741 return; 742 } 743 744 if (current_frame_length_ > GetControlFrameBufferMaxSize()) { 745 DLOG(WARNING) << "Received control frame with way too big of a payload: " 746 << current_frame_length_; 747 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 748 return; 749 } 750 751 if (current_frame_type_ == CREDENTIAL) { 752 CHANGE_STATE(SPDY_CREDENTIAL_FRAME_PAYLOAD); 753 return; 754 } 755 756 // Determine the frame size without variable-length data. 757 int32 frame_size_without_variable_data; 758 switch (current_frame_type_) { 759 case SYN_STREAM: 760 syn_frame_processed_ = true; 761 frame_size_without_variable_data = GetSynStreamMinimumSize(); 762 break; 763 case SYN_REPLY: 764 syn_frame_processed_ = true; 765 frame_size_without_variable_data = GetSynReplyMinimumSize(); 766 break; 767 case HEADERS: 768 frame_size_without_variable_data = GetHeadersMinimumSize(); 769 break; 770 case SETTINGS: 771 frame_size_without_variable_data = GetSettingsMinimumSize(); 772 break; 773 default: 774 frame_size_without_variable_data = -1; 775 break; 776 } 777 778 if ((frame_size_without_variable_data == -1) && 779 (current_frame_length_ > kControlFrameBufferSize)) { 780 // We should already be in an error state. Double-check. 781 DCHECK_EQ(SPDY_ERROR, state_); 782 if (state_ != SPDY_ERROR) { 783 LOG(DFATAL) << display_protocol_ 784 << " control frame buffer too small for fixed-length frame."; 785 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 786 } 787 return; 788 } 789 790 if (frame_size_without_variable_data > 0) { 791 // We have a control frame with a header block. We need to parse the 792 // remainder of the control frame's header before we can parse the header 793 // block. The start of the header block varies with the control type. 794 DCHECK_GE(frame_size_without_variable_data, 795 static_cast<int32>(current_frame_buffer_length_)); 796 remaining_control_header_ = frame_size_without_variable_data - 797 current_frame_buffer_length_; 798 CHANGE_STATE(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK); 799 return; 800 } 801 802 CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 803} 804 805size_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 806 size_t max_bytes) { 807 size_t bytes_to_read = std::min(*len, max_bytes); 808 DCHECK_GE(kControlFrameBufferSize, 809 current_frame_buffer_length_ + bytes_to_read); 810 memcpy(current_frame_buffer_.get() + current_frame_buffer_length_, 811 *data, 812 bytes_to_read); 813 current_frame_buffer_length_ += bytes_to_read; 814 *data += bytes_to_read; 815 *len -= bytes_to_read; 816 return bytes_to_read; 817} 818 819size_t SpdyFramer::GetSerializedLength(const int spdy_version, 820 const SpdyHeaderBlock* headers) { 821 const size_t num_name_value_pairs_size 822 = (spdy_version < 3) ? sizeof(uint16) : sizeof(uint32); 823 const size_t length_of_name_size = num_name_value_pairs_size; 824 const size_t length_of_value_size = num_name_value_pairs_size; 825 826 size_t total_length = num_name_value_pairs_size; 827 for (SpdyHeaderBlock::const_iterator it = headers->begin(); 828 it != headers->end(); 829 ++it) { 830 // We add space for the length of the name and the length of the value as 831 // well as the length of the name and the length of the value. 832 total_length += length_of_name_size + it->first.size() + 833 length_of_value_size + it->second.size(); 834 } 835 return total_length; 836} 837 838void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, 839 const int spdy_version, 840 const SpdyHeaderBlock* headers) { 841 if (spdy_version < 3) { 842 frame->WriteUInt16(headers->size()); // Number of headers. 843 } else { 844 frame->WriteUInt32(headers->size()); // Number of headers. 845 } 846 SpdyHeaderBlock::const_iterator it; 847 for (it = headers->begin(); it != headers->end(); ++it) { 848 if (spdy_version < 3) { 849 frame->WriteString(it->first); 850 frame->WriteString(it->second); 851 } else { 852 frame->WriteStringPiece32(it->first); 853 frame->WriteStringPiece32(it->second); 854 } 855 } 856} 857 858// TODO(phajdan.jr): Clean up after we no longer need 859// to workaround http://crbug.com/139744. 860#if !defined(USE_SYSTEM_ZLIB) 861 862// These constants are used by zlib to differentiate between normal data and 863// cookie data. Cookie data is handled specially by zlib when compressing. 864enum ZDataClass { 865 // kZStandardData is compressed normally, save that it will never match 866 // against any other class of data in the window. 867 kZStandardData = Z_CLASS_STANDARD, 868 // kZCookieData is compressed in its own Huffman blocks and only matches in 869 // its entirety and only against other kZCookieData blocks. Any matches must 870 // be preceeded by a kZStandardData byte, or a semicolon to prevent matching 871 // a suffix. It's assumed that kZCookieData ends in a semicolon to prevent 872 // prefix matches. 873 kZCookieData = Z_CLASS_COOKIE, 874 // kZHuffmanOnlyData is only Huffman compressed - no matches are performed 875 // against the window. 876 kZHuffmanOnlyData = Z_CLASS_HUFFMAN_ONLY, 877}; 878 879// WriteZ writes |data| to the deflate context |out|. WriteZ will flush as 880// needed when switching between classes of data. 881static void WriteZ(const base::StringPiece& data, 882 ZDataClass clas, 883 z_stream* out) { 884 int rv; 885 886 // If we are switching from standard to non-standard data then we need to end 887 // the current Huffman context to avoid it leaking between them. 888 if (out->clas == kZStandardData && 889 clas != kZStandardData) { 890 out->avail_in = 0; 891 rv = deflate(out, Z_PARTIAL_FLUSH); 892 DCHECK_EQ(Z_OK, rv); 893 DCHECK_EQ(0u, out->avail_in); 894 DCHECK_LT(0u, out->avail_out); 895 } 896 897 out->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data.data())); 898 out->avail_in = data.size(); 899 out->clas = clas; 900 if (clas == kZStandardData) { 901 rv = deflate(out, Z_NO_FLUSH); 902 } else { 903 rv = deflate(out, Z_PARTIAL_FLUSH); 904 } 905 if (!data.empty()) { 906 // If we didn't provide any data then zlib will return Z_BUF_ERROR. 907 DCHECK_EQ(Z_OK, rv); 908 } 909 DCHECK_EQ(0u, out->avail_in); 910 DCHECK_LT(0u, out->avail_out); 911} 912 913// WriteLengthZ writes |n| as a |length|-byte, big-endian number to |out|. 914static void WriteLengthZ(size_t n, 915 unsigned length, 916 ZDataClass clas, 917 z_stream* out) { 918 char buf[4]; 919 DCHECK_LE(length, sizeof(buf)); 920 for (unsigned i = 1; i <= length; i++) { 921 buf[length - i] = n; 922 n >>= 8; 923 } 924 WriteZ(base::StringPiece(buf, length), clas, out); 925} 926 927// WriteHeaderBlockToZ serialises |headers| to the deflate context |z| in a 928// manner that resists the length of the compressed data from compromising 929// cookie data. 930void SpdyFramer::WriteHeaderBlockToZ(const SpdyHeaderBlock* headers, 931 z_stream* z) const { 932 unsigned length_length = 4; 933 if (spdy_version_ < 3) 934 length_length = 2; 935 936 WriteLengthZ(headers->size(), length_length, kZStandardData, z); 937 938 std::map<std::string, std::string>::const_iterator it; 939 for (it = headers->begin(); it != headers->end(); ++it) { 940 WriteLengthZ(it->first.size(), length_length, kZStandardData, z); 941 WriteZ(it->first, kZStandardData, z); 942 943 if (it->first == "cookie") { 944 // We require the cookie values (save for the last) to end with a 945 // semicolon and (save for the first) to start with a space. This is 946 // typically the format that we are given them in but we reserialize them 947 // to be sure. 948 949 std::vector<base::StringPiece> cookie_values; 950 size_t cookie_length = 0; 951 base::StringPiece cookie_data(it->second); 952 953 for (;;) { 954 while (!cookie_data.empty() && 955 (cookie_data[0] == ' ' || cookie_data[0] == '\t')) { 956 cookie_data.remove_prefix(1); 957 } 958 if (cookie_data.empty()) 959 break; 960 961 size_t i; 962 for (i = 0; i < cookie_data.size(); i++) { 963 if (cookie_data[i] == ';') 964 break; 965 } 966 if (i < cookie_data.size()) { 967 cookie_values.push_back(cookie_data.substr(0, i)); 968 cookie_length += i + 2 /* semicolon and space */; 969 cookie_data.remove_prefix(i + 1); 970 } else { 971 cookie_values.push_back(cookie_data); 972 cookie_length += cookie_data.size(); 973 cookie_data.remove_prefix(i); 974 } 975 } 976 977 WriteLengthZ(cookie_length, length_length, kZStandardData, z); 978 for (size_t i = 0; i < cookie_values.size(); i++) { 979 std::string cookie; 980 // Since zlib will only back-reference complete cookies, a cookie that 981 // is currently last (and so doesn't have a trailing semicolon) won't 982 // match if it's later in a non-final position. The same is true of 983 // the first cookie. 984 if (i == 0 && cookie_values.size() == 1) { 985 cookie = cookie_values[i].as_string(); 986 } else if (i == 0) { 987 cookie = cookie_values[i].as_string() + ";"; 988 } else if (i < cookie_values.size() - 1) { 989 cookie = " " + cookie_values[i].as_string() + ";"; 990 } else { 991 cookie = " " + cookie_values[i].as_string(); 992 } 993 WriteZ(cookie, kZCookieData, z); 994 } 995 } else if (it->first == "accept" || 996 it->first == "accept-charset" || 997 it->first == "accept-encoding" || 998 it->first == "accept-language" || 999 it->first == "host" || 1000 it->first == "version" || 1001 it->first == "method" || 1002 it->first == "scheme" || 1003 it->first == ":host" || 1004 it->first == ":version" || 1005 it->first == ":method" || 1006 it->first == ":scheme" || 1007 it->first == "user-agent") { 1008 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1009 WriteZ(it->second, kZStandardData, z); 1010 } else { 1011 // Non-whitelisted headers are Huffman compressed in their own block, but 1012 // don't match against the window. 1013 WriteLengthZ(it->second.size(), length_length, kZStandardData, z); 1014 WriteZ(it->second, kZHuffmanOnlyData, z); 1015 } 1016 } 1017 1018 z->avail_in = 0; 1019 int rv = deflate(z, Z_SYNC_FLUSH); 1020 DCHECK_EQ(Z_OK, rv); 1021 z->clas = kZStandardData; 1022} 1023#endif // !defined(USE_SYSTEM_ZLIB) 1024 1025size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 1026 size_t len) { 1027 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 1028 size_t original_len = len; 1029 1030 if (remaining_control_header_ > 0) { 1031 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 1032 remaining_control_header_); 1033 remaining_control_header_ -= bytes_read; 1034 remaining_data_length_ -= bytes_read; 1035 } 1036 1037 if (remaining_control_header_ == 0) { 1038 SpdyFrameReader reader(current_frame_buffer_.get(), 1039 current_frame_buffer_length_); 1040 reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header. 1041 1042 switch (current_frame_type_) { 1043 case SYN_STREAM: 1044 { 1045 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1046 DCHECK(successful_read); 1047 1048 SpdyStreamId associated_to_stream_id = kInvalidStream; 1049 successful_read = reader.ReadUInt31(&associated_to_stream_id); 1050 DCHECK(successful_read); 1051 1052 SpdyPriority priority = 0; 1053 successful_read = reader.ReadUInt8(&priority); 1054 DCHECK(successful_read); 1055 if (protocol_version() < 3) { 1056 priority = priority >> 6; 1057 } else { 1058 priority = priority >> 5; 1059 } 1060 1061 uint8 slot = 0; 1062 if (protocol_version() < 3) { 1063 // SPDY 2 had an unused byte here. Seek past it. 1064 reader.Seek(1); 1065 } else { 1066 successful_read = reader.ReadUInt8(&slot); 1067 DCHECK(successful_read); 1068 } 1069 1070 DCHECK(reader.IsDoneReading()); 1071 visitor_->OnSynStream( 1072 current_frame_stream_id_, 1073 associated_to_stream_id, 1074 priority, 1075 slot, 1076 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0, 1077 (current_frame_flags_ & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 1078 } 1079 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1080 break; 1081 case SYN_REPLY: 1082 case HEADERS: 1083 // SYN_REPLY and HEADERS are the same, save for the visitor call. 1084 { 1085 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1086 DCHECK(successful_read); 1087 if (protocol_version() < 3) { 1088 // SPDY 2 had two unused bytes here. Seek past them. 1089 reader.Seek(2); 1090 } 1091 DCHECK(reader.IsDoneReading()); 1092 if (current_frame_type_ == SYN_REPLY) { 1093 visitor_->OnSynReply( 1094 current_frame_stream_id_, 1095 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 1096 } else { 1097 visitor_->OnHeaders( 1098 current_frame_stream_id_, 1099 (current_frame_flags_ & CONTROL_FLAG_FIN) != 0); 1100 } 1101 } 1102 CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 1103 break; 1104 case SETTINGS: 1105 visitor_->OnSettings(current_frame_flags_ & 1106 SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS); 1107 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); 1108 break; 1109 default: 1110 DCHECK(false); 1111 } 1112 } 1113 return original_len - len; 1114} 1115 1116// Does not buffer the control payload. Instead, either passes directly to the 1117// visitor or decompresses and then passes directly to the visitor, via 1118// IncrementallyDeliverControlFrameHeaderData() or 1119// IncrementallyDecompressControlFrameHeaderData() respectively. 1120size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 1121 size_t data_len) { 1122 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 1123 1124 bool processed_successfully = true; 1125 if (current_frame_type_ != SYN_STREAM && 1126 current_frame_type_ != SYN_REPLY && 1127 current_frame_type_ != HEADERS) { 1128 LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock."; 1129 } 1130 size_t process_bytes = std::min(data_len, remaining_data_length_); 1131 if (process_bytes > 0) { 1132 if (enable_compression_) { 1133 processed_successfully = IncrementallyDecompressControlFrameHeaderData( 1134 current_frame_stream_id_, data, process_bytes); 1135 } else { 1136 processed_successfully = IncrementallyDeliverControlFrameHeaderData( 1137 current_frame_stream_id_, data, process_bytes); 1138 } 1139 1140 remaining_data_length_ -= process_bytes; 1141 } 1142 1143 // Handle the case that there is no futher data in this frame. 1144 if (remaining_data_length_ == 0 && processed_successfully) { 1145 // The complete header block has been delivered. We send a zero-length 1146 // OnControlFrameHeaderData() to indicate this. 1147 visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0); 1148 1149 // If this is a FIN, tell the caller. 1150 if (current_frame_flags_ & CONTROL_FLAG_FIN) { 1151 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1152 } 1153 1154 CHANGE_STATE(SPDY_AUTO_RESET); 1155 } 1156 1157 // Handle error. 1158 if (!processed_successfully) { 1159 return data_len; 1160 } 1161 1162 // Return amount processed. 1163 return process_bytes; 1164} 1165 1166size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, 1167 size_t data_len) { 1168 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); 1169 DCHECK_EQ(SETTINGS, current_frame_type_); 1170 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); 1171 size_t processed_bytes = 0; 1172 1173 // Loop over our incoming data. 1174 while (unprocessed_bytes > 0) { 1175 // Process up to one setting at a time. 1176 size_t processing = std::min( 1177 unprocessed_bytes, 1178 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); 1179 1180 // Check if we have a complete setting in our input. 1181 if (processing == 8) { 1182 // Parse the setting directly out of the input without buffering. 1183 if (!ProcessSetting(data + processed_bytes)) { 1184 set_error(SPDY_INVALID_CONTROL_FRAME); 1185 return processed_bytes; 1186 } 1187 } else { 1188 // Continue updating settings_scratch_.setting_buf. 1189 memcpy(settings_scratch_.setting_buf + settings_scratch_.setting_buf_len, 1190 data + processed_bytes, 1191 processing); 1192 settings_scratch_.setting_buf_len += processing; 1193 1194 // Check if we have a complete setting buffered. 1195 if (settings_scratch_.setting_buf_len == 8) { 1196 if (!ProcessSetting(settings_scratch_.setting_buf)) { 1197 set_error(SPDY_INVALID_CONTROL_FRAME); 1198 return processed_bytes; 1199 } 1200 // Reset settings_scratch_.setting_buf for our next setting. 1201 settings_scratch_.setting_buf_len = 0; 1202 } 1203 } 1204 1205 // Iterate. 1206 unprocessed_bytes -= processing; 1207 processed_bytes += processing; 1208 } 1209 1210 // Check if we're done handling this SETTINGS frame. 1211 remaining_data_length_ -= processed_bytes; 1212 if (remaining_data_length_ == 0) { 1213 CHANGE_STATE(SPDY_AUTO_RESET); 1214 } 1215 1216 return processed_bytes; 1217} 1218 1219bool SpdyFramer::ProcessSetting(const char* data) { 1220 // Extract fields. 1221 // Maintain behavior of old SPDY 2 bug with byte ordering of flags/id. 1222 const uint32 id_and_flags_wire = *(reinterpret_cast<const uint32*>(data)); 1223 SettingsFlagsAndId id_and_flags = 1224 SettingsFlagsAndId::FromWireFormat(spdy_version_, id_and_flags_wire); 1225 uint8 flags = id_and_flags.flags(); 1226 uint32 value = ntohl(*(reinterpret_cast<const uint32*>(data + 4))); 1227 1228 // Validate id. 1229 switch (id_and_flags.id()) { 1230 case SETTINGS_UPLOAD_BANDWIDTH: 1231 case SETTINGS_DOWNLOAD_BANDWIDTH: 1232 case SETTINGS_ROUND_TRIP_TIME: 1233 case SETTINGS_MAX_CONCURRENT_STREAMS: 1234 case SETTINGS_CURRENT_CWND: 1235 case SETTINGS_DOWNLOAD_RETRANS_RATE: 1236 case SETTINGS_INITIAL_WINDOW_SIZE: 1237 // Valid values. 1238 break; 1239 default: 1240 DLOG(WARNING) << "Unknown SETTINGS ID: " << id_and_flags.id(); 1241 return false; 1242 } 1243 SpdySettingsIds id = static_cast<SpdySettingsIds>(id_and_flags.id()); 1244 1245 // Detect duplciates. 1246 if (static_cast<uint32>(id) <= settings_scratch_.last_setting_id) { 1247 DLOG(WARNING) << "Duplicate entry or invalid ordering for id " << id 1248 << " in " << display_protocol_ << " SETTINGS frame " 1249 << "(last settikng id was " 1250 << settings_scratch_.last_setting_id << ")."; 1251 return false; 1252 } 1253 settings_scratch_.last_setting_id = id; 1254 1255 // Validate flags. 1256 uint8 kFlagsMask = SETTINGS_FLAG_PLEASE_PERSIST | SETTINGS_FLAG_PERSISTED; 1257 if ((flags & ~(kFlagsMask)) != 0) { 1258 DLOG(WARNING) << "Unknown SETTINGS flags provided for id " << id << ": " 1259 << flags; 1260 return false; 1261 } 1262 1263 // Validation succeeded. Pass on to visitor. 1264 visitor_->OnSetting(id, flags, value); 1265 return true; 1266} 1267 1268size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 1269 size_t original_len = len; 1270 if (remaining_data_length_) { 1271 size_t bytes_read = 1272 UpdateCurrentFrameBuffer(&data, &len, remaining_data_length_); 1273 remaining_data_length_ -= bytes_read; 1274 if (remaining_data_length_ == 0) { 1275 SpdyFrameReader reader(current_frame_buffer_.get(), 1276 current_frame_buffer_length_); 1277 reader.Seek(GetControlFrameHeaderSize()); // Skip frame header. 1278 1279 // Use frame-specific handlers. 1280 switch (current_frame_type_) { 1281 case PING: { 1282 SpdyPingId id = 0; 1283 bool successful_read = reader.ReadUInt32(&id); 1284 DCHECK(successful_read); 1285 DCHECK(reader.IsDoneReading()); 1286 visitor_->OnPing(id); 1287 } 1288 break; 1289 case WINDOW_UPDATE: { 1290 uint32 delta_window_size = 0; 1291 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1292 DCHECK(successful_read); 1293 successful_read = reader.ReadUInt31(&delta_window_size); 1294 DCHECK(successful_read); 1295 DCHECK(reader.IsDoneReading()); 1296 visitor_->OnWindowUpdate(current_frame_stream_id_, 1297 delta_window_size); 1298 } 1299 break; 1300 case RST_STREAM: { 1301 bool successful_read = reader.ReadUInt32(¤t_frame_stream_id_); 1302 DCHECK(successful_read); 1303 SpdyRstStreamStatus status = RST_STREAM_INVALID; 1304 uint32 status_raw = status; 1305 successful_read = reader.ReadUInt32(&status_raw); 1306 DCHECK(successful_read); 1307 if (status_raw > RST_STREAM_INVALID && 1308 status_raw < RST_STREAM_NUM_STATUS_CODES) { 1309 status = static_cast<SpdyRstStreamStatus>(status_raw); 1310 } else { 1311 // TODO(hkhalil): Probably best to OnError here, depending on 1312 // our interpretation of the spec. Keeping with existing liberal 1313 // behavior for now. 1314 } 1315 DCHECK(reader.IsDoneReading()); 1316 visitor_->OnRstStream(current_frame_stream_id_, status); 1317 } 1318 break; 1319 case GOAWAY: { 1320 bool successful_read = reader.ReadUInt31(¤t_frame_stream_id_); 1321 DCHECK(successful_read); 1322 SpdyGoAwayStatus status = GOAWAY_OK; 1323 if (spdy_version_ >= 3) { 1324 uint32 status_raw = GOAWAY_OK; 1325 successful_read = reader.ReadUInt32(&status_raw); 1326 DCHECK(successful_read); 1327 if (status_raw > static_cast<uint32>(GOAWAY_INVALID) && 1328 status_raw < static_cast<uint32>(GOAWAY_NUM_STATUS_CODES)) { 1329 status = static_cast<SpdyGoAwayStatus>(status_raw); 1330 } else { 1331 // TODO(hkhalil): Probably best to OnError here, depending on 1332 // our interpretation of the spec. Keeping with existing liberal 1333 // behavior for now. 1334 } 1335 } 1336 DCHECK(reader.IsDoneReading()); 1337 visitor_->OnGoAway(current_frame_stream_id_, status); 1338 } 1339 break; 1340 default: 1341 // Unreachable. 1342 LOG(FATAL) << "Unhandled control frame " << current_frame_type_; 1343 } 1344 1345 CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 1346 } 1347 } 1348 return original_len - len; 1349} 1350 1351size_t SpdyFramer::ProcessCredentialFramePayload(const char* data, size_t len) { 1352 if (len > 0) { 1353 bool processed_succesfully = visitor_->OnCredentialFrameData(data, len); 1354 remaining_data_length_ -= len; 1355 if (!processed_succesfully) { 1356 set_error(SPDY_CREDENTIAL_FRAME_CORRUPT); 1357 } else if (remaining_data_length_ == 0) { 1358 visitor_->OnCredentialFrameData(NULL, 0); 1359 CHANGE_STATE(SPDY_AUTO_RESET); 1360 } 1361 } 1362 return len; 1363} 1364 1365size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 1366 size_t original_len = len; 1367 1368 if (remaining_data_length_ > 0) { 1369 size_t amount_to_forward = std::min(remaining_data_length_, len); 1370 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 1371 // Only inform the visitor if there is data. 1372 if (amount_to_forward) { 1373 visitor_->OnStreamFrameData( 1374 current_frame_stream_id_, data, amount_to_forward, false); 1375 } 1376 } 1377 data += amount_to_forward; 1378 len -= amount_to_forward; 1379 remaining_data_length_ -= amount_to_forward; 1380 1381 // If the FIN flag is set, and there is no more data in this data 1382 // frame, inform the visitor of EOF via a 0-length data frame. 1383 if (!remaining_data_length_ && current_frame_flags_ & DATA_FLAG_FIN) { 1384 visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true); 1385 } 1386 } 1387 1388 if (remaining_data_length_ == 0) { 1389 CHANGE_STATE(SPDY_AUTO_RESET); 1390 } 1391 return original_len - len; 1392} 1393 1394size_t SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 1395 size_t header_length, 1396 SpdyHeaderBlock* block) const { 1397 SpdyFrameReader reader(header_data, header_length); 1398 1399 // Read number of headers. 1400 uint32 num_headers; 1401 if (spdy_version_ < 3) { 1402 uint16 temp; 1403 if (!reader.ReadUInt16(&temp)) { 1404 DLOG(INFO) << "Unable to read number of headers."; 1405 return 0; 1406 } 1407 num_headers = temp; 1408 } else { 1409 if (!reader.ReadUInt32(&num_headers)) { 1410 DLOG(INFO) << "Unable to read number of headers."; 1411 return 0; 1412 } 1413 } 1414 1415 // Read each header. 1416 for (uint32 index = 0; index < num_headers; ++index) { 1417 base::StringPiece temp; 1418 1419 // Read header name. 1420 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 1421 : !reader.ReadStringPiece32(&temp)) { 1422 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " 1423 << num_headers << ")."; 1424 return 0; 1425 } 1426 std::string name = temp.as_string(); 1427 1428 // Read header value. 1429 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) 1430 : !reader.ReadStringPiece32(&temp)) { 1431 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " 1432 << num_headers << ")."; 1433 return 0; 1434 } 1435 std::string value = temp.as_string(); 1436 1437 // Ensure no duplicates. 1438 if (block->find(name) != block->end()) { 1439 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " 1440 << num_headers << ")."; 1441 return 0; 1442 } 1443 1444 // Store header. 1445 (*block)[name] = value; 1446 } 1447 return reader.GetBytesConsumed(); 1448} 1449 1450/* static */ 1451bool SpdyFramer::ParseCredentialData(const char* data, size_t len, 1452 SpdyCredential* credential) { 1453 DCHECK(credential); 1454 1455 SpdyFrameReader parser(data, len); 1456 base::StringPiece temp; 1457 if (!parser.ReadUInt16(&credential->slot)) { 1458 return false; 1459 } 1460 1461 if (!parser.ReadStringPiece32(&temp)) { 1462 return false; 1463 } 1464 credential->proof = temp.as_string(); 1465 1466 while (!parser.IsDoneReading()) { 1467 if (!parser.ReadStringPiece32(&temp)) { 1468 return false; 1469 } 1470 credential->certs.push_back(temp.as_string()); 1471 } 1472 return true; 1473} 1474 1475SpdyFrame* SpdyFramer::CreateSynStream( 1476 SpdyStreamId stream_id, 1477 SpdyStreamId associated_stream_id, 1478 SpdyPriority priority, 1479 uint8 credential_slot, 1480 SpdyControlFlags flags, 1481 bool compressed, 1482 const SpdyHeaderBlock* headers) { 1483 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL); 1484 DCHECK_EQ(enable_compression_, compressed); 1485 1486 SpdySynStreamIR syn_stream(stream_id); 1487 syn_stream.set_associated_to_stream_id(associated_stream_id); 1488 syn_stream.set_priority(priority); 1489 syn_stream.set_slot(credential_slot); 1490 syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); 1491 syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); 1492 // TODO(hkhalil): Avoid copy here. 1493 *(syn_stream.GetMutableNameValueBlock()) = *headers; 1494 1495 scoped_ptr<SpdyFrame> syn_frame(SerializeSynStream(syn_stream)); 1496 return syn_frame.release(); 1497} 1498 1499SpdySerializedFrame* SpdyFramer::SerializeSynStream( 1500 const SpdySynStreamIR& syn_stream) { 1501 uint8 flags = 0; 1502 if (syn_stream.fin()) { 1503 flags |= CONTROL_FLAG_FIN; 1504 } 1505 if (syn_stream.unidirectional()) { 1506 flags |= CONTROL_FLAG_UNIDIRECTIONAL; 1507 } 1508 1509 // The size of this frame, including variable-length name-value block. 1510 const size_t size = GetSynStreamMinimumSize() 1511 + GetSerializedLength(syn_stream.name_value_block()); 1512 1513 SpdyFrameBuilder builder(size); 1514 builder.WriteControlFrameHeader(*this, SYN_STREAM, flags); 1515 builder.WriteUInt32(syn_stream.stream_id()); 1516 builder.WriteUInt32(syn_stream.associated_to_stream_id()); 1517 uint8 priority = syn_stream.priority(); 1518 if (priority > GetLowestPriority()) { 1519 DLOG(DFATAL) << "Priority out-of-bounds."; 1520 priority = GetLowestPriority(); 1521 } 1522 builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); 1523 builder.WriteUInt8(syn_stream.slot()); 1524 DCHECK_EQ(GetSynStreamMinimumSize(), builder.length()); 1525 SerializeNameValueBlock(&builder, syn_stream); 1526 1527 if (visitor_) 1528 visitor_->OnSynStreamCompressed(size, builder.length()); 1529 1530 return builder.take(); 1531} 1532 1533SpdyFrame* SpdyFramer::CreateSynReply( 1534 SpdyStreamId stream_id, 1535 SpdyControlFlags flags, 1536 bool compressed, 1537 const SpdyHeaderBlock* headers) { 1538 DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); 1539 DCHECK_EQ(enable_compression_, compressed); 1540 1541 SpdySynReplyIR syn_reply(stream_id); 1542 syn_reply.set_fin(flags & CONTROL_FLAG_FIN); 1543 // TODO(hkhalil): Avoid copy here. 1544 *(syn_reply.GetMutableNameValueBlock()) = *headers; 1545 1546 scoped_ptr<SpdyFrame> reply_frame(SerializeSynReply(syn_reply)); 1547 return reply_frame.release(); 1548} 1549 1550SpdySerializedFrame* SpdyFramer::SerializeSynReply( 1551 const SpdySynReplyIR& syn_reply) { 1552 uint8 flags = 0; 1553 if (syn_reply.fin()) { 1554 flags |= CONTROL_FLAG_FIN; 1555 } 1556 1557 // The size of this frame, including variable-length name-value block. 1558 size_t size = GetSynReplyMinimumSize() 1559 + GetSerializedLength(syn_reply.name_value_block()); 1560 1561 SpdyFrameBuilder builder(size); 1562 builder.WriteControlFrameHeader(*this, SYN_REPLY, flags); 1563 builder.WriteUInt32(syn_reply.stream_id()); 1564 if (protocol_version() < 3) { 1565 builder.WriteUInt16(0); // Unused. 1566 } 1567 DCHECK_EQ(GetSynReplyMinimumSize(), builder.length()); 1568 SerializeNameValueBlock(&builder, syn_reply); 1569 1570 return builder.take(); 1571} 1572 1573SpdyFrame* SpdyFramer::CreateRstStream( 1574 SpdyStreamId stream_id, 1575 SpdyRstStreamStatus status) const { 1576 SpdyRstStreamIR rst_stream(stream_id, status); 1577 return SerializeRstStream(rst_stream); 1578} 1579 1580SpdySerializedFrame* SpdyFramer::SerializeRstStream( 1581 const SpdyRstStreamIR& rst_stream) const { 1582 SpdyFrameBuilder builder(GetRstStreamSize()); 1583 builder.WriteControlFrameHeader(*this, RST_STREAM, 0); 1584 builder.WriteUInt32(rst_stream.stream_id()); 1585 builder.WriteUInt32(rst_stream.status()); 1586 DCHECK_EQ(GetRstStreamSize(), builder.length()); 1587 return builder.take(); 1588} 1589 1590SpdyFrame* SpdyFramer::CreateSettings( 1591 const SettingsMap& values) const { 1592 SpdySettingsIR settings; 1593 for (SettingsMap::const_iterator it = values.begin(); 1594 it != values.end(); 1595 ++it) { 1596 settings.AddSetting(it->first, 1597 (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, 1598 (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, 1599 it->second.second); 1600 } 1601 return SerializeSettings(settings); 1602} 1603 1604SpdySerializedFrame* SpdyFramer::SerializeSettings( 1605 const SpdySettingsIR& settings) const { 1606 uint8 flags = 0; 1607 if (settings.clear_settings()) { 1608 flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; 1609 } 1610 const SpdySettingsIR::ValueMap* values = &(settings.values()); 1611 1612 // Size, in bytes, of this SETTINGS frame. 1613 const size_t size = GetSettingsMinimumSize() + (values->size() * 8); 1614 1615 SpdyFrameBuilder builder(size); 1616 builder.WriteControlFrameHeader(*this, SETTINGS, flags); 1617 builder.WriteUInt32(values->size()); 1618 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); 1619 for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); 1620 it != values->end(); 1621 ++it) { 1622 uint8 setting_flags = 0; 1623 if (it->second.persist_value) { 1624 setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; 1625 } 1626 if (it->second.persisted) { 1627 setting_flags |= SETTINGS_FLAG_PERSISTED; 1628 } 1629 SettingsFlagsAndId flags_and_id(setting_flags, it->first); 1630 uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); 1631 builder.WriteBytes(&id_and_flags_wire, 4); 1632 builder.WriteUInt32(it->second.value); 1633 } 1634 DCHECK_EQ(size, builder.length()); 1635 return builder.take(); 1636} 1637 1638SpdyFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { 1639 SpdyPingIR ping(unique_id); 1640 return SerializePing(ping); 1641} 1642 1643SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { 1644 SpdyFrameBuilder builder(GetPingSize()); 1645 builder.WriteControlFrameHeader(*this, PING, 0); 1646 builder.WriteUInt32(ping.id()); 1647 DCHECK_EQ(GetPingSize(), builder.length()); 1648 return builder.take(); 1649} 1650 1651SpdyFrame* SpdyFramer::CreateGoAway( 1652 SpdyStreamId last_accepted_stream_id, 1653 SpdyGoAwayStatus status) const { 1654 SpdyGoAwayIR goaway(last_accepted_stream_id, status); 1655 return SerializeGoAway(goaway); 1656} 1657 1658SpdySerializedFrame* SpdyFramer::SerializeGoAway( 1659 const SpdyGoAwayIR& goaway) const { 1660 SpdyFrameBuilder builder(GetGoAwaySize()); 1661 builder.WriteControlFrameHeader(*this, GOAWAY, 0); 1662 builder.WriteUInt32(goaway.last_good_stream_id()); 1663 if (protocol_version() >= 3) { 1664 builder.WriteUInt32(goaway.status()); 1665 } 1666 DCHECK_EQ(GetGoAwaySize(), builder.length()); 1667 return builder.take(); 1668} 1669 1670SpdyFrame* SpdyFramer::CreateHeaders( 1671 SpdyStreamId stream_id, 1672 SpdyControlFlags flags, 1673 bool compressed, 1674 const SpdyHeaderBlock* header_block) { 1675 // Basically the same as CreateSynReply(). 1676 DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); 1677 DCHECK_EQ(enable_compression_, compressed); 1678 1679 SpdyHeadersIR headers(stream_id); 1680 headers.set_fin(flags & CONTROL_FLAG_FIN); 1681 // TODO(hkhalil): Avoid copy here. 1682 *(headers.GetMutableNameValueBlock()) = *header_block; 1683 1684 scoped_ptr<SpdyFrame> headers_frame(SerializeHeaders(headers)); 1685 return headers_frame.release(); 1686} 1687 1688SpdySerializedFrame* SpdyFramer::SerializeHeaders( 1689 const SpdyHeadersIR& headers) { 1690 uint8 flags = 0; 1691 if (headers.fin()) { 1692 flags |= CONTROL_FLAG_FIN; 1693 } 1694 1695 // The size of this frame, including variable-length name-value block. 1696 size_t size = GetHeadersMinimumSize() 1697 + GetSerializedLength(headers.name_value_block()); 1698 1699 SpdyFrameBuilder builder(size); 1700 builder.WriteControlFrameHeader(*this, HEADERS, flags); 1701 builder.WriteUInt32(headers.stream_id()); 1702 if (protocol_version() < 3) { 1703 builder.WriteUInt16(0); // Unused. 1704 } 1705 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); 1706 1707 SerializeNameValueBlock(&builder, headers); 1708 1709 return builder.take(); 1710} 1711 1712SpdyFrame* SpdyFramer::CreateWindowUpdate( 1713 SpdyStreamId stream_id, 1714 uint32 delta_window_size) const { 1715 SpdyWindowUpdateIR window_update(stream_id, delta_window_size); 1716 return SerializeWindowUpdate(window_update); 1717} 1718 1719SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( 1720 const SpdyWindowUpdateIR& window_update) const { 1721 SpdyFrameBuilder builder(GetWindowUpdateSize()); 1722 builder.WriteControlFrameHeader(*this, WINDOW_UPDATE, kNoFlags); 1723 builder.WriteUInt32(window_update.stream_id()); 1724 builder.WriteUInt32(window_update.delta()); 1725 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); 1726 return builder.take(); 1727} 1728 1729// TODO(hkhalil): Gut with SpdyCredential removal. 1730SpdyFrame* SpdyFramer::CreateCredentialFrame( 1731 const SpdyCredential& credential) const { 1732 SpdyCredentialIR credential_ir(credential.slot); 1733 credential_ir.set_proof(credential.proof); 1734 for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); 1735 cert != credential.certs.end(); 1736 ++cert) { 1737 credential_ir.AddCertificate(*cert); 1738 } 1739 return SerializeCredential(credential_ir); 1740} 1741 1742SpdySerializedFrame* SpdyFramer::SerializeCredential( 1743 const SpdyCredentialIR& credential) const { 1744 size_t size = GetCredentialMinimumSize(); 1745 size += 4 + credential.proof().length(); // Room for proof. 1746 for (SpdyCredentialIR::CertificateList::const_iterator it = 1747 credential.certificates()->begin(); 1748 it != credential.certificates()->end(); 1749 ++it) { 1750 size += 4 + it->length(); // Room for certificate. 1751 } 1752 1753 SpdyFrameBuilder builder(size); 1754 builder.WriteControlFrameHeader(*this, CREDENTIAL, 0); 1755 builder.WriteUInt16(credential.slot()); 1756 DCHECK_EQ(GetCredentialMinimumSize(), builder.length()); 1757 builder.WriteStringPiece32(credential.proof()); 1758 for (SpdyCredentialIR::CertificateList::const_iterator it = 1759 credential.certificates()->begin(); 1760 it != credential.certificates()->end(); 1761 ++it) { 1762 builder.WriteStringPiece32(*it); 1763 } 1764 DCHECK_EQ(size, builder.length()); 1765 return builder.take(); 1766} 1767 1768SpdyFrame* SpdyFramer::CreateDataFrame( 1769 SpdyStreamId stream_id, const char* data, 1770 uint32 len, SpdyDataFlags flags) const { 1771 DCHECK_EQ(0, flags & (!DATA_FLAG_FIN)); 1772 1773 SpdyDataIR data_ir(stream_id, base::StringPiece(data, len)); 1774 data_ir.set_fin(flags & DATA_FLAG_FIN); 1775 return SerializeData(data_ir); 1776} 1777 1778SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const { 1779 const size_t kSize = GetDataFrameMinimumSize() + data.data().length(); 1780 1781 SpdyDataFlags flags = DATA_FLAG_NONE; 1782 if (data.fin()) { 1783 flags = DATA_FLAG_FIN; 1784 } 1785 1786 SpdyFrameBuilder builder(kSize); 1787 builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1788 builder.WriteBytes(data.data().data(), data.data().length()); 1789 DCHECK_EQ(kSize, builder.length()); 1790 return builder.take(); 1791} 1792 1793SpdySerializedFrame* SpdyFramer::SerializeDataFrameHeader( 1794 const SpdyDataIR& data) const { 1795 const size_t kSize = GetDataFrameMinimumSize(); 1796 1797 SpdyDataFlags flags = DATA_FLAG_NONE; 1798 if (data.fin()) { 1799 flags = DATA_FLAG_FIN; 1800 } 1801 1802 SpdyFrameBuilder builder(kSize); 1803 builder.WriteDataFrameHeader(*this, data.stream_id(), flags); 1804 if (protocol_version() < 4) { 1805 builder.OverwriteLength(*this, data.data().length()); 1806 } else { 1807 builder.OverwriteLength(*this, data.data().length() + kSize); 1808 } 1809 DCHECK_EQ(kSize, builder.length()); 1810 return builder.take(); 1811} 1812 1813size_t SpdyFramer::GetSerializedLength(const SpdyHeaderBlock& headers) { 1814 const size_t uncompressed_length = 1815 GetSerializedLength(protocol_version(), &headers); 1816 if (!enable_compression_) { 1817 return uncompressed_length; 1818 } 1819 z_stream* compressor = GetHeaderCompressor(); 1820 // Since we'll be performing lots of flushes when compressing the data, 1821 // zlib's lower bounds may be insufficient. 1822 return 2 * deflateBound(compressor, uncompressed_length); 1823} 1824 1825// The following compression setting are based on Brian Olson's analysis. See 1826// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 1827// for more details. 1828#if defined(USE_SYSTEM_ZLIB) 1829// System zlib is not expected to have workaround for http://crbug.com/139744, 1830// so disable compression in that case. 1831// TODO(phajdan.jr): Remove the special case when it's no longer necessary. 1832static const int kCompressorLevel = 0; 1833#else // !defined(USE_SYSTEM_ZLIB) 1834static const int kCompressorLevel = 9; 1835#endif // !defined(USE_SYSTEM_ZLIB) 1836static const int kCompressorWindowSizeInBits = 11; 1837static const int kCompressorMemLevel = 1; 1838 1839z_stream* SpdyFramer::GetHeaderCompressor() { 1840 if (header_compressor_.get()) 1841 return header_compressor_.get(); // Already initialized. 1842 1843 header_compressor_.reset(new z_stream); 1844 memset(header_compressor_.get(), 0, sizeof(z_stream)); 1845 1846 int success = deflateInit2(header_compressor_.get(), 1847 kCompressorLevel, 1848 Z_DEFLATED, 1849 kCompressorWindowSizeInBits, 1850 kCompressorMemLevel, 1851 Z_DEFAULT_STRATEGY); 1852 if (success == Z_OK) { 1853 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 1854 : kV3Dictionary; 1855 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 1856 : kV3DictionarySize; 1857 success = deflateSetDictionary(header_compressor_.get(), 1858 reinterpret_cast<const Bytef*>(dictionary), 1859 dictionary_size); 1860 } 1861 if (success != Z_OK) { 1862 LOG(WARNING) << "deflateSetDictionary failure: " << success; 1863 header_compressor_.reset(NULL); 1864 return NULL; 1865 } 1866 return header_compressor_.get(); 1867} 1868 1869z_stream* SpdyFramer::GetHeaderDecompressor() { 1870 if (header_decompressor_.get()) 1871 return header_decompressor_.get(); // Already initialized. 1872 1873 header_decompressor_.reset(new z_stream); 1874 memset(header_decompressor_.get(), 0, sizeof(z_stream)); 1875 1876 int success = inflateInit(header_decompressor_.get()); 1877 if (success != Z_OK) { 1878 LOG(WARNING) << "inflateInit failure: " << success; 1879 header_decompressor_.reset(NULL); 1880 return NULL; 1881 } 1882 return header_decompressor_.get(); 1883} 1884 1885// Incrementally decompress the control frame's header block, feeding the 1886// result to the visitor in chunks. Continue this until the visitor 1887// indicates that it cannot process any more data, or (more commonly) we 1888// run out of data to deliver. 1889bool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 1890 SpdyStreamId stream_id, 1891 const char* data, 1892 size_t len) { 1893 // Get a decompressor or set error. 1894 z_stream* decomp = GetHeaderDecompressor(); 1895 if (decomp == NULL) { 1896 LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 1897 set_error(SPDY_DECOMPRESS_FAILURE); 1898 return false; 1899 } 1900 1901 bool processed_successfully = true; 1902 char buffer[kHeaderDataChunkMaxSize]; 1903 1904 decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 1905 decomp->avail_in = len; 1906 DCHECK_LT(0u, stream_id); 1907 while (decomp->avail_in > 0 && processed_successfully) { 1908 decomp->next_out = reinterpret_cast<Bytef*>(buffer); 1909 decomp->avail_out = arraysize(buffer); 1910 1911 int rv = inflate(decomp, Z_SYNC_FLUSH); 1912 if (rv == Z_NEED_DICT) { 1913 const char* dictionary = (spdy_version_ < 3) ? kV2Dictionary 1914 : kV3Dictionary; 1915 const int dictionary_size = (spdy_version_ < 3) ? kV2DictionarySize 1916 : kV3DictionarySize; 1917 const DictionaryIds& ids = g_dictionary_ids.Get(); 1918 const uLong dictionary_id = (spdy_version_ < 3) ? ids.v2_dictionary_id 1919 : ids.v3_dictionary_id; 1920 // Need to try again with the right dictionary. 1921 if (decomp->adler == dictionary_id) { 1922 rv = inflateSetDictionary(decomp, 1923 reinterpret_cast<const Bytef*>(dictionary), 1924 dictionary_size); 1925 if (rv == Z_OK) 1926 rv = inflate(decomp, Z_SYNC_FLUSH); 1927 } 1928 } 1929 1930 // Inflate will generate a Z_BUF_ERROR if it runs out of input 1931 // without producing any output. The input is consumed and 1932 // buffered internally by zlib so we can detect this condition by 1933 // checking if avail_in is 0 after the call to inflate. 1934 bool input_exhausted = ((rv == Z_BUF_ERROR) && (decomp->avail_in == 0)); 1935 if ((rv == Z_OK) || input_exhausted) { 1936 size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 1937 if (debug_visitor_ != NULL) { 1938 debug_visitor_->OnDecompressedHeaderBlock(decompressed_len, len); 1939 } 1940 if (decompressed_len > 0) { 1941 processed_successfully = visitor_->OnControlFrameHeaderData( 1942 stream_id, buffer, decompressed_len); 1943 } 1944 if (!processed_successfully) { 1945 // Assume that the problem was the header block was too large for the 1946 // visitor. 1947 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 1948 } 1949 } else { 1950 DLOG(WARNING) << "inflate failure: " << rv << " " << len; 1951 set_error(SPDY_DECOMPRESS_FAILURE); 1952 processed_successfully = false; 1953 } 1954 } 1955 return processed_successfully; 1956} 1957 1958bool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 1959 SpdyStreamId stream_id, const char* data, size_t len) { 1960 bool read_successfully = true; 1961 while (read_successfully && len > 0) { 1962 size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 1963 read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 1964 bytes_to_deliver); 1965 data += bytes_to_deliver; 1966 len -= bytes_to_deliver; 1967 if (!read_successfully) { 1968 // Assume that the problem was the header block was too large for the 1969 // visitor. 1970 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 1971 } 1972 } 1973 return read_successfully; 1974} 1975 1976void SpdyFramer::SerializeNameValueBlockWithoutCompression( 1977 SpdyFrameBuilder* builder, 1978 const SpdyNameValueBlock& name_value_block) const { 1979 // Serialize number of headers. 1980 if (protocol_version() < 3) { 1981 builder->WriteUInt16(name_value_block.size()); 1982 } else { 1983 builder->WriteUInt32(name_value_block.size()); 1984 } 1985 1986 // Serialize each header. 1987 for (SpdyHeaderBlock::const_iterator it = name_value_block.begin(); 1988 it != name_value_block.end(); 1989 ++it) { 1990 if (protocol_version() < 3) { 1991 builder->WriteString(it->first); 1992 builder->WriteString(it->second); 1993 } else { 1994 builder->WriteStringPiece32(it->first); 1995 builder->WriteStringPiece32(it->second); 1996 } 1997 } 1998} 1999 2000void SpdyFramer::SerializeNameValueBlock( 2001 SpdyFrameBuilder* builder, 2002 const SpdyFrameWithNameValueBlockIR& frame) { 2003 if (!enable_compression_) { 2004 return SerializeNameValueBlockWithoutCompression(builder, 2005 frame.name_value_block()); 2006 } 2007 2008 // First build an uncompressed version to be fed into the compressor. 2009 const size_t uncompressed_len = GetSerializedLength( 2010 protocol_version(), &(frame.name_value_block())); 2011 SpdyFrameBuilder uncompressed_builder(uncompressed_len); 2012 SerializeNameValueBlockWithoutCompression(&uncompressed_builder, 2013 frame.name_value_block()); 2014 scoped_ptr<SpdyFrame> uncompressed_payload(uncompressed_builder.take()); 2015 2016 z_stream* compressor = GetHeaderCompressor(); 2017 if (!compressor) { 2018 LOG(DFATAL) << "Could not obtain compressor."; 2019 return; 2020 } 2021 2022 base::StatsCounter compressed_frames("spdy.CompressedFrames"); 2023 base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 2024 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 2025 2026 // Create an output frame. 2027 // Since we'll be performing lots of flushes when compressing the data, 2028 // zlib's lower bounds may be insufficient. 2029 // 2030 // TODO(akalin): Avoid the duplicate calculation with 2031 // GetSerializedLength(const SpdyHeaderBlock&). 2032 const int compressed_max_size = 2033 2 * deflateBound(compressor, uncompressed_len); 2034 2035 // TODO(phajdan.jr): Clean up after we no longer need 2036 // to workaround http://crbug.com/139744. 2037#if defined(USE_SYSTEM_ZLIB) 2038 compressor->next_in = reinterpret_cast<Bytef*>(uncompressed_payload->data()); 2039 compressor->avail_in = uncompressed_len; 2040#endif // defined(USE_SYSTEM_ZLIB) 2041 compressor->next_out = reinterpret_cast<Bytef*>( 2042 builder->GetWritableBuffer(compressed_max_size)); 2043 compressor->avail_out = compressed_max_size; 2044 2045 // TODO(phajdan.jr): Clean up after we no longer need 2046 // to workaround http://crbug.com/139744. 2047#if defined(USE_SYSTEM_ZLIB) 2048 int rv = deflate(compressor, Z_SYNC_FLUSH); 2049 if (rv != Z_OK) { // How can we know that it compressed everything? 2050 // This shouldn't happen, right? 2051 LOG(WARNING) << "deflate failure: " << rv; 2052 // TODO(akalin): Upstream this return. 2053 return; 2054 } 2055#else 2056 WriteHeaderBlockToZ(&frame.name_value_block(), compressor); 2057#endif // defined(USE_SYSTEM_ZLIB) 2058 2059 int compressed_size = compressed_max_size - compressor->avail_out; 2060 builder->Seek(compressed_size); 2061 builder->RewriteLength(*this); 2062 2063 pre_compress_bytes.Add(uncompressed_len); 2064 post_compress_bytes.Add(compressed_size); 2065 2066 compressed_frames.Increment(); 2067 2068 if (debug_visitor_ != NULL) { 2069 debug_visitor_->OnCompressedHeaderBlock(uncompressed_len, compressed_size); 2070 } 2071} 2072 2073} // namespace net 2074