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