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