1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// TODO(rtenhove) clean up frame buffer size calculations so that we aren't 6201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// constantly adding and subtracting header sizes; this is ugly and error- 7201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// prone. 8201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_framer.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/stats_counters.h" 130888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#ifndef ANDROID 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/third_party/valgrind/memcheck.h" 150888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#endif 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_frame_builder.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/spdy/spdy_bitmasks.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(USE_SYSTEM_ZLIB) 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <zlib.h> 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "third_party/zlib/zlib.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace { 2672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// The following compression setting are based on Brian Olson's analysis. See 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac792 2972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// for more details. 30de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#ifdef ANDROID 31de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurunconst int kCompressorLevel = 0; 32de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#else 3372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int kCompressorLevel = 9; 34de6c9f9aec5e2e7e66cb77140f7418fc29644ef0Selim Gurun#endif 3572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int kCompressorWindowSizeInBits = 11; 3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int kCompressorMemLevel = 1; 3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Adler ID for the SPDY header compressor dictionary. 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenuLong dictionary_id = 0; 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 4172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace 4272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace spdy { 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// This is just a hacked dictionary to use for shrinking HTTP-like headers. 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// TODO(mbelshe): Use a scientific methodology for computing the dictionary. 4772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char SpdyFramer::kDictionary[] = 4872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "optionsgetheadpostputdeletetraceacceptaccept-charsetaccept-encodingaccept-" 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "languageauthorizationexpectfromhostif-modified-sinceif-matchif-none-matchi" 5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "f-rangeif-unmodifiedsincemax-forwardsproxy-authorizationrangerefererteuser" 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "-agent10010120020120220320420520630030130230330430530630740040140240340440" 5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "5406407408409410411412413414415416417500501502503504505accept-rangesageeta" 5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "glocationproxy-authenticatepublicretry-afterservervarywarningwww-authentic" 5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "ateallowcontent-basecontent-encodingcache-controlconnectiondatetrailertran" 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "sfer-encodingupgradeviawarningcontent-languagecontent-lengthcontent-locati" 5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "oncontent-md5content-rangecontent-typeetagexpireslast-modifiedset-cookieMo" 5772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "ndayTuesdayWednesdayThursdayFridaySaturdaySundayJanFebMarAprMayJunJulAugSe" 5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "pOctNovDecchunkedtext/htmlimage/pngimage/jpgimage/gifapplication/xmlapplic" 5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "ation/xhtmltext/plainpublicmax-agecharset=iso-8859-1utf-8gzipdeflateHTTP/1" 6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ".1statusversionurl"; 6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst int SpdyFramer::kDictionarySize = arraysize(kDictionary); 6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// By default is compression on or off. 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SpdyFramer::compression_default_ = true; 653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint SpdyFramer::spdy_version_ = kSpdyProtocolVersion; 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The initial size of the control frame buffer; this is used internally 68201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// as we parse through control frames. (It is exposed here for unit test 69201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// purposes.) 70201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochsize_t SpdyFramer::kControlFrameBufferInitialSize = 8 * 1024; 71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 72201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// The maximum size of the control frame buffer that we support. 73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// TODO(mbelshe): We should make this stream-based so there are no limits. 74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochsize_t SpdyFramer::kControlFrameBufferMaxSize = 16 * 1024; 75201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunconst SpdyStreamId SpdyFramer::kInvalidStream = -1; 772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunconst size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; 782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#ifdef DEBUG_SPDY_STATE_CHANGES 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHANGE_STATE(newstate) \ 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch{ \ 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch do { \ 83201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch LOG(INFO) << "Changing state from: " \ 84201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << StateToString(state_) \ 85201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch << " to " << StateToString(newstate) << "\n"; \ 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch state_ = newstate; \ 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } while (false); \ 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#define CHANGE_STATE(newstate) (state_ = newstate) 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunint DecompressHeaderBlockInZStream(z_stream* decompressor) { 942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int rv = inflate(decompressor, Z_SYNC_FLUSH); 952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (rv == Z_NEED_DICT) { 962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Need to try again with the right dictionary. 972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (decompressor->adler == dictionary_id) { 982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun rv = inflateSetDictionary(decompressor, 992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun (const Bytef*)SpdyFramer::kDictionary, 1002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyFramer::kDictionarySize); 1012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (rv == Z_OK) 1022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun rv = inflate(decompressor, Z_SYNC_FLUSH); 1032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return rv; 1062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 1072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Retrieve serialized length of SpdyHeaderBlock. 1092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t GetSerializedLength(const SpdyHeaderBlock* headers) { 1102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t total_length = SpdyControlFrame::kNumNameValuePairsSize; 1112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock::const_iterator it; 1122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun for (it = headers->begin(); it != headers->end(); ++it) { 1132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // We add space for the length of the name and the length of the value as 1142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // well as the length of the name and the length of the value. 1152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun total_length += SpdyControlFrame::kLengthOfNameSize + 1162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun it->first.size() + 1172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFrame::kLengthOfValueSize + 1182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun it->second.size(); 1192c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1202c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return total_length; 1212c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 1222c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1232c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Serializes a SpdyHeaderBlock. 1242c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunvoid WriteHeaderBlock(SpdyFrameBuilder* frame, const SpdyHeaderBlock* headers) { 1252c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun frame->WriteUInt16(headers->size()); // Number of headers. 1262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock::const_iterator it; 1272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun for (it = headers->begin(); it != headers->end(); ++it) { 1282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool wrote_header; 1292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun wrote_header = frame->WriteString(it->first); 1302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun wrote_header &= frame->WriteString(it->second); 1312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(wrote_header); 1322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 1342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Creates a FlagsAndLength. 1362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim GurunFlagsAndLength CreateFlagsAndLength(SpdyControlFlags flags, size_t length) { 1372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 1382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun FlagsAndLength flags_length; 1392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun flags_length.length_ = htonl(static_cast<uint32>(length)); 1402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_EQ(0, flags & ~kControlFlagsMask); 1412c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun flags_length.flags_[0] = flags; 1422c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return flags_length; 1432c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 1442c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFramer::SpdyFramer() 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : state_(SPDY_RESET), 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_code_(SPDY_NO_ERROR), 1482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_data_(0), 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch remaining_control_payload_(0), 1502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_header_(0), 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_frame_buffer_(NULL), 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_frame_len_(0), 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch current_frame_capacity_(0), 1542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun validate_control_frame_sizes_(true), 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch enable_compression_(compression_default_), 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch visitor_(NULL) { 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFramer::~SpdyFramer() { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (header_compressor_.get()) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deflateEnd(header_compressor_.get()); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (header_decompressor_.get()) { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inflateEnd(header_decompressor_.get()); 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CleanupStreamCompressorsAndDecompressors(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete [] current_frame_buffer_; 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunconst char* SpdyFramer::StatusCodeToString(int status_code) { 1712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun switch (status_code) { 1722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case INVALID: 1732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "INVALID"; 1742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case PROTOCOL_ERROR: 1752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "PROTOCOL_ERROR"; 1762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case INVALID_STREAM: 1772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "INVALID_STREAM"; 1782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case REFUSED_STREAM: 1792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "REFUSED_STREAM"; 1802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case UNSUPPORTED_VERSION: 1812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "UNSUPPORTED_VERSION"; 1822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case CANCEL: 1832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "CANCEL"; 1842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case INTERNAL_ERROR: 1852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "INTERNAL_ERROR"; 1862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case FLOW_CONTROL_ERROR: 1872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "FLOW_CONTROL_ERROR"; 1882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 1892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "UNKNOWN_STATUS"; 1902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 1912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunconst char* SpdyFramer::ControlTypeToString(SpdyControlType type) { 1932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun switch (type) { 1942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_STREAM: 1952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "SYN_STREAM"; 1962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_REPLY: 1972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "SYN_REPLY"; 1982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case RST_STREAM: 1992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "RST_STREAM"; 2002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SETTINGS: 2012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "SETTINGS"; 2022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NOOP: 2032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "NOOP"; 2042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case PING: 2052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "PING"; 2062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case GOAWAY: 2072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "GOAWAY"; 2082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case HEADERS: 2092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "HEADERS"; 2102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case WINDOW_UPDATE: 2112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "WINDOW_UPDATE"; 2122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NUM_CONTROL_FRAME_TYPES: 2132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 2142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 2152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "UNKNOWN_CONTROL_TYPE"; 2162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 2172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsize_t SpdyFramer::ProcessInput(const char* data, size_t len) { 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(visitor_); 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t original_len = len; 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (len != 0) { 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (state_) { 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_ERROR: 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_DONE: 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch goto bottom; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_AUTO_RESET: 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_RESET: 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Reset(); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHANGE_STATE(SPDY_READING_COMMON_HEADER); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_READING_COMMON_HEADER: { 2363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t bytes_read = ProcessCommonHeader(data, len); 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len -= bytes_read; 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += bytes_read; 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Arguably, this case is not necessary, as no bytes are consumed here. 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // I felt it was a nice partitioning, however (which probably indicates 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that it should be refactored into its own function!) 2452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // TODO(hkhalil): Remove -- while loop above prevents proper handling of 2462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // zero-length control frames. 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProcessControlFrameHeader(); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: { 2522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Control frames that contain header blocks (SYN_STREAM, SYN_REPLY, 2532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // HEADERS) take a different path through the state machine - they 2542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // will go: 2552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 1. SPDY_INTERPRET_CONTROL_FRAME_COMMON HEADER 2562c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 2. SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 2572c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 3. SPDY_CONTROL_FRAME_HEADER_BLOCK 2582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 2592c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // All other control frames will use the alternate route: 2602c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 1. SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER 2612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // 2. SPDY_CONTROL_FRAME_PAYLOAD 2622c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int bytes_read = ProcessControlFrameBeforeHeaderBlock(data, len); 2632c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun len -= bytes_read; 2642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun data += bytes_read; 2652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun continue; 2662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 2672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_HEADER_BLOCK: { 2692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int bytes_read = ProcessControlFrameHeaderBlock(data, len); 2702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun len -= bytes_read; 2712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun data += bytes_read; 2722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun continue; 2732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 2742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_CONTROL_FRAME_PAYLOAD: { 2763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t bytes_read = ProcessControlFramePayload(data, len); 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len -= bytes_read; 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += bytes_read; 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // intentional fallthrough 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_IGNORE_REMAINING_PAYLOAD: 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // control frame has too-large payload 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // intentional fallthrough 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SPDY_FORWARD_STREAM_FRAME: { 2853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick size_t bytes_read = ProcessDataFramePayload(data, len); 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch len -= bytes_read; 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data += bytes_read; 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch default: 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bottom: 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return original_len - len; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::Reset() { 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen state_ = SPDY_RESET; 30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen error_code_ = SPDY_NO_ERROR; 3012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_data_ = 0; 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen remaining_control_payload_ = 0; 3032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_header_ = 0; 30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame_len_ = 0; 30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_frame_capacity_ != kControlFrameBufferInitialSize) { 30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete [] current_frame_buffer_; 30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame_buffer_ = 0; 30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame_capacity_ = 0; 30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExpandControlFrameBuffer(kControlFrameBufferInitialSize); 31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SpdyFramer::ParseHeaderBlock(const SpdyFrame* frame, 31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyHeaderBlock* block) { 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyControlFrame control_frame(frame->data(), false); 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen uint32 type = control_frame.type(); 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (type != SYN_STREAM && type != SYN_REPLY && type != HEADERS) 31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Find the header data within the control frame. 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<SpdyFrame> decompressed_frame(DecompressFrame(*frame)); 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!decompressed_frame.get()) 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char *header_data = NULL; 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int header_length = 0; 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (type) { 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SYN_STREAM: 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySynStreamControlFrame syn_frame(decompressed_frame->data(), false); 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_data = syn_frame.header_block(); 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_length = syn_frame.header_block_len(); 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SYN_REPLY: 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySynReplyControlFrame syn_frame(decompressed_frame->data(), false); 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_data = syn_frame.header_block(); 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_length = syn_frame.header_block_len(); 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 343201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch case HEADERS: 34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyHeadersControlFrame header_frame(decompressed_frame->data(), false); 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_data = header_frame.header_block(); 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen header_length = header_frame.header_block_len(); 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 349201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch break; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder builder(header_data, header_length); 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void* iter = NULL; 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint16 num_headers; 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (builder.ReadUInt16(&iter, &num_headers)) { 356201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch int index; 357201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (index = 0; index < num_headers; ++index) { 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string name; 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string value; 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!builder.ReadString(&iter, &name)) 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!builder.ReadString(&iter, &value)) 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch break; 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!name.size() || !value.size()) 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (block->find(name) == block->end()) { 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (*block)[name] = value; 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return index == num_headers && 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch iter == header_data + header_length; 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t SpdyFramer::UpdateCurrentFrameBuffer(const char** data, size_t* len, 3792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t max_bytes) { 3802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_to_read = std::min(*len, max_bytes); 3812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_GE(current_frame_capacity_, current_frame_len_ + bytes_to_read); 3822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun memcpy(¤t_frame_buffer_[current_frame_len_], *data, bytes_to_read); 3832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun current_frame_len_ += bytes_to_read; 3842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun *data += bytes_to_read; 3852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun *len -= bytes_to_read; 3862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return bytes_to_read; 3872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 3882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 3892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, 3902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len) { 3912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); 3922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_GT(remaining_control_header_, 0u); 3932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t original_len = len; 3942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 3952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_header_) { 3962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 3972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_header_); 3982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_header_ -= bytes_read; 3992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_header_ == 0) { 4002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFrame control_frame(current_frame_buffer_, false); 4012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(control_frame.type() == SYN_STREAM || 4022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == SYN_REPLY || 4032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == HEADERS); 4042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun visitor_->OnControl(&control_frame); 4052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK); 4072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return original_len - len; 4102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 4112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Does not buffer the control payload. Instead, either passes directly to the 4132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// visitor or decompresses and then passes directly to the visitor, via 4142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// IncrementallyDeliverControlFrameHeaderData() or 4152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// IncrementallyDecompressControlFrameHeaderData() respectively. 4162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t SpdyFramer::NewProcessControlFrameHeaderBlock(const char* data, 4172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t data_len) { 4182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 4192c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFrame control_frame(current_frame_buffer_, false); 4202c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool processed_successfully = true; 4212c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(control_frame.type() == SYN_STREAM || 4222c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == SYN_REPLY || 4232c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == HEADERS); 4242c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t process_bytes = std::min(data_len, remaining_control_payload_); 4252c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_GT(process_bytes, 0u); 4262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (enable_compression_) { 4282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun processed_successfully = IncrementallyDecompressControlFrameHeaderData( 4292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &control_frame, data, process_bytes); 4302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } else { 4312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun processed_successfully = IncrementallyDeliverControlFrameHeaderData( 4322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &control_frame, data, process_bytes); 4332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_ -= process_bytes; 4352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Handle the case that there is no futher data in this frame. 4372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_payload_ == 0 && processed_successfully) { 4382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The complete header block has been delivered. We send a zero-length 4392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // OnControlFrameHeaderData() to indicate this. 4402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun visitor_->OnControlFrameHeaderData( 4412c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun GetControlFrameStreamId(&control_frame), NULL, 0); 4422c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4432c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // If this is a FIN, tell the caller. 4442c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (control_frame.flags() & CONTROL_FLAG_FIN) { 4452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame), 4462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun NULL, 0); 4472c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4492c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CHANGE_STATE(SPDY_RESET); 4502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Handle error. 4532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!processed_successfully) { 4542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return data_len; 4552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4562c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4572c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Return amount processed. 4582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return process_bytes; 4592c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 4602c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, 4622c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t data_len) { 4632c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); 4642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t original_data_len = data_len; 4652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFrame control_frame(current_frame_buffer_, false); 4662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool read_successfully = true; 4672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(control_frame.type() == SYN_STREAM || 4682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == SYN_REPLY || 4692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame.type() == HEADERS); 4702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (enable_compression_) { 4722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Note that the header block is held in the frame's payload, and is not 4732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // part of the frame's headers. 4742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_payload_ > 0) { 4752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_read = UpdateCurrentFrameBuffer( 4762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &data, 4772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &data_len, 4782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_); 4792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_ -= bytes_read; 4802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_payload_ == 0) { 4812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun read_successfully = IncrementallyDecompressControlFrameHeaderData( 4822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &control_frame); 4832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } else { 4862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_to_send = std::min(data_len, remaining_control_payload_); 4872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_GT(bytes_to_send, 0u); 4882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun read_successfully = IncrementallyDeliverControlFrameHeaderData( 4892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun &control_frame, data, bytes_to_send); 4902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun data_len -= bytes_to_send; 4912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_ -= bytes_to_send; 4922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 4932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_control_payload_ == 0 && read_successfully) { 4942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // The complete header block has been delivered. 4952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun visitor_->OnControlFrameHeaderData(GetControlFrameStreamId(&control_frame), 4962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun NULL, 0); 4972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 4982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // If this is a FIN, tell the caller. 4992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (control_frame.flags() & CONTROL_FLAG_FIN) { 5002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun visitor_->OnStreamFrameData(GetControlFrameStreamId(&control_frame), 5012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun NULL, 0); 5022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 5042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CHANGE_STATE(SPDY_RESET); 5052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!read_successfully) { 5072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return original_data_len; 5082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return original_data_len - data_len; 5102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 5112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 5122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun/* static */ 5132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunbool SpdyFramer::ParseHeaderBlockInBuffer(const char* header_data, 5142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t header_length, 5152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock* block) { 5162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyFrameBuilder builder(header_data, header_length); 5172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun void* iter = NULL; 5182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun uint16 num_headers; 5192c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (builder.ReadUInt16(&iter, &num_headers)) { 5202c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun for (int index = 0; index < num_headers; ++index) { 5212c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun std::string name; 5222c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun std::string value; 5232c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!builder.ReadString(&iter, &name)) 5242c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 5252c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!builder.ReadString(&iter, &value)) 5262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 5272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (block->find(name) == block->end()) { 5282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun (*block)[name] = value; 5292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } else { 5302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 5312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return true; 5342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 5352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 5362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 5372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdySynStreamControlFrame* SpdyFramer::CreateSynStream( 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyStreamId stream_id, SpdyStreamId associated_stream_id, int priority, 5402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(stream_id, static_cast<SpdyStreamId>(0)); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick frame.WriteUInt16(kControlFlagMask | spdy_version_); 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(SYN_STREAM); 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // Placeholder for the length and flags 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(stream_id); 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(associated_stream_id); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(ntohs(priority) << 6); // Priority. 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(headers->size()); // Number of headers. 5552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock::const_iterator it; 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (it = headers->begin(); it != headers->end(); ++it) { 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool wrote_header; 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrote_header = frame.WriteString(it->first); 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrote_header &= frame.WriteString(it->second); 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(wrote_header); 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Write the length and flags. 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t length = frame.length() - SpdyFrame::size(); 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FlagsAndLength flags_length; 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.length_ = htonl(static_cast<uint32>(length)); 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0, flags & ~kControlFlagsMask); 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.flags_[0] = flags; 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun scoped_ptr<SpdySynStreamControlFrame> syn_frame( 5732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (compressed) { 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<SpdySynStreamControlFrame*>( 5762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CompressControlFrame(*syn_frame.get())); 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 5782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return syn_frame.release(); 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 581201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSpdySynReplyControlFrame* SpdyFramer::CreateSynReply(SpdyStreamId stream_id, 5822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(stream_id, 0u); 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 587201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 5883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick frame.WriteUInt16(kControlFlagMask | spdy_version_); 589201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(SYN_REPLY); 590201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(0); // Placeholder for the length and flags. 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(stream_id); 592201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(0); // Unused 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 594201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(headers->size()); // Number of headers. 5952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock::const_iterator it; 596201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch for (it = headers->begin(); it != headers->end(); ++it) { 597201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch bool wrote_header; 598201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch wrote_header = frame.WriteString(it->first); 599201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch wrote_header &= frame.WriteString(it->second); 600201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK(wrote_header); 601201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 603201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Write the length and flags. 604201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch size_t length = frame.length() - SpdyFrame::size(); 605201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 606201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch FlagsAndLength flags_length; 607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch flags_length.length_ = htonl(static_cast<uint32>(length)); 608201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(0, flags & ~kControlFlagsMask); 609201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch flags_length.flags_[0] = flags; 610201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); 611201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 6122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun scoped_ptr<SpdySynReplyControlFrame> reply_frame( 6132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); 614201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (compressed) { 615201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return reinterpret_cast<SpdySynReplyControlFrame*>( 6162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CompressControlFrame(*reply_frame.get())); 617201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch } 6182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return reply_frame.release(); 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* static */ 622201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSpdyRstStreamControlFrame* SpdyFramer::CreateRstStream(SpdyStreamId stream_id, 623201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyStatusCodes status) { 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(stream_id, 0u); 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 626201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_NE(status, INVALID); 627201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_LT(status, NUM_STATUS_CODES); 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 6303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick frame.WriteUInt16(kControlFlagMask | spdy_version_); 631201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(RST_STREAM); 632201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(8); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(stream_id); 634201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(status); 635201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); 636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch/* static */ 639c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdySettingsControlFrame* SpdyFramer::CreateSettings( 640c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdySettings& values) { 641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick frame.WriteUInt16(kControlFlagMask | spdy_version_); 643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(SETTINGS); 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t settings_size = SpdySettingsControlFrame::size() - SpdyFrame::size() + 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8 * values.size(); 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(settings_size); 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(values.size()); 648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdySettings::const_iterator it = values.begin(); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (it != values.end()) { 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(it->first.id_); 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(it->second); 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it; 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 657201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch/* static */ 6582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim GurunSpdyNoOpControlFrame* SpdyFramer::CreateNopFrame() { 659201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFrameBuilder frame; 660201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(kControlFlagMask | spdy_version_); 661201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(NOOP); 662201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(0); 6632c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return reinterpret_cast<SpdyNoOpControlFrame*>(frame.take()); 6642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 6652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 6662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun/* static */ 6672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim GurunSpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) { 6682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyFrameBuilder frame; 6692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion); 6702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun frame.WriteUInt16(PING); 6712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t ping_size = SpdyPingControlFrame::size() - SpdyFrame::size(); 6722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun frame.WriteUInt32(ping_size); 6732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun frame.WriteUInt32(unique_id); 6742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); 675201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 676201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 677201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch/* static */ 678201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( 679201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyStreamId last_accepted_stream_id) { 680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); 681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFrameBuilder frame; 683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(kControlFlagMask | spdy_version_); 684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(GOAWAY); 685201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch size_t go_away_size = SpdyGoAwayControlFrame::size() - SpdyFrame::size(); 686201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(go_away_size); 687201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(last_accepted_stream_id); 688201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); 689201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 690201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 691201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSpdyHeadersControlFrame* SpdyFramer::CreateHeaders(SpdyStreamId stream_id, 6922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyControlFlags flags, bool compressed, const SpdyHeaderBlock* headers) { 693201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Basically the same as CreateSynReply(). 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(stream_id, 0u); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 698201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(kControlFlagMask | kSpdyProtocolVersion); 699201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(HEADERS); 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(0); // Placeholder for the length and flags. 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(stream_id); 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(0); // Unused 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt16(headers->size()); // Number of headers. 7052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyHeaderBlock::const_iterator it; 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (it = headers->begin(); it != headers->end(); ++it) { 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool wrote_header; 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrote_header = frame.WriteString(it->first); 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch wrote_header &= frame.WriteString(it->second); 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(wrote_header); 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Write the length and flags. 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t length = frame.length() - SpdyFrame::size(); 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, length & ~static_cast<size_t>(kLengthMask)); 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FlagsAndLength flags_length; 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.length_ = htonl(static_cast<uint32>(length)); 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0, flags & ~kControlFlagsMask); 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.flags_[0] = flags; 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteBytesToOffset(4, &flags_length, sizeof(flags_length)); 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7222c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun scoped_ptr<SpdyHeadersControlFrame> headers_frame( 7232c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (compressed) { 725201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return reinterpret_cast<SpdyHeadersControlFrame*>( 7262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun CompressControlFrame(*headers_frame.get())); 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 7282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return headers_frame.release(); 729201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 730201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 731201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch/* static */ 732201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochSpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( 733201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyStreamId stream_id, 734201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch uint32 delta_window_size) { 735201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_GT(stream_id, 0u); 736201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 737201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_GT(delta_window_size, 0u); 738201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_LE(delta_window_size, spdy::kSpdyStreamMaximumWindowSize); 739201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 740201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFrameBuilder frame; 741201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(kControlFlagMask | spdy_version_); 742201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt16(WINDOW_UPDATE); 743201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch size_t window_update_size = SpdyWindowUpdateControlFrame::size() - 744201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch SpdyFrame::size(); 745201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(window_update_size); 746201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(stream_id); 747201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch frame.WriteUInt32(delta_window_size); 748201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 75172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen/* static */ 75272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, 75372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySettings* settings) { 75472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(frame->type(), SETTINGS); 75572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(settings); 75672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 75772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyFrameBuilder parser(frame->header_block(), frame->header_block_len()); 75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* iter = NULL; 75972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen for (size_t index = 0; index < frame->num_entries(); ++index) { 76072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen uint32 id; 76172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen uint32 value; 76272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!parser.ReadUInt32(&iter, &id)) 76372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 76472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!parser.ReadUInt32(&iter, &value)) 76572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 76672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen settings->insert(settings->end(), std::make_pair(id, value)); 76772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 76872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 76972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 77072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data, 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch uint32 len, SpdyDataFlags flags) { 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyFrameBuilder frame; 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_GT(stream_id, 0u); 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, stream_id & ~kStreamIdMask); 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteUInt32(stream_id); 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0u, len & ~static_cast<size_t>(kLengthMask)); 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FlagsAndLength flags_length; 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.length_ = htonl(len); 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(0, flags & ~kDataFlagsMask); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch flags_length.flags_[0] = flags; 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame.WriteBytes(&flags_length, sizeof(flags_length)); 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 78772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen frame.WriteBytes(data, len); 78872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_ptr<SpdyFrame> data_frame(frame.take()); 78972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyDataFrame* rv; 79072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (flags & DATA_FLAG_COMPRESSED) { 79172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = reinterpret_cast<SpdyDataFrame*>(CompressFrame(*data_frame.get())); 79272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 79372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen rv = reinterpret_cast<SpdyDataFrame*>(data_frame.release()); 79472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 79572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 79672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (flags & DATA_FLAG_FIN) { 79772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupCompressorForStream(stream_id); 79872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 79972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 80072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return rv; 80172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 80272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 80372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyFrame* SpdyFramer::CompressFrame(const SpdyFrame& frame) { 80472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (frame.is_control_frame()) { 80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return CompressControlFrame( 80672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyControlFrame&>(frame)); 80772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 80872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return CompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame)); 80972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 81172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyFrame* SpdyFramer::DecompressFrame(const SpdyFrame& frame) { 81272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (frame.is_control_frame()) { 81372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DecompressControlFrame( 81472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyControlFrame&>(frame)); 81572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return DecompressDataFrame(reinterpret_cast<const SpdyDataFrame&>(frame)); 81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 81872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 81972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyFrame* SpdyFramer::DuplicateFrame(const SpdyFrame& frame) { 82072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int size = SpdyFrame::size() + frame.length(); 82172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyFrame* new_frame = new SpdyFrame(size); 82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(new_frame->data(), frame.data(), size); 82372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return new_frame; 82472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 82572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 82672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SpdyFramer::IsCompressible(const SpdyFrame& frame) const { 82772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The important frames to compress are those which contain large 82872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // amounts of compressible data - namely the headers in the SYN_STREAM 82972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // and SYN_REPLY. 83072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(mbelshe): Reconcile this with the spec when the spec is 83172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // explicit about which frames compress and which do not. 83272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (frame.is_control_frame()) { 83372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdyControlFrame& control_frame = 83472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyControlFrame&>(frame); 83572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return control_frame.type() == SYN_STREAM || 83672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen control_frame.type() == SYN_REPLY; 83772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 83872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 83972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdyDataFrame& data_frame = 84072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyDataFrame&>(frame); 84172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return (data_frame.flags() & DATA_FLAG_COMPRESSED) != 0; 84272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 84372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 84472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char* SpdyFramer::StateToString(int state) { 84572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (state) { 84672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_ERROR: 84772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "ERROR"; 84872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_DONE: 84972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "DONE"; 85072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_AUTO_RESET: 85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "AUTO_RESET"; 85272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_RESET: 85372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "RESET"; 85472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_READING_COMMON_HEADER: 85572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "READING_COMMON_HEADER"; 85672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: 85772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "INTERPRET_CONTROL_FRAME_COMMON_HEADER"; 85872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_CONTROL_FRAME_PAYLOAD: 85972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "CONTROL_FRAME_PAYLOAD"; 86072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_IGNORE_REMAINING_PAYLOAD: 86172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "IGNORE_REMAINING_PAYLOAD"; 86272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_FORWARD_STREAM_FRAME: 86372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "FORWARD_STREAM_FRAME"; 8642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 8652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK"; 8662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_HEADER_BLOCK: 8672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return "SPDY_CONTROL_FRAME_HEADER_BLOCK"; 86872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 86972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "UNKNOWN_STATE"; 87072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 87172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 87272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst char* SpdyFramer::ErrorCodeToString(int error_code) { 87372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (error_code) { 87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_NO_ERROR: 87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "NO_ERROR"; 87672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_INVALID_CONTROL_FRAME: 87772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "INVALID_CONTROL_FRAME"; 87872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_CONTROL_PAYLOAD_TOO_LARGE: 87972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "CONTROL_PAYLOAD_TOO_LARGE"; 88072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_ZLIB_INIT_FAILURE: 88172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "ZLIB_INIT_FAILURE"; 88272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_UNSUPPORTED_VERSION: 88372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "UNSUPPORTED_VERSION"; 88472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_DECOMPRESS_FAILURE: 88572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "DECOMPRESS_FAILURE"; 88672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_COMPRESS_FAILURE: 88772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "COMPRESS_FAILURE"; 88872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 88972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return "UNKNOWN_ERROR"; 89072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 89172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 89272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::set_enable_compression(bool value) { 89372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen enable_compression_ = value; 89472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 89672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::set_enable_compression_default(bool value) { 89772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen compression_default_ = value; 89872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 90072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensize_t SpdyFramer::ProcessCommonHeader(const char* data, size_t len) { 90172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This should only be called when we're in the SPDY_READING_COMMON_HEADER 90272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // state. 90372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(state_, SPDY_READING_COMMON_HEADER); 90472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 90572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t original_len = len; 90672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyFrame current_frame(current_frame_buffer_, false); 90772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 90872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen do { 90972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_frame_len_ < SpdyFrame::size()) { 91072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t bytes_desired = SpdyFrame::size() - current_frame_len_; 9112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun UpdateCurrentFrameBuffer(&data, &len, bytes_desired); 91272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Check for an empty data frame. 91372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_frame_len_ == SpdyFrame::size() && 91472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen !current_frame.is_control_frame() && 91572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame.length() == 0) { 91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_frame.flags() & CONTROL_FLAG_FIN) { 91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyDataFrame data_frame(current_frame_buffer_, false); 91872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnStreamFrameData(data_frame.stream_id(), NULL, 0); 91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 92072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_AUTO_RESET); 92172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 92272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 92372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 9242c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_data_ = current_frame.length(); 92572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 92672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // This is just a sanity check for help debugging early frame errors. 9272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_data_ > 1000000u) { 92872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << 92972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "Unexpectedly large frame. Spdy session is likely corrupt."; 93072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 93172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 93272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // if we're here, then we have the common header all received. 93372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!current_frame.is_control_frame()) 93472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME); 93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen else 93672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER); 93772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } while (false); 93872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 93972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return original_len - len; 94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 94172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 94272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::ProcessControlFrameHeader() { 94372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(SPDY_NO_ERROR, error_code_); 94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_LE(SpdyFrame::size(), current_frame_len_); 94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyControlFrame current_control_frame(current_frame_buffer_, false); 94672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 94772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We check version before we check validity: version can never be 'invalid', 94872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // it can only be unsupported. 94972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.version() != spdy_version_) { 95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_UNSUPPORTED_VERSION); 95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Next up, check to see if we have valid data. This should be after version 95572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // checking (otherwise if the the type were out of bounds due to a version 95672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // upgrade we would misclassify the error) and before checking the type 95772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // (type can definitely be out of bounds) 95872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!current_control_frame.AppearsToBeAValidControlFrame()) { 95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 96072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 96172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 96272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 96372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Do some sanity checking on the control frame sizes. 96472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (current_control_frame.type()) { 96572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SYN_STREAM: 96672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() < 96772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySynStreamControlFrame::size() - SpdyControlFrame::size()) 96872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 96972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 97072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SYN_REPLY: 97172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() < 97272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySynReplyControlFrame::size() - SpdyControlFrame::size()) 97372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 97472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 97572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case RST_STREAM: 97672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() != 97772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyRstStreamControlFrame::size() - SpdyFrame::size()) 97872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 97972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 98072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SETTINGS: 98172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() < 98272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdySettingsControlFrame::size() - SpdyControlFrame::size()) 98372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 98472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 9852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // TODO(hkhalil): Remove NOOP. 98672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case NOOP: 98772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // NOOP. Swallow it. 9882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DLOG(INFO) << "Attempted frame size validation for NOOP. Resetting."; 98972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_AUTO_RESET); 99072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 99172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case GOAWAY: 99272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() != 99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyGoAwayControlFrame::size() - SpdyFrame::size()) 99472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 99572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 99672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case HEADERS: 99772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() < 99872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyHeadersControlFrame::size() - SpdyControlFrame::size()) 99972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 100072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 100172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case WINDOW_UPDATE: 100272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_control_frame.length() != 100372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyWindowUpdateControlFrame::size() - SpdyControlFrame::size()) 100472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 100572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 10062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case PING: 10072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (current_control_frame.length() != 10082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyPingControlFrame::size() - SpdyControlFrame::size()) 10092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_INVALID_CONTROL_FRAME); 10102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 101172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen default: 10122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun LOG(WARNING) << "Valid spdy control frame with unhandled type: " 101372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << current_control_frame.type(); 101472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(false); 101572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_INVALID_CONTROL_FRAME); 101672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 101772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 101872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 101972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen remaining_control_payload_ = current_control_frame.length(); 102072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (remaining_control_payload_ > kControlFrameBufferMaxSize) { 102172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 102272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 102372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 102472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 102572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ExpandControlFrameBuffer(remaining_control_payload_); 102672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_CONTROL_FRAME_PAYLOAD); 102772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 102872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 102972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensize_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) { 103072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t original_len = len; 103172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen do { 103272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (remaining_control_payload_) { 10332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, 10342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_); 10352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_control_payload_ -= bytes_read; 10362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_data_ -= bytes_read; 103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (remaining_control_payload_) 103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 103972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 104072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyControlFrame control_frame(current_frame_buffer_, false); 104172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnControl(&control_frame); 104272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 104372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If this is a FIN, tell the caller. 104472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (control_frame.type() == SYN_REPLY && 104572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen control_frame.flags() & CONTROL_FLAG_FIN) { 104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnStreamFrameData(reinterpret_cast<SpdySynReplyControlFrame*>( 104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &control_frame)->stream_id(), 104872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NULL, 0); 104972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 105072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 105172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_IGNORE_REMAINING_PAYLOAD); 105272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } while (false); 105372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return original_len - len; 105472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 105572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensize_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { 105772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t original_len = len; 105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SpdyDataFrame current_data_frame(current_frame_buffer_, false); 10602c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (remaining_data_) { 10612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t amount_to_forward = std::min(remaining_data_, len); 106272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { 106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (current_data_frame.flags() & DATA_FLAG_COMPRESSED) { 106472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen z_stream* decompressor = 106572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen GetStreamDecompressor(current_data_frame.stream_id()); 106672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!decompressor) 106772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 106872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 106972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t decompressed_max_size = amount_to_forward * 100; 107072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_array<char> decompressed(new char[decompressed_max_size]); 107172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressor->next_in = reinterpret_cast<Bytef*>( 107272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const_cast<char*>(data)); 107372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressor->avail_in = amount_to_forward; 107472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressor->next_out = 107572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<Bytef*>(decompressed.get()); 107672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressor->avail_out = decompressed_max_size; 107772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 107872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = inflate(decompressor, Z_SYNC_FLUSH); 107972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (rv != Z_OK) { 108072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LOG(WARNING) << "inflate failure: " << rv; 108172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen set_error(SPDY_DECOMPRESS_FAILURE); 108272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 108372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 108472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t decompressed_size = decompressed_max_size - 108572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressor->avail_out; 108672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 108772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Only inform the visitor if there is data. 108872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (decompressed_size) 108972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnStreamFrameData(current_data_frame.stream_id(), 109072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressed.get(), 109172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen decompressed_size); 109272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen amount_to_forward -= decompressor->avail_in; 109372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 109472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // The data frame was not compressed. 109572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Only inform the visitor if there is data. 109672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (amount_to_forward) 109772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnStreamFrameData(current_data_frame.stream_id(), 109872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data, amount_to_forward); 109972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 110072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 110172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data += amount_to_forward; 110272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen len -= amount_to_forward; 11032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun remaining_data_ -= amount_to_forward; 1104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // If the FIN flag is set, and there is no more data in this data 110672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // frame, inform the visitor of EOF via a 0-length data frame. 11072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!remaining_data_ && 110872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_data_frame.flags() & DATA_FLAG_FIN) { 110972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnStreamFrameData(current_data_frame.stream_id(), NULL, 0); 111072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CleanupDecompressorForStream(current_data_frame.stream_id()); 111172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 111272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 111372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_AUTO_RESET); 1114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 111572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return original_len - len; 1116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochz_stream* SpdyFramer::GetHeaderCompressor() { 1119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (header_compressor_.get()) 1120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return header_compressor_.get(); // Already initialized. 1121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_compressor_.reset(new z_stream); 1123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(header_compressor_.get(), 0, sizeof(z_stream)); 1124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int success = deflateInit2(header_compressor_.get(), 1126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorLevel, 1127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Z_DEFLATED, 1128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorWindowSizeInBits, 1129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorMemLevel, 1130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Z_DEFAULT_STRATEGY); 1131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success == Z_OK) 1132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = deflateSetDictionary(header_compressor_.get(), 1133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const Bytef*>(kDictionary), 1134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDictionarySize); 1135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success != Z_OK) { 1136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "deflateSetDictionary failure: " << success; 1137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_compressor_.reset(NULL); 1138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return header_compressor_.get(); 1141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochz_stream* SpdyFramer::GetHeaderDecompressor() { 1144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (header_decompressor_.get()) 1145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return header_decompressor_.get(); // Already initialized. 1146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_decompressor_.reset(new z_stream); 1148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(header_decompressor_.get(), 0, sizeof(z_stream)); 1149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Compute the id of our dictionary so that we know we're using the 1151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // right one when asked for it. 1152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dictionary_id == 0) { 1153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dictionary_id = adler32(0L, Z_NULL, 0); 1154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dictionary_id = adler32(dictionary_id, 1155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const Bytef*>(kDictionary), 1156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDictionarySize); 1157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int success = inflateInit(header_decompressor_.get()); 1160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success != Z_OK) { 1161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "inflateInit failure: " << success; 1162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_decompressor_.reset(NULL); 1163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return header_decompressor_.get(); 1166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochz_stream* SpdyFramer::GetStreamCompressor(SpdyStreamId stream_id) { 1169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap::iterator it = stream_compressors_.find(stream_id); 1170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != stream_compressors_.end()) 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return it->second; // Already initialized. 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<z_stream> compressor(new z_stream); 1174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(compressor.get(), 0, sizeof(z_stream)); 1175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int success = deflateInit2(compressor.get(), 1177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorLevel, 1178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Z_DEFLATED, 1179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorWindowSizeInBits, 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kCompressorMemLevel, 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Z_DEFAULT_STRATEGY); 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success != Z_OK) { 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "deflateInit failure: " << success; 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_compressors_[stream_id] = compressor.release(); 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochz_stream* SpdyFramer::GetStreamDecompressor(SpdyStreamId stream_id) { 1190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap::iterator it = stream_decompressors_.find(stream_id); 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != stream_decompressors_.end()) 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return it->second; // Already initialized. 1193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<z_stream> decompressor(new z_stream); 1195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memset(decompressor.get(), 0, sizeof(z_stream)); 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int success = inflateInit(decompressor.get()); 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success != Z_OK) { 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "inflateInit failure: " << success; 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return stream_decompressors_[stream_id] = decompressor.release(); 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1205c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyControlFrame* SpdyFramer::CompressControlFrame( 1206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdyControlFrame& frame) { 1207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* compressor = GetHeaderCompressor(); 1208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!compressor) 1209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<SpdyControlFrame*>( 1211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressFrameWithZStream(frame, compressor)); 1212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 121472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSpdyDataFrame* SpdyFramer::CompressDataFrame(const SpdyDataFrame& frame) { 121572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen z_stream* compressor = GetStreamCompressor(frame.stream_id()); 121672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!compressor) 121772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return NULL; 121872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return reinterpret_cast<SpdyDataFrame*>( 121972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CompressFrameWithZStream(frame, compressor)); 122072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 122172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyControlFrame* SpdyFramer::DecompressControlFrame( 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdyControlFrame& frame) { 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor = GetHeaderDecompressor(); 1225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!decompressor) 1226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<SpdyControlFrame*>( 1228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DecompressFrameWithZStream(frame, decompressor)); 1229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Incrementally decompress the control frame's header block, feeding the 12322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// result to the visitor in chunks. Continue this until the visitor 12332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// indicates that it cannot process any more data, or (more commonly) we 12342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// run out of data to deliver. 12352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunbool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 12362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* control_frame) { 12372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun z_stream* decomp = GetHeaderDecompressor(); 12382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int payload_length; 12392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int header_length; 12402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* payload; 12412c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool read_successfully = true; 12422c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool more = true; 12432c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun char buffer[kHeaderDataChunkMaxSize]; 12442c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 12452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!GetFrameBoundaries( 12462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun *control_frame, &payload_length, &header_length, &payload)) { 12472c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DLOG(ERROR) << "Control frame of type " 12482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun << SpdyFramer::ControlTypeToString(control_frame->type()) 12492c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun <<" doesn't have headers"; 12502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 12512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 12522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); 12532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->avail_in = payload_length; 12542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); 12552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_LT(0u, stream_id); 12562c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun while (more && read_successfully) { 12572c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->next_out = reinterpret_cast<Bytef*>(buffer); 12582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->avail_out = arraysize(buffer); 12592c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int rv = DecompressHeaderBlockInZStream(decomp); 12602c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (rv != Z_OK) { 12612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_DECOMPRESS_FAILURE); 12622c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DLOG(WARNING) << "inflate failure: " << rv; 12632c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun more = read_successfully = false; 12642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } else { 12652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_GT(arraysize(buffer), decomp->avail_out); 12662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len = arraysize(buffer) - decomp->avail_out; 12672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun read_successfully = visitor_->OnControlFrameHeaderData(stream_id, buffer, 12682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun len); 12692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!read_successfully) { 12702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Assume that the problem was the header block was too large for the 12712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // visitor. 12722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 12732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 12742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun more = decomp->avail_in > 0; 12752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 12762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 12772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return read_successfully; 12782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 12792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 12802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// Incrementally decompress the control frame's header block, feeding the 12812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// result to the visitor in chunks. Continue this until the visitor 12822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// indicates that it cannot process any more data, or (more commonly) we 12832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun// run out of data to deliver. 12842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunbool SpdyFramer::IncrementallyDecompressControlFrameHeaderData( 12852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* control_frame, 12862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* data, 12872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len) { 12882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Get a decompressor or set error. 12892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun z_stream* decomp = GetHeaderDecompressor(); 12902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (decomp == NULL) { 12912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun LOG(DFATAL) << "Couldn't get decompressor for handling compressed headers."; 12922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_DECOMPRESS_FAILURE); 12932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 12942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 12952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 12962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool processed_successfully = true; 12972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun char buffer[kHeaderDataChunkMaxSize]; 12982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 12992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(data)); 13002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->avail_in = len; 13012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); 13022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_LT(0u, stream_id); 13032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun while (decomp->avail_in > 0 && processed_successfully) { 13042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->next_out = reinterpret_cast<Bytef*>(buffer); 13052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun decomp->avail_out = arraysize(buffer); 13062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun int rv = DecompressHeaderBlockInZStream(decomp); 13072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (rv != Z_OK) { 13082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_DECOMPRESS_FAILURE); 13092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DLOG(WARNING) << "inflate failure: " << rv; 13102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun processed_successfully = false; 13112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } else { 13122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t decompressed_len = arraysize(buffer) - decomp->avail_out; 13132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (decompressed_len > 0) { 13142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun processed_successfully = visitor_->OnControlFrameHeaderData( 13152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id, buffer, decompressed_len); 13162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!processed_successfully) { 13182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Assume that the problem was the header block was too large for the 13192c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // visitor. 13202c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 13212c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13222c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13232c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13242c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return processed_successfully; 13252c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 13262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 13272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunbool SpdyFramer::IncrementallyDeliverControlFrameHeaderData( 13282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* control_frame, const char* data, size_t len) { 13292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bool read_successfully = true; 13302c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyStreamId stream_id = GetControlFrameStreamId(control_frame); 13312c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_LT(0u, stream_id); 13322c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun while (read_successfully && len > 0) { 13332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t bytes_to_deliver = std::min(len, kHeaderDataChunkMaxSize); 13342c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun read_successfully = visitor_->OnControlFrameHeaderData(stream_id, data, 13352c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun bytes_to_deliver); 13362c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun data += bytes_to_deliver; 13372c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun len -= bytes_to_deliver; 13382c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (!read_successfully) { 13392c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // Assume that the problem was the header block was too large for the 13402c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // visitor. 13412c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); 13422c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13432c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13442c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return read_successfully; 13452c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 13462c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 13472c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunsize_t SpdyFramer::GetMinimumControlFrameSize(SpdyControlType type) { 13482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun switch (type) { 13492c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_STREAM: 13502c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdySynStreamControlFrame::size(); 13512c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_REPLY: 13522c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdySynReplyControlFrame::size(); 13532c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case RST_STREAM: 13542c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyRstStreamControlFrame::size(); 13552c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SETTINGS: 13562c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdySettingsControlFrame::size(); 13572c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NOOP: 13582c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyNoOpControlFrame::size(); 13592c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case PING: 13602c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyPingControlFrame::size(); 13612c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case GOAWAY: 13622c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyGoAwayControlFrame::size(); 13632c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case HEADERS: 13642c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyHeadersControlFrame::size(); 13652c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case WINDOW_UPDATE: 13662c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return SpdyWindowUpdateControlFrame::size(); 13672c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NUM_CONTROL_FRAME_TYPES: 13682c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 13692c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 13702c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun LOG(ERROR) << "Unknown SPDY control frame type " << type; 13712c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return 0x7FFFFFFF; // Max signed 32bit int 13722c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 13732c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 13742c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun/* static */ 13752c4085b2006233b5e3a3fe507d62642377b5dc2eSelim GurunSpdyStreamId SpdyFramer::GetControlFrameStreamId( 13762c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const SpdyControlFrame* control_frame) { 13772c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun SpdyStreamId stream_id = kInvalidStream; 13782c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun if (control_frame != NULL) { 13792c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun switch (control_frame->type()) { 13802c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_STREAM: 13812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( 13822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame)->stream_id(); 13832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 13842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SYN_REPLY: 13852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id = reinterpret_cast<const SpdySynReplyControlFrame*>( 13862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame)->stream_id(); 13872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 13882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case HEADERS: 13892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id = reinterpret_cast<const SpdyHeadersControlFrame*>( 13902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame)->stream_id(); 13912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 13922c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case RST_STREAM: 13932c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id = reinterpret_cast<const SpdyRstStreamControlFrame*>( 13942c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame)->stream_id(); 13952c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 13962c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case WINDOW_UPDATE: 13972c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun stream_id = reinterpret_cast<const SpdyWindowUpdateControlFrame*>( 13982c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun control_frame)->stream_id(); 13992c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 14002c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // All of the following types are not part of a particular stream. 14012c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // They all fall through to the invalid control frame type case. 14022c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // (The default case isn't used so that the compile will break if a new 14032c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // control frame type is added but not included here.) 14042c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SETTINGS: 14052c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NOOP: 14062c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case PING: 14072c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case GOAWAY: 14082c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case NUM_CONTROL_FRAME_TYPES: // makes compiler happy 14092c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun break; 14102c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 14112c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun } 14122c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return stream_id; 14132c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 14142c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 14152c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunvoid SpdyFramer::set_validate_control_frame_sizes(bool value) { 14162c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun validate_control_frame_sizes_ = value; 14172c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 14182c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyDataFrame* SpdyFramer::DecompressDataFrame(const SpdyDataFrame& frame) { 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor = GetStreamDecompressor(frame.stream_id()); 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!decompressor) 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return reinterpret_cast<SpdyDataFrame*>( 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DecompressFrameWithZStream(frame, decompressor)); 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFrame* SpdyFramer::CompressFrameWithZStream(const SpdyFrame& frame, 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* compressor) { 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int payload_length; 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int header_length; 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* payload; 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter compressed_frames("spdy.CompressedFrames"); 1434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter pre_compress_bytes("spdy.PreCompressSize"); 1435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); 1436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enable_compression_) 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DuplicateFrame(frame); 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create an output frame. 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int compressed_max_size = deflateBound(compressor, payload_length); 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_frame_size = header_length + compressed_max_size; 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size)); 1447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size()); 1448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); 1450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressor->avail_in = payload_length; 1451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + 1452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_length; 1453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressor->avail_out = compressed_max_size; 1454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Data packets have a 'compressed' flag. 1456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!new_frame->is_control_frame()) { 1457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* data_frame = 1458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<SpdyDataFrame*>(new_frame.get()); 1459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_frame->set_flags(data_frame->flags() | DATA_FLAG_COMPRESSED); 1460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14620888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#ifndef ANDROID 1463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Make sure that all the data we pass to zlib is defined. 1464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This way, all Valgrind reports on the compressed data are zlib's fault. 1465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (void)VALGRIND_CHECK_MEM_IS_DEFINED(compressor->next_in, 1466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen compressor->avail_in); 14670888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#endif 1468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = deflate(compressor, Z_SYNC_FLUSH); 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != Z_OK) { // How can we know that it compressed everything? 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This shouldn't happen, right? 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "deflate failure: " << rv; 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int compressed_size = compressed_max_size - compressor->avail_out; 1477dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 14780888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#ifndef ANDROID 1479dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We trust zlib. Also, we can't do anything about it. 1480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // See http://www.zlib.net/zlib_faq.html#faq36 1481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (void)VALGRIND_MAKE_MEM_DEFINED(new_frame->data() + header_length, 1482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen compressed_size); 14830888ad5615957327be92abf6dcbb768a1977ab49Kristian Monsen#endif 1484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_frame->set_length(header_length + compressed_size - SpdyFrame::size()); 1486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pre_compress_bytes.Add(payload_length); 1488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch post_compress_bytes.Add(new_frame->length()); 1489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch compressed_frames.Increment(); 1491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new_frame.release(); 1493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1495c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSpdyFrame* SpdyFramer::DecompressFrameWithZStream(const SpdyFrame& frame, 1496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor) { 1497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int payload_length; 1498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int header_length; 1499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* payload; 1500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1501ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter decompressed_frames("spdy.DecompressedFrames"); 1502ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter pre_decompress_bytes("spdy.PreDeCompressSize"); 1503ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::StatsCounter post_decompress_bytes("spdy.PostDeCompressSize"); 1504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!enable_compression_) 1506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DuplicateFrame(frame); 1507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) 1509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!frame.is_control_frame()) { 1512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const SpdyDataFrame& data_frame = 1513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const SpdyDataFrame&>(frame); 1514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((data_frame.flags() & DATA_FLAG_COMPRESSED) == 0) 1515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DuplicateFrame(frame); 1516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Create an output frame. Assume it does not need to be longer than 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the input data. 1520201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch size_t decompressed_max_size = kControlFrameBufferInitialSize; 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_frame_size = header_length + decompressed_max_size; 1522201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch if (frame.length() > decompressed_max_size) 1523201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch return NULL; 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SpdyFrame> new_frame(new SpdyFrame(new_frame_size)); 1525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch memcpy(new_frame->data(), frame.data(), frame.length() + SpdyFrame::size()); 1526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressor->avail_in = payload_length; 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + 1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch header_length; 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressor->avail_out = decompressed_max_size; 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv = inflate(decompressor, Z_SYNC_FLUSH); 1534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == Z_NEED_DICT) { 1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Need to try again with the right dictionary. 1536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (decompressor->adler == dictionary_id) { 1537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = inflateSetDictionary(decompressor, (const Bytef*)kDictionary, 1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kDictionarySize); 1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == Z_OK) 1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = inflate(decompressor, Z_SYNC_FLUSH); 1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != Z_OK) { // How can we know that it decompressed everything? 1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(WARNING) << "inflate failure: " << rv; 1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unset the compressed flag for data frames. 1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!new_frame->is_control_frame()) { 1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SpdyDataFrame* data_frame = 1551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<SpdyDataFrame*>(new_frame.get()); 1552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_frame->set_flags(data_frame->flags() & ~DATA_FLAG_COMPRESSED); 1553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int decompressed_size = decompressed_max_size - decompressor->avail_out; 1556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_frame->set_length(header_length + decompressed_size - SpdyFrame::size()); 1557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1558ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // If there is data left, then the frame didn't fully decompress. This 1559ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // means that there is stranded data at the end of this frame buffer which 1560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // will be ignored. 1561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(decompressor->avail_in, 0u); 1562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pre_decompress_bytes.Add(frame.length()); 1564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch post_decompress_bytes.Add(new_frame->length()); 1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch decompressed_frames.Increment(); 1567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return new_frame.release(); 1569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyFramer::CleanupCompressorForStream(SpdyStreamId id) { 1572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap::iterator it = stream_compressors_.find(id); 1573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != stream_compressors_.end()) { 1574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* compressor = it->second; 1575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deflateEnd(compressor); 1576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete compressor; 1577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_compressors_.erase(it); 1578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyFramer::CleanupDecompressorForStream(SpdyStreamId id) { 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap::iterator it = stream_decompressors_.find(id); 1583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (it != stream_decompressors_.end()) { 1584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor = it->second; 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inflateEnd(decompressor); 1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete decompressor; 1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_decompressors_.erase(it); 1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SpdyFramer::CleanupStreamCompressorsAndDecompressors() { 1592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CompressorMap::iterator it; 1593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it = stream_compressors_.begin(); 1595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (it != stream_compressors_.end()) { 1596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* compressor = it->second; 1597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch deflateEnd(compressor); 1598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete compressor; 1599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it; 1600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_compressors_.clear(); 1602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it = stream_decompressors_.begin(); 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch while (it != stream_decompressors_.end()) { 1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch z_stream* decompressor = it->second; 1606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch inflateEnd(decompressor); 1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete decompressor; 1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++it; 1609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch stream_decompressors_.clear(); 1611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsensize_t SpdyFramer::BytesSafeToRead() const { 161472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (state_) { 161572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_ERROR: 161672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_DONE: 161772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_AUTO_RESET: 161872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_RESET: 161972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 162072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_READING_COMMON_HEADER: 162172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_LT(current_frame_len_, SpdyFrame::size()); 162272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return SpdyFrame::size() - current_frame_len_; 162372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_INTERPRET_CONTROL_FRAME_COMMON_HEADER: 162472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 16252c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // TODO(rtenneti): Add support for SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK 16262c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun // and SPDY_CONTROL_FRAME_HEADER_BLOCK. 16272c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK: 16282c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun case SPDY_CONTROL_FRAME_HEADER_BLOCK: 16292c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return 0; 163072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_CONTROL_FRAME_PAYLOAD: 163172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_IGNORE_REMAINING_PAYLOAD: 163272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SPDY_FORWARD_STREAM_FRAME: 16332c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return remaining_data_; 1634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 163572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // We should never get to here. 163672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return 0; 163772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 1638c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::set_error(SpdyError error) { 164072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(visitor_); 164172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen error_code_ = error; 164272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen CHANGE_STATE(SPDY_ERROR); 164372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen visitor_->OnError(this); 1644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 164672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SpdyFramer::ExpandControlFrameBuffer(size_t size) { 164772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t alloc_size = size + SpdyFrame::size(); 16482c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK_LE(alloc_size, kControlFrameBufferMaxSize); 164972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (alloc_size <= current_frame_capacity_) 165072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 165172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char* new_buffer = new char[alloc_size]; 165272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen memcpy(new_buffer, current_frame_buffer_, current_frame_len_); 165372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete [] current_frame_buffer_; 165472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame_capacity_ = alloc_size; 165572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen current_frame_buffer_ = new_buffer; 1656c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool SpdyFramer::GetFrameBoundaries(const SpdyFrame& frame, 165972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int* payload_length, 166072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int* header_length, 166172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const char** payload) const { 166272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen size_t frame_size; 166372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (frame.is_control_frame()) { 166472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdyControlFrame& control_frame = 166572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyControlFrame&>(frame); 166672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (control_frame.type()) { 166772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SYN_STREAM: 166872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 166972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdySynStreamControlFrame& syn_frame = 167072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdySynStreamControlFrame&>(frame); 167172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen frame_size = SpdySynStreamControlFrame::size(); 167272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload_length = syn_frame.header_block_len(); 167372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *header_length = frame_size; 167472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload = frame.data() + *header_length; 167572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 167672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 167772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case SYN_REPLY: 167872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 167972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdySynReplyControlFrame& syn_frame = 168072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdySynReplyControlFrame&>(frame); 168172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen frame_size = SpdySynReplyControlFrame::size(); 168272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload_length = syn_frame.header_block_len(); 168372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *header_length = frame_size; 168472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload = frame.data() + *header_length; 168572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 168672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 168772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case HEADERS: 168872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen { 168972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const SpdyHeadersControlFrame& headers_frame = 169072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen reinterpret_cast<const SpdyHeadersControlFrame&>(frame); 169172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen frame_size = SpdyHeadersControlFrame::size(); 169272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload_length = headers_frame.header_block_len(); 169372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *header_length = frame_size; 169472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload = frame.data() + *header_length; 169572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 169672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 169772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen default: 169872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(mbelshe): set an error? 169972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; // We can't compress this frame! 170072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 170172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 170272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen frame_size = SpdyFrame::size(); 170372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *header_length = frame_size; 170472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload_length = frame.length(); 170572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen *payload = frame.data() + SpdyFrame::size(); 170672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 170772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 1708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace spdy 1711