15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2009 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/http_interface.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
74e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_frame.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/dump_cache/url_utilities.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/flip_config.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/sm_connection.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/tools/flip_server/spdy_util.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpSM::HttpSM(SMConnection* connection,
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               SMInterface* sm_spdy_interface,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               MemoryCache* memory_cache,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               FlipAcceptor* acceptor)
193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    : http_framer_(new BalsaFrame),
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stream_id_(0),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      server_idx_(-1),
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      connection_(connection),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sm_spdy_interface_(sm_spdy_interface),
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_list_(connection->output_list()),
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      output_ordering_(connection),
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      memory_cache_(connection->memory_cache()),
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      acceptor_(acceptor) {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_framer_->set_balsa_visitor(this);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_framer_->set_balsa_headers(&headers_);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_framer_->set_is_request(false);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpSM::~HttpSM() {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Reset();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete http_framer_;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void HttpSM::ProcessBodyData(const char* input, size_t size) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process Body Data: stream "
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << stream_id_ << ": size " << size;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->SendDataFrame(stream_id_, input, size, 0, false);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::ProcessHeaders(const BalsaHeaders& headers) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string host =
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string method = headers.request_method().as_string();
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VLOG(1) << ACCEPTOR_CLIENT_IDENT
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << "Received Request: " << headers.request_uri().as_string() << " "
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << method;
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::string filename =
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        EncodeURL(headers.request_uri().as_string(), host, method);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NewStream(stream_id_, 0, filename);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_id_ += 2;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << connection_->server_ip_ << ":" << connection_->server_port_
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << " ";
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->SendSynReply(stream_id_, headers);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::MessageDone() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone. Sending EOF: "
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "stream " << stream_id_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->SendEOF(stream_id_);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone.";
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::HandleHeaderError(BalsaFrame* framer) { HandleError(); }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::HandleChunkingError(BalsaFrame* framer) { HandleError(); }
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::HandleBodyError(BalsaFrame* framer) { HandleError(); }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::HandleError() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::AddToOutputOrder(const MemCacheIter& mci) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_ordering_.AddToOutputOrder(mci);
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::InitSMInterface(SMInterface* sm_spdy_interface, int32 server_idx) {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sm_spdy_interface_ = sm_spdy_interface;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  server_idx_ = server_idx;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              SMInterface* sm_interface,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              EpollServer* epoll_server,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int fd,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::string server_ip,
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::string server_port,
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              std::string remote_ip,
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool use_ssl) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << "connection.";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->InitSMConnection(connection_pool,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                sm_interface,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                epoll_server,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                fd,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                server_ip,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                server_port,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                remote_ip,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                use_ssl);
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::ProcessReadInput(const char* data, size_t len) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process read input: stream "
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << stream_id_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_framer_->ProcessInput(data, len);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::ProcessWriteInput(const char* data, size_t len) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process write input: size "
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << len << ": stream " << stream_id_;
1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  char* dataPtr = new char[len];
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(dataPtr, data, len);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataFrame* data_frame = new DataFrame;
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  data_frame->data = dataPtr;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_frame->size = len;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_frame->delete_when_done = true;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->EnqueueDataFrame(data_frame);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return len;
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpSM::MessageFullyRead() const {
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_framer_->MessageFullyRead();
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::SetStreamID(uint32 stream_id) { stream_id_ = stream_id; }
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool HttpSM::Error() const { return http_framer_->Error(); }
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* HttpSM::ErrorAsString() const {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode());
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::Reset() {
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream " << stream_id_;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_framer_->Reset();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::ResetForNewConnection() {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << "to: " << connection_->server_ip_ << ":"
155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            << connection_->server_port_ << " ";
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Message has not been fully read, either it is incomplete or the
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // server is closing the connection to signal message end.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!MessageFullyRead()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << "HTTP response closed before end of file detected. "
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "Sending EOF to spdy.";
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->SendEOF(stream_id_);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_ordering_.Reset();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_framer_->Reset();
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sm_spdy_interface_) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->ResetForNewInterface(server_idx_);
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::Cleanup() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER)) {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << "HttpSM Request Fully Read; stream_id: " << stream_id_;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connection_->Cleanup("request complete");
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int HttpSM::PostAcceptHook() { return 1; }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::NewStream(uint32 stream_id,
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                       uint32 priority,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       const std::string& filename) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemCacheIter mci;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mci.stream_id = stream_id;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mci.priority = priority;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!memory_cache_->AssignFileData(filename, &mci)) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error creating new stream.
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound";
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendErrorNotFound(stream_id);
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToOutputOrder(mci);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::SendEOF(uint32 stream_id) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendEOFImpl(stream_id);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sm_spdy_interface_->ResetForNewInterface(server_idx_);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::SendErrorNotFound(uint32 stream_id) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendErrorNotFoundImpl(stream_id);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return SendSynReplyImpl(stream_id, headers);
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::SendDataFrame(uint32 stream_id,
215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           const char* data,
216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           int64 len,
217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           uint32 flags,
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           bool compress) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDataFrameImpl(stream_id, data, len, flags, compress);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::SendEOFImpl(uint32 stream_id) {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataFrame* df = new DataFrame;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->data = "0\r\n\r\n";
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->size = 5;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->delete_when_done = false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnqueueDataFrame(df);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Reset();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::SendErrorNotFoundImpl(uint32 stream_id) {
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BalsaHeaders my_headers;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found");
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  my_headers.RemoveAllOfHeader("content-length");
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  my_headers.AppendHeader("transfer-encoding", "chunked");
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendSynReplyImpl(stream_id, my_headers);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDataFrame(stream_id, "page not found", 14, 0, false);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendEOFImpl(stream_id);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_ordering_.RemoveStreamId(stream_id);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimpleBuffer sb;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers.WriteHeaderAndEndingToBuffer(&sb);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataFrame* df = new DataFrame;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->size = sb.ReadableBytes();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buffer = new char[df->size];
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->data = buffer;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->delete_when_done = true;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sb.Read(buffer, df->size);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << stream_id_;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t df_size = df->size;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnqueueDataFrame(df);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return df_size;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpSM::SendSynStreamImpl(uint32 stream_id,
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const BalsaHeaders& headers) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SimpleBuffer sb;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  headers.WriteHeaderAndEndingToBuffer(&sb);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataFrame* df = new DataFrame;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->size = sb.ReadableBytes();
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buffer = new char[df->size];
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->data = buffer;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->delete_when_done = true;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sb.Read(buffer, df->size);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << stream_id_;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t df_size = df->size;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnqueueDataFrame(df);
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return df_size;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void HttpSM::SendDataFrameImpl(uint32 stream_id,
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               const char* data,
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               int64 len,
280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               uint32 flags,
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                               bool compress) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char chunk_buf[128];
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string chunk_description(chunk_buf);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DataFrame* df = new DataFrame;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->size = chunk_description.size() + len + 2;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* buffer = new char[df->size];
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->data = buffer;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  df->delete_when_done = true;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer, chunk_description.data(), chunk_description.size());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer + chunk_description.size(), data, len);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer + chunk_description.size() + len, "\r\n", 2);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnqueueDataFrame(df);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::EnqueueDataFrame(DataFrame* df) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream "
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << stream_id_;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connection_->EnqueueDataFrame(df);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpSM::GetOutput() {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemCacheIter* mci = output_ordering_.GetIter();
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (mci == NULL) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput: nothing to "
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "output!?: stream " << stream_id_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!mci->transformed_header) {
310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    mci->bytes_sent =
311a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SendSynReply(mci->stream_id, *(mci->file_data->headers()));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mci->transformed_header = true;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "header stream_id: [" << mci->stream_id << "]";
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (mci->body_bytes_consumed >= mci->file_data->body().size()) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendEOF(mci->stream_id);
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_ordering_.RemoveStreamId(mci->stream_id);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << mci->stream_id << "]";
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t num_to_write =
325ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      mci->file_data->body().size() - mci->body_bytes_consumed;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_to_write > mci->max_segment_size)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    num_to_write = mci->max_segment_size;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SendDataFrame(mci->stream_id,
330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                mci->file_data->body().data() + mci->body_bytes_consumed,
331a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                num_to_write,
332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                0,
333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                true);
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << mci->stream_id << "]: " << num_to_write;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mci->body_bytes_consumed += num_to_write;
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mci->bytes_sent += num_to_write;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
341