15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/spdy_interface.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_framer.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/spdy/spdy_protocol.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/dump_cache/url_utilities.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/tools/flip_server/constants.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/flip_config.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/http_interface.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/spdy_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string SpdySM::forward_ip_header_; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpdyFrameDataFrame : public DataFrame { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) explicit SpdyFrameDataFrame(SpdyFrame* spdy_frame) : frame(spdy_frame) { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data = spdy_frame->data(); 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size = spdy_frame->size(); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) virtual ~SpdyFrameDataFrame() { delete frame; } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyFrame* frame; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SpdySM::SpdySM(SMConnection* connection, 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SMInterface* sm_http_interface, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EpollServer* epoll_server, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryCache* memory_cache, 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) FlipAcceptor* acceptor, 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SpdyMajorVersion spdy_version) 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) : buffered_spdy_framer_(new BufferedSpdyFramer(spdy_version, true)), 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_spdy_session_(false), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_(connection), 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_list_(connection->output_list()), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_(connection), 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_outgoing_stream_id_(2), 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) epoll_server_(epoll_server), 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) acceptor_(acceptor), 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memory_cache_(memory_cache), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_on_error_(false) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffered_spdy_framer_->set_visitor(this); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SpdySM::~SpdySM() { } 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::InitSMConnection(SMConnectionPoolInterface* connection_pool, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SMInterface* sm_interface, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EpollServer* epoll_server, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string server_ip, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string server_port, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string remote_ip, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_ssl) { 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Initializing server connection."; 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) connection_->InitSMConnection(connection_pool, 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sm_interface, 67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) epoll_server, 68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fd, 69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) server_ip, 70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) server_port, 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) remote_ip, 72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) use_ssl); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SMInterface* SpdySM::NewConnectionInterface() { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SMConnection* server_connection = 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SMConnection::NewSMConnection(epoll_server_, 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NULL, 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) memory_cache_, 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) acceptor_, 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "http_conn: "); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (server_connection == NULL) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "SpdySM: Could not create server connection"; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Creating new HTTP interface"; 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SMInterface* sm_http_interface = 88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) new HttpSM(server_connection, this, memory_cache_, acceptor_); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sm_http_interface; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SMInterface* SpdySM::FindOrMakeNewSMConnectionInterface( 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& server_ip, 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const std::string& server_port) { 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SMInterface* sm_http_interface; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int32 server_idx; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unused_server_interface_list.empty()) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm_http_interface = NewConnectionInterface(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_idx = server_interface_list.size(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_interface_list.push_back(sm_http_interface); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "SpdySM: Making new server connection on index: " << server_idx; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_idx = unused_server_interface_list.back(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_server_interface_list.pop_back(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm_http_interface = server_interface_list.at(server_idx); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reusing connection on " 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "index: " << server_idx; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm_http_interface->InitSMInterface(this, server_idx); 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sm_http_interface->InitSMConnection(NULL, 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) sm_http_interface, 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) epoll_server_, 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) -1, 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_ip, 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) server_port, 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string(), 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) false); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sm_http_interface; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int SpdySM::SpdyHandleNewStream(SpdyStreamId stream_id, 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyPriority priority, 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const SpdyHeaderBlock& headers, 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string& http_data, 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool* is_https_scheme) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *is_https_scheme = false; 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSyn(" << stream_id << ")"; 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: # headers: " << headers.size(); 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator method = headers.end(); 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator host = headers.end(); 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator path = headers.end(); 136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator scheme = headers.end(); 137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator version = headers.end(); 138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyHeaderBlock::const_iterator url = headers.end(); 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string path_string, host_string, version_string; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (spdy_version() == SPDY2) { 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) url = headers.find("url"); 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) method = headers.find("method"); 145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) version = headers.find("version"); 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scheme = headers.find("scheme"); 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (url == headers.end() || method == headers.end() || 148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) version == headers.end() || scheme == headers.end()) { 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is " 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "missing. Not creating stream"; 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 152a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // url->second here only ever seems to contain just the path. When this 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // path contains a query string with a http:// in one of its values, 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // UrlUtilities::GetUrlPath will fail and always return a / breaking 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the request. GetUrlPath assumes the absolute URL is being passed in. 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) path_string = UrlUtilities::GetUrlPath(url->second); 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host_string = UrlUtilities::GetUrlHost(url->second); 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) version_string = version->second; 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) method = headers.find(":method"); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) host = headers.find(":host"); 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) path = headers.find(":path"); 164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scheme = headers.find(":scheme"); 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (method == headers.end() || host == headers.end() || 166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) path == headers.end() || scheme == headers.end()) { 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: A mandatory header is " 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << "missing. Not creating stream"; 169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return 0; 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host_string = host->second; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) path_string = path->second; 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) version_string = "HTTP/1.1"; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (scheme->second.compare("https") == 0) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *is_https_scheme = true; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second 1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << " " << path_string; 1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string filename = EncodeURL(path_string, 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) host_string, 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) method->second); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NewStream(stream_id, priority, filename); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) http_data += 1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) method->second + " " + path_string + " " + version_string + "\r\n"; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Request: " << method->second << " " 1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << path_string << " " << version_string; 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) http_data += "Host: " + (*is_https_scheme ? 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) acceptor_->https_server_ip_ : 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) acceptor_->http_server_ip_) + "\r\n"; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SpdyHeaderBlock::const_iterator i = headers.begin(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != headers.end(); ++i) { 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if ((i->first.size() > 0 && i->first[0] == ':') || 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i->first == "host" || 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == method || 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == host || 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == path || 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == scheme || 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == version || 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i == url) { 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Ignore the entry. 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) http_data += i->first + ": " + i->second + "\r\n"; 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << i->first.c_str() << ":" 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << i->second.c_str(); 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (forward_ip_header_.length()) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // X-Client-Cluster-IP header 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_data += forward_ip_header_ + ": " + 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) connection_->client_ip() + "\r\n"; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) http_data += "\r\n"; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(3) << ACCEPTOR_CLIENT_IDENT << "SpdySM: HTTP Request:\n" << http_data; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::OnStreamFrameData(SpdyStreamId stream_id, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* data, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t len, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fin) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: StreamData(" << stream_id 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", [" << len << "])"; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StreamToSmif::iterator it = stream_to_smif_.find(stream_id); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == stream_to_smif_.end()) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << "Dropping frame from unknown stream " << stream_id; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!valid_spdy_session_) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_on_error_ = true; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SMInterface* interface = it->second; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interface->ProcessWriteInput(data, len); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::OnSynStream(SpdyStreamId stream_id, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyStreamId associated_stream_id, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyPriority priority, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool unidirectional, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string http_data; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_https_scheme; 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int ret = SpdyHandleNewStream( 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_id, priority, headers, http_data, &is_https_scheme); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ret) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "SpdySM: Could not convert spdy into http."; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've seen a valid looking SYN_STREAM, consider this to have 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // been a real spdy session. 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_spdy_session_ = true; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string server_ip; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string server_port; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_https_scheme) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_ip = acceptor_->https_server_ip_; 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port = acceptor_->https_server_port_; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_ip = acceptor_->http_server_ip_; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_port = acceptor_->http_server_port_; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SMInterface* sm_http_interface = 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindOrMakeNewSMConnectionInterface(server_ip, server_port); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_to_smif_[stream_id] = sm_http_interface; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sm_http_interface->SetStreamID(stream_id); 275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sm_http_interface->ProcessWriteInput(http_data.c_str(), http_data.size()); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::OnSynReply(SpdyStreamId stream_id, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(willchan): if there is an error parsing headers, we 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should send a RST_STREAM. 284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnSynReply(" << stream_id << ")"; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::OnHeaders(SpdyStreamId stream_id, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool fin, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SpdyHeaderBlock& headers) { 290a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnHeaders(" << stream_id << ")"; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SpdySM::OnRstStream(SpdyStreamId stream_id, SpdyRstStreamStatus status) { 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: OnRstStream(" << stream_id 295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) << ")"; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_.RemoveStreamId(stream_id); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 29903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool SpdySM::OnUnknownFrame(SpdyStreamId stream_id, int frame_type) { 30003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return false; 30103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 30203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdySM::ProcessReadInput(const char* data, size_t len) { 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffered_spdy_framer_->ProcessInput(data, len); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)size_t SpdySM::ProcessWriteInput(const char* data, size_t len) { return 0; } 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySM::MessageFullyRead() const { 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return buffered_spdy_framer_->MessageFullyRead(); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SpdySM::Error() const { 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return close_on_error_ || buffered_spdy_framer_->HasError(); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* SpdySM::ErrorAsString() const { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(Error()); 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SpdyFramer::ErrorCodeToString(buffered_spdy_framer_->error_code()); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::ResetForNewInterface(int32 server_idx) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Reset for new interface: " 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "server_idx: " << server_idx; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unused_server_interface_list.push_back(server_idx); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::ResetForNewConnection() { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // seq_num is not cleared, intentionally. 334a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffered_spdy_framer_.reset(); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid_spdy_session_ = false; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_.Reset(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_outgoing_stream_id_ = 2; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Send a settings frame 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SpdySM::PostAcceptHook() { 342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // We should have buffered_spdy_framer_ set after reuse 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsMap settings; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings[SETTINGS_MAX_CONCURRENT_STREAMS] = 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SettingsFlagsAndValue(SETTINGS_FLAG_NONE, 100); 347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyFrame* settings_frame = buffered_spdy_framer_->CreateSettings(settings); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending Settings Frame"; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnqueueDataFrame(new SpdyFrameDataFrame(settings_frame)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::NewStream(uint32 stream_id, 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint32 priority, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& filename) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemCacheIter mci; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci.stream_id = stream_id; 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci.priority = priority; 3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(yhirano): The program will crash when 3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // acceptor_->flip_handler_type_ != FLIP_HANDLER_SPDY_SERVER. 3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // It should be fixed or an assertion should be placed. 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (acceptor_->flip_handler_type_ == FLIP_HANDLER_SPDY_SERVER) { 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!memory_cache_->AssignFileData(filename, &mci)) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error creating new stream. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound"; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendErrorNotFound(stream_id); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddToOutputOrder(mci); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddToOutputOrder(mci); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::AddToOutputOrder(const MemCacheIter& mci) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_.AddToOutputOrder(mci); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SpdySM::SendEOF(uint32 stream_id) { SendEOFImpl(stream_id); } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::SendErrorNotFound(uint32 stream_id) { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendErrorNotFoundImpl(stream_id); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdySM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SendSynStreamImpl(stream_id, headers); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdySM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SendSynReplyImpl(stream_id, headers); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SpdySM::SendDataFrame(uint32 stream_id, 395a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* data, 396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 len, 397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) uint32 flags, 398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool compress) { 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyDataFlags spdy_flags = static_cast<SpdyDataFlags>(flags); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendDataFrameImpl(stream_id, data, len, spdy_flags, compress); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::SendEOFImpl(uint32 stream_id) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendDataFrame(stream_id, NULL, 0, DATA_FLAG_FIN, false); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending EOF: " << stream_id; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) KillStream(stream_id); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_to_smif_.erase(stream_id); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::SendErrorNotFoundImpl(uint32 stream_id) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BalsaHeaders my_headers; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found"); 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendSynReplyImpl(stream_id, my_headers); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendDataFrame(stream_id, "wtf?", 4, DATA_FLAG_FIN, false); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_.RemoveStreamId(stream_id); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::KillStream(uint32 stream_id) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_output_ordering_.RemoveStreamId(stream_id); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::CopyHeaders(SpdyHeaderBlock& dest, const BalsaHeaders& headers) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BalsaHeaders::const_header_lines_iterator hi = 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.header_lines_begin(); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hi != headers.header_lines_end(); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++hi) { 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is illegal to send SPDY headers with empty value or header 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // names. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hi->first.length() || !hi->second.length()) 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Key must be all lower case in SPDY headers. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string key = hi->first.as_string(); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::transform(key.begin(), key.end(), key.begin(), ::tolower); 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock::iterator fhi = dest.find(key); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fhi == dest.end()) { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest[key] = hi->second.as_string(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dest[key] = (std::string(fhi->second.data(), fhi->second.size()) + "\0" + 440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string(hi->second.data(), hi->second.size())); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These headers have no value 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dest.erase("X-Associated-Content"); // TODO(mbelshe): case-sensitive 446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dest.erase("X-Original-Url"); // TODO(mbelshe): case-sensitive 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdySM::SendSynStreamImpl(uint32 stream_id, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BalsaHeaders& headers) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock block; 452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) CopyHeaders(block, headers); 453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (spdy_version() == SPDY2) { 454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["method"] = headers.request_method().as_string(); 455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!headers.HasHeader("version")) 456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["version"] = headers.request_version().as_string(); 457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (headers.HasHeader("X-Original-Url")) { 458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string original_url = 459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.GetHeader("X-Original-Url").as_string(); 460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["url"] = UrlUtilities::GetUrlPath(original_url); 461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["url"] = headers.request_uri().as_string(); 463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":method"] = headers.request_method().as_string(); 466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":version"] = headers.request_version().as_string(); 467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (headers.HasHeader("X-Original-Url")) { 468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string original_url = 469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.GetHeader("X-Original-Url").as_string(); 470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":path"] = UrlUtilities::GetUrlPath(original_url); 471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":host"] = UrlUtilities::GetUrlPath(original_url); 472a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 473a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":path"] = headers.request_uri().as_string(); 474a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (block.find("host") != block.end()) { 475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":host"] = headers.GetHeader("Host").as_string(); 476a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block.erase("host"); 477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 478a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynStream( 4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream_id, 0, 0, CONTROL_FLAG_NONE, &block); 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t df_size = fsrcf->size(); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf)); 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynStreamheader " 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << stream_id; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return df_size; 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t SpdySM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) { 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyHeaderBlock block; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CopyHeaders(block, headers); 495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (spdy_version() == SPDY2) { 496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["status"] = headers.response_code().as_string() + " " + 497a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.response_reason_phrase().as_string(); 498a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block["version"] = headers.response_version().as_string(); 499a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 500a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":status"] = headers.response_code().as_string() + " " + 501a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.response_reason_phrase().as_string(); 502a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) block[":version"] = headers.response_version().as_string(); 503a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrame* fsrcf = buffered_spdy_framer_->CreateSynReply( 507a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) stream_id, CONTROL_FLAG_NONE, &block); 5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t df_size = fsrcf->size(); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnqueueDataFrame(new SpdyFrameDataFrame(fsrcf)); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending SynReplyheader " 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << stream_id; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return df_size; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void SpdySM::SendDataFrameImpl(uint32 stream_id, 517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const char* data, 518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int64 len, 519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyDataFlags flags, 520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool compress) { 521a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(buffered_spdy_framer_); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(mbelshe): We can't compress here - before going into the 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // priority queue. Compression needs to be done 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // with late binding. 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len == 0) { 526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SpdyFrame* fdf = 527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) buffered_spdy_framer_->CreateDataFrame(stream_id, data, len, flags); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnqueueDataFrame(new SpdyFrameDataFrame(fdf)); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chop data frames into chunks so that one stream can't monopolize the 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // output channel. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (len > 0) { 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 size = std::min(len, static_cast<int64>(kSpdySegmentSize)); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpdyDataFlags chunk_flags = flags; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we chunked this block, and the FIN flag was set, there is more 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // data coming. So, remove the flag. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((size < len) && (flags & DATA_FLAG_FIN)) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunk_flags = static_cast<SpdyDataFlags>(chunk_flags & ~DATA_FLAG_FIN); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SpdyFrame* fdf = buffered_spdy_framer_->CreateDataFrame( 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stream_id, data, size, chunk_flags); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnqueueDataFrame(new SpdyFrameDataFrame(fdf)); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: Sending data frame " 5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << stream_id << " [" << size << "] shrunk to " 5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) << (fdf->size() - kSpdyOverhead) << ", flags=" << flags; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data += size; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) len -= size; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::EnqueueDataFrame(DataFrame* df) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connection_->EnqueueDataFrame(df); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SpdySM::GetOutput() { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (client_output_list_->size() < 2) { 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemCacheIter* mci = client_output_ordering_.GetIter(); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mci == NULL) { 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "SpdySM: GetOutput: nothing to output!?"; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!mci->transformed_header) { 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci->transformed_header = true; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput transformed " 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "header stream_id: [" << mci->stream_id << "]"; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((mci->stream_id % 2) == 0) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is a server initiated stream. 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ideally, we'd do a 'syn-push' here, instead of a syn-reply. 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BalsaHeaders headers; 576ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch headers.CopyFrom(*(mci->file_data->headers())); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers.ReplaceOrAppendHeader("status", "200"); 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers.ReplaceOrAppendHeader("version", "http/1.1"); 579a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) headers.SetRequestFirstlineFromStringPieces( 580a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) "PUSH", mci->file_data->filename(), ""); 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci->bytes_sent = SendSynStream(mci->stream_id, headers); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BalsaHeaders headers; 584ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch headers.CopyFrom(*(mci->file_data->headers())); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci->bytes_sent = SendSynReply(mci->stream_id, headers); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 589ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (mci->body_bytes_consumed >= mci->file_data->body().size()) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput " 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "remove_stream_id: [" << mci->stream_id << "]"; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendEOF(mci->stream_id); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t num_to_write = 596ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch mci->file_data->body().size() - mci->body_bytes_consumed; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_to_write > mci->max_segment_size) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_to_write = mci->max_segment_size; 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool should_compress = false; 601ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!mci->file_data->headers()->HasHeader("content-encoding")) { 602ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (mci->file_data->headers()->HasHeader("content-type")) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string content_type = 604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch mci->file_data->headers()->GetHeader("content-type").as_string(); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content_type.find("image") == content_type.npos) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) should_compress = true; 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendDataFrame(mci->stream_id, 611ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch mci->file_data->body().data() + mci->body_bytes_consumed, 612a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) num_to_write, 613a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 0, 614a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) should_compress); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(2) << ACCEPTOR_CLIENT_IDENT << "SpdySM: GetOutput SendDataFrame[" 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << mci->stream_id << "]: " << num_to_write; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci->body_bytes_consumed += num_to_write; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mci->bytes_sent += num_to_write; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SpdySM::CreateFramer(SpdyMajorVersion spdy_version) { 623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!buffered_spdy_framer_); 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffered_spdy_framer_.reset(new BufferedSpdyFramer(spdy_version, true)); 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) buffered_spdy_framer_->set_visitor(this); 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 629