1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2009 The Chromium Authors. All rights reserved.
2dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Use of this source code is governed by a BSD-style license that can be
3dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// found in the LICENSE file.
4dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
5dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/http_interface.h"
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/dump_cache/url_utilities.h"
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/balsa_frame.h"
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/flip_config.h"
10dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/sm_connection.h"
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/tools/flip_server/spdy_util.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
13dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace net {
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
15dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpSM::HttpSM(SMConnection* connection,
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               SMInterface* sm_spdy_interface,
17dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               EpollServer* epoll_server,
18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               MemoryCache* memory_cache,
19dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen               FlipAcceptor* acceptor)
20dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    : seq_num_(0),
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      http_framer_(new BalsaFrame),
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      stream_id_(0),
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      server_idx_(-1),
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      connection_(connection),
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      sm_spdy_interface_(sm_spdy_interface),
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      output_list_(connection->output_list()),
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      output_ordering_(connection),
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      memory_cache_(connection->memory_cache()),
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      acceptor_(acceptor) {
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_framer_->set_balsa_visitor(this);
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_framer_->set_balsa_headers(&headers_);
32dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY)
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    http_framer_->set_is_request(false);
34dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
35dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHttpSM::~HttpSM() {
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  Reset();
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete http_framer_;
38dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
39dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::ProcessBodyData(const char *input, size_t size) {
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process Body Data: stream "
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << stream_id_ << ": size " << size;
44dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_spdy_interface_->SendDataFrame(stream_id_, input, size, 0, false);
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::ProcessHeaders(const BalsaHeaders& headers) {
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string host =
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      UrlUtilities::GetUrlHost(headers.GetHeader("Host").as_string());
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string method = headers.request_method().as_string();
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Received Request: "
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << headers.request_uri().as_string() << " " << method;
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string filename = EncodeURL(headers.request_uri().as_string(),
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                host, method);
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NewStream(stream_id_, 0, filename);
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    stream_id_ += 2;
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Received Response from "
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << connection_->server_ip_ << ":"
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << connection_->server_port_ << " ";
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_spdy_interface_->SendSynReply(stream_id_, headers);
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::MessageDone() {
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone. Sending EOF: "
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "stream " << stream_id_;
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_spdy_interface_->SendEOF(stream_id_);
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: MessageDone.";
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::HandleHeaderError(BalsaFrame* framer) {
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandleError();
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::HandleChunkingError(BalsaFrame* framer) {
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandleError();
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::HandleBodyError(BalsaFrame* framer) {
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  HandleError();
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::HandleError() {
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Error detected";
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::AddToOutputOrder(const MemCacheIter& mci) {
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_ordering_.AddToOutputOrder(mci);
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendOKResponse(uint32 stream_id, std::string* output) {
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendOKResponseImpl(stream_id, output);
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::InitSMInterface(SMInterface* sm_spdy_interface,
102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                             int32 server_idx) {
103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sm_spdy_interface_ = sm_spdy_interface;
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  server_idx_ = server_idx;
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::InitSMConnection(SMConnectionPoolInterface* connection_pool,
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              SMInterface* sm_interface,
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              EpollServer* epoll_server,
110dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              int fd,
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              std::string server_ip,
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              std::string server_port,
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              std::string remote_ip,
114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                              bool use_ssl) {
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Initializing server "
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << "connection.";
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  connection_->InitSMConnection(connection_pool,
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                sm_interface,
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                epoll_server,
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                fd,
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                server_ip,
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                server_port,
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                remote_ip,
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                use_ssl);
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::ProcessReadInput(const char* data, size_t len) {
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process read input: stream "
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << stream_id_;
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return http_framer_->ProcessInput(data, len);
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::ProcessWriteInput(const char* data, size_t len) {
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Process write input: size "
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << len << ": stream " << stream_id_;
136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char * dataPtr = new char[len];
137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memcpy(dataPtr, data, len);
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DataFrame* data_frame = new DataFrame;
139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_frame->data = (const char *)dataPtr;
140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_frame->size = len;
141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  data_frame->delete_when_done = true;
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  connection_->EnqueueDataFrame(data_frame);
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return len;
144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpSM::MessageFullyRead() const {
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return http_framer_->MessageFullyRead();
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SetStreamID(uint32 stream_id) {
151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  stream_id_ = stream_id;
152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool HttpSM::Error() const {
155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return http_framer_->Error();
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst char* HttpSM::ErrorAsString() const {
159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return BalsaFrameEnums::ErrorCodeToString(http_framer_->ErrorCode());
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::Reset() {
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Reset: stream "
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << stream_id_;
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_framer_->Reset();
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::ResetForNewConnection() {
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(1) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Server connection closing "
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      << "to: " << connection_->server_ip_ << ":"
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      << connection_->server_port_ << " ";
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Message has not been fully read, either it is incomplete or the
175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // server is closing the connection to signal message end.
176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!MessageFullyRead()) {
177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    VLOG(2) << "HTTP response closed before end of file detected. "
178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            << "Sending EOF to spdy.";
179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    sm_spdy_interface_->SendEOF(stream_id_);
180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
181dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  seq_num_ = 0;
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_ordering_.Reset();
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  http_framer_->Reset();
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (sm_spdy_interface_) {
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_spdy_interface_->ResetForNewInterface(server_idx_);
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
188dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::Cleanup() {
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!(acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER)) {
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << "HttpSM Request Fully Read; stream_id: " << stream_id_;
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    connection_->Cleanup("request complete");
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
196dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenint HttpSM::PostAcceptHook() {
197dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return 1;
198dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
199dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
200dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::NewStream(uint32 stream_id, uint32 priority,
201dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       const std::string& filename) {
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MemCacheIter mci;
203dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  mci.stream_id = stream_id;
204dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  mci.priority = priority;
205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!memory_cache_->AssignFileData(filename, &mci)) {
206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // error creating new stream.
207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending ErrorNotFound";
208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SendErrorNotFound(stream_id);
209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  } else {
210dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AddToOutputOrder(mci);
211dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
212dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
213dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
214dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendEOF(uint32 stream_id) {
215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendEOFImpl(stream_id);
216dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_PROXY) {
217dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    sm_spdy_interface_->ResetForNewInterface(server_idx_);
218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
220dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendErrorNotFound(uint32 stream_id) {
222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendErrorNotFoundImpl(stream_id);
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
224dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
225dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::SendSynStream(uint32 stream_id, const BalsaHeaders& headers) {
226dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return 0;
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::SendSynReply(uint32 stream_id, const BalsaHeaders& headers) {
230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return SendSynReplyImpl(stream_id, headers);
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendDataFrame(uint32 stream_id, const char* data, int64 len,
234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                   uint32 flags, bool compress) {
235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendDataFrameImpl(stream_id, data, len, flags, compress);
236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendEOFImpl(uint32 stream_id) {
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DataFrame* df = new DataFrame;
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->data = "0\r\n\r\n";
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->size = 5;
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->delete_when_done = false;
243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EnqueueDataFrame(df);
244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) {
245dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Reset();
246dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
247dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
248dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendErrorNotFoundImpl(uint32 stream_id) {
250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BalsaHeaders my_headers;
251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "404", "Not Found");
252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.RemoveAllOfHeader("content-length");
253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.AppendHeader("transfer-encoding", "chunked");
254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendSynReplyImpl(stream_id, my_headers);
255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendDataFrame(stream_id, "page not found", 14, 0, false);
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendEOFImpl(stream_id);
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_ordering_.RemoveStreamId(stream_id);
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendOKResponseImpl(uint32 stream_id, std::string* output) {
261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  BalsaHeaders my_headers;
262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.SetFirstlineFromStringPieces("HTTP/1.1", "200", "OK");
263dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.RemoveAllOfHeader("content-length");
264dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  my_headers.AppendHeader("transfer-encoding", "chunked");
265dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendSynReplyImpl(stream_id, my_headers);
266dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendDataFrame(stream_id, output->c_str(), output->size(), 0, false);
267dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendEOFImpl(stream_id);
268dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  output_ordering_.RemoveStreamId(stream_id);
269dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
270dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
271dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::SendSynReplyImpl(uint32 stream_id, const BalsaHeaders& headers) {
272dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SimpleBuffer sb;
273dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  headers.WriteHeaderAndEndingToBuffer(&sb);
274dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DataFrame* df = new DataFrame;
275dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->size = sb.ReadableBytes();
276dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char* buffer = new char[df->size];
277dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->data = buffer;
278dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->delete_when_done = true;
279dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sb.Read(buffer, df->size);
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
281dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << stream_id_;
282dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t df_size = df->size;
283dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EnqueueDataFrame(df);
284dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return df_size;
285dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
286dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
287dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t HttpSM::SendSynStreamImpl(uint32 stream_id,
288dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                 const BalsaHeaders& headers) {
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SimpleBuffer sb;
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  headers.WriteHeaderAndEndingToBuffer(&sb);
291dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DataFrame* df = new DataFrame;
292dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->size = sb.ReadableBytes();
293dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char* buffer = new char[df->size];
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->data = buffer;
295dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->delete_when_done = true;
296dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  sb.Read(buffer, df->size);
297dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Sending HTTP Reply header "
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << stream_id_;
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t df_size = df->size;
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EnqueueDataFrame(df);
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return df_size;
302dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
303dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::SendDataFrameImpl(uint32 stream_id, const char* data, int64 len,
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                       uint32 flags, bool compress) {
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char chunk_buf[128];
307dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  snprintf(chunk_buf, sizeof(chunk_buf), "%x\r\n", (unsigned int)len);
308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::string chunk_description(chunk_buf);
309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DataFrame* df = new DataFrame;
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->size = chunk_description.size() + len + 2;
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  char* buffer = new char[df->size];
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->data = buffer;
313dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  df->delete_when_done = true;
314dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memcpy(buffer, chunk_description.data(), chunk_description.size());
315dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memcpy(buffer + chunk_description.size(), data, len);
316dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  memcpy(buffer + chunk_description.size() + len, "\r\n", 2);
317dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  EnqueueDataFrame(df);
318dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
319dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
320dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::EnqueueDataFrame(DataFrame* df) {
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: Enqueue data frame: stream "
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << stream_id_;
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  connection_->EnqueueDataFrame(df);
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid HttpSM::GetOutput() {
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  MemCacheIter* mci = output_ordering_.GetIter();
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (mci == NULL) {
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput: nothing to "
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "output!?: stream " << stream_id_;
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!mci->transformed_header) {
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    mci->bytes_sent = SendSynReply(mci->stream_id,
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   *(mci->file_data->headers));
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    mci->transformed_header = true;
337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput transformed "
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << "header stream_id: [" << mci->stream_id << "]";
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (mci->body_bytes_consumed >= mci->file_data->body.size()) {
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    SendEOF(mci->stream_id);
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    output_ordering_.RemoveStreamId(mci->stream_id);
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    VLOG(2) << ACCEPTOR_CLIENT_IDENT << "GetOutput remove_stream_id: ["
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen            << mci->stream_id << "]";
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t num_to_write =
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    mci->file_data->body.size() - mci->body_bytes_consumed;
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (num_to_write > mci->max_segment_size)
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    num_to_write = mci->max_segment_size;
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SendDataFrame(mci->stream_id,
354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                mci->file_data->body.data() + mci->body_bytes_consumed,
355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                num_to_write, 0, true);
356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  VLOG(2) << ACCEPTOR_CLIENT_IDENT << "HttpSM: GetOutput SendDataFrame["
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          << mci->stream_id << "]: " << num_to_write;
358dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  mci->body_bytes_consumed += num_to_write;
359dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  mci->bytes_sent += num_to_write;
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace net
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
364