1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be 3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file. 4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_interface.h" 6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <string> 8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_framer.h" 10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/spdy/spdy_protocol.h" 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/dump_cache/url_utilities.h" 12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/flip_config.h" 13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/http_interface.h" 14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_util.h" 15dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::kSpdyStreamMaximumWindowSize; 17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::CONTROL_FLAG_NONE; 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::DATA_FLAG_COMPRESSED; 19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::DATA_FLAG_FIN; 20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::RST_STREAM; 21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SETTINGS_MAX_CONCURRENT_STREAMS; 22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SYN_REPLY; 23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SYN_STREAM; 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SettingsFlagsAndId; 25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyControlFrame; 26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdySettingsControlFrame; 27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyDataFlags; 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyDataFrame; 29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyRstStreamControlFrame; 30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyFrame; 31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyFramer; 32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyFramerVisitorInterface; 33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyHeaderBlock; 34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdySetting; 35dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdySettings; 36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdyStreamId; 37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdySynReplyControlFrame; 38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenusing spdy::SpdySynStreamControlFrame; 39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net { 41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SpdySM::disable_data_compression_ = true; 44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static 45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::string SpdySM::forward_ip_header_; 46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenclass SpdyFrameDataFrame : public DataFrame { 48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen public: 49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyFrameDataFrame(SpdyFrame* spdy_frame) 50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : frame(spdy_frame) { 51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data = spdy_frame->data(); 52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen size = spdy_frame->length() + SpdyFrame::size(); 53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen virtual ~SpdyFrameDataFrame() { 56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete frame; 57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SpdyFrame* frame; 60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}; 61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 62dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSpdySM::SpdySM(SMConnection* connection, 63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface* sm_http_interface, 64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EpollServer* epoll_server, 65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MemoryCache* memory_cache, 66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FlipAcceptor* acceptor) 67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : seq_num_(0), 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_(new SpdyFramer), 69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen valid_spdy_session_(false), 70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen connection_(connection), 71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_list_(connection->output_list()), 72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_(connection), 73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen next_outgoing_stream_id_(2), 74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen epoll_server_(epoll_server), 75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen acceptor_(acceptor), 76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memory_cache_(memory_cache), 77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen close_on_error_(false) { 78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_->set_visitor(this); 79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 81dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSpdySM::~SpdySM() { 82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete spdy_framer_; 83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::InitSMConnection(SMConnectionPoolInterface* connection_pool, 86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface* sm_interface, 87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EpollServer* epoll_server, 88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int fd, 89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string server_ip, 90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string server_port, 91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string remote_ip, 92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool use_ssl) { 93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT 94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "SpdySM: Initializing server connection."; 95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen connection_->InitSMConnection(connection_pool, sm_interface, 96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen epoll_server, fd, server_ip, server_port, 97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen remote_ip, use_ssl); 98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 100dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSMInterface* SpdySM::NewConnectionInterface() { 101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMConnection* server_connection = 102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMConnection::NewSMConnection(epoll_server_, 103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NULL, 104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memory_cache_, 105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen acceptor_, 106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen "http_conn: "); 107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (server_connection == NULL) { 108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "SpdySM: Could not create server connection"; 109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return NULL; 110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Creating new HTTP interface"; 112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface *sm_http_interface = new HttpSM(server_connection, 113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen this, 114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen epoll_server_, 115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen memory_cache_, 116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen acceptor_); 117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return sm_http_interface; 118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 120dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSMInterface* SpdySM::FindOrMakeNewSMConnectionInterface( 121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string server_ip, std::string server_port) { 122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface *sm_http_interface; 123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int32 server_idx; 124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (unused_server_interface_list.empty()) { 125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface = NewConnectionInterface(); 126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_idx = server_interface_list.size(); 127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_interface_list.push_back(sm_http_interface); 128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT 129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "SpdySM: Making new server connection on index: " 130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << server_idx; 131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_idx = unused_server_interface_list.back(); 133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen unused_server_interface_list.pop_back(); 134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface = server_interface_list.at(server_idx); 135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reusing connection on " 136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "index: " << server_idx; 137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface->InitSMInterface(this, server_idx); 140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface->InitSMConnection(NULL, sm_http_interface, 141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen epoll_server_, -1, 142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_ip, server_port, "", false); 143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return sm_http_interface; 145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint SpdySM::SpdyHandleNewStream(const SpdyControlFrame* frame, 148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string &http_data, 149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool *is_https_scheme) { 150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool parsed_headers = false; 151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock headers; 152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SpdySynStreamControlFrame* syn_stream = 153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen reinterpret_cast<const SpdySynStreamControlFrame*>(frame); 154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen *is_https_scheme = false; 156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parsed_headers = spdy_framer_->ParseHeaderBlock(frame, &headers); 157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn(" 158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << syn_stream->stream_id() << ")"; 159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: headers parsed?: " 160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << (parsed_headers? "yes": "no"); 161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (parsed_headers) { 162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: " 163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << headers.size(); 164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator url = headers.find("url"); 166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator method = headers.find("method"); 167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (url == headers.end() || method == headers.end()) { 168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: didn't find method or url " 169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "or method. Not creating stream"; 170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 0; 171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator scheme = headers.find("scheme"); 174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (scheme->second.compare("https") == 0) { 175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen *is_https_scheme = true; 176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // url->second here only ever seems to contain just the path. When this 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // path contains a query string with a http:// in one of its values, 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // UrlUtilities::GetUrlPath will fail and always return a / breaking 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the request. GetUrlPath assumes the absolute URL is being passed in. 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string uri; 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (url->second.compare(0,4,"http") == 0) 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uri = UrlUtilities::GetUrlPath(url->second); 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen else 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen uri = std::string(url->second); 187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) { 188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator referer = headers.find("referer"); 189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string host = UrlUtilities::GetUrlHost(url->second); 190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second 191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << " " << uri; 192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string filename = EncodeURL(uri, host, method->second); 193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NewStream(syn_stream->stream_id(), 194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen reinterpret_cast<const SpdySynStreamControlFrame*> 195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen (frame)->priority(), 196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen filename); 197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator version = headers.find("version"); 199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_data += method->second + " " + uri + " " + version->second + "\r\n"; 200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " " 201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << uri << " " << version->second; 202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (SpdyHeaderBlock::iterator i = headers.begin(); 203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen i != headers.end(); ++i) { 204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_data += i->first + ": " + i->second + "\r\n"; 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":" 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << i->second.c_str(); 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (forward_ip_header_.length()) { 209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // X-Client-Cluster-IP header 210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_data += forward_ip_header_ + ": " + 211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen connection_->client_ip() + "\r\n"; 212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_data += "\r\n"; 214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(3) << ACCEPTOR_CLIENT_IDENT << "SpdySM: HTTP Request:\n" << http_data; 217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 1; 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::OnControl(const SpdyControlFrame* frame) { 221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock headers; 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool parsed_headers = false; 223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen switch (frame->type()) { 224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case SYN_STREAM: 225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen { 226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SpdySynStreamControlFrame* syn_stream = 227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen reinterpret_cast<const SpdySynStreamControlFrame*>(frame); 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string http_data; 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool is_https_scheme; 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int ret = SpdyHandleNewStream(frame, http_data, &is_https_scheme); 232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!ret) { 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "SpdySM: Could not convert spdy into http."; 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We've seen a valid looking SYN_STREAM, consider this to have 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // been a real spdy session. 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen valid_spdy_session_ = true; 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) { 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string server_ip; 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string server_port; 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (is_https_scheme) { 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_ip = acceptor_->https_server_ip_; 245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_port = acceptor_->https_server_port_; 246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_ip = acceptor_->http_server_ip_; 248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen server_port = acceptor_->http_server_port_; 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface *sm_http_interface = 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FindOrMakeNewSMConnectionInterface(server_ip, server_port); 252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen stream_to_smif_[syn_stream->stream_id()] = sm_http_interface; 253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface->SetStreamID(syn_stream->stream_id()); 254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sm_http_interface->ProcessWriteInput(http_data.c_str(), 255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen http_data.size()); 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case SYN_REPLY: 261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen parsed_headers = spdy_framer_->ParseHeaderBlock(frame, &headers); 262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSynReply(" << 263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen reinterpret_cast<const SpdySynReplyControlFrame*>(frame)->stream_id() 264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << ")"; 265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen case RST_STREAM: 267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen { 268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const SpdyRstStreamControlFrame* rst_stream = 269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen reinterpret_cast<const SpdyRstStreamControlFrame*>(frame); 270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnRst(" 271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << rst_stream->stream_id() << ")"; 272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.RemoveStreamId(rst_stream ->stream_id()); 273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen break; 275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen default: 277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "SpdySM: Unknown control frame type"; 278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2812c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunbool SpdySM::OnControlFrameHeaderData(spdy::SpdyStreamId stream_id, 2822c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun const char* header_data, 2832c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun size_t len) { 2842c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(false); 2852c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun return false; 2862c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 2872c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 2882c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurunvoid SpdySM::OnDataFrameHeader(const spdy::SpdyDataFrame* frame) { 2892c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun DCHECK(false); 2902c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun} 2912c4085b2006233b5e3a3fe507d62642377b5dc2eSelim Gurun 292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::OnStreamFrameData(SpdyStreamId stream_id, 293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const char* data, size_t len) { 294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: StreamData(" << stream_id 295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << ", [" << len << "])"; 296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen StreamToSmif::iterator it = stream_to_smif_.find(stream_id); 297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (it == stream_to_smif_.end()) { 298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << "Dropping frame from unknown stream " << stream_id; 299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!valid_spdy_session_) 300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen close_on_error_ = true; 301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SMInterface* interface = it->second; 305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) 306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen interface->ProcessWriteInput(data, len); 307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::ProcessReadInput(const char* data, size_t len) { 310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return spdy_framer_->ProcessInput(data, len); 311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::ProcessWriteInput(const char* data, size_t len) { 314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 0; 315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SpdySM::MessageFullyRead() const { 318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return spdy_framer_->MessageFullyRead(); 319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool SpdySM::Error() const { 322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return close_on_error_ || spdy_framer_->HasError(); 323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char* SpdySM::ErrorAsString() const { 326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(Error()); 327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return SpdyFramer::ErrorCodeToString(spdy_framer_->error_code()); 328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::ResetForNewInterface(int32 server_idx) { 331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reset for new interface: " 332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "server_idx: " << server_idx; 333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen unused_server_interface_list.push_back(server_idx); 334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::ResetForNewConnection() { 337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // seq_num is not cleared, intentionally. 338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen delete spdy_framer_; 339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_ = new SpdyFramer; 340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_->set_visitor(this); 341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen valid_spdy_session_ = false; 342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.Reset(); 343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen next_outgoing_stream_id_ = 2; 344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Send a settings frame 347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint SpdySM::PostAcceptHook() { 348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdySettings settings; 349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SettingsFlagsAndId settings_id(SETTINGS_MAX_CONCURRENT_STREAMS); 350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen settings.push_back(SpdySetting(settings_id, 100)); 351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdySettingsControlFrame* settings_frame = 352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_->CreateSettings(settings); 353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending Settings Frame"; 355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EnqueueDataFrame(new SpdyFrameDataFrame(settings_frame)); 356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return 1; 357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::NewStream(uint32 stream_id, 360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen uint32 priority, 361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const std::string& filename) { 362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MemCacheIter mci; 363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci.stream_id = stream_id; 364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci.priority = priority; 365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) { 366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!memory_cache_->AssignFileData(filename, &mci)) { 367dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // error creating new stream. 368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound"; 369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendErrorNotFound(stream_id); 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 371dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddToOutputOrder(mci); 372dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 373dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen AddToOutputOrder(mci); 375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::AddToOutputOrder(const MemCacheIter& mci) { 379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.AddToOutputOrder(mci); 380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendEOF(uint32 stream_id) { 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendEOFImpl(stream_id); 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendErrorNotFound(uint32 stream_id) { 387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendErrorNotFoundImpl(stream_id); 388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 389dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendOKResponse(uint32 stream_id, std::string* output) { 391dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendOKResponseImpl(stream_id, output); 392dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) { 395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return SendSynStreamImpl(stream_id, headers); 396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { 399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return SendSynReplyImpl(stream_id, headers); 400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendDataFrame(uint32 stream_id, const char* data, int64 len, 403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen uint32 flags, bool compress) { 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags); 405dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendDataFrameImpl(stream_id, data, len, spdy_flags, compress); 406dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 407dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendEOFImpl(uint32 stream_id) { 409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendDataFrame(stream_id, NULL, 0, DATA_FLAG_FIN, false); 410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending EOF: " << stream_id; 411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen KillStream(stream_id); 412dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen stream_to_smif_.erase(stream_id); 413dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 414dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendErrorNotFoundImpl(uint32 stream_id) { 416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BalsaHeaders my_headers; 417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found"); 418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendSynReplyImpl(stream_id, my_headers); 419dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendDataFrame(stream_id, "wtf?", 4, DATA_FLAG_FIN, false); 420dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.RemoveStreamId(stream_id); 421dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendOKResponseImpl(uint32 stream_id, std::string* output) { 424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BalsaHeaders my_headers; 425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK"); 426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendSynReplyImpl(stream_id, my_headers); 427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendDataFrame( 428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen stream_id, output->c_str(), output->size(), DATA_FLAG_FIN, false); 429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.RemoveStreamId(stream_id); 430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::KillStream(uint32 stream_id) { 433dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen client_output_ordering_.RemoveStreamId(stream_id); 434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) { 437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (BalsaHeaders::const_header_lines_iterator hi = 438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.header_lines_begin(); 439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen hi != headers.header_lines_end(); 440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ++hi) { 441dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // It is illegal to send SPDY headers with empty value or header 442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // names. 443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!hi->first.length() || !hi->second.length()) 444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 445dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock::iterator fhi = dest.find(hi->first.as_string()); 447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (fhi == dest.end()) { 448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dest[hi->first.as_string()] = hi->second.as_string(); 449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dest[hi->first.as_string()] = ( 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string(fhi->second.data(), fhi->second.size()) + "\0" + 452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string(hi->second.data(), hi->second.size())); 453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // These headers have no value 457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dest.erase("X-Associated-Content"); // TODO(mbelshe): case-sensitive 458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen dest.erase("X-Original-Url"); // TODO(mbelshe): case-sensitive 459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::SendSynStreamImpl(uint32 stream_id, 462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const BalsaHeaders& headers) { 463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock block; 464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["method"] = headers.request_method().as_string(); 465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!headers.HasHeader("status")) 466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["status"] = headers.response_code().as_string(); 467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!headers.HasHeader("version")) 468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["version"] =headers.response_version().as_string(); 469dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (headers.HasHeader("X-Original-Url")) { 470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string original_url = headers.GetHeader("X-Original-Url").as_string(); 471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["path"] = UrlUtilities::GetUrlPath(original_url); 472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 473dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["path"] = headers.request_uri().as_string(); 474dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 475dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CopyHeaders(block, headers); 476dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 477dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdySynStreamControlFrame* fsrcf = 478dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_->CreateSynStream(stream_id, 0, 0, CONTROL_FLAG_NONE, true, 479dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &block); 480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen size_t df_size = fsrcf->length() + SpdyFrame::size(); 481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf)); 482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 483dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynStreamheader " 484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << stream_id; 485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return df_size; 486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { 489dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyHeaderBlock block; 490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen CopyHeaders(block, headers); 491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["status"] = headers.response_code().as_string() + " " + 492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.response_reason_phrase().as_string(); 493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen block["version"] = headers.response_version().as_string(); 494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdySynReplyControlFrame* fsrcf = 496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen spdy_framer_->CreateSynReply(stream_id, CONTROL_FLAG_NONE, true, &block); 497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen size_t df_size = fsrcf->length() + SpdyFrame::size(); 498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf)); 499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynReplyheader " 501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << stream_id; 502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return df_size; 503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 504dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len, 506dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyDataFlags flags, bool compress) { 507dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Force compression off if disabled via command line. 508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (disable_data_compression()) 509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen flags = static_cast<SpdyDataFlags>(flags & ~DATA_FLAG_COMPRESSED); 510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(mbelshe): We can't compress here - before going into the 512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // priority queue. Compression needs to be done 513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // with late binding. 514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (len == 0) { 515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyDataFrame* fdf = spdy_framer_->CreateDataFrame(stream_id, data, len, 516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen flags); 517dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EnqueueDataFrame(new SpdyFrameDataFrame(fdf)); 518dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 519dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 520dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 521dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Chop data frames into chunks so that one stream can't monopolize the 522dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // output channel. 523dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (len > 0) { 524dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 size = std::min(len, static_cast<int64>(kSpdySegmentSize)); 525dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyDataFlags chunk_flags = flags; 526dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 527dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If we chunked this block, and the FIN flag was set, there is more 528dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // data coming. So, remove the flag. 529dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((size < len) && (flags & DATA_FLAG_FIN)) 530dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_flags = static_cast<SpdyDataFlags>(chunk_flags & ~DATA_FLAG_FIN); 531dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 532dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SpdyDataFrame* fdf = spdy_framer_->CreateDataFrame(stream_id, data, size, 533dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen chunk_flags); 534dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EnqueueDataFrame(new SpdyFrameDataFrame(fdf)); 535dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 536dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending data frame " 537dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << stream_id << " [" << size << "] shrunk to " << fdf->length() 538dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << ", flags=" << flags; 539dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 540dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data += size; 541dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen len -= size; 542dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 543dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 544dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 545dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::EnqueueDataFrame(DataFrame* df) { 546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen connection_->EnqueueDataFrame(df); 547dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 548dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 549dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SpdySM::GetOutput() { 550dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (client_output_list_->size() < 2) { 551dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen MemCacheIter* mci = client_output_ordering_.GetIter(); 552dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mci == NULL) { 553dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT 554dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "SpdySM: GetOutput: nothing to output!?"; 555dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 556dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 557dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!mci->transformed_header) { 558dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->transformed_header = true; 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput transformed " 560dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "header stream_id: [" << mci->stream_id << "]"; 561dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if ((mci->stream_id % 2) == 0) { 562dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // this is a server initiated stream. 563dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Ideally, we'd do a 'syn-push' here, instead of a syn-reply. 564dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BalsaHeaders headers; 565dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.CopyFrom(*(mci->file_data->headers)); 566dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.ReplaceOrAppendHeader("status", "200"); 567dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.ReplaceOrAppendHeader("version", "http/1.1"); 568dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.SetRequestFirstlineFromStringPieces("PUSH", 569dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->file_data->filename, 570dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ""); 571dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->bytes_sent = SendSynStream(mci->stream_id, headers); 572dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 573dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen BalsaHeaders headers; 574dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen headers.CopyFrom(*(mci->file_data->headers)); 575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->bytes_sent = SendSynReply(mci->stream_id, headers); 576dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 577dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 578dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 579dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mci->body_bytes_consumed >= mci->file_data->body.size()) { 580dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput " 581dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "remove_stream_id: [" << mci->stream_id << "]"; 582dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendEOF(mci->stream_id); 583dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 584dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 585dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen size_t num_to_write = 586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->file_data->body.size() - mci->body_bytes_consumed; 587dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (num_to_write > mci->max_segment_size) 588dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen num_to_write = mci->max_segment_size; 589dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 590dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen bool should_compress = false; 591dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!mci->file_data->headers->HasHeader("content-encoding")) { 592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (mci->file_data->headers->HasHeader("content-type")) { 593dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string content_type = 594dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->file_data->headers->GetHeader("content-type").as_string(); 595dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (content_type.find("image") == content_type.npos) 596dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen should_compress = true; 597dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 599dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 600dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen SendDataFrame(mci->stream_id, 601dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->file_data->body.data() + mci->body_bytes_consumed, 602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen num_to_write, 0, should_compress); 603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame[" 604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << mci->stream_id << "]: " << num_to_write; 605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->body_bytes_consumed += num_to_write; 606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen mci->bytes_sent += num_to_write; 607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 608dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 609dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 610dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} // namespace net 611dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 612